forked from: てらこ23で発表したものの説明2

by CZQ forked from てらこ23で発表したものの説明2 (diff: 1)
マトリックスを使って台形な変形
4点のポイントを用意して、その位置を元に変形。
台形といっても三角形が2つ合体させてます。
だらだら長いソースになってしまったけど、
_draw
_getTransformMatrix
の部分が重要なんで、他は無視無視無視無視無視無視無視無視!!
♥0 | Line 142 | Modified 2012-04-26 23:29:11 | MIT License
play

ActionScript3 source code

/**
 * Copyright CZQ ( http://wonderfl.net/user/CZQ )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/z8Ip
 */

// forked from y_tti's てらこ23で発表したものの説明2
/*
マトリックスを使って台形な変形
4点のポイントを用意して、その位置を元に変形。
台形といっても三角形が2つ合体させてます。
だらだら長いソースになってしまったけど、
_draw
_getTransformMatrix
の部分が重要なんで、他は無視無視無視無視無視無視無視無視!!
*/
package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.geom.Matrix;
    import flash.geom.Point;
    
    import net.hires.debug.Stats;
    
    [SWF(width = "465", height = "465", frameRate = "30", backgroundColor = "0x000000")]
    public class Teraco23_Matrix2 extends Sprite
    {
        private var _container:Sprite;
        private var _canvas:Sprite;
        private var _bmd:BitmapData;
        private var _stageW:Number = 465;
        private var _stageH:Number = 465;
        
        private var _cP0:CirclePoint;
        private var _cP1:CirclePoint;
        private var _cP2:CirclePoint;
        private var _cP3:CirclePoint;
        
        public function Teraco23_Matrix2()
        {
            //テスト用のBitmapData取得(重要じゃないので無視無視)
            _bmd = Bitmap(new TestImage()).bitmapData;
            
            //キャンバスを用意してコンテナに入れる(重要じゃないので無視無視)
            _canvas = new Sprite();
            _container = new Sprite();
            _container.addChild(_canvas);
            addChild(_container);
            _container.x = (_stageW - _bmd.width)/2;
            _container.y = (_stageH - _bmd.height)/2;
            
            //画像の大きさに合わせ、3点のポイントを配置(左上、右上、左下の3点)
            //CirclePointのコンストラクタの中で初期状態のポイント位置を保持してます。(initPoint)
            //その初期ポイントと、マウスドラッグで移動したポイントを比較してるのが、_drawの中。
            _cP0 = new CirclePoint(0,0);
            _cP1 = new CirclePoint(_bmd.width,0);
            _cP2 = new CirclePoint(0,_bmd.height);
            _cP3 = new CirclePoint(_bmd.width,_bmd.height);
            _container.addChild(_cP0);
            _container.addChild(_cP1);
            _container.addChild(_cP2);
            _container.addChild(_cP3);
            
            //ポイントのドラッグとかの設定
            //※ドラッグした時に_drawを呼び出してます。
            _cP0.addEventListener(MouseEvent.MOUSE_DOWN , _cPMouseDownHandler );
            _cP1.addEventListener(MouseEvent.MOUSE_DOWN , _cPMouseDownHandler );
            _cP2.addEventListener(MouseEvent.MOUSE_DOWN , _cPMouseDownHandler );
            _cP3.addEventListener(MouseEvent.MOUSE_DOWN , _cPMouseDownHandler );
            
            _draw();
            
            //速度とかメモリとかチェック(重要じゃないので無視無視)
            addChild(new Stats());
        }
        
        private function _draw():void {
            /**
             * ポイントの番号は↓な感じ。
             *   1--------2
             *   ----------
             *   ----------
             *   3--------4
             */            
            //初期状態のポイント取得
            var aP0:Point = _cP0.initPoint;
            var aP1:Point = _cP1.initPoint;
            var aP2:Point = _cP2.initPoint;
            var aP3:Point = _cP3.initPoint;
            //初期状態のポイントよりマトリックス取得
            var initMatrix1:Matrix = _getTransformMatrix( aP0 , aP1 , aP2 );
            var initMatrix2:Matrix = _getTransformMatrix( aP3 , aP2 , aP1 );
            
            //変更状態のポイント取得
            var bP0:Point = new Point(_cP0.x , _cP0.y );
            var bP1:Point = new Point(_cP1.x , _cP1.y );
            var bP2:Point = new Point(_cP2.x , _cP2.y );
            var bP3:Point = new Point(_cP3.x , _cP3.y );
            //変更状態のポイントよりマトリックス取得
            var editMatrix1:Matrix = _getTransformMatrix( bP0 , bP1 , bP2 );
            var editMatrix2:Matrix = _getTransformMatrix( bP3 , bP2 , bP1 );
            
            //初期状態と変更状態のマトリックスを合体
            var newMatrix1:Matrix = initMatrix1.clone();
            newMatrix1.concat(editMatrix1);
            var newMatrix2:Matrix = initMatrix2.clone();
            newMatrix2.concat(editMatrix2);
            
            //マトリックスを適応
            _canvas.graphics.clear();
            
            //分割した1個目を描画
            _canvas.graphics.lineStyle(1 , 0x00FF00);
            _canvas.graphics.beginBitmapFill(_bmd , newMatrix1 );
            _canvas.graphics.moveTo(bP0.x , bP0.y );
            _canvas.graphics.lineTo(bP1.x , bP1.y );
            _canvas.graphics.lineTo(bP2.x , bP2.y );
            _canvas.graphics.endFill();
            
            //分割した2個目を描画
            _canvas.graphics.lineStyle(1 , 0x00FF00);
            _canvas.graphics.beginBitmapFill(_bmd , newMatrix2 );
            _canvas.graphics.moveTo(bP3.x , bP3.y );
            _canvas.graphics.lineTo(bP1.x , bP1.y );
            _canvas.graphics.lineTo(bP2.x , bP2.y );
            _canvas.graphics.endFill();
        }
        
        
        private function _getTransformMatrix($pt0:Point, $pt1:Point, $pt2:Point):Matrix
        {
            /*
            http://www.adobe.com/jp/devnet/flash/articles/matrix_class.html
            a: 水平方向の伸縮率 = 変換後の幅/もとの幅
            b: 垂直方向の傾斜率 = 垂直方向の傾斜/もとの幅
            c: 水平方向の傾斜率 = 水平方向の傾斜/もとの高さ
            d: 垂直方向の伸縮率 = 変換後の高さ/もとの高さ
            tx: 水平方向の移動ピクセル数
            ty: 垂直方向の移動ピクセル数
            */
            var w:Number = _bmd.width;
            var h:Number = _bmd.height;
            var mat:Matrix = new Matrix();
            mat.a = ($pt1.x - $pt0.x) / w;
            mat.b = ($pt1.y - $pt0.y) / w;
            mat.c = ($pt2.x - $pt0.x) / h;
            mat.d = ($pt2.y - $pt0.y) / h;
            mat.tx = $pt0.x;
            mat.ty = $pt0.y;
            return mat;
        }
        
        //こっからマウスのドラッグとかの設定(無視無視)
        private function _cPMouseDownHandler(e:MouseEvent):void {
            CirclePoint(e.target).startDrag();
            CirclePoint(e.target).addEventListener(MouseEvent.MOUSE_MOVE , _cPMouseMoveHandler );
            stage.addEventListener(MouseEvent.MOUSE_UP , _cPMouseUpHandler );
        }
        
        private function _cPMouseUpHandler(e:MouseEvent):void {
            CirclePoint(e.target).stopDrag();
            CirclePoint(e.target).removeEventListener(MouseEvent.MOUSE_MOVE , _cPMouseMoveHandler );
            stage.removeEventListener(MouseEvent.MOUSE_UP , _cPMouseUpHandler );
        }
        
        private function _cPMouseMoveHandler(e:MouseEvent):void {
            _draw();
        }
        
        

    }
}


import flash.display.Bitmap;
import flash.display.Shape;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.geom.Point;

/**
 * 赤い点を書いてる。
 * それと初期状態のポイントをinitPointに保持してる。
 */
class CirclePoint extends Sprite {
    public var initPoint:Point;
    public function CirclePoint($x:Number , $y:Number) {
        this.x = $x;
        this.y = $y;
        this.initPoint = new Point( $x , $y );
        this.graphics.beginFill(0xFF0000,1);
        this.graphics.drawCircle(0,0,10);
        this.graphics.endFill();
        this.buttonMode = true;
    }
}

/**
 * このTestImageクラスは画像の代わりに無理矢理、
 * BitmapDataを作成してるだけなので無視無視無視無視無視。
 */
class TestImage extends Bitmap {
    private var _w:Number = 200;
    private var _h:Number = 200;
    public function TestImage():void {
        var s:Shape = new Shape();
        s.graphics.beginFill(0xCCCCCC , 1 );
        s.graphics.drawRect(0,0,_w,_h);
        s.graphics.beginFill(0xFCFCFC , 1 );
        s.graphics.drawRoundRect(30 , 30 , 30 , 10 , 20 ,20);
        s.graphics.drawRoundRect(140 , 30 , 30 , 10 , 20 ,20);
        s.graphics.drawCircle(50,70,10);
        s.graphics.drawCircle(150,70,10);
        s.graphics.drawCircle(75,120,5);
        s.graphics.drawCircle(125,120,5);
        s.graphics.drawRoundRect(40 , 170 , 120 , 10 , 20 ,20);
        s.graphics.endFill();
        
        var bmd:BitmapData = new BitmapData(_w,_h);
        bmd.draw(s);
        this.bitmapData = bmd;
    }
}