Beautifl - Flash Gallery

Preview

定幅図形(ルーローの三角形)
sakusan393 2010年4月3日 MIT License
?
◆定幅図形の生成◆  
先日、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  
でも正円でもそれっぽく動いてる。  
(ほぼ正方形の残像が確認できる)
      /*
◆定幅図形の生成◆
先日、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.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 _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;
        
        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;
        }
        
        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, 80);
            _hSlider3.addEventListener(Event.CHANGE, onHSliderChange3);
            _labelHSlider3 = new Label(this, 20, 90);
            _hSlider3.maximum = 10000000000;
            _hSlider3.minimum = 0;
            _hSlider3.value = 3333333333;
            _labelHSlider3.text = "revolution proportion:0.333333333";
            
            // 横方向スライダー4:定幅図の公転/自転比率
            _hSlider4 = new HSlider(this, 20, 110);
            _hSlider4.addEventListener(Event.CHANGE, onHSliderChange4);
            _labelHSlider4 = new Label(this, 20, 120);
            _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(_hSlider.value%2 == 0) {
                index = _hSlider.value -1;
            }else{
                index = _hSlider.value;
            }
            _labelHSlider.text = "polygon index:"+String(index);
            _maxPoint = index;
            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 = "revolution proportion:"+_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;
            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);
            _containerSp.graphics.moveTo(_points[0].x,_points[0].y);
            for(i = 1; i < _maxPoint; i++){
                _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);
        }
    }
}