リマソン第2弾 (定義編) Created: 2010-03-04 by tenasaku tenasaku forked:1favorite:1lines:173license : MIT License modified : 2010-03-04 20:45:11 Embed Tweet package { // Created: 2010-03-04 by tenasaku import flash.display.Sprite; import flash.events.Event; import flash.text.TextField; public class Main extends Sprite { // リマソン(蝸牛線)の定義を説明するためのプログラムです // 円周 ( 直径: d ) の上に一点 O を固定し、 // その点 O を通る直線 (緑色) と円周のもうひとつの // 交点 P から, 一定の距離 a だけ離れた点 Q を // その直線の延長上にとるとします // 直線をぐるっと360度動かしたとき 動点 Q の描く軌跡が // リマソンです // a = d のときの形はとくに カージオイド と呼ばれています private var _banner:TextField; // タイトルなどを表示 private var _tf:TextField; // 時々刻々の情報を表示 private var Li:Limacon; // 本日の主役リマソンさん private var Ray:Sprite; // ガイド役の直線 // プログラム本体... public function Main():void { [SWF(width="465",height="465",backgroundcolor="#000000")] // 前振りなしにいきなり主役が登場するのは、 // 見出し用のテキストフィールドの値に // 主役 Li のプロパティを引用しているからです Li = new Limacon(180, 90, 0); Li.color = 0x800000; Li.thickness = 2; Li.x = 152; Li.y = 232; Li.showCircle = true; Li.circleColor = 0x000000; Li.draw(); addChild(Li); // ガイド用の直線 Ray = new Sprite(); Ray.graphics.clear(); addChild(Ray); // 見出し用テキストフィールド _banner = new TextField(); _banner.background = true; _banner.backgroundColor = 0xffffff; _banner.text = "Pascal's Limaçon\n[ a = " + String(Li.a / Li.d) + "d ]"; _banner.x = 10; _banner.y = 2; _banner.textColor = 0x800000; _banner.width = 200; _banner.height = 80; _banner.alpha = 0.6 addChild(_banner); // 表示用テキストフィールド _tf = new TextField(); _tf.text = ""; _tf.x = 10; _tf.y = 40; _tf.width = 200; _tf.textColor = 0x000080; addChild(_tf); // 各フレームごとに表示を更新するハンドラーを登録 addEventListener(Event.ENTER_FRAME, _as_time_passes); } // draw a straight line passing thru limaçon's origin and the mouse position ... // 原点とマウスの位置を通る直線を描きます (しかし妙にコムズカシくなってしまった...) private function draw_ray():void { var dx:Number = mouseX - Li.x; // <dx,dy> is the orientation of the line var dy:Number = mouseY - Li.y; var nx:Number; // <nx,ny> is the orthogonal direction var ny:Number; var Ax:Number; // at <Ax,Ay>, the line crosses the boundary. var Ay:Number; var Bx:Number; // <Bx,By> is the other cross point. var By:Number; Ray.graphics.clear(); Ray.graphics.lineStyle(1,0x00ff00); // Draw only if <dx,dy> is not the zero vector... if (( dx != 0 ) || (dy != 0)) { // normalize <dx,dy>... var _r:Number = Math.sqrt(dx * dx + dy * dy); dx /= _r; dy /= _r; // a unit vector perpendicular to <dx,dy> nx = - dy; ny = + dx; // Determine where does the line cross the boundary of Stage. var _NW:Number = nx * (-Li.x) + ny * (-Li.y); var _SW:Number = nx * (-Li.x) + ny * (stage.stageHeight-Li.y); var _SE:Number = nx * (stage.stageWidth-Li.x) + ny * (stage.stageHeight-Li.y); var _NE:Number = nx * (stage.stageWidth-Li.x) + ny * (-Li.y); var _EAST:Boolean = ( _NE*_SE < 0 ); // if the line crosses the east end of stage. var _WEST:Boolean = ( _NW*_SW < 0 ); // if the line crosses the west end of stage. var _NORTH:Boolean = ( _NE*_NW <= 0 ); // if the line crosses the north end of stage. var _SOUTH:Boolean = ( _SE*_SW <= 0 ); // if the line crosses the south end of stage. if ( _EAST ) { // if _EAST, then dx can never be zero. Bx = stage.stageWidth; By = Li.y + (dy/dx)*(stage.stageWidth-Li.x); if ( _NORTH ) { Ax = Li.x - (dx/dy)*Li.y; Ay = 0; } else { if ( _SOUTH ) { Ax = Li.x + (dx/dy)*(stage.stageHeight-Li.y); Ay = stage.stageHeight; } else { // _WEST must be the case Ax = 0; Ay = Li.y - (dy/dx)*Li.x; } } } else { // if not _EAST, three cases remain... if ( _NORTH && _SOUTH ) { Ax = Li.x - (dx/dy)*Li.y; Ay = 0; Bx = Li.x + (dx/dy)*(stage.stageHeight-Li.y); By = stage.stageHeight; } if ( _NORTH && _WEST ) { Ax = Li.x - (dx/dy)*Li.y; Ay = 0; Bx = 0; By = Li.y - (dy/dx)*Li.x; } if ( _SOUTH && _WEST ) { Ax = Li.x + (dx/dy)*(stage.stageHeight-Li.y); Ay = stage.stageHeight; Bx = 0; By = Li.y - (dy/dx)*Li.x; } } Ray.graphics.moveTo(Ax,Ay); Ray.graphics.lineTo(Bx,By); } } // マウスがステージにあれば原点から直線を引き、 // 方向(角度)をテキストフィールドに表示します private function _as_time_passes(e:Event):void { if ( ( mouseX >= 0) && (mouseY >= 0) && (mouseX < stage.stageWidth) && (mouseY < stage.stageHeight) ) { draw_ray(); } var deg:int = Math.round(Math.atan2( - (mouseY-Li.y), mouseX-Li.x) / Math.PI*180); _tf.text = "direction = " + String(deg) + " (deg)"; } } // end of class Main } // end of package /* ===================== */ // Limacon: a class which embodies Pascal's Limaçon. // -------- // Pascal's Limaçon is the plain curve determined by the polar equation // r = d*cos(theta - phi) + a [ where 0 <= theta <= 2*PI ]. // -------- // Note: // Constructor doesn't draw. You call draw() method explicitly. // -------- import flash.display.Sprite; class Limacon extends Sprite { public var d:Number; // Set by the constructor. public var a:Number; // ditto. public var phi:Number; // ditto. These three parameters are mandatory. public var thickness:uint; // default: 2 public var color:uint; // default: 0x000000 ( black ) public var showCircle:Boolean; // Want the circle displayed? (defalut: false) public var showLine:Boolean; // Want the diameter displayed? (defalut: false) public var circleColor:uint; // default: 0xffffff ( white ) public var lineColor:uint; // default: 0xffffff ( white ) // Draws the curve using given parameters public function draw():void { var i:int; var t:Number; var r:Number; this.graphics.clear(); this.graphics.lineStyle(thickness, color); for ( i = 0; i <= 90; ++i ) { t = this.phi + i * Math.PI / 45; r = this.d * Math.cos(t - phi) + this.a; if (i == 0) { this.graphics.moveTo(r * Math.cos(t), r * Math.sin(t)); } else { this.graphics.lineTo(r * Math.cos(t), r * Math.sin(t)); } } if ( showCircle ) { this.graphics.lineStyle(1, this.circleColor); this.graphics.drawCircle(this.d / 2 * Math.cos(phi), - this.d / 2 * Math.sin(phi), d / 2); } if ( showLine ) { this.graphics.lineStyle(1, this.lineColor); graphics.moveTo(0, 0); graphics.lineTo((this.d + this.a * 1.2) * Math.cos(phi), (this.d + this.a * 1.2) * Math.sin(phi)); } } // Constructor... public function Limacon(_d:Number, _a:Number, _phi:Number):void { this.d = _d; this.a = _a; while ( _phi < 0 ) { _phi += Math.PI * 2; } while ( _phi >= Math.PI * 2 ) { _phi -= Math.PI * 2; } this.phi = _phi; this.thickness = 2; this.showCircle = false; this.showLine = false; this.color = 0x000000; this.circleColor = 0xffffff; this.lineColor = 0xffffff; } } Code Fullscreen Preview Fullscreen digitrick 数学の視覚化 mouseY mouseX thickness Boolean Math.cos Math.PI addChild backgroundColor alpha background Math.sin TextField height textColor width addEventListener Math.atan2 Math.round Math.sqrt text sort new page view favorite forked pv32235 forked from: リマソン第2弾 (定義編) l.dijkman forked:1 favorite:2lines:172 (diff:268)