In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

ルーローの多角形

2n+1 角形に拡張 
幅と高さからあるべき中心位置を逆算してみた
◆定幅図形の生成◆
先日、NHKの高校講座の数学で、「ルーローの三角形」を知り再現してみるテスト。
ロータリーエンジンの原理とか、7角形でイギリスのコインとかで使われてる図形。
参考:http://ja.wikipedia.org/wiki/%E3%83%AB%E3%83%BC%E3%83%AD%E3%83%BC%E3%81%AE%E4%B8%89%E8%A7%92%E5%BD%A2

四角形の穴を開けれるドリルを作れるそうなので、ドリルの動きを再現。
※厳密には三角形の公転軌道は円ではなく、楕円になるらしいけど、計算が理解できず断念。。。
参考:http://www.geocities.jp/ikuro_kotaro/koramu/322_drill4.htm
でも正円でもそれっぽく動いてる。
(ほぼ正方形の残像が確認できる)
/**
 * Copyright keno42 ( http://wonderfl.net/user/keno42 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wnYz
 */

// 2n+1 角形に拡張 
// forked from keno42's forked from: 定幅図形(ルーローの三角形)
// 幅と高さからあるべき中心位置を逆算してみた
// forked from sakusan393's 定幅図形(ルーローの三角形)
/*
◆定幅図形の生成◆
先日、NHKの高校講座の数学で、「ルーローの三角形」を知り再現してみるテスト。
ロータリーエンジンの原理とか、7角形でイギリスのコインとかで使われてる図形。
参考:http://ja.wikipedia.org/wiki/%E3%83%AB%E3%83%BC%E3%83%AD%E3%83%BC%E3%81%AE%E4%B8%89%E8%A7%92%E5%BD%A2

四角形の穴を開けれるドリルを作れるそうなので、ドリルの動きを再現。
※厳密には三角形の公転軌道は円ではなく、楕円になるらしいけど、計算が理解できず断念。。。
参考:http://www.geocities.jp/ikuro_kotaro/koramu/322_drill4.htm
でも正円でもそれっぽく動いてる。
(ほぼ正方形の残像が確認できる)

*/

package {
	import com.bit101.components.HSlider;
	import com.bit101.components.Label;
	import flash.geom.Matrix;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageQuality;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.ColorTransform;
	import flash.geom.Point;
	
	[SWF(width=465,height=465,backgroundColor=0,frameRate=60)]
	
	public class ReuleauxTriangle extends Sprite{
		private var _points:Array = [];
		private var _curvePoints:Array = [];
		private var _centerPoint:Point;
		private var _maxPoint:int = 3;
		private var _radius:int = 100;
		private var _a:Number = _radius * Math.sqrt(3);
		private var _containerSp:Sprite;
		
		private var _hSlider:HSlider;
		private var _labelHSlider:Label;
		private var _hSlider2:HSlider;
		private var _labelHSlider2:Label;
		private var _hSlider3:HSlider;
		private var _labelHSlider3:Label;
		private var _hSlider4:HSlider;
		private var _labelHSlider4:Label;
		
		private var _countAngleIndex:int= 2;
		private var _countAngle:int = 0;
		private var _bm:Bitmap;
		private var _bmd:BitmapData;
		private var _rotationRadius:int = 60;
		private var _proportion:Number = 0.333333333;
		
		private var _bmpColoerTrans:ColorTransform;
		private const CURVE_STEP:int = 30;
		
		public function ReuleauxTriangle(){
			super();
			this.addEventListener(Event.ADDED_TO_STAGE, init);
		}
		private function init(e:Event):void{
			stage.align = StageAlign.LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.quality = StageQuality.MEDIUM;
			
			_bmpColoerTrans = new ColorTransform(0.9,0.99,0.999999);
			
			_bm = new Bitmap();
			_bmd = new BitmapData(465,465,false,0x0);
			_bm.bitmapData = _bmd;
			addChild(_bm);
			
			_containerSp = new Sprite()
			_containerSp.x = stage.stageWidth/2;
			_containerSp.y = stage.stageHeight/2;
			
			_centerPoint = new Point(0, 0);
			setSlider();
			drawFig();
			
			stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, downHandler);
		}
		private function downHandler(e:MouseEvent):void{
			_bmd.fillRect(_bmd.rect, 0x0);
		}
		private function enterFrameHandler(e:Event):void{
			_bmd.draw(this,null,null);
			_bmd.colorTransform(_bmd.rect,_bmpColoerTrans);
			if(!_containerSp.parent) addChild(_containerSp);
			_containerSp.rotation += _countAngleIndex*_proportion;
			//_countAngle += -_countAngleIndex;
			//_containerSp.x = Math.cos(_countAngle*Math.PI/180) * _rotationRadius + stage.stageWidth/2;
			//_containerSp.y = Math.sin(_countAngle*Math.PI/180) * _rotationRadius + stage.stageHeight/2;
			var angle:Number = _containerSp.rotation;
			angle = (angle + 360) % (360 / _maxPoint);
			if ( angle < ( 90 / _maxPoint ) ) {
				_containerSp.x = 0.5 * _a - _radius * Math.cos( angle * Math.PI / 180 );
				_containerSp.y = - (_a * 0.5 - _radius * Math.cos( (angle- (90/_maxPoint)) * Math.PI / 180 ) );
			} else if ( angle < ( 180 / _maxPoint ) ) {
				_containerSp.x = - (_a * 0.5 - _radius * Math.cos( (angle-(180/_maxPoint)) * Math.PI / 180 ) );
				_containerSp.y = - (_a * 0.5 - _radius * Math.cos( (angle- (90/_maxPoint)) * Math.PI / 180 ) );
			} else if ( angle < ( 270 / _maxPoint ) ) {
				_containerSp.x = - (_a * 0.5 - _radius * Math.cos( (angle-(180/_maxPoint)) * Math.PI / 180 ) );
				_containerSp.y = ( _a * 0.5 - _radius * Math.cos( (angle- (270/_maxPoint)) * Math.PI / 180 ) );
			} else {
				_containerSp.x = 0.5 * _a - _radius * Math.cos( (angle-(360/_maxPoint)) * Math.PI / 180 );
				_containerSp.y = ( _a * 0.5 - _radius * Math.cos( (angle- (270 / _maxPoint)) * Math.PI / 180 ) );
			}
			_containerSp.x += stage.stageWidth/2;
			_containerSp.y += stage.stageHeight/2;
		}
		
		private function drawFig():void{
			setPoint();	
			createCurveTo();	
			createLineTo();
		}
		//コントロール用のスライダー定義
		private function setSlider():void {
			// 横方向スライダー:定幅図の画数
			_hSlider = new HSlider(this, 20, 20);
			_hSlider.addEventListener(Event.CHANGE, onHSliderChange);
			_labelHSlider = new Label(this, 20, 30);
			_labelHSlider.text = "fig polygon:3";
			_hSlider.maximum = 19;
			_hSlider.minimum = 3;
			
			/*
			// 横方向スライダー2:円軌道の半径
			_hSlider2 = new HSlider(this, 20, 50);
			_hSlider2.addEventListener(Event.CHANGE, onHSliderChange2);
			_labelHSlider2 = new Label(this, 20, 60);
			_hSlider2.maximum = 200;
			_hSlider2.minimum = 0;
			_hSlider2.value = _rotationRadius;
			_labelHSlider2.text = "revolution radius:60";
			*/
			
			// 横方向スライダー3:回転速度
			_hSlider3 = new HSlider(this, 20, 50);
			_hSlider3.addEventListener(Event.CHANGE, onHSliderChange3);
			_labelHSlider3 = new Label(this, 20, 60);
			_hSlider3.maximum = 10000000000;
			_hSlider3.minimum = 0;
			_hSlider3.value = 3333333333;
			_labelHSlider3.text = "rotation speed:0.333333333";
			
			// 横方向スライダー4:図形の半径
			_hSlider4 = new HSlider(this, 20, 80);
			_hSlider4.addEventListener(Event.CHANGE, onHSliderChange4);
			_labelHSlider4 = new Label(this, 20, 90);
			_hSlider4.maximum = 300;
			_hSlider4.minimum = 100;
			_labelHSlider4.text = "fig radius:100";
			
		}
		private function onHSliderChange(e:Event):void{
			trace(_hSlider.value %2);
			_bmd.fillRect(_bmd.rect , 0x0);
			var index:int;
			if(Math.floor(_hSlider.value)%2 == 0) {
				index = _hSlider.value -1;
			}else{
				index = _hSlider.value;
			}
			_labelHSlider.text = "polygon index:"+String(index);
			_maxPoint = index;
			_a = 2 * _radius * Math.sin( Math.PI * Math.floor(_maxPoint / 2) / _maxPoint );
			drawFig();
		}
		private function onHSliderChange2(e:Event):void{
			_bmd.fillRect(_bmd.rect , 0x0);
			_labelHSlider2.text = "revolution radius:" +_hSlider2.value; ;
			_rotationRadius = _hSlider2.value;			
		}
		private function onHSliderChange3(e:Event):void{
			_bmd.fillRect(_bmd.rect , 0x0);
			_labelHSlider3.text = "rotation speed:"+_hSlider3.value/10000000000;
			_proportion = _hSlider3.value/10000000000;			
		}
		private function onHSliderChange4(e:Event):void{
			_bmd.fillRect(_bmd.rect , 0x0);
			_labelHSlider4.text = "fig radius:"+_hSlider4.value;
			_radius = _hSlider4.value;
			_a = 2 * _radius * Math.sin( Math.PI * Math.floor(_maxPoint / 2) / _maxPoint );
//			_a = _radius * Math.sqrt(3);
			drawFig();
		}
		
		private function setPoint():void{
			_points = [];
			_curvePoints = [];
			var totalInteriorAngle:int = 180 * (_maxPoint -2);
			var angle:Number = 360 / _maxPoint;
			
			var i:int;
			for(i = 0; i < _maxPoint; i++){
				var dx:Number = _radius*Math.cos(angle * i * Math.PI/180) + _centerPoint.x;
				var dy:Number = _radius*Math.sin(angle * i * Math.PI/180) + _centerPoint.y;
				_points.push(new Point(dx,dy));
			};
			var distIndex:int = (_maxPoint/2 | 0) + 1;
			var rRadius:Number = Point.distance(_points[0],_points[distIndex]);
			
			for(i = 0; i < _maxPoint; i++){
				var cangle:Number = 360 / _maxPoint;
				var nextIndex:int;
				nextIndex = distIndex + i;
				if(nextIndex>_maxPoint-1) nextIndex -= _maxPoint;			
				var offsetAngle:Number = Math.atan2(_points[i].y - _points[nextIndex].y , _points[i].x - _points[nextIndex].x);
				var addAngle:Number = totalInteriorAngle/_maxPoint/(_maxPoint-2)/2;
				var rAngle:Number = offsetAngle + Math.PI/180 * addAngle;
				var cdx:Number = rRadius*Math.cos(rAngle) + _centerPoint.x + (_points[nextIndex].x - _centerPoint.x);
				var cdy:Number = rRadius*Math.sin(rAngle) + _centerPoint.y + (_points[nextIndex].y - _centerPoint.y);
				_curvePoints.push(new Point(cdx,cdy));
			}
		}
		//基本となる正図形を描画
		private function createLineTo():void{
			_containerSp.graphics.lineStyle(1,0xEEEEFF);
			_containerSp.graphics.moveTo(_points[0].x,_points[0].y);
			var i:int;
			for(i = 1; i < _maxPoint; i++){
				_containerSp.graphics.lineTo(_points[i].x, _points[i].y);
			}
			_containerSp.graphics.lineTo(_points[0].x,_points[0].y);
		}
		//定幅図形を描画
		private function createCurveTo():void{
			_containerSp.graphics.clear();
			/*
			//ベジェ曲線用のポイントを描画
			for(var i:int = 0; i < _curvePoints.length; i++){
				_containerSp.graphics.beginFill(0xFF0000);
				_containerSp.graphics.drawCircle(_curvePoints[i].x,_curvePoints[i].y,5);
				_containerSp.graphics.endFill();
			}
			*/
			_containerSp.graphics.beginFill(0xFF0000);
			_containerSp.graphics.drawCircle(_centerPoint.x,_centerPoint.y,5);
			_containerSp.graphics.endFill();
			//カーブ曲線でつなぐ
			_containerSp.graphics.lineStyle(2, 0x00FFFF);
			for (var i:int = 0; i < _maxPoint; i++) {
				var point:Point = new Point(_points[(i+Math.floor(_maxPoint/2))%_maxPoint].x - _points[i].x, _points[(i+Math.floor(_maxPoint/2))%_maxPoint].y - _points[i].y);
				_containerSp.graphics.moveTo(point.x+_points[i].x, point.y+_points[i].y);
				var matrix:Matrix = new Matrix();
				matrix.rotate(Math.PI / _maxPoint / CURVE_STEP);
				for ( var j:int = 0; j < CURVE_STEP; j++ ) {
					point = matrix.transformPoint(point);
					_containerSp.graphics.lineTo(point.x+_points[i].x,point.y+_points[i].y);
				}
				//_containerSp.graphics.curveTo(_curvePoints[i-1].x,_curvePoints[i-1].y,_points[i].x, _points[i].y);
			}
			//_containerSp.graphics.curveTo(_curvePoints[i-1].x,_curvePoints[i-1].y,_points[0].x,_points[0].y);
		}
	}
}