/**
* Copyright tenasaku ( http://wonderfl.net/user/tenasaku )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/kA8r
*/
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;
}
}