基于Jni技术局部区域抽取技术的研究
2017-07-24◆张跃
◆张 跃
(渤海船舶职业学院 辽宁 125105)
基于Jni技术局部区域抽取技术的研究
◆张 跃
(渤海船舶职业学院 辽宁 125105)
在三维图形中,对区域进行不规则的划分,并对划分后区域内的地形进行抽取有着非常重要的应用。通常三维图形其边界多是不规则的,因此使用球,正方形等规则图形进行区域的选择存在一定的局限性,并且通过程序来判断三角形是否在指定的区域内部是繁琐的。因此本文使用了Windows API函数,利用Jni接口在Java中调用API函数,简化了区域的不规则划分及区域内部三角形的抽取过程。
Jni技术;API函数;局域区域抽取
0 引言
局域区域的抽取技术在三维图形中,有着非常重要的应用。它包括两个部分的操作,一是在三角网格模型上交互式指定局域区域,二是对划分后的局域区域进行抽取。
一般来说,用户在网格上选择几个顶点作为控制点,然后用多面体曲面上的线将相邻的控制点连接起来成为一个环,这个环围成的区域就是用户选择的区域。当区域划分后,首先必须知道有哪些三角形在区域的内部以及这些三角形的三点坐标值,然后把在区域内部的三角形挑选出来。这样就需要判断一个点是否在一个指定区域的内部。传统的判断点在三角形内的算法有面积法,向量法等。这些方法都各有其缺点,比如面积法,计算量比较大,不能跟后续的处理相配合等弊端。
本文研究的是基于Jni技术的区域划分及区域内三角形的筛选,通过Windows API中的PtInRegion函数和CreatePolygonRgn函数来简化实现过程。
1 Jni技术简介
Java本地接口(Java Native Interface, Jni)属于JDK的一部分,是Java提供的一个工具,它使程序员能使用除Java之外其他语言写的代码。通过使用Jni编写程序,可以让代码方便地实现跨平台特性。Jni在不同平台上的实现步骤相同。除了生成动态链接库的方法不同外,其他实现方法是相同的。
Jni允许运行在Java虚拟机上的Java代码操作其他语言(例如C、汇编语言)编写的应用程序和库。从Java中调用C/C++的具体实现步骤如下:
(1)声明一个本地方法,它与普通方法相似,只是加上关键字”native”作为前缀,而且没有方法体。本地方法的实现放在系统的动态链接库中,在windows环境下为dll文件。
(2)在调用本地方法的Java类中用System.loadLibrary加载存放本地方法的动态链接库。
(3)编译该类,并用Javah带参出-Jni来产生本地方法原型的头文件。
(4)用C/C++实现本地方法,并通过编译、连接生成动态链接库。
除了互操作方面的作用之外, Jni允许你执行进一步的任务,包括: (1)抛出和捕捉来自本地方法的异常,然后让Java应用程序对这些异常进行处理;(2)通过Invocation API,你可以将JVM嵌入本地应用程序;(3)专门的Jni函数允许本地方法装载Java类并获得类的信息;(4)本地方法可以使用JNI来执行运行时的检查。
2 技术实现
首先需要进行局部区域的划分,由于正方形,矩形,球形等区域选择的局限性,因此想利用多边形区域进行选择。API函数中的CreatePolygonRgn函数的主要用途就是创建一个由一系列点所围成的多边形区域。通过用户用鼠标在三角网模型中点击出想要局部贴图的多边形区域。图1为区域选择的效果图。
图1 区域选择
区域划分后,要想把区域抽取出来,首先必须知道有哪些三角形在区域的内部以及这些三角形的三点坐标值,然后才能把区域内部的三角形挑选出来。这样就需要判断一个点是否在一个指定区域的内部。传统的判断点在三角形内的算法有面积法,向量法等。这些方法都各有其缺点,比如面积法,计算量比较大,不能跟后续的处理(如:消除隐藏面)相配合等弊端。而API函数PtInRegion的主要作用就是判断点是否在指定的区域内部,并且有返回值。通过判断点是否在区域的内部来判断有哪些三角形在区域的内部,来完成区域内三角形的筛选。
在Java中要直接实现API函数有一定的困难,因此本算法中使用了Jni,它允许Java代码和其他语言写的代码进行交互,用于为Java提供一个本地代码的接口。写一个Java类,在这个类中包含了需要调用的本地方法的描述。
public native void pJudge(int[] x,int[] y);
static
{ System.loadLibrary("kk"); }
使用VC来编写本地方法的实现函数,最后编译成.dll文件,其程序片段如下:
#include "jni.h"
#include
#include "Circle.h"
#include
JNIEXPORT void JNICALL Java_Circle_pJudge(JNIEnv *env,jobject, jintArray array, jintArray array1)
{ int len =env->GetArrayLength(array);jint* elems =env-> GetIntArrayElements(array, 0);
jint* judge =env-> GetIntArrayElements(array1, 0);
const POINT co[]={};
HRGN hRgn=CreatePolygonRgn(co,4,ALTERNATE);
int flag=(int)PtInRegion(hRgn,judge[0],judge[1]);
judge[2]=flag;
env->SetIntArrayRegion(array1,0,3,judge); }
用户通过鼠标点击后,将获得的多边形区域的各个顶点的坐标数据以及所要判断的是否在该区域内的点的坐标数据通过 Jni接口导入VC中,再利用CreatePolygonRgn和PtInRegion函数计算,将VC中计算后得到的结果再通过JNI接口传回到Java程序中。这样完成了区域的快速划分及局部区域的拾取。
在这一过程,把各个三角形中心坐标信息写入到数据结构中,并使用三角形中心坐标来代替此三角形进行计算,可以避免三角形共点产生的重复计算而引起的耗费过多计算时间问题。数据结构的具体设计为:
点类:
import java.util.*;
class Point{
int pointnumber;
float x,y,z;
String trianglenumber;
Point(int pointnumber,float x,float y,float z,String trianglenumber)
{this.pointnumber=pointnumber;
this.x=x;
this.y=y;
this.z=z;
this.trianglenumber=trianglenumber;}}
三角形类:
import java.util.*;
class Triangle{
int trianglenumber;
String pointnumber;
Point(int trianglenumber,String pointnumber)
{this.trianglenumber=trianglenumber;
this.pointnumber=pointnumber;} }
重心类:
import java.util.*;
class Focus{
int focusnumber;
float x,y,z;
String trianglenumber;
Point(int focusrnumber,float x,float y,float z,String trianglenumber)
{this.focusnumber=focusnumber;
this.x=x;
this.y=y;
this.z=z;
this.trianglenumber=trianglenumber;} }
3 结论
本算法可以在三维图形应用中,快速实现区域划分及划分后区域的筛选工作,但是更多适用于精度要求较低的情况。同时本文也给出了在Java中调用Windows API函数的常用方法。
[1]刘刚,金小刚,冯结青,彭群生.稠密网格上交互指定局部区域的新方法.计算机工程与应用,2003.
[2]沙嘉祥,宁书宁,林捷.利用JNI实现企业JAVA程序与传统应用程序的集成.计算机现代化,2004.