2 * PROJECT: NyARToolkit
\r
3 * --------------------------------------------------------------------------------
\r
4 * This work is based on the original ARToolKit developed by
\r
7 * HITLab, University of Washington, Seattle
\r
8 * http://www.hitl.washington.edu/artoolkit/
\r
10 * The NyARToolkit is Java edition ARToolKit class library.
\r
11 * Copyright (C)2008-2009 Ryo Iizuka
\r
13 * This program is free software: you can redistribute it and/or modify
\r
14 * it under the terms of the GNU General Public License as published by
\r
15 * the Free Software Foundation, either version 3 of the License, or
\r
16 * (at your option) any later version.
\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
23 * You should have received a copy of the GNU General Public License
\r
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
\r
26 * For further information please contact.
\r
27 * http://nyatla.jp/nyatoolkit/
\r
28 * <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
\r
31 package jp.nyatla.nyartoolkit.core.types;
\r
35 * このクラスは、0=a*x+b*y+cのパラメータを格納します。
\r
36 * x,yの増加方向は、x=L→R,y=B→Tです。 y軸が反転しているので注意してください。
\r
39 public class NyARLinear
\r
49 * この関数は、指定サイズのオブジェクト配列を作ります。
\r
55 public static NyARLinear[] createArray(int i_number)
\r
57 NyARLinear[] ret=new NyARLinear[i_number];
\r
58 for(int i=0;i<i_number;i++)
\r
60 ret[i]=new NyARLinear();
\r
65 * この関数は、引数値からパラメータをインスタンスへコピーします。
\r
69 public final void copyFrom(NyARLinear i_source)
\r
77 * この関数は、直線の交点を計算します。
\r
85 public final boolean crossPos(NyARLinear l_line_2,NyARDoublePoint2d o_point)
\r
87 final double w1 = this.a * l_line_2.b - l_line_2.a * this.b;
\r
91 o_point.x = (this.b * l_line_2.c - l_line_2.b * this.c) / w1;
\r
92 o_point.y = (l_line_2.a * this.c - this.a * l_line_2.c) / w1;
\r
96 * この関数は、直線の交点を計算します。
\r
108 public final boolean crossPos(double i_a,double i_b,double i_c,NyARDoublePoint2d o_point)
\r
110 final double w1 = this.a * i_b - i_a * this.b;
\r
114 o_point.x = (this.b * i_c - i_b * this.c) / w1;
\r
115 o_point.y = (i_a * this.c - this.a * i_c) / w1;
\r
119 * この関数は、直線の交点を計算します。
\r
131 public final boolean crossPos(double i_a,double i_b,double i_c,NyARIntPoint2d o_point)
\r
133 final double w1 = this.a * i_b - i_a * this.b;
\r
137 o_point.x = (int)((this.b * i_c - i_b * this.c) / w1);
\r
138 o_point.y = (int)((i_a * this.c - this.a * i_c) / w1);
\r
142 * この関数は、2直線が交差しているかを返します。
\r
144 * 交差しているか確認するオブジェクト
\r
148 public final boolean isCross(NyARLinear l_line_2)
\r
150 final double w1 = this.a * l_line_2.b - l_line_2.a * this.b;
\r
151 return (w1 == 0.0)?false:true;
\r
155 * この関数は、2点を結ぶ直線式を計算して、インスタンスに格納します。
\r
164 public final boolean makeLinearWithNormalize(NyARIntPoint2d i_point1,NyARIntPoint2d i_point2)
\r
166 return makeLinearWithNormalize(i_point1.x,i_point1.y,i_point2.x,i_point2.y);
\r
169 * この関数は、2点を結ぶ直線式を計算して、インスタンスに格納します。
\r
176 * 直線式が求るとtrueを返します。
\r
178 public final boolean makeLinearWithNormalize(NyARDoublePoint2d i_point1,NyARDoublePoint2d i_point2)
\r
180 return makeLinearWithNormalize(i_point1.x,i_point1.y,i_point2.x,i_point2.y);
\r
183 * この関数は、2点を結ぶ直線式を計算して、インスタンスに格納します。
\r
194 * 直線式が求るとtrueを返します。
\r
196 public final boolean makeLinearWithNormalize(double x1,double y1,double x2,double y2)
\r
200 double sq=Math.sqrt(dx*dx+dy*dy);
\r
207 this.c=(x1*(y1-y2)+y1*(x2-x1))*sq;
\r
211 * この関数は、傾きと通過点から直線式を計算して、インスタンスへセットします。
\r
221 public final void setVector(double i_dx,double i_dy,double i_x,double i_y)
\r
225 this.c=(i_dx*i_y-i_dy*i_x);
\r
229 * この関数は、{@link NyARVecLinear2d}を直線式に変換して、インスタンスへセットします。
\r
233 public final void setVector(NyARVecLinear2d i_vector)
\r
235 this.a= i_vector.dy;
\r
236 this.b=-i_vector.dx;
\r
237 this.c=(i_vector.dx*i_vector.y-i_vector.dy*i_vector.x);
\r
241 * この関数は、{@link NyARVecLinear2d}を正規化された直線式に変換して、インスタンスへセットします。
\r
245 public final boolean setVectorWithNormalize(NyARVecLinear2d i_vector)
\r
247 double dx=i_vector.dx;
\r
248 double dy=i_vector.dy;
\r
249 double sq=Math.sqrt(dx*dx+dy*dy);
\r
256 this.c=-(this.a*i_vector.x+this.b*i_vector.y);
\r
260 * この関数は、i_x,i_yを通過する、i_linearの法線を計算して、インスタンスへ格納します。
\r
266 * 法線を計算する直線式(この引数にはthisを指定できます。)
\r
268 public final void normalLine(double i_x,double i_y,NyARLinear i_linear)
\r
270 double la=i_linear.a;
\r
271 double lb=i_linear.b;
\r
274 this.c=-(lb*i_x-la*i_y);
\r
277 * この関数は、i_x,i_yを通るこの直線の法線と、i_linearが交わる点を返します。
\r
287 * 交点が求まれば、trueを返します。
\r
289 public final boolean normalLineCrossPos(double i_x,double i_y,NyARLinear i_linear,NyARDoublePoint2d o_point)
\r
294 double lc=-(la*i_x+lb*i_y);
\r
296 final double w1 = i_linear.a * lb - la * i_linear.b;
\r
300 o_point.x = ((i_linear.b * lc - lb * i_linear.c) / w1);
\r
301 o_point.y = ((la * i_linear.c - i_linear.a * lc) / w1);
\r
305 // * i_x,i_yを通るこの直線の法線上での、この直線とi_linearの距離の二乗値を返します。
\r
306 // * i_x,i_yに直線上の点を指定すると、この直線の垂線上での、もう一方の直線との距離の二乗値が得られます。
\r
307 // * @param i_linear
\r
310 // * @param o_point
\r
312 // * 交点が無い場合、無限大を返します。
\r
314 // public final double sqDistWithLinear(NyARLinear i_linear, double i_x,double i_y)
\r
317 // double la=this.b;
\r
318 // double lb=-this.a;
\r
319 // double lc=-(la*i_x+lb*i_y);
\r
321 // final double w1 = i_linear.a * lb - la * i_linear.b;
\r
322 // if (w1 == 0.0) {
\r
323 // return Double.POSITIVE_INFINITY;
\r
325 // double x=i_x-((i_linear.b * lc - lb * i_linear.c) / w1);
\r
326 // double y=i_y-((la * i_linear.c - i_linear.a * lc) / w1);
\r
331 * この関数は、直線を0,0基点(左上)の矩形でクリッピングしたときの、端点を計算します。
\r
337 * 端点を返すオブジェクト配列。2要素である必要があります。
\r
341 public final boolean makeSegmentLine(int i_width,int i_height,NyARIntPoint2d[] o_point)
\r
344 NyARIntPoint2d ptr=o_point[0];
\r
345 if(this.crossPos(0,-1,0,ptr) && ptr.x>=0 && ptr.x<i_width)
\r
351 if(this.crossPos(0,-1,i_height-1,ptr) && ptr.x>=0 && ptr.x<i_width)
\r
353 //y=(rect.y+rect.h-1)の線
\r
360 if(this.crossPos(-1,0,0,ptr) && ptr.y>=0 && ptr.y<i_height)
\r
369 if(this.crossPos(-1,0,i_width-1, ptr) && ptr.y>=0 && ptr.y<i_height)
\r
380 * この関数は、直線を矩形でクリッピングしたときの、端点を計算します。
\r
390 * 端点を返すオブジェクト配列。2要素である必要があります。
\r
394 public final boolean makeSegmentLine(int i_left,int i_top,int i_width,int i_height,NyARIntPoint2d[] o_point)
\r
396 int bottom=i_top+i_height;
\r
397 int right=i_left+i_width;
\r
399 NyARIntPoint2d ptr=o_point[0];
\r
400 if(this.crossPos(0,-1,i_top,ptr) && ptr.x>=i_left && ptr.x<right)
\r
406 if(this.crossPos(0,-1,bottom-1,ptr) && ptr.x>=i_left && ptr.x<right)
\r
408 //y=(rect.y+rect.h-1)の線
\r
415 if(this.crossPos(-1,0,i_left,ptr) && ptr.y>=i_top && ptr.y<bottom)
\r
424 if(this.crossPos(-1,0,right-1, ptr) && ptr.y>=i_top && ptr.y<bottom)
\r
435 * この関数は、この直線と、i_sp1とi_sp2の作る線分との、二乗距離値の合計を返します。
\r
436 * 計算方法は、線分の端点を通過する直線の法線上での、端点と直線の距離の合計です。
\r
437 * 線分と直線の類似度を判定する数値になります。
\r
443 * 二乗距離値の合計。距離が取れないときは無限大です。
\r
445 public final double sqDistBySegmentLineEdge(NyARDoublePoint2d i_sp1,NyARDoublePoint2d i_sp2)
\r
454 w1 = this.a * lb - la * this.b;
\r
456 return Double.POSITIVE_INFINITY;
\r
458 //i_sp1と、i_linerの交点
\r
459 lc=-(la*i_sp1.x+lb*i_sp1.y);
\r
460 x = ((this.b * lc - lb * this.c) / w1)-i_sp1.x;
\r
461 y = ((la * this.c - this.a * lc) / w1)-i_sp1.y;
\r
462 double sqdist=x*x+y*y;
\r
464 lc=-(la*i_sp2.x+lb*i_sp2.y);
\r
465 x = ((this.b * lc - lb * this.c) / w1)-i_sp2.x;
\r
466 y = ((la * this.c - this.a * lc) / w1)-i_sp2.y;
\r
468 return sqdist+x*x+y*y;
\r
471 * この関数は、頂点群から最小二乗法を使用して直線を計算します。
\r
474 * @param i_number_of_data
\r
477 * 計算に成功すると、trueを返します。
\r
479 public boolean leastSquares(NyARDoublePoint2d[] i_points,int i_number_of_data)
\r
481 assert(i_number_of_data>1);
\r
483 double sum_xy = 0, sum_x = 0, sum_y = 0, sum_x2 = 0;
\r
484 for (i=0; i<i_number_of_data; i++){
\r
485 NyARDoublePoint2d ptr=i_points[i];
\r
487 sum_xy += xw * ptr.y;
\r
492 this.b =-(i_number_of_data * sum_x2 - sum_x*sum_x);
\r
493 this.a = (i_number_of_data * sum_xy - sum_x * sum_y);
\r
494 this.c = (sum_x2 * sum_y - sum_xy * sum_x);
\r