/* * 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