リマソン第3弾 (角の三等分編)
---------------
パスカルのリマソン(蝸牛線)による角の三等分
図をクリックすると補助線を表示
もう一度クリックすると解説文を表示
さらにもう一度クリックすると最初の表示に戻る
まだちょっと文字の表示がオカシイ...
2010-03-08 by tenasaku
/**
* Copyright tenasaku ( http://wonderfl.net/user/tenasaku )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/knk4
*/
/* ---------------
パスカルのリマソン(蝸牛線)による角の三等分
図をクリックすると補助線を表示
もう一度クリックすると解説文を表示
さらにもう一度クリックすると最初の表示に戻る
まだちょっと文字の表示がオカシイ...
*/
// 2010-03-08 by tenasaku
package {
import flash.display.*;
import flash.events.*;
import flash.text.*;
public class Main extends Sprite {
private const _W:uint = 465; // assumed width of Stage
private const _H:uint = 465; // assumed height of Stage
private const _limaScale:uint = 100;
private var _descriptionLevel:int;
private var _limacon:Sprite;
private var _solution:Sprite;
private var _description:TextField;
private var _tip:TextField;
private var _C:LabeledPoint;
private var _O:LabeledPoint;
private var _P:LabeledPoint;
private var _Q:LabeledPoint;
private var _R:LabeledPoint;
private var _X:LabeledPoint;
private var _theta:Number;
private var _time:Number;
public function Main():void {
// ステージを描画領域の左上隅に合せる
stage.align = StageAlign.TOP_LEFT;
// 縮尺しない (クロップされる可能性がある)
stage.scaleMode = StageScaleMode.NO_SCALE;
// 背景色を変更する
this.graphics.beginFill(0xffffff);
this.graphics.drawRect(0,0,_W,_H);
this.graphics.endFill();
// 用法を示す短かいテキスト
_tip = new TextField();
_tip.width = _W/2;
_tip.height = 24;
_tip.text = "図をクリックしてください...";
_tip.x = 2;
_tip.y = _H - _tip.height;
addChild(_tip);
// 説明書きテキストを準備するが, まだ描画しない...
_description = new TextField();
_description.x = 0;
_description.y = 0;
_description.width = _W;
_description.height = _H;
_description.text = "リマソンは任意の角を三等分する\n\nこの図において ∠POX は ∠PCX の三分の二である.\n\nCを中心として半径OCの円と直線OPとの交点をQとする\nリマソンの定義から, このとき OC = CQ = QP である\nOPと平行にCから直線 CR を引こう. すると\n(1) ∠RCX = ∠QOC (同位角だから).\n(2) ∠QCR = ∠OQC (錯角だから).\nいっぽう\n(3) ∠OQC = ∠QOC (△OQCが二等辺三角形だから)\n(4) ∠OQC は ∠QCP の二倍 (△OCPが二等辺三角形だから)\nこれと条項(2)から\n(5) ∠PCR は ∠QCR の半分\n条項(1),(2)から ∠QCR = ∠RCX なので\n(6) ∠PCR は ∠RCX の半分\nとなり\n\t∠PCX = ∠PCR + ∠RCX = ∠RCX の1.5倍\nこれと条項(1)から\n\t∠PCX = ∠QOC の1.5 倍\nとなって求める結論が得られる.";
_description.background = true;
_description.backgroundColor = 0xffccff;
_description.textColor = 0x000000;
_description.alpha = 0.9;
_description.visible = false;
addChild(_description);
// リマソンを描く
_limacon = new Sprite();
_limacon.graphics.clear();
_limacon.graphics.lineStyle(1,0x808080);
_limacon.graphics.moveTo(-0.5*_limaScale,0);
_limacon.graphics.lineTo( 3.5*_limaScale,0);
_limacon.graphics.drawCircle(_limaScale,0,_limaScale);
_limacon.graphics.lineStyle(2,0x800000);
var i:int = 0;
for (i = 0; i <= 90; ++i) {
var t:Number = Math.PI/45*i;
var px:Number = 1+Math.cos(t)+Math.cos(2*t);
var py:Number = Math.sin(t)+Math.sin(2*t);
if ( i == 0 ) {
_limacon.graphics.moveTo(px*_limaScale,py*(-_limaScale));
} else {
_limacon.graphics.lineTo(px*_limaScale,py*(-_limaScale));
}
}
_limacon.x = _W/5;
_limacon.y = _H/2;
addChild(_limacon);
_solution = new Sprite();
_solution.x = _limacon.x;
_solution.y = _limacon.y;
_solution.graphics.clear();
_P = new LabeledPoint(3*_limaScale,0);
_P.labelText.text = "P";
_P.showLabel();
_P.labelDx = 15;
_P.labelDy = -8;
_Q = new LabeledPoint(2*_limaScale,0);
_Q.labelText.text = "Q";
_Q.showLabel();
_Q.labelDx = -15;
_Q.labelDy = -8;
_R = new LabeledPoint(2.5*_limaScale,0);
_R.labelText.text = "R";
_R.showLabel();
_R.labelDx = 5;
_R.labelDy = 8;
_R.dotSize = 0;
_O = new LabeledPoint(0,0);
_O.labelText.text = "O";
_O.labelText.visible = true;
_C = new LabeledPoint(_limaScale,0);
_C.labelText.text = "C";
_C.labelText.visible = true;
_X = new LabeledPoint(3.2*_limaScale,0);
_X.labelText.text = "X";
_X.labelDx = 18;
_X.dotSize = 0;
_X.labelText.visible = true;
_theta = 0;
// 最初は説明を一切表示しない
_descriptionLevel = 0;
_Q.visible = false;
_R.visible = false;
_solution.addChild(_O);
_solution.addChild(_C);
_solution.addChild(_P);
_solution.addChild(_Q);
_solution.addChild(_R);
_solution.addChild(_X);
drawSolution();
addChild(_solution);
_time = 0;
stage.addEventListener(Event.ENTER_FRAME, inEveryFrame);
stage.addEventListener(MouseEvent.CLICK, whenYouClickMe);
}
private function inEveryFrame(e:Event):void {
if (( _descriptionLevel >= 2 )&&(Math.abs(_theta-Math.PI/4)<0.01)) { return; }
drawSolution();
_theta = Math.PI/4*(1-Math.cos(_time*Math.PI*2));
_time += 1/180;
while (_time >= 1) { _time -= 1; }
}
private function whenYouClickMe(e:Event):void {
_descriptionLevel = (++_descriptionLevel)%3;
switch ( _descriptionLevel ) {
case 0:
_Q.visible = false;
_R.visible = false;
_limacon.scaleX = 1.0;
_limacon.scaleY = 1.0;
_solution.scaleX = _limacon.scaleX;
_solution.scaleY = _limacon.scaleY;
_limacon.x = _W/5;
_limacon.y = _H/2;
_solution.x = _limacon.x;
_solution.y = _limacon.y;
_description.visible = false;
break;
case 1:
_Q.visible = true;
_R.visible = true;
_limacon.scaleX = 1.0;
_limacon.scaleY = 1.0;
_solution.scaleX = _limacon.scaleX;
_solution.scaleY = _limacon.scaleY;
_limacon.x = _W/5;
_limacon.y = _H/2;
_solution.x = _limacon.x;
_solution.y = _limacon.y;
_description.visible = false;
break;
case 2:
_Q.visible = true;
_R.visible = true;
_limacon.scaleX = 0.667;
_limacon.scaleY = 0.667;
_solution.scaleX = _limacon.scaleX;
_solution.scaleY = _limacon.scaleY;
_limacon.x = _W/2;
_limacon.y = _H/3*2;
_solution.x = _limacon.x;
_solution.y = _limacon.y;
_description.visible = true;
break;
}
drawSolution();
}
private function drawSolution():void {
// put Labeled Point P
_P.x = _limaScale*(1 + Math.cos(_theta*2/3) + Math.cos(_theta*4/3));
_P.y = -_limaScale*(Math.sin(_theta*2/3) + Math.sin(_theta*4/3));
// put Labeled Point P
_Q.x = _limaScale*(1 + Math.cos(_theta*4/3));
_Q.y = -_limaScale*(Math.sin(_theta*4/3));
// put Labeled Point P
_R.x = _limaScale*(1 + 1.5*Math.cos(_theta*2/3));
_R.y = -_limaScale*(1.5*Math.sin(_theta*2/3));
// connect P and O by line
_solution.graphics.clear();
_solution.graphics.lineStyle(2,0xff0000);
_solution.graphics.moveTo(_O.x,_O.y);
_solution.graphics.lineTo(_P.x,_P.y);
// connect P and C by line
_solution.graphics.lineStyle(2,0x0000ff);
_solution.graphics.moveTo(_C.x,_C.y);
_solution.graphics.lineTo(_P.x,_P.y);
if ( _Q.visible ) {
// connect Q and C by line
_solution.graphics.lineStyle(1,0x666666);
_solution.graphics.moveTo(_Q.x,_Q.y);
_solution.graphics.lineTo(_C.x,_C.y);
// connect R and C by line
_solution.graphics.moveTo(_R.x,_R.y);
_solution.graphics.lineTo(_C.x,_C.y);
}
_X.redraw();
_C.redraw();
_O.redraw();
_P.redraw();
if ( _Q.visible ) {
_Q.redraw();
_R.redraw();
}
}
}
}
import flash.display.Sprite;
import flash.text.*;
// 図の上の点を表わすドットと点に名前をつけるラベルをスプライト化したクラス
class LabeledPoint extends Sprite {
public var labelText:TextField;
public var labelFormat:TextFormat;
public var labelDx:Number; // ラベルの横位置
public var labelDy:Number; // ラベルの縦位置
public var dotSize:Number;
public var dotColor:uint;
public function LabeledPoint(_x:Number,_y:Number) {
this.x = _x;
this.y = _y;
labelFormat = new TextFormat();
labelFormat.align = TextFormatAlign.CENTER;
labelFormat.size = 14;
labelText = new TextField();
labelText.defaultTextFormat = labelFormat;
labelText.visible = false;
labelText.type = "dynamic";
labelText.selectable = false;
labelText.multiline = false;
labelDx = -15;
labelDy = -8;
labelText.width = 16;
labelText.height = 16;
dotSize = 3.0;
dotColor = 0x000000;
addChild(labelText);
redraw();
}
public function redraw():void {
labelText.x = labelDx - labelText.width/2;
labelText.y = labelDy - labelText.height/2;
this.graphics.clear();
if ( dotSize > 0 ) {
this.graphics.beginFill(dotColor);
this.graphics.drawCircle(0,0,dotSize);
this.graphics.endFill();
}
}
public function showLabel():void {
labelText.visible = true;
}
public function hideLabel():void {
labelText.visible = false;
}
}