OSDN Git Service

[リリース]NyARToolkit 1.0.0
[nyartoolkit-and/nyartoolkit-and.git] / src / jp / nyatla / nyartoolkit / core / NyARMarker.java
1 /* \r
2  * PROJECT: NyARToolkit\r
3  * --------------------------------------------------------------------------------\r
4  * This work is based on the original ARToolKit developed by\r
5  *   Hirokazu Kato\r
6  *   Mark Billinghurst\r
7  *   HITLab, University of Washington, Seattle\r
8  * http://www.hitl.washington.edu/artoolkit/\r
9  *\r
10  * The NyARToolkit is Java version ARToolkit class library.\r
11  * Copyright (C)2008 R.Iizuka\r
12  *\r
13  * This program is free software; you can redistribute it and/or\r
14  * modify it under the terms of the GNU General Public License\r
15  * as published by the Free Software Foundation; either version 2\r
16  * of the License, or (at your option) any later version.\r
17  * \r
18  * This program is distributed in the hope that it will be useful,\r
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
21  * GNU General Public License for more details.\r
22  * \r
23  * You should have received a copy of the GNU General Public License\r
24  * along with this framework; if not, write to the Free Software\r
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
26  * \r
27  * For further information please contact.\r
28  *      http://nyatla.jp/nyatoolkit/\r
29  *      <airmail(at)ebony.plala.or.jp>\r
30  * \r
31  */\r
32 package jp.nyatla.nyartoolkit.core;\r
33 \r
34 \r
35 \r
36 \r
37 \r
38 \r
39 \r
40 /**\r
41  * typedef struct {\r
42  *      int     area;\r
43  *      double  pos[2];\r
44  *      int     coord_num;\r
45  *      int     x_coord[AR_CHAIN_MAX];\r
46  *      int     y_coord[AR_CHAIN_MAX];\r
47  *      int     vertex[5];\r
48  * } ARMarkerInfo2;\r
49  * \r
50  */\r
51 class NyARMarker\r
52 {\r
53     /**\r
54      * メモリブロックのサイズ(32*4=128kb)\r
55      */\r
56     private static final int ALLOCATE_PAGE_SIZE=256;\r
57     /**\r
58      * メモリブロックの初期サイズ\r
59      */\r
60     private static final int INITIAL_SIZE=1;\r
61     int[]       x_coord=new int[INITIAL_SIZE];\r
62     int[]       y_coord=new int[INITIAL_SIZE];\r
63     int         coord_num;\r
64     int         area;\r
65     final double[] pos=new double[2];\r
66     final int[] mkvertex=new int[5];\r
67     /**\r
68      * coordバッファをi_chain_num以上のサイズに再アロケートする。\r
69      * 内容の引継ぎは行われない。\r
70      * @param i_chain_num\r
71      */\r
72     private void reallocCoordArray(int i_chain_num)\r
73     {\r
74         if(x_coord.length<i_chain_num){\r
75             //ALLOCATE_PAGE_SIZE単位で確保する。\r
76             int new_size=((i_chain_num+ALLOCATE_PAGE_SIZE-1)/ALLOCATE_PAGE_SIZE)*ALLOCATE_PAGE_SIZE;\r
77             x_coord=new int[new_size];\r
78             y_coord=new int[new_size];\r
79             coord_num=0;\r
80         }\r
81     }\r
82     public void setCoordXY(int i_v1,int i_coord_num,int[] i_xcoord,int[] i_ycoord)\r
83     {\r
84         //メモリの割り当て保障\r
85         reallocCoordArray(i_coord_num+1);\r
86         //[A B C]を[B C A]に並べなおす。\r
87         System.arraycopy(i_xcoord,i_v1,x_coord,0,i_coord_num-i_v1);\r
88         System.arraycopy(i_xcoord,0,x_coord,i_coord_num-i_v1, i_v1);\r
89         x_coord[i_coord_num]=x_coord[0];\r
90         System.arraycopy(i_ycoord,i_v1,y_coord,0,i_coord_num-i_v1);\r
91         System.arraycopy(i_ycoord,0,y_coord,i_coord_num-i_v1, i_v1);\r
92         y_coord[i_coord_num]=y_coord[0];\r
93         coord_num=i_coord_num+1;\r
94         return;\r
95 //arGetContour関数から取り外した部分 \r
96 //      int[]      wx=new int[v1];//new int[Config.AR_CHAIN_MAX];\r
97 //      int[]      wy=new int[v1]; //new int[Config.AR_CHAIN_MAX];   \r
98 //      for(i=0;i<v1;i++) {\r
99 //          wx[i] = marker_ref.x_coord[i];//wx[i] = marker_info2->x_coord[i];\r
100 //          wy[i] = marker_ref.y_coord[i];//wy[i] = marker_info2->y_coord[i];\r
101 //      }\r
102 //      for(i=0;i<marker_ref.coord_num-v1;i++) {//for(i=v1;i<marker_info2->coord_num;i++) {\r
103 //          marker_ref.x_coord[i] = marker_ref.x_coord[i+v1];//marker_info2->x_coord[i-v1] = marker_info2->x_coord[i];\r
104 //          marker_ref.y_coord[i] = marker_ref.y_coord[i+v1];//marker_info2->y_coord[i-v1] = marker_info2->y_coord[i];\r
105 //      }\r
106 //      for(i=0;i<v1;i++) {\r
107 //          marker_ref.x_coord[i-v1+marker_ref.coord_num] = wx[i];//marker_info2->x_coord[i-v1+marker_info2->coord_num] = wx[i];\r
108 //          marker_ref.y_coord[i-v1+marker_ref.coord_num] = wy[i];//marker_info2->y_coord[i-v1+marker_info2->coord_num] = wy[i];\r
109 //      }\r
110 //      marker_ref.x_coord[marker_ref.coord_num] = marker_ref.x_coord[0];//marker_info2->x_coord[marker_info2->coord_num] = marker_info2->x_coord[0];\r
111 //      marker_ref.y_coord[marker_ref.coord_num] = marker_ref.y_coord[0];//marker_info2->y_coord[marker_info2->coord_num] = marker_info2->y_coord[0];\r
112 //      marker_ref.coord_num++;//marker_info2->coord_num++;\r
113     }\r
114     private final NyARVertexCounter wk_checkSquare_wv1=new NyARVertexCounter();\r
115     private final NyARVertexCounter wk_checkSquare_wv2=new NyARVertexCounter();\r
116     /**\r
117      * static int arDetectMarker2_check_square( int area, ARMarkerInfo2 *marker_info2, double factor )\r
118      * 関数の代替関数\r
119      * OPTIMIZED STEP [450->397]\r
120      * @param i_area\r
121      * @param i_factor\r
122      * @return\r
123      */\r
124     public boolean checkSquare(int i_area,double i_factor,double i_pos_x,double i_pos_y)\r
125     {\r
126         final int[] l_vertex=mkvertex;\r
127         final int[] l_x_coord=x_coord;\r
128         final int[] l_y_coord=y_coord;\r
129         final NyARVertexCounter wv1=wk_checkSquare_wv1;\r
130         final NyARVertexCounter wv2=wk_checkSquare_wv2;\r
131         int             sx, sy;\r
132         int             dmax, d, v1;\r
133         \r
134         int v2;//           int   wvnum1,wvnum2,v2;\r
135         double          thresh;\r
136         int             i;\r
137         \r
138         dmax = 0;\r
139         v1 = 0;\r
140         sx = l_x_coord[0];//sx = marker_info2->x_coord[0];\r
141         sy = l_y_coord[0];//sy = marker_info2->y_coord[0];\r
142         for(i=1;i<this.coord_num-1;i++){//for(i=1;i<marker_info2->coord_num-1;i++) {\r
143             d = (l_x_coord[i]-sx)*(l_x_coord[i]-sx)+ (l_y_coord[i]-sy)*(l_y_coord[i]-sy);\r
144             if( d > dmax ) {\r
145                 dmax = d;\r
146                 v1 = i;\r
147             }\r
148         }\r
149 \r
150         thresh = (i_area/0.75) * 0.01 * i_factor;\r
151 \r
152         l_vertex[0] = 0;\r
153 \r
154         if(!wv1.getVertex(l_x_coord,l_y_coord, 0,  v1,thresh)){     //if( get_vertex(marker_info2->x_coord, marker_info2->y_coord, 0,  v1,thresh, wv1, &wvnum1) < 0 ) {\r
155             return false;\r
156         }\r
157         if(!wv2.getVertex(l_x_coord,l_y_coord,v1,  this.coord_num-1, thresh)) {//if(get_vertex(marker_info2->x_coord, marker_info2->y_coord,v1,  marker_info2->coord_num-1, thresh, wv2, &wvnum2) < 0 ) {\r
158             return false;\r
159         }\r
160 \r
161         if(wv1.number_of_vertex==1 && wv2.number_of_vertex==1) {//if( wvnum1 == 1 && wvnum2 == 1 ) {\r
162             l_vertex[1] = wv1.vertex[0];\r
163             l_vertex[2] = v1;\r
164             l_vertex[3] = wv2.vertex[0];\r
165         }else if( wv1.number_of_vertex>1 && wv2.number_of_vertex==0 ) {//}else if( wvnum1 > 1 && wvnum2 == 0 ) {\r
166             v2 = v1 / 2;\r
167             if(!wv1.getVertex(l_x_coord,l_y_coord,0,  v2, thresh)) {\r
168                 return false;\r
169             }\r
170             if(!wv2.getVertex(l_x_coord,l_y_coord,v2,  v1, thresh)) {\r
171                 return false;\r
172             }\r
173             if(wv1.number_of_vertex==1 && wv2.number_of_vertex==1 ) {\r
174                 l_vertex[1] = wv1.vertex[0];\r
175                 l_vertex[2] = wv2.vertex[0];\r
176                 l_vertex[3] = v1;\r
177             }else{\r
178                 return false;\r
179             }\r
180         }else if(wv1.number_of_vertex==0 && wv2.number_of_vertex> 1 ) {\r
181             v2 = (v1 + this.coord_num-1) / 2;\r
182 \r
183             if(!wv1.getVertex(l_x_coord,l_y_coord,v1, v2, thresh)) {\r
184                 return false;\r
185             }\r
186             if(!wv2.getVertex(l_x_coord,l_y_coord,v2, this.coord_num-1, thresh)) {\r
187                 return false;\r
188             }\r
189             if( wv1.number_of_vertex==1 && wv2.number_of_vertex==1 ) {\r
190                 l_vertex[1] = v1;\r
191                 l_vertex[2] = wv1.vertex[0];\r
192                 l_vertex[3] = wv2.vertex[0];\r
193             }\r
194             else {\r
195                 return false;\r
196             }\r
197         }\r
198         else {\r
199             return false;\r
200         }\r
201         l_vertex[4] = this.coord_num-1;//この値使ってるの?\r
202         //\r
203         area   = i_area;\r
204         pos[0] = i_pos_x;\r
205         pos[1] = i_pos_y;\r
206 //      marker_holder[marker_num2].pos[1] = wpos[i*2+1];        \r
207         return true;\r
208     }        \r
209 }\r
210 \r
211 \r
212 /**\r
213  * get_vertex関数を切り離すためのクラス\r
214  *\r
215  */\r
216 final class NyARVertexCounter\r
217 {\r
218     public final int[] vertex=new int[10];//5まで削れる\r
219     public int number_of_vertex;\r
220     private double thresh;\r
221     private int[] x_coord;\r
222     private int[] y_coord;\r
223 \r
224     public boolean getVertex(int[] i_x_coord, int[] i_y_coord, int st,  int ed,double i_thresh)\r
225     {\r
226         this.number_of_vertex=0;\r
227         this.thresh=i_thresh;\r
228         this.x_coord=i_x_coord;\r
229         this.y_coord=i_y_coord;\r
230         return get_vertex(st,ed);\r
231     }\r
232     /**\r
233      * static int get_vertex( int x_coord[], int y_coord[], int st,  int ed,double thresh, int vertex[], int *vnum)\r
234      * 関数の代替関数\r
235      * @param x_coord\r
236      * @param y_coord\r
237      * @param st\r
238      * @param ed\r
239      * @param thresh\r
240      * @return\r
241      */\r
242     private boolean get_vertex(int st,  int ed)\r
243     {\r
244         double   d, dmax;\r
245         double   a, b, c;\r
246         int      i, v1=0;\r
247         final int[] lx_coord=this.x_coord;\r
248         final int[] ly_coord=this.y_coord;       \r
249         a = ly_coord[ed] - ly_coord[st];\r
250         b = lx_coord[st] - lx_coord[ed];\r
251         c = lx_coord[ed]*ly_coord[st] - ly_coord[ed]*lx_coord[st];\r
252         dmax = 0;\r
253         for(i=st+1;i<ed;i++) {\r
254             d = a*lx_coord[i] + b*ly_coord[i] + c;\r
255             if( d*d > dmax ) {\r
256                 dmax = d*d;\r
257                 v1 = i;\r
258             }\r
259         }\r
260         if( dmax/(a*a+b*b) > thresh ) {\r
261             if(!get_vertex(st,  v1)){\r
262                 return false;\r
263             }\r
264             if(number_of_vertex > 5 ){\r
265                 return false;\r
266             }\r
267             vertex[number_of_vertex] = v1;//vertex[(*vnum)] = v1;\r
268             number_of_vertex++;//(*vnum)++;\r
269         \r
270             if(!get_vertex(v1,  ed)){\r
271                 return false;\r
272             }\r
273         }\r
274         return true;\r
275     }\r
276 }\r
277 \r