◆張 躍
(渤海船舶職業學院 遼寧 125105)
基于Jni技術局部區域抽取技術的研究
◆張 躍
(渤海船舶職業學院 遼寧 125105)
在三維圖形中,對區域進行不規則的劃分,并對劃分后區域內的地形進行抽取有著非常重要的應用。通常三維圖形其邊界多是不規則的,因此使用球,正方形等規則圖形進行區域的選擇存在一定的局限性,并且通過程序來判斷三角形是否在指定的區域內部是繁瑣的。因此本文使用了Windows API函數,利用Jni接口在Java中調用API函數,簡化了區域的不規則劃分及區域內部三角形的抽取過程。
Jni技術;API函數;局域區域抽取
局域區域的抽取技術在三維圖形中,有著非常重要的應用。它包括兩個部分的操作,一是在三角網格模型上交互式指定局域區域,二是對劃分后的局域區域進行抽取。
一般來說,用戶在網格上選擇幾個頂點作為控制點,然后用多面體曲面上的線將相鄰的控制點連接起來成為一個環,這個環圍成的區域就是用戶選擇的區域。當區域劃分后,首先必須知道有哪些三角形在區域的內部以及這些三角形的三點坐標值,然后把在區域內部的三角形挑選出來。這樣就需要判斷一個點是否在一個指定區域的內部。傳統的判斷點在三角形內的算法有面積法,向量法等。這些方法都各有其缺點,比如面積法,計算量比較大,不能跟后續的處理相配合等弊端。
本文研究的是基于Jni技術的區域劃分及區域內三角形的篩選,通過Windows API中的PtInRegion函數和CreatePolygonRgn函數來簡化實現過程。
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來執行運行時的檢查。
首先需要進行局部區域的劃分,由于正方形,矩形,球形等區域選擇的局限性,因此想利用多邊形區域進行選擇。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;} }
本算法可以在三維圖形應用中,快速實現區域劃分及劃分后區域的篩選工作,但是更多適用于精度要求較低的情況。同時本文也給出了在Java中調用Windows API函數的常用方法。
[1]劉剛,金小剛,馮結青,彭群生.稠密網格上交互指定局部區域的新方法.計算機工程與應用,2003.
[2]沙嘉祥,寧書寧,林捷.利用JNI實現企業JAVA程序與傳統應用程序的集成.計算機現代化,2004.