スポンサーサイト

-------- | --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[ActionScript 3.0] 変換行列

2007-12-20 | 21:13


fig.1において赤い図形を青い図形の位置に移動する変換行列を考える。
これはfig.2において赤い座標系の変換行列に対してその逆行列を掛けて黒い原点座標系に変換し、さらに青い座標系の変換行列を掛けることに等しい。
その [赤い座標系の変換行列の逆行列 と 青い座標系の変換行列 の合成変換] を fig.3の緑の図形にも適用すると、変換後の緑の図形は赤い図形に対する変換前の位置関係を保つ位置に移動する。

↓のウィンドウでマウスドラッグで適当に線を引くと、その線に沿って赤い図形が移動し、その後以前の位置関係を保つ位置に緑の図形も移動します。

package
{
        import flash.display.*;
        import flash.geom.*;
        import flash.events.*;
        import flash.filters.*;
        import flash.utils.*;
        
        import caurina.transitions.Tweener;
        
        [SWF(width="500", height="500", framerate="30", backgroundColor="#fff0f0")]
        public class MatrixTest extends Sprite
        {
                private var box:Box;
                private var box2:Box;
                private var point:Point;
                private var ma:Matrix;
                public function MatrixTest()
                {
                        addChild(box = new Box( 50, 0xff0000));
                        box.x = 100;
                        box.y = 200;
                        addChild(box2 = new Box( 50, 0xff00));
                        box2.x = 300;
                        box2.y = 250;
                        
                        stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
                        stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
                        stage.addEventListener (MouseEvent.MOUSE_MOVE, onMouseMove);
                }
                
                private function onMouseDown(e:Event):void{
                        point = new Point(stage.mouseX, stage.mouseY);
                }
                
                private function onMouseMove(e:Event):void{
                        if(point != null){
                                graphics.clear();
                                graphics.lineStyle(1,0);
                                graphics.moveTo(point.x, point.y);
                                graphics.lineTo (stage.mouseX, stage.mouseY);
                        }
                }
                
                private function onMouseUp(e:Event):void{
                        if(point != null){
                                var x:int = stage.mouseX - point.x ;
                                var y:int = stage.mouseY - point.y;
                                var len:Number = Math.sqrt(x*x+y*y);
                                
                                if(len < 1)
                                return;
                                
                                // 引かれた線分の変換行列
                                var mb:Matrix = new Matrix();
                                mb.a = x/len;
                                mb.c = -y/len;
                                mb.b = -mb.c;
                                mb.d = mb.a;
                                mb.tx = point.x;
                                mb.ty = point.y;
                                
                                // boxの変換行列
                                ma = box.transform.matrix.clone();
                                ma.invert(); // 逆行列をとって
                                ma.concat(mb); // mbとの積
                                
                                var mma:Matrix = box.transform.matrix.clone();
                                mma.concat(ma);
                                
                                var theta:Number = matrix2theta(mb);
                                Tweener.addTween(box,
                                                                                 {x:mma.tx, y:mma.ty, rotation:theta*180/Math.PI,
                                                                                         onComplete:function():void{
                                                
                                                // box2の変換行列
                                                var mc:Matrix = box2.transform.matrix.clone();
                                                mc.concat(ma); // maとの積
                                                
                                                theta= matrix2theta(mc);
                                                Tweener.addTween(box2,
                                                                                     {x:mc.tx, y:mc.ty, rotation:theta*180/Math.PI,
                                                                                             time:2, transition:"linear"}); },
                                        time:2, transition:"linear"});
                                
                        }
                        point = null;
                }
                
                private function matrix2theta(m:Matrix):Number{
                        var len:Number = Math.sqrt(m.a*m.a+m.c*m.c);
                        var theta:Number = Math.acos(m.a/len);
                        if (Math.asin(m.c/len) < 0)
                        theta *= -1;
                        return theta*-1;
                }
                
        }
}

import flash.display.*;
import flash.geom.*;
internal class Box extends Sprite{
        public var len:int;
        public function Box(len:int, c:int = 0xff){
                this.len = len;
                graphics.lineStyle(5, c, 0.5);
                graphics.moveTo (0 , 0);
                graphics.lineTo(len, 0);
                graphics.lineTo(len, -len);
                graphics.lineTo(0, -len);
                graphics.lineTo(0, 0);
                graphics.moveTo(len, -len);
                graphics.lineTo(len/2, -len*3/2);
                graphics.lineTo(0, -len);
        }
}

スポンサーサイト
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。