OSDN Git Service

git-svn-id: http://svn.sourceforge.jp/svnroot/nyartoolkit/NyARToolkit/trunk@786 7cac0...
[nyartoolkit-and/nyartoolkit-and.git] / lib / src.rpf / jp / nyatla / nyartoolkit / rpf / utils / LineBaseVertexDetector.java
1 package jp.nyatla.nyartoolkit.rpf.utils;\r
2 \r
3 import jp.nyatla.nyartoolkit.NyARException;\r
4 import jp.nyatla.nyartoolkit.core.types.*;\r
5 \r
6 /**\r
7  * このクラスは、4本の直線式から、凸包の頂点を計算する機能を提供します。\r
8  */\r
9 public class LineBaseVertexDetector\r
10 {\r
11         /** 頂点の組合せテーブル(4,5頂点用)*/\r
12         private final static int[][] _45vertextable={\r
13                         {1,2,4,3},{0,2,5,3},{0,1,5,4},{0,1,5,4},{0,2,5,3},{1,2,4,3}};\r
14         /** 頂点組合せテーブル。(6頂点用)*/\r
15         private final static int[][] _order_table={{0,1,5,4},{0,2,5,3},{1,2,4,3}};\r
16         /** ワーク変数*/\r
17         private NyARDoublePoint2d[] __wk_v=NyARDoublePoint2d.createArray(6);\r
18         /**\r
19          * 4直線の交点から、凸包の頂点座標を計算します。\r
20          * @param i_line\r
21          * 直線式の配列です。要素数は4である必要があります。\r
22          * @param o_point\r
23          * 検出した頂点の座標です。要素数は4である必要があります。\r
24          * @return\r
25          * 凸包を計算できると、trueを返します。\r
26          * @throws NyARException\r
27          */\r
28         public boolean line2SquareVertex(VecLinearCoordinates.VecLinearCoordinatePoint[] i_line,NyARDoublePoint2d[] o_point) throws NyARException\r
29         {\r
30                 \r
31                 NyARDoublePoint2d[] v=this.__wk_v;\r
32                 int number_of_vertex=0;\r
33                 int non_vertexid=0;\r
34                 int ptr=0;\r
35                 for(int i=0;i<3;i++){\r
36                         for(int i2=i+1;i2<4;i2++){\r
37                                 if(i_line[i].crossPos(i_line[i2],v[ptr])){\r
38                                         number_of_vertex++;\r
39                                 }else{\r
40                                         non_vertexid=ptr;\r
41                                 }\r
42                                 ptr++;\r
43                         }\r
44                 }\r
45                 int num_of_plus=-1;\r
46                 int[] target_order;\r
47                 switch(number_of_vertex){\r
48                 case 4:\r
49                 case 5:\r
50                         //正の外積の数を得る。0,4ならば、目的の図形\r
51                         num_of_plus=countPlusExteriorProduct(v,_45vertextable[non_vertexid]);\r
52                         target_order=_45vertextable[non_vertexid];\r
53                         break;\r
54                 case 6:\r
55                         //(0-5),(1-4),(2-3)の頂点ペアの組合せを試す。頂点の検索順は、(0,1,5,4),(0,2,5,3),(1,2,4,3)\r
56                         //3パターンについて、正の外積の数を得る。0,4のものがあればOK\r
57                         int order_id=-1;\r
58                         num_of_plus=-1;\r
59                         for(int i=0;i<3;i++){\r
60                                 num_of_plus=countPlusExteriorProduct(v,_order_table[i]);\r
61                                 if(num_of_plus%4==0){\r
62                                         order_id=i;\r
63                                         break;\r
64                                 }\r
65                         }\r
66                         if(order_id==-1){\r
67                                 return false;\r
68                         }\r
69                         target_order=_order_table[order_id];\r
70                         break;\r
71                 default:\r
72                         //他の頂点数の時はNG\r
73                         return false;\r
74                 }\r
75                 //回転方向の正規化(ここパラメータ化しようよ)\r
76                 switch(num_of_plus){\r
77                 case  0:\r
78                         //逆回転で検出した場合\r
79                         for(int i=0;i<4;i++){\r
80                                 o_point[i].setValue(v[target_order[3-i]]);\r
81                         }\r
82                         break;\r
83                 case  4:\r
84                         //正回転で検出した場合\r
85                         for(int i=0;i<4;i++){\r
86                                 o_point[i].setValue(v[target_order[i]]);\r
87                         }\r
88                         break;\r
89                 default:\r
90                         return false;\r
91                 }\r
92                 return true;\r
93         }\r
94 \r
95         /**\r
96          * 4頂点を巡回して、正の外積数を数えます。\r
97          * @param p\r
98          * 頂点配列。4要素である事。\r
99          * @param order\r
100          * 頂点のインデクス配列。4要素である事。\r
101          * @return\r
102          * 正の外積数\r
103          */\r
104         private final static int countPlusExteriorProduct(NyARDoublePoint2d[] p,int[] order)\r
105         {\r
106                 int ret=0;\r
107                 for(int i=0;i<4;i++){\r
108                         if(0<NyARDoublePoint2d.crossProduct3Point(p[order[i+0]],p[order[(i+1)%4]],p[order[(i+2)%4]])){\r
109                                 ret++;\r
110                         }\r
111                 }\r
112                 return ret;\r
113         }\r
114 }