/* * 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.nyidmarker { import jp.nyatla.nyartoolkit.as3.core.squaredetect.*; import jp.nyatla.nyartoolkit.as3.core.raster.*; import jp.nyatla.nyartoolkit.as3.core.raster.rgb.*; import jp.nyatla.nyartoolkit.as3.core.rasterreader.*; import jp.nyatla.nyartoolkit.as3.core.types.*; /** * ラスタ画像の任意矩形から、NyARIdMarkerDataを抽出します。 * */ public class NyIdMarkerPickup { private var _perspective_reader:PerspectivePixelReader; private var __pickFromRaster_th:TThreshold=new TThreshold(); private var __pickFromRaster_encoder:MarkerPattEncoder=new MarkerPattEncoder(); public function NyIdMarkerPickup() { this._perspective_reader=new PerspectivePixelReader(); return; } /** * i_imageから、idマーカを読みだします。 * o_dataにはマーカデータ、o_paramにはまーかのパラメータを返却します。 * @param image * @param i_square * @param o_data * @param o_param * @return * @throws NyARException */ public function pickFromRaster(image:INyARRgbRaster,i_vertex:Vector.,o_data:NyIdMarkerPattern,o_param:NyIdMarkerParam):Boolean { //遠近法のパラメータを計算 if(!this._perspective_reader.setSourceSquare(i_vertex)){ return false; }; var reader:INyARRgbPixelReader=image.getRgbPixelReader(); var raster_size:NyARIntSize=image.getSize(); var th:TThreshold=this.__pickFromRaster_th; var encoder:MarkerPattEncoder=this.__pickFromRaster_encoder; //マーカパラメータを取得 this._perspective_reader.detectThresholdValue(reader,raster_size,th); if(!this._perspective_reader.readDataBits(reader,raster_size,th, encoder)){ return false; } var d:int=encoder.encode(o_data); if(d<0){ return false; } o_param.direction=d; o_param.threshold=th.th; return true; } } } import jp.nyatla.as3utils.*; import jp.nyatla.nyartoolkit.as3.core.utils.*; import jp.nyatla.nyartoolkit.as3.core.rasterreader.*; import jp.nyatla.nyartoolkit.as3.core.types.*; import jp.nyatla.nyartoolkit.as3.nyidmarker.*; import jp.nyatla.nyartoolkit.as3.nyidmarker.data.*; /** * NyARColorPatt_NyIdMarkerがラスタからPerspective変換して読みだすためのクラス * */ class PerspectivePixelReader { private var _param_gen:NyARPerspectiveParamGenerator_O1=new NyARPerspectiveParamGenerator_O1(1,1,100,100); private var _cparam:Vector.=new Vector.(8); public function PerspectivePixelReader() { return; } public function setSourceSquare(i_vertex:Vector.):Boolean { return this._param_gen.getParam(i_vertex, this._cparam); } /** * 矩形からピクセルを切り出します * @param i_lt_x * @param i_lt_y * @param i_step_x * @param i_step_y * @param i_width * @param i_height * @param i_out_st * o_pixelへの格納場所の先頭インデクス * @param o_pixel * @throws NyARException */ private function rectPixels(i_reader:INyARRgbPixelReader,i_raster_size:NyARIntSize,i_lt_x:int,i_lt_y:int,i_step_x:int,i_step_y:int,i_width:int,i_height:int,i_out_st:int,o_pixel:Vector.):Boolean { var cpara:Vector.=this._cparam; var ref_x:Vector.=this._ref_x; var ref_y:Vector.=this._ref_y; var pixcel_temp:Vector.=this._pixcel_temp; var raster_width:int=i_raster_size.w; var raster_height:int=i_raster_size.h; var out_index:int=i_out_st; var cpara_6:Number=cpara[6]; var cpara_0:Number=cpara[0]; var cpara_3:Number=cpara[3]; for(var i:int=0;i=raster_width||y>=raster_height) { return false; } ref_x[pt]=x; ref_y[pt]=y; pt++; } //1行分のピクセルを取得(場合によっては専用アクセサを書いた方がいい) i_reader.getPixelSet(ref_x,ref_y,i_width,pixcel_temp); //グレースケールにしながら、line→mapへの転写 for(i2=0;i2,i_width:int):Boolean { var c:int=i_freq[1]-i_freq[0]; var count:int=i_width*2-1; for (var i:int= 1; i < count; i++) { var n:int=i_freq[i+1]-i_freq[i]; var v:int=n*100/c; if(v>150 || v<50){ return false; } c=n; } return true; } /** * i_freq_count_tableとi_freq_tableの内容を調査し、最も大きな周波数成分を返します。 * @param i_freq_count_table * @param i_freq_table * @param o_freq_table * @return * 見つかれば0以上、密辛ければ0未満 */ private static function getMaxFreq(i_freq_count_table:Vector.,i_freq_table:Vector.,o_freq_table:Vector.):int { //一番成分の大きいものを得る var index:int=-1; var max:int = 0; var i:int; for(i=0;i=new Vector.(108); private var _ref_y:Vector.=new Vector.(108); //(model+1)*4*3とTHRESHOLD_PIXEL*3のどちらか大きい方 private var _pixcel_temp:Vector.=new Vector.(108*3); private var _freq_count_table:Vector.=new Vector.(MAX_FREQ); private var _freq_table:Vector.=new Vector.((MAX_FREQ*2-1)*MAX_FREQ*2/2); /** * i_y1行目とi_y2行目を平均して、タイミングパターンの周波数を得ます。 * LHLを1周期として、たとえばLHLHLの場合は2を返します。LHLHやHLHL等の始端と終端のレベルが異なるパターンを * 検出した場合、関数は失敗します。 * * @param i_y1 * @param i_y2 * @param i_th_h * @param i_th_l * @param o_edge_index * 検出したエッジ位置(H->L,L->H)のインデクスを受け取る配列です。 * [FRQ_POINTS]以上の配列を指定してください。 * @return * @throws NyARException */ public function getRowFrequency(i_reader:INyARRgbPixelReader,i_raster_size:NyARIntSize,i_y1:int,i_th_h:int,i_th_l:int,o_edge_index:Vector.):int { var i:int; //3,4,5,6,7,8,9,10 var freq_count_table:Vector.=this._freq_count_table; //0,2,4,6,8,10,12,14,16,18,20の要素を持つ配列 var freq_table:Vector.=this._freq_table; //初期化 var cpara:Vector.=this._cparam; // final INyARRgbPixelReader reader=this._raster.getRgbPixelReader(); var ref_x:Vector.=this._ref_x; var ref_y:Vector.=this._ref_y; var pixcel_temp:Vector.=this._pixcel_temp; for(i=0;i<10;i++){ freq_count_table[i]=0; } for(i=0;i<110;i++){ freq_table[i]=0; } var raster_width:int=i_raster_size.w; var raster_height:int=i_raster_size.h; var cpara_0:Number=cpara[0]; var cpara_3:Number=cpara[3]; var cpara_6:Number=cpara[6]; //10-20ピクセル目からタイミングパターンを検出 for (i = 0; i < FREQ_SAMPLE_NUM; i++) { var i2:int; //2行分のピクセルインデックスを計算 var cy0:Number=1+i_y1+i; var cpy0_12:Number=cpara[1]*cy0+cpara[2]; var cpy0_45:Number=cpara[4]*cy0+cpara[5]; var cpy0_7:Number=cpara[7]*cy0+1.0; var pt:int=0; for(i2=0;i2=raster_width||y>=raster_height) { return -1; } ref_x[pt]=x; ref_y[pt]=y; pt++; } //ピクセルを取得(入力画像を多様化するならここから先を調整すること) i_reader.getPixelSet(ref_x,ref_y,FRQ_POINTS,pixcel_temp); //o_edge_indexを一時的に破壊して調査する var freq_t:int=getFreqInfo(pixcel_temp,i_th_h,i_th_l,o_edge_index); //周期は3-10であること if(freq_tMAX_FREQ){ continue; } //周期は等間隔であること if(!checkFreqWidth(o_edge_index,freq_t)){ continue; } //検出カウンタを追加 freq_count_table[freq_t]++; var table_st:int=(freq_t-1)*freq_t; for(i2=0;i2):int { var i:int; var cpara:Vector.=this._cparam; // final INyARRgbPixelReader reader=this._raster.getRgbPixelReader(); var ref_x:Vector.=this._ref_x; var ref_y:Vector.=this._ref_y; var pixcel_temp:Vector.=this._pixcel_temp; //0,2,4,6,8,10,12,14,16,18,20=(11*20)/2=110 //初期化 var freq_count_table:Vector.=this._freq_count_table; for(i=0;i<10;i++){ freq_count_table[i]=0; } var freq_table:Vector. = this._freq_table; for(i=0;i<110;i++){ freq_table[i]=0; } var raster_width:int=i_raster_size.w; var raster_height:int=i_raster_size.h; var cpara7:Number=cpara[7]; var cpara4:Number=cpara[4]; var cpara1:Number=cpara[1]; //基準点から4ピクセルを参照パターンとして抽出 for (i = 0; i < FREQ_SAMPLE_NUM; i++) { var i2:int; var cx0:int=1+i+i_x1; var cp6_0:Number=cpara[6]*cx0; var cpx0_0:Number=cpara[0]*cx0+cpara[2]; var cpx3_0:Number=cpara[3]*cx0+cpara[5]; var pt:int=0; for(i2=0;i2=raster_width||y>=raster_height) { return -1; } ref_x[pt]=x; ref_y[pt]=y; pt++; } //ピクセルを取得(入力画像を多様化するならここを調整すること) i_reader.getPixelSet(ref_x,ref_y,FRQ_POINTS,pixcel_temp); var freq_t:int=getFreqInfo(pixcel_temp,i_th_h,i_th_l,o_edge_index); //周期は3-10であること if(freq_tMAX_FREQ){ continue; } //周期は等間隔であること if(!checkFreqWidth(o_edge_index,freq_t)){ continue; } //検出カウンタを追加 freq_count_table[freq_t]++; var table_st:int=(freq_t-1)*freq_t; for(i2=0;i2,i_th_h:int,i_th_l:int,o_edge_index:Vector.):int { //トークンを解析して、周波数を計算 var i:int=0; var frq_l2h:int=0; var frq_h2l:int = 0; var index:int,pix:int; while(iHトークンを検出する while(ii_th_h){ //トークン発見 o_edge_index[frq_l2h+frq_h2l]=i; frq_l2h++; break; } i++; } i++; //L->Hトークンを検出する while(i,i_out:THighAndLow ):void { var h3:int,h2:int,h1:int,h0:int,l3:int,l2:int,l1:int,l0:int; h3=h2=h1=h0=l3=l2=l1=l0=i_pixcel[0]; for(var i:int=i_pixcel.length-1;i>=1;i--){ var pix:int=i_pixcel[i]; if(h0pix){ if(l1>pix){ if(l2>pix){ if(l3>pix){ l0=l1; l1=l2; l2=l3; l3=pix; }else{ l0=l1; l1=l2; l2=pix; } }else{ l0=l1; l1=pix; } }else{ l0=pix; } } } i_out.l=(l0+l1+l2+l3)/4; i_out.h=(h0+h1+h2+h3)/4; return; } private var __detectThresholdValue_hl:THighAndLow=new THighAndLow(); private var __detectThresholdValue_tpt:NyARIntPoint2d=new NyARIntPoint2d(); private var _th_pixels:Vector.=new Vector.(THRESHOLD_SAMPLE*4); /** * 指定した場所のピクセル値を調査して、閾値を計算して返します。 * @param i_reader * @param i_x * @param i_y * @return * @throws NyARException */ public function detectThresholdValue(i_reader:INyARRgbPixelReader,i_raster_size:NyARIntSize,o_threshold:TThreshold):void { var th_pixels:Vector.=this._th_pixels; //左上のピックアップ領域からピクセルを得る(00-24) rectPixels(i_reader,i_raster_size,THRESHOLD_SAMPLE_LT,THRESHOLD_SAMPLE_LT,THRESHOLD_STEP,THRESHOLD_STEP,THRESHOLD_PIXEL,THRESHOLD_PIXEL,0,th_pixels); //左下のピックアップ領域からピクセルを得る(25-49) rectPixels(i_reader,i_raster_size,THRESHOLD_SAMPLE_LT,THRESHOLD_SAMPLE_RB,THRESHOLD_STEP,THRESHOLD_STEP,THRESHOLD_PIXEL,THRESHOLD_PIXEL,THRESHOLD_SAMPLE,th_pixels); //右上のピックアップ領域からピクセルを得る(50-74) rectPixels(i_reader,i_raster_size,THRESHOLD_SAMPLE_RB,THRESHOLD_SAMPLE_LT,THRESHOLD_STEP,THRESHOLD_STEP,THRESHOLD_PIXEL,THRESHOLD_PIXEL,THRESHOLD_SAMPLE*2,th_pixels); //右下のピックアップ領域からピクセルを得る(75-99) rectPixels(i_reader,i_raster_size,THRESHOLD_SAMPLE_RB,THRESHOLD_SAMPLE_RB,THRESHOLD_STEP,THRESHOLD_STEP,THRESHOLD_PIXEL,THRESHOLD_PIXEL,THRESHOLD_SAMPLE*3,th_pixels); var hl:THighAndLow=this.__detectThresholdValue_hl; //Ptailで求めたピクセル平均 getPtailHighAndLow(th_pixels,hl); //閾値中心 var th:int=(hl.h+hl.l)/2; //ヒステリシス(差分の20%) var th_sub:int=(hl.h-hl.l)/5; o_threshold.th=th; o_threshold.th_h=th+th_sub;//ヒステリシス付き閾値 o_threshold.th_l=th-th_sub;//ヒステリシス付き閾値 //エッジを計算(明点重心) var lt_x:int,lt_y:int,lb_x:int,lb_y:int,rt_x:int,rt_y:int,rb_x:int,rb_y:int; var tpt:NyARIntPoint2d=this.__detectThresholdValue_tpt; //LT if(getHighPixelCenter(0,th_pixels,THRESHOLD_PIXEL,THRESHOLD_PIXEL,th,tpt)){ lt_x=tpt.x*THRESHOLD_STEP; lt_y=tpt.y*THRESHOLD_STEP; }else{ lt_x=11; lt_y=11; } //LB if(getHighPixelCenter(THRESHOLD_SAMPLE*1,th_pixels,THRESHOLD_PIXEL,THRESHOLD_PIXEL,th,tpt)){ lb_x=tpt.x*THRESHOLD_STEP; lb_y=tpt.y*THRESHOLD_STEP; }else{ lb_x=11; lb_y=-1; } //RT if(getHighPixelCenter(THRESHOLD_SAMPLE*2,th_pixels,THRESHOLD_PIXEL,THRESHOLD_PIXEL,th,tpt)){ rt_x=tpt.x*THRESHOLD_STEP; rt_y=tpt.y*THRESHOLD_STEP; }else{ rt_x=-1; rt_y=11; } //RB if(getHighPixelCenter(THRESHOLD_SAMPLE*3,th_pixels,THRESHOLD_PIXEL,THRESHOLD_PIXEL,th,tpt)){ rb_x=tpt.x*THRESHOLD_STEP; rb_y=tpt.y*THRESHOLD_STEP; }else{ rb_x=-1; rb_y=-1; } //トラッキング開始位置の決定 o_threshold.lt_x=(lt_x+lb_x)/2+THRESHOLD_SAMPLE_LT-1; o_threshold.rb_x=(rt_x+rb_x)/2+THRESHOLD_SAMPLE_RB+1; o_threshold.lt_y=(lt_y+rt_y)/2+THRESHOLD_SAMPLE_LT-1; o_threshold.rb_y=(lb_y+rb_y)/2+THRESHOLD_SAMPLE_RB+1; return; } private function getHighPixelCenter(i_st:int,i_pixels:Vector.,i_width:int,i_height:int,i_th:int,o_point:NyARIntPoint2d):Boolean { var rp:int=i_st; var pos_x:int=0; var pos_y:int=0; var number_of_pos:int=0; for(var i:int=0;ii_th){ pos_x+=i2; pos_y+=i; number_of_pos++; } } } if(number_of_pos>0){ pos_x/=number_of_pos; pos_y/=number_of_pos; }else{ return false; } o_point.x=pos_x; o_point.y=pos_y; return true; } private var __detectDataBitsIndex_freq_index1:Vector.=new Vector.(FRQ_POINTS); private var __detectDataBitsIndex_freq_index2:Vector.=new Vector.(FRQ_POINTS); private function detectDataBitsIndex(i_reader:INyARRgbPixelReader,i_raster_size:NyARIntSize,i_th:TThreshold,o_index_row:Vector.,o_index_col:Vector.):int { var i:int; //周波数を測定 var freq_index1:Vector.=this.__detectDataBitsIndex_freq_index1; var freq_index2:Vector.=this.__detectDataBitsIndex_freq_index2; var frq_t:int=getRowFrequency(i_reader,i_raster_size,i_th.lt_y,i_th.th_h,i_th.th_l,freq_index1); var frq_b:int=getRowFrequency(i_reader,i_raster_size,i_th.rb_y,i_th.th_h,i_th.th_l,freq_index2); //周波数はまとも? if((frq_t<0 && frq_b<0) || frq_t==frq_b){ return -1; } //タイミングパターンからインデクスを作成 var freq_h:int,freq_v:int; var index:Vector.; if(frq_t>frq_b){ freq_h=frq_t; index=freq_index1; }else{ freq_h=frq_b; index=freq_index2; } for(i=0;ifrq_r){ freq_v=frq_l; index=freq_index1; }else{ freq_v=frq_r; index=freq_index2; } //同じ周期? if(freq_v!=freq_h){ return -1; } for(i=0;iMAX_FREQ){ return -1; } return freq_v; } private var __readDataBits_index_bit_x:Vector.=new Vector.(MAX_DATA_BITS*2); private var __readDataBits_index_bit_y:Vector.=new Vector.(MAX_DATA_BITS*2); public function readDataBits(i_reader:INyARRgbPixelReader, i_raster_size:NyARIntSize, i_th:TThreshold, o_bitbuffer:MarkerPattEncoder):Boolean { var index_x:Vector.=this.__readDataBits_index_bit_x; var index_y:Vector.=this.__readDataBits_index_bit_y; //読み出し位置を取得 var size:int=detectDataBitsIndex(i_reader,i_raster_size,i_th,index_x,index_y); var resolution:int=size+size-1; if(size<0){ return false; } if(!o_bitbuffer.initEncoder(size-1)){ return false; } var cpara:Vector.=this._cparam; var ref_x:Vector.=this._ref_x; var ref_y:Vector.=this._ref_y; var pixcel_temp:Vector.=this._pixcel_temp; var cpara_0:Number=cpara[0]; var cpara_1:Number=cpara[1]; var cpara_3:Number=cpara[3]; var cpara_6:Number=cpara[6]; var th:int=i_th.th; var p:int=0; for (var i:int = 0; i < resolution; i++) { var i2:int; //1列分のピクセルのインデックス値を計算する。 var cy0:Number=1+index_y[i*2+0]; var cy1:Number=1+index_y[i*2+1]; var cpy0_12:Number=cpara_1*cy0+cpara[2]; var cpy0_45:Number=cpara[4]*cy0+cpara[5]; var cpy0_7:Number=cpara[7]*cy0+1.0; var cpy1_12:Number=cpara_1*cy1+cpara[2]; var cpy1_45:Number=cpara[4]*cy1+cpara[5]; var cpy1_7:Number=cpara[7]*cy1+1.0; var pt:int=0; for(i2=0;i2th?0:1); p++; } } /* for(int i=0;i<225*4;i++){ this.vertex_x[i]=0; this.vertex_y[i]=0; } for(int i=0;i<(resolution)*2;i++){ for(int i2=0;i2<(resolution)*2;i2++){ this.vertex_x[i*(resolution)*2+i2]=(int)index_x[i2]; this.vertex_y[i*(resolution)*2+i2]=(int)index_y[i]; } } */ return true; } public function setSquare(i_vertex:Vector.):Boolean { if (!this._param_gen.getParam(i_vertex,this._cparam)) { return false; } return true; } } class MarkerPattDecoder { public function decode(model:int,domain:int,mask:int):void { } } /** * マーカパターンのエンコーダです。 * */ class MarkerPattEncoder { private static const _bit_table_3:Vector.=Vector.([ 25, 26, 27, 28, 29, 30, 31, 48, 9, 10, 11, 12, 13, 32, 47, 24, 1, 2, 3, 14, 33, 46, 23, 8, 0, 4, 15, 34, 45, 22, 7, 6, 5, 16, 35, 44, 21, 20, 19, 18, 17, 36, 43, 42, 41, 40, 39, 38, 37 ]); private static const _bit_table_2:Vector.=Vector.([ 9, 10, 11, 12, 13, 24, 1, 2, 3, 14, 23, 8, 0, 4, 15, 22, 7, 6, 5, 16, 21, 20, 19, 18, 17]); private static const _bit_tables:Vector.>=Vector.>([ _bit_table_2,_bit_table_3,null,null,null,null,null]); /** * RECT(0):[0]=(0) * RECT(1):[1]=(1-8) * RECT(2):[2]=(9-16),[3]=(17-24) * RECT(3):[4]=(25-32),[5]=(33-40),[6]=(41-48) */ private var _bit_table:Vector.; private var _bits:Vector.=new Vector.(16); private var _work:Vector.=new Vector.(16); private var _model:int; public function setBitByBitIndex(i_index_no:int,i_value:int):void { NyAS3Utils.assert(i_value==0 || i_value==1); var bit_no:int=this._bit_table[i_index_no]; if(bit_no==0){ this._bits[0]=i_value; }else{ var bidx:int=(bit_no-1)/8+1; var sidx:int=(bit_no-1)%8; this._bits[bidx]=(this._bits[bidx]&(~(0x01<>(sidx))&(0x01); } } public function getModel():int { return this._model; } private static function getControlValue(i_model:int,i_data:Vector.):int { var v:int; switch(i_model){ case 2: v=(i_data[2] & 0x0e)>>1; return v>=5?v-1:v; case 3: v=(i_data[4] & 0x3e)>>1; return v>=21?v-1:v; case 4: case 5: case 6: case 7: default: break; } return -1; } public static function getCheckValue(i_model:int,i_data:Vector.):int { var v:int; switch(i_model){ case 2: v=(i_data[2] & 0xe0)>>5; return v>5?v-1:v; case 3: v=((i_data[4] & 0x80)>>7) |((i_data[5] & 0x0f)<<1); return v>21?v-1:v; case 4: case 5: case 6: case 7: default: break; } return -1; } public function initEncoder(i_model:int):Boolean { if(i_model>3 || i_model<2){ //Lv4以降に対応する時は、この制限を変える。 return false; } this._bit_table=_bit_tables[i_model-2]; this._model=i_model; return true; } private function getDirection():int { var l:int,t:int,r:int,b:int; var timing_pat:int; switch(this._model){ case 2: //トラッキングセルを得る t=this._bits[2] & 0x1f; r=((this._bits[2] & 0xf0)>>4)|((this._bits[3]&0x01)<<4); b=this._bits[3] & 0x1f; l=((this._bits[3] & 0xf0)>>4)|((this._bits[2]&0x01)<<4); timing_pat=0x0a; break; case 3: t=this._bits[4] & 0x7f; r=((this._bits[4] & 0xc0)>>6)|((this._bits[5] & 0x1f)<<2); b=((this._bits[5] & 0xf0)>>4)|((this._bits[6] & 0x07)<<4); l=((this._bits[6] & 0xfc)>>2)|((this._bits[4] & 0x01)<<6); timing_pat=0x2a; break; default: return -3; } //タイミングパターンの比較 if(t==timing_pat){ if(r==timing_pat){ return (b!=timing_pat && l!=timing_pat)?2:-2; }else if(l==timing_pat){ return (b!=timing_pat && r!=timing_pat)?3:-2; } }else if(b==timing_pat){ if(r==timing_pat){ return (t!=timing_pat && l!=timing_pat)?1:-2; }else if(l==timing_pat){ return (t!=timing_pat && r!=timing_pat)?0:-2; } } return -1; } /** * 格納しているマーカパターンをエンコードして、マーカデータを返します。 * @param o_out * @return * 成功すればマーカの方位を返却します。失敗すると-1を返します。 */ public function encode(o_out:NyIdMarkerPattern):int { var d:int=getDirection(); if(d<0){ return -1; } //回転ビットの取得 getRotatedBits(d,o_out.data); var model:int=this._model; //周辺ビットの取得 o_out.model=model; var control_bits:int=getControlValue(model,o_out.data); o_out.check=getCheckValue(model,o_out.data); o_out.ctrl_mask=control_bits%5; o_out.ctrl_domain=control_bits/5; if(o_out.ctrl_domain!=0 || o_out.ctrl_mask!=0){ return -1;//ドメイン、マスクは現在0のみなので、それ以外の場合-1(失敗)を返す } //マスク解除処理を実装すること return d; } private function getRotatedBits(i_direction:int,o_out:Vector.):void { var sl:int=i_direction*2; var sr:int=8-sl; var w1:int; o_out[0]=this._bits[0]; //RECT1 w1=this._bits[1]; o_out[1]=((w1<>sr))& 0xff; //RECT2 sl=i_direction*4; sr=16-sl; w1=this._bits[2]|(this._bits[3]<<8); w1=(w1<>sr); o_out[2]=w1 & 0xff; o_out[3]=(w1>>8) & 0xff; if(this._model<2){ return; } //RECT3 sl=i_direction*6; sr=24-sl; w1=this._bits[4]|(this._bits[5]<<8)|(this._bits[6]<<16); w1=(w1<>sr); o_out[4]=w1 & 0xff; o_out[5]=(w1>>8) & 0xff; o_out[6]=(w1>>16) & 0xff; if(this._model<3){ return; } //RECT4(Lv4以降はここの制限を変える) // shiftLeft(this._bits,7,3,i_direction*8); // if(this._model<4){ // return; // } return; } public function shiftLeft(i_pack:Vector.,i_start:int,i_length:int,i_ls:int):void { var i:int; var work:Vector.=this._work; //端数シフト var mod_shift:int=i_ls%8; for(i=i_length-1;i>=1;i--){ work[i]=(i_pack[i+i_start]<>(8-mod_shift))); } work[0]=(i_pack[i_start]<>(8-mod_shift))); //バイトシフト var byte_shift:int=(i_ls/8)%i_length; for(i=i_length-1;i>=0;i--){ i_pack[(byte_shift+i)%i_length+i_start]=0xff & work[i]; } return; } } class TThreshold { public var th_h:int; public var th_l:int; public var th:int; public var lt_x:int; public var lt_y:int; public var rb_x:int; public var rb_y:int; } class THighAndLow{ public var h:int; public var l:int; }