Beautifl - Flash Gallery

Thumbnail : 2点透視図法で描く立方体
2点透視図法で描く立方体
shinano_cake_koubou 2010-03-24 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

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() */
		
	}
}