/*
* PROJECT: NyARToolkitAS3
* --------------------------------------------------------------------------------
* 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 NyARToolkitAS3 is AS3 edition ARToolKit class library.
* Copyright (C)2010 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 .
*
* For further information please contact.
* http://nyatla.jp/nyatoolkit/
* or
*
*/
package jp.nyatla.nyartoolkit.as3.core.transmat
{
import jp.nyatla.nyartoolkit.as3.core.types.*;
import jp.nyatla.nyartoolkit.as3.core.squaredetect.*;
import jp.nyatla.nyartoolkit.as3.core.types.matrix.*;
import jp.nyatla.nyartoolkit.as3.core.param.*;
import jp.nyatla.nyartoolkit.as3.core.transmat.rotmatrix.*;
import jp.nyatla.nyartoolkit.as3.core.transmat.optimize.*;
import jp.nyatla.nyartoolkit.as3.core.transmat.solver.*;
/**
* This class calculates ARMatrix from square information and holds it. --
* 変換行列を計算して、結果を保持するクラス。
*
*/
public class NyARTransMat implements INyARTransMat
{
private var _projection_mat_ref:NyARPerspectiveProjectionMatrix;
protected var _rotmatrix:NyARRotMatrix;
protected var _transsolver:INyARTransportVectorSolver;
protected var _mat_optimize:NyARPartialDifferentiationOptimize;
private var _ref_dist_factor:NyARCameraDistortionFactor;
public function NyARTransMat(i_param:NyARParam)
{
var dist:NyARCameraDistortionFactor=i_param.getDistortionFactor();
var pmat:NyARPerspectiveProjectionMatrix=i_param.getPerspectiveProjectionMatrix();
this._transsolver=new NyARTransportVectorSolver(pmat,4);
//互換性が重要な時は、NyARRotMatrix_ARToolKitを使うこと。
//理屈はNyARRotMatrix_NyARToolKitもNyARRotMatrix_ARToolKitも同じだけど、少しだけ値がずれる。
this._rotmatrix = new NyARRotMatrix(pmat);
this._mat_optimize=new NyARPartialDifferentiationOptimize(pmat);
this._ref_dist_factor=dist;
this._projection_mat_ref=pmat;
}
private var __transMat_vertex_2d:Vector. = NyARDoublePoint2d.createArray(4);
private var __transMat_vertex_3d:Vector. = NyARDoublePoint3d.createArray(4);
private var __transMat_trans:NyARDoublePoint3d=new NyARDoublePoint3d();
/**
* 頂点情報を元に、エラー閾値を計算します。
* @param i_vertex
*/
private function makeErrThreshold(i_vertex:Vector.):Number
{
var a:Number,b:Number,l1:Number,l2:Number;
a=i_vertex[0].x-i_vertex[2].x;
b=i_vertex[0].y-i_vertex[2].y;
l1=a*a+b*b;
a=i_vertex[1].x-i_vertex[3].x;
b=i_vertex[1].y-i_vertex[3].y;
l2=a*a+b*b;
return (Math.sqrt(l1>l2?l1:l2))/200;
}
/**
* double arGetTransMat( ARMarkerInfo *marker_info,double center[2], double width, double conv[3][4] )
*
* @param i_square
* 計算対象のNyARSquareオブジェクト
* @param i_direction
* @param i_width
* @return
* @throws NyARException
*/
public function transMat(i_square:NyARSquare,i_offset:NyARRectOffset,o_result_conv:NyARTransMatResult):void
{
var trans:NyARDoublePoint3d=this.__transMat_trans;
var err_threshold:Number=makeErrThreshold(i_square.sqvertex);
//平行移動量計算機に、2D座標系をセット
var vertex_2d:Vector.=this.__transMat_vertex_2d;
var vertex_3d:Vector.=this.__transMat_vertex_3d;
this._ref_dist_factor.ideal2ObservBatch(i_square.sqvertex, vertex_2d,4);
this._transsolver.set2dVertex(vertex_2d,4);
//回転行列を計算
this._rotmatrix.initRotBySquare(i_square.line,i_square.sqvertex);
//回転後の3D座標系から、平行移動量を計算
this._rotmatrix.getPoint3dBatch(i_offset.vertex,vertex_3d,4);
this._transsolver.solveTransportVector(vertex_3d,trans);
//計算結果の最適化(平行移動量と回転行列の最適化)
o_result_conv.error=this.optimize(this._rotmatrix, trans, this._transsolver,i_offset.vertex, vertex_2d,err_threshold);
// マトリクスの保存
this.updateMatrixValue(this._rotmatrix, trans,o_result_conv);
return;
}
/*
* (non-Javadoc)
* @see jp.nyatla.nyartoolkit.core.transmat.INyARTransMat#transMatContinue(jp.nyatla.nyartoolkit.core.NyARSquare, int, double, jp.nyatla.nyartoolkit.core.transmat.NyARTransMatResult)
*/
public function transMatContinue(i_square:NyARSquare,i_offset:NyARRectOffset,o_result_conv:NyARTransMatResult):void
{
var trans:NyARDoublePoint3d=this.__transMat_trans;
// io_result_convが初期値なら、transMatで計算する。
if (!o_result_conv.has_value) {
this.transMat(i_square,i_offset, o_result_conv);
return;
}
//最適化計算の閾値を決定
var err_threshold:Number=makeErrThreshold(i_square.sqvertex);
//平行移動量計算機に、2D座標系をセット
var vertex_2d:Vector.=this.__transMat_vertex_2d;
var vertex_3d:Vector.=this.__transMat_vertex_3d;
this._ref_dist_factor.ideal2ObservBatch(i_square.sqvertex, vertex_2d,4);
this._transsolver.set2dVertex(vertex_2d,4);
//回転行列を計算
this._rotmatrix.initRotByPrevResult(o_result_conv);
//回転後の3D座標系から、平行移動量を計算
this._rotmatrix.getPoint3dBatch(i_offset.vertex,vertex_3d,4);
this._transsolver.solveTransportVector(vertex_3d,trans);
//現在のエラーレートを計算しておく
var min_err:Number=errRate(this._rotmatrix,trans,i_offset.vertex, vertex_2d,4,vertex_3d);
var rot:NyARDoubleMatrix33=this.__rot;
//エラーレートが前回のエラー値より閾値分大きかったらアゲイン
if(min_err,i_2d_vertex:Vector.,i_err_threshold:Number):Number
{
//System.out.println("START");
var vertex_3d:Vector.=this.__transMat_vertex_3d;
//初期のエラー値を計算
var min_err:Number=errRate(io_rotmat, io_transvec, i_offset_3d, i_2d_vertex,4,vertex_3d);
var rot:NyARDoubleMatrix33=this.__rot;
rot.setValue_NyARDoubleMatrix33(io_rotmat);
for (var i:int = 0;i<5; i++) {
//変換行列の最適化
this._mat_optimize.modifyMatrix(rot, io_transvec, i_offset_3d, i_2d_vertex, 4);
var err:Number=errRate(rot,io_transvec, i_offset_3d, i_2d_vertex,4,vertex_3d);
//System.out.println("E:"+err);
if(min_err-err,i_vertex2d:Vector.,i_number_of_vertex:int,o_rot_vertex:Vector.):Number
{
var cp:NyARPerspectiveProjectionMatrix = this._projection_mat_ref;
var cp00:Number=cp.m00;
var cp01:Number=cp.m01;
var cp02:Number=cp.m02;
var cp11:Number=cp.m11;
var cp12:Number=cp.m12;
var err:Number=0;
for(var i:int=0;i