/* 
 * PROJECT: NyARToolkit
 * --------------------------------------------------------------------------------
 * This work is based on the original ARToolKit developed by
 *   Hirokazu Kato
 *   Mark Billinghurst
 *   HITLab, University of Washington, Seattle
 * http://www.hitl.washington.edu/artoolkit/
 *
 * The NyARToolkit is Java edition ARToolKit class library.
 * Copyright (C)2008-2009 Ryo Iizuka
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * For further information please contact.
 *	http://nyatla.jp/nyatoolkit/
 *	<airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
 * 
 */
package jp.nyatla.nyartoolkit.core.squaredetect;

import jp.nyatla.nyartoolkit.core.types.*;

/**
 * このクラスは、矩形情報を格納します。 ARToolKitのARMarkerInfoに相当しますが、このクラスは理想座標のみを取り扱います。
 */
public class NyARSquare {
	/** 矩形の辺の直線式です。 */
	public NyARLinear[] line = NyARLinear.createArray(4);
	/** 矩形の頂点です。 line[n]と、line[(n+3)%4]の交点でもあります。 */
	public NyARDoublePoint2d[] sqvertex = NyARDoublePoint2d.createArray(4);

	/**
	 * この関数は、矩形の中心点を計算します。
	 * 
	 * @param o_out
	 *            結果を格納するバッファ。
	 */
	public void getCenter2d(NyARDoublePoint2d o_out) {
		o_out.x = (this.sqvertex[0].x + this.sqvertex[1].x + this.sqvertex[2].x + this.sqvertex[3].x) / 4;
		o_out.y = (this.sqvertex[0].y + this.sqvertex[1].y + this.sqvertex[2].y + this.sqvertex[3].y) / 4;
		return;
	}

	/**
	 * この関数は、頂点同士の距離から、頂点のシフト量（回転量）を返します。 よく似た２つの矩形の頂点同士の、頂点の対応を取るために使用します。
	 * 
	 * @param i_square
	 *            比較対象の矩形
	 * @return シフト量を数値で返します。
	 *         シフト量はthis-i_squareです。1の場合、this.sqvertex[0]とi_square.
	 *         sqvertex[1]が対応点になる(shift量1)であることを示します。
	 */
	public int checkVertexShiftValue(NyARSquare i_square) {
		NyARDoublePoint2d[] a = this.sqvertex;
		NyARDoublePoint2d[] b = i_square.sqvertex;

		// 3-0番目
		int min_dist = Integer.MAX_VALUE;
		int min_index = 0;
		int xd, yd;
		for (int i = 3; i >= 0; i--) {
			int d = 0;
			for (int i2 = 3; i2 >= 0; i2--) {
				xd = (int) (a[i2].x - b[(i2 + i) % 4].x);
				yd = (int) (a[i2].y - b[(i2 + i) % 4].y);
				d += xd * xd + yd * yd;
			}
			if (min_dist > d) {
				min_dist = d;
				min_index = i;
			}
		}
		return min_index;
	}

	/** 4とnの最大公約数テーブル */
	private final static int[] _gcd_table4 = { -1, 1, 2, 1 };

	/**
	 * この関数は、頂点を左回転して、矩形を回転させます。
	 * 
	 * @param i_shift
	 *            シフト量。4未満、0以上である事。
	 */
	public void rotateVertexL(int i_shift) {
		assert (i_shift < 4);
		NyARDoublePoint2d vertext;
		NyARLinear linet;
		if (i_shift == 0) {
			return;
		}
		int t1, t2;
		int d, i, j, mk;
		int ll = 4 - i_shift;
		d = _gcd_table4[ll];// NyMath.gcn(4,ll);
		mk = (4 - ll) % 4;
		for (i = 0; i < d; i++) {
			linet = this.line[i];
			vertext = this.sqvertex[i];
			for (j = 1; j < 4 / d; j++) {
				t1 = (i + (j - 1) * mk) % 4;
				t2 = (i + j * mk) % 4;
				this.line[t1] = this.line[t2];
				this.sqvertex[t1] = this.sqvertex[t2];
			}
			t1 = (i + ll) % 4;
			this.line[t1] = linet;
			this.sqvertex[t1] = vertext;
		}
	}
}