Beautifl - Flash Gallery

Preview

2点透視図法で描く立方体
shinano_cake_koubou 2010年3月24日 MIT License
?
2点透視図法で描く立方体   
黒丸の操作点を移動すると、EL,GL,VPと立方体の高さが変更できます。
      package {
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;

    /**
    * 2点透視図法で描く立方体 
    * 黒丸の操作点を移動すると、EL,GL,VPと立方体の高さが変更できます。
    *
    *
    */
    [SWF (width=468, height=468, backgroundColor="#CCCCCC")]
    public class Perspective2_Cube extends Sprite
    {
        /*------------------------------ 定数 ----------------------------------*/
        public const PADDING:int            = 10;                /* 余白 */        
        public const BG_COLOR:int        = 0xFFFFFF;            /* 背景色 */
        public const BG_ALPHA:Number        = 1;                /* 背景の透過率 */
        
        public const LINE_COLOR:int        = 0x666666;            /* 線の色  */
        public const LINE_WIDTH:int        = 1;                    /* 線の太さ  */
        
        public const CUBELINE_COLOR:int    = 0x222222;            /* 立方体の線の色  */
        public const CUBELINE_WIDTH:int    = 2;                    /* 立方体の線の太さ  */        
        
        public const CIRCLE_COLOR:int    = 0x333333;            /* 操作点の色 */
        public const CIRCLE_R:int        = 5;                    /* 操作点の大きさ */
                
        /*------------------------------ 変数 ----------------------------------*/
        public  var eyeLevelY:Number        =   200;                /* eyeLine y */
        public  var vpLeftX:Number        =   200;                /* 消失点 (left) x */
        public  var vpRightX:Number        =   1000;            /* 消失点(right) x */
        public  var glX:Number            =    600;                /* ground line x */
        public  var glY:Number            =    500;                /* ground line y */
        public  var    cubeHeight:Number    =    300;                /* 立方体の高さ  */
        
        private var startX:Number        ;                    /* 左端 */
        private var endX:Number            ;                     /* 右端 */
        
        private var line:Shape = new Shape();                    /* 線 */
        private var cubeLine:Shape = new Shape();                /* 立方体の線 */
        
        private var circleVpLeft:Shape = new Shape();            /* 消失点の操作点(左) */            
        private var circleVpRight:Shape = new Shape();        /* 消失点の操作点(右) */
        private var glCircle:Shape = new Shape();                /* GLの操作点 */
        private var cubeHeightCircle:Shape = new Shape();        /* 立方体の高さの操作点 */
        
        private var back:Shape = new Shape();                    /* 背景 */
        
        private var vpLeftDragged:Boolean = false;            /* 操作点(LVP)がドラッグされているかどうかのフラグ  */
        private var vpRightDragged:Boolean = false;            /* 操作点(RVP)がドラッグされているかどうかのフラグ  */
        private var glDragged:Boolean = false;                /* 操作点(GL) がドラッグされているかどうかのフラグ  */
        private var cubeDragged:Boolean = false;                /* 操作点(立方体の高さ)がドラッグされているかどうかのフラグ  */
                
        private var cubeLeftScale:Number  = 0.75;                /* 立方体の幅 */
        private var cubeRightScale:Number = 0.75;                /* 立方体の奥行 */
        
        private var cubeRightBtmX:Number;                        /* 立方体(右下x座標) */
        private var cubeRightBtmY:Number;                        /* 立方体(右下y座標) */
        private var cubeLeftBtmX:Number;                        /* 立方体(左下x座標) */
        private var cubeLeftBtmY:Number;                        /* 立方体(左下y座標) */            
        private var cubeRightTopX:Number;                        /* 立方体(右上x座標) */
        private var cubeRightTopY:Number;                        /* 立方体(右上y座標) */
        private var cubeLeftTopX:Number;                        /* 立方体(左上x座標) */
        private var cubeLeftTopY:Number;                        /* 立方体(左上y座標) */
        
        private var cubeBackBtmX:Number;                        /* 立方体(奥下x座標) */
        private var cubeBackBtmY:Number;                        /* 立方体(奥下y座標) */
        private var cubeBackTopX:Number;                        /* 立方体(奥上x座標) */
        private var cubeBackTopY:Number;                        /* 立方体(奥上y座標) */
        
        private var w:int = 465;
        private var h:int = 465;
        
        /*---------------------------- Initialization ---------------------------*/ 
        
        /** コンストラクタ */
        public function  Perspective2_Cube()
        {
            init();            
        }        
        
        /** 初期化処理 */
        private function init():void
        {                    
            this.stage.align = StageAlign.TOP_LEFT;
            this.stage.scaleMode = StageScaleMode.NO_SCALE;
            this.mouseEnabled = true;
            
            //this.addEventListener(FlexEvent.CREATION_COMPLETE,onComplete);        /* 完了を待つ  flex用*/
            onComplete(new Event("nop"));            
        }
        
        /*---------------------------- Event Handelr ----------------------------*/
        
        /** stageができるのを待つ */
        private function onComplete(e:Event):void
        {
    
            this.startX             = PADDING;
            this.endX             = this.w - PADDING;
            
            eyeLevelY            =   this.h*1/2;                                        /* eyeLine y */
            vpLeftX                =   this.w*1/10;                                    /* 消失点 (left) x */
            vpRightX                =   this.w-this.w*2/10;                                /* 消失点(right) x */
            glX                    =    this.w*2/3;                                        /* ground line x */
            glY                    =    this.h*5/7;                                        /* ground line y */
            cubeHeight            =    glY-eyeLevelY*4/5;                                /* 立方体の高さ  */
        
            this.stage.addEventListener(MouseEvent.MOUSE_DOWN,onMouseClick);        /* マウスイベントを拾う */
            this.stage.addEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);
            this.stage.addEventListener(MouseEvent.MOUSE_UP,onMouseRelease);
            //this.addEventListener(ResizeEvent.RESIZE,onResize);
            
            back = new Shape();                                                        /* 背景 */
            back.graphics.beginFill(BG_COLOR,BG_ALPHA);            
            back.graphics.drawRoundRect(PADDING,PADDING,this.w-PADDING*2,this.h-PADDING*2,PADDING,PADDING);
            back.graphics.endFill();
            
            this.addChild(back);                                                    /* 図形の追加 */
            this.addChild(line);
            this.addChild(cubeLine);
            this.addChild(cubeHeightCircle);
            this.addChild(circleVpLeft);
            this.addChild(circleVpRight);
            this.addChild(glCircle);
            
            this.draw();                                                            /* 描画 */            
        }
        
        /** マウスクリック時 */
        private function onMouseClick(e:MouseEvent):void
        {
            clearFlag();                                                            /* ドラッグ状態をクリア */
            
            if(circleVpLeft.hitTestPoint(e.stageX,e.stageY)){                        /* ドラッグ状態をセット */
                vpLeftDragged = true;
            }else if(circleVpRight.hitTestPoint(e.stageX,e.stageY)){            
                vpRightDragged = true;
            }else if(glCircle.hitTestPoint(e.stageX,e.stageY)){
                glDragged = true;    
            }else if(cubeHeightCircle.hitTestPoint(e.stageX,e.stageY)){
                cubeDragged = true;
            }
        }
        
        /** すべての操作点のドラッグ状態を解除する */
        private function clearFlag():void
        {
            vpLeftDragged = false;
            vpRightDragged = false;    
            glDragged = false;
            cubeDragged = false;
        }
        
        /** マウスを動かしたとき */
        private function onMouseMove(e:MouseEvent):void
        {
            if(vpLeftDragged){                                                        /* ドラッグされてる操作点を移動 */
                eyeLevelY = e.localY;
                vpLeftX = e.localX;                
            }else if(vpRightDragged){
                eyeLevelY = e.localY;
                vpRightX = e.localX;
            }else if(glDragged){
                glY = e.localY;
                glX = e.localX;
            }else if(cubeDragged){
                cubeHeight = glY - e.localY;
                glX = e.localX;
            }
            
            draw();                                                                    /* 再描画 */
        }
        
        /** マウスを離したとき */
        private function onMouseRelease(e:MouseEvent):void
        {
            clearFlag();                                                            /* ドラッグ状態を解除 */
        }
        
        /** リサイズ時の処理 */
        private function onResize(e:Event):void
        {
            back.graphics.clear();
            back.graphics.beginFill(BG_COLOR,BG_ALPHA);            
            back.graphics.drawRoundRect(PADDING,PADDING,this.w-PADDING,this.h-PADDING,PADDING,PADDING);
            back.graphics.endFill();
            
            this.draw();
        }
        
        /*--------------------------------------- Drawing ------------------------------------*/
        
        /** 描画処理 */
        public function draw():void{
            
            this.initLine();                                                        /* 描画の初期化 */            
            this.calcCubePoint();                                                    /* 立方体の座標の算出 */                                
            this.drawLine();                                                        /* 線の描画 */
            this.drawCube();                                                        /* 立方体の描画 */
            this.drawCircle();                                                        /* 操作点の描画 */                
        
        }/* End of draw() */

        /** 線の初期化 */        
        private function initLine():void
        {
            /* 初期化 */
            line.graphics.clear();                                                    /* clear */                            
            circleVpLeft.graphics.clear();
            circleVpRight.graphics.clear();
            glCircle.graphics.clear();
            cubeLine.graphics.clear();
            cubeHeightCircle.graphics.clear();
            
            /* 線の設定 */
            line.graphics.lineStyle(LINE_WIDTH,LINE_COLOR);                            /* set line style */
            cubeLine.graphics.lineStyle(CUBELINE_WIDTH,CUBELINE_COLOR);                        
        }
        
        /** 立方体の座標の計算 */
        private function calcCubePoint():void
        {
            /* 立方体の頂点の座標 */
            cubeRightBtmX    = glX + (vpRightX - glX)*(1-cubeLeftScale);                /* 立方体(右下x座標) */
            cubeRightBtmY    = eyeLevelY + (glY-eyeLevelY)*cubeLeftScale;            /* 立方体(右下y座標) */
            cubeLeftBtmX        = glX + (vpLeftX - glX)*(1-cubeRightScale);                /* 立方体(左下x座標) */
            cubeLeftBtmY        = eyeLevelY + (glY-eyeLevelY)*cubeRightScale;            /* 立方体(左下y座標) */
            
            cubeRightTopX    = glX + (vpRightX - glX)*(1-cubeLeftScale);                /* 立方体(右上x座標) */
            cubeRightTopY    = eyeLevelY + (glY-eyeLevelY -cubeHeight)*cubeLeftScale;/* 立方体(右上y座標) */
            cubeLeftTopX        = glX + (vpLeftX - glX)*(1-cubeRightScale);                /* 立方体(左上x座標) */
            cubeLeftTopY        = eyeLevelY + (glY-eyeLevelY -cubeHeight )*cubeRightScale;/* 立方体(左上y座標) */
            
            if( vpRightX == vpLeftX ){                                                    /* LVP = RVPの時 */
                vpRightX -= 0.1;                                                        /* ちょっとずらす */
            }
            
            /* ------------------------------------- 立方体(奥下の座標を求める )-------------------------------------- */
            
            /* 計算用の変数 */
            var a:Number;
            var c:Number;
            var b:Number;
            var d:Number;                        
            
            if((eyeLevelY != cubeLeftBtmY) && (glY != cubeLeftBtmY)){                    /* アイレベル != 立方体の下部の頂点 */
                                                                                        /* かつ  GL != 立方体の下部の頂点 */
                                                                                                            
                /* LVP(左上)->GL(下)への直線を  y= ax+ b , GL(下)->RVP(右上)への直線を  y= cx + d とおき、この一次方程式を解く */
            
                a = (cubeRightBtmY - eyeLevelY) / (cubeRightBtmX-vpLeftX) ;                        
                c = (eyeLevelY - cubeLeftBtmY) / (vpRightX - cubeLeftBtmX ); 
                b =  eyeLevelY;
                d = ((vpRightX-vpLeftX)*cubeLeftBtmY - (cubeLeftBtmX-vpLeftX)*eyeLevelY) / (vpRightX- cubeLeftBtmX);
            
                cubeBackBtmX = (d - b)/(a - c)  + vpLeftX ;                                /* 立方体(奥下x座標) */
                cubeBackBtmY = a * (d - b)/(a - c) + b;                                    /* 立方体(奥下y座標) */
                
            }            
            
            /* ------------------------------------- 立方体(奥上の座標を求める )-------------------------------------- */
                
            if((eyeLevelY != cubeLeftTopY) && (glY != cubeLeftTopY)){                    /* アイレベル != 立方体の上部の頂点のとき */
                                                                                        /* かつ  GL != 立方体の上部の頂点のとき */
                
                /* LVP(左上)->GL(下)への直線を  y= ax+ b , GL(下)->RVP(右上)への直線を  y= cx + d とおき、この一次方程式を解く */                        
                a = (cubeRightTopY - eyeLevelY) / (cubeRightTopX-vpLeftX) ;                        
                c = (eyeLevelY - cubeLeftTopY) / (vpRightX - cubeLeftTopX ); 
                b =  eyeLevelY;
                d = ((vpRightX-vpLeftX)*cubeLeftTopY - (cubeLeftTopX-vpLeftX)*eyeLevelY) / (vpRightX- cubeLeftTopX);
                            
                cubeBackTopX = (d - b)/(a - c)  + vpLeftX ;                                /* 立方体(奥上x座標) */
                cubeBackTopY = a * (d - b)/(a - c) + b;                                    /* 立方体(奥上y座標) */
                
            }
            
            /* 調整 */
            if((eyeLevelY == glY) && (eyeLevelY == cubeLeftTopY)) {                        /* アイレベル = GL */
                cubeBackTopX = eyeLevelY;                                                /* 立方体(奥上y座標) */
                cubeBackBtmY = eyeLevelY;                                                /* 立方体(奥下y座標) */
                cubeBackTopX = (cubeRightBtmX-cubeRightBtmX)>> 1;                        /* 立方体(奥上x座標) */
                cubeBackBtmX = (cubeRightBtmX-cubeRightBtmX)>> 1;                        /* 立方体(奥下x座標) */                
            }else if(eyeLevelY == glY) {                                                /* アイレベル = GL */
                cubeBackBtmX = cubeBackTopX;                                            /* 立方体(奥上x座標) */
                cubeBackBtmY = eyeLevelY;                                                /* 立方体(奥上y座標) */
            }else if(eyeLevelY == cubeLeftTopY) {                                        /* アイレベル = 立方体の上部の頂点のとき */
                cubeBackTopX = cubeBackBtmX;                                            /* 立方体(奥上x座標) */
                cubeBackTopY = eyeLevelY;                                                /* 立方体(奥上y座標) */                
            }        
            
    
                                            
        }/* End of calcCubePoint() */
        
        /** 線の描画(立方体以外) */
        private function drawLine():void
        {
            line.graphics.moveTo(this.startX,eyeLevelY);                                /* Eye Level             */
            line.graphics.lineTo(this.w,eyeLevelY);
            
            line.graphics.moveTo(this.startX,glY);                                        /* Ground Line            */
            line.graphics.lineTo(this.w,glY);
                
            line.graphics.moveTo(vpLeftX,eyeLevelY);                                    /* LVP -> GL              */
            line.graphics.lineTo(glX,glY );
            line.graphics.lineTo(vpRightX,eyeLevelY);                                    /* GL -> RVP             */
            
            line.graphics.moveTo(vpLeftX,eyeLevelY);                                    /* LVP -> CubeTop         */
            line.graphics.lineTo(glX,glY - cubeHeight);    
            line.graphics.lineTo(vpRightX,eyeLevelY);                                    /* CubeTop -> RVP         */
            
            line.graphics.moveTo(vpLeftX,eyeLevelY);            
            line.graphics.lineTo(cubeRightTopX,cubeRightTopY);
            line.graphics.moveTo(vpRightX,eyeLevelY);
            line.graphics.lineTo(cubeLeftTopX,cubeLeftTopY);
            
            line.graphics.moveTo(vpLeftX,eyeLevelY);
            line.graphics.lineTo(cubeRightBtmX,cubeRightBtmY);            
            line.graphics.moveTo(vpRightX,eyeLevelY);
            line.graphics.lineTo(cubeLeftBtmX,cubeLeftBtmY);    
            
        }/* End of drawLine() */
        
        /** 立方体の描画 */
        private function drawCube():void
        {
            cubeLine.graphics.moveTo(cubeRightBtmX,cubeRightBtmY);                        
            cubeLine.graphics.lineTo(cubeRightTopX,cubeRightTopY);
            cubeLine.graphics.moveTo(cubeLeftBtmX,cubeLeftBtmY);
            cubeLine.graphics.lineTo(cubeLeftTopX,cubeLeftTopY);
            
            cubeLine.graphics.moveTo(cubeLeftBtmX,cubeLeftBtmY);
            cubeLine.graphics.lineTo(glX,glY);
            cubeLine.graphics.lineTo(cubeRightBtmX,cubeRightBtmY);
            
            cubeLine.graphics.lineTo(cubeBackBtmX,cubeBackBtmY);
            cubeLine.graphics.lineTo(cubeLeftBtmX,cubeLeftBtmY);
            
            cubeLine.graphics.moveTo(cubeRightTopX,cubeRightTopY);
            cubeLine.graphics.lineTo(cubeBackTopX,cubeBackTopY);    
            cubeLine.graphics.lineTo(cubeLeftTopX,cubeLeftTopY);
            
            cubeLine.graphics.moveTo(cubeBackTopX,cubeBackTopY);
            cubeLine.graphics.lineTo(cubeBackBtmX,cubeBackBtmY);                    
            
            cubeLine.graphics.moveTo(cubeLeftTopX,cubeLeftTopY);
            cubeLine.graphics.lineTo(glX,glY - cubeHeight);
            cubeLine.graphics.lineTo(cubeRightTopX,cubeRightTopY);
                            
            cubeLine.graphics.moveTo(glX,glY);                                
            cubeLine.graphics.lineTo(glX,glY - cubeHeight);
                        
        }/* End of drawCube() */
        
        /** 操作点の描画 */
        private function drawCircle():void
        {
            circleVpLeft.graphics.beginFill(CIRCLE_COLOR,1);                                /* left viewPoNumber */            
            circleVpLeft.graphics.drawCircle(vpLeftX,eyeLevelY,CIRCLE_R);
            circleVpLeft.graphics.endFill();
            
            circleVpRight.graphics.beginFill(CIRCLE_COLOR,1);                                /* right viewPoNumber */                        
            circleVpRight.graphics.drawCircle(vpRightX,eyeLevelY,CIRCLE_R);
            circleVpRight.graphics.endFill();
            
            glCircle.graphics.beginFill(CIRCLE_COLOR,1);                                    /* gl */                        
            glCircle.graphics.drawCircle(glX,glY,CIRCLE_R);
            glCircle.graphics.endFill();
            
            cubeHeightCircle.graphics.beginFill(CIRCLE_COLOR,1);                            /* cubeHeight */                        
            cubeHeightCircle.graphics.drawCircle(glX,glY - cubeHeight,5);
            cubeHeightCircle.graphics.endFill();
            
        }/* End of drawCircle() */
        
    }
}