定幅図形(ルーローの三角形)
◆定幅図形の生成◆
先日、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 sakusan393 ( http://wonderfl.net/user/sakusan393 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/cE5u
*/
/*
◆定幅図形の生成◆
先日、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);
}
}
}