In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

平行四辺形に内接する楕円の作図

赤と青の大きい点はドラッグ可能です
平行四辺形に内接する楕円を作図します
出展: 数学100の勝利 43
Get Adobe Flash player
by keno42 06 Feb 2010
/**
 * Copyright keno42 ( http://wonderfl.net/user/keno42 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/lzsu
 */

package  
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Point;
        // 赤と青の大きい点はドラッグ可能です
        // 平行四辺形に内接する楕円を作図します
        // 出展: 数学100の勝利 43
	public class Heikou_Daen extends Sprite
	{
		private var mpA:MovablePoint = new MovablePoint(4, 0xFFFF0000, true);
		private var mpB:MovablePoint = new MovablePoint(4, 0xFFFF0000, true);
		private var mpC:MovablePoint = new MovablePoint(4, 0xFFFF8888, false);
		private var mpD:MovablePoint = new MovablePoint(4, 0xFFFF0000, true);
		private var mpN:MovablePoint = new MovablePoint(4, 0xFF0000FF, true);
		
		// 弧(1/4)の分割数
		private const NUM:int = 20;
		public function Heikou_Daen() 
		{
			mpA.x = 70;
			mpA.y = 370;
			addChild(mpA);
			mpB.x = 380;
			mpB.y = 310;
			addChild(mpB);
			addChild(mpC);
			mpD.x = 80;
			mpD.y = 130;
			addChild(mpD);
			mpN.x = 300;
			mpN.y = 300;
			addChild(mpN);
			this.addEventListener("startRefresh", onStartRefresh, true);
			this.addEventListener("stopRefresh", onStopRefresh, true);
			_refresh();
		}
		
		private function onStopRefresh(e:Event):void 
		{
			removeEventListener(Event.ENTER_FRAME, onEnterFrame);
			_refresh();
		}
		
		private function onStartRefresh(e:Event):void 
		{
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		private function onEnterFrame(e:Event):void 
		{
			_refresh();
		}
		
		private function _refresh():void
		{
			// CをAB+ADに移動
			mpC.x = mpB.x + mpD.x - mpA.x;
			mpC.y = mpB.y + mpD.y - mpA.y;
			
			// Nを垂点に移動
			var nLoc:Point = GeomUtil.getSuiten(mpA.x, mpA.y, mpB.x, mpB.y, mpN.x, mpN.y);
			
			var nCase:int = 0;
			if ( nLoc.x > mpA.x && nLoc.x > mpB.x )
				nCase = 1;
			else if ( nLoc.x < mpA.x && nLoc.x < mpB.x )
				nCase = 2;
			if ( mpA.x > mpB.x ) nCase |= 4;
			
			switch( nCase ) {
				case 5:
				case 2:
					nLoc = GeomUtil.getNaibunten(mpA.x, mpA.y, mpB.x, mpB.y, 0.0001);
					break;
				case 1:
				case 6:
					nLoc = GeomUtil.getNaibunten(mpA.x, mpA.y, mpB.x, mpB.y, 0.9999);
					break;
			}
			
			mpN.x = nLoc.x;
			mpN.y = nLoc.y;
			
			// 描画
			graphics.clear();
			graphics.lineStyle(2, 0x0);
			graphics.moveTo(mpA.x, mpA.y);
			graphics.lineTo(mpB.x, mpB.y);
			graphics.lineTo(mpC.x, mpC.y);
			graphics.lineTo(mpD.x, mpD.y);
			graphics.lineTo(mpA.x, mpA.y);
			
			// 接点の計算
			var temp:Point = new Point(mpC.x - mpA.x, mpC.y - mpA.y);
			var K:Point = GeomUtil.getKoten(mpN.x, mpN.y, mpN.x + temp.x, mpN.y + temp.y, mpB.x, mpB.y, mpC.x, mpC.y);
			var temp2:Point = new Point(mpD.x - mpB.x, mpD.y - mpB.y);
			var H:Point = GeomUtil.getKoten(mpN.x, mpN.y, mpN.x + temp2.x, mpN.y + temp2.y, mpA.x, mpA.y, mpD.x, mpD.y);
			var M:Point = new Point(K.x + H.x - mpN.x, K.y + H.y - mpN.y);
			
			// 中央の計算
			var O:Point = GeomUtil.getChuten(mpA.x, mpA.y, mpC.x, mpC.y);
			
			// 弧上の点の計算
			var i:int, s:Number, p:Point;
			var points:Array = [];
			// N-OK x M-CK
			for ( i = 0; i < NUM; i++ ) {
				s = i / NUM;
				var OKs:Point = GeomUtil.getNaibunten(O.x, O.y, K.x, K.y, s);
				var CKs:Point = GeomUtil.getNaibunten(mpC.x, mpC.y, K.x, K.y, s);
				p = GeomUtil.getKoten( mpN.x, mpN.y, OKs.x, OKs.y, M.x, M.y, CKs.x, CKs.y );
				points.push(p);
			}
			// M-KO x N-KB
			for ( i = 0; i < NUM; i++ ) {
				s = i / NUM;
				var KOs:Point = GeomUtil.getNaibunten(K.x, K.y, O.x, O.y, s);
				var KBs:Point = GeomUtil.getNaibunten(K.x, K.y, mpB.x, mpB.y, s);
				p = GeomUtil.getKoten( M.x, M.y, KOs.x, KOs.y, mpN.x, mpN.y , KBs.x, KBs.y);
				points.push(p);
			}
			for ( i = 0; i < 2*NUM; i++ ) {
				points.push(new Point(2 * O.x - points[i].x, 2 * O.y - points[i].y));
			}
			points.push( M );
			graphics.lineStyle(0, 0x00FF00);
			graphics.moveTo(M.x, M.y);
			var len:int = points.length;
			for ( i = 0; i < len; i++ ) {
				graphics.lineTo(points[i].x, points[i].y);
			}
			graphics.lineStyle(0, 0x0000FF);
			for ( i = 0; i < len; i++ ) {
				graphics.drawCircle(points[i].x, points[i].y, 2);
			}
			
		}
		
		
	}
	
}

import flash.display.*;
import flash.events.*;
import flash.geom.Matrix;
// ドラッグで移動する点
class MovablePoint extends Sprite{
    public function MovablePoint(radius:Number, color:uint, isMovable:Boolean){
        this.graphics.lineStyle(1, color);
        this.graphics.beginFill(color & 0xFFFFFF, 0.75);
        this.graphics.drawCircle(0, 0, radius);
        
        if( isMovable ){
            this.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
            this.buttonMode = true;
        }
    }
    private function onDown(e:MouseEvent):void{
        this.startDrag();
        this.dispatchEvent(new Event("startRefresh"));
        this.addEventListener(MouseEvent.MOUSE_UP, onUp);
        this.stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
    }
    private function onUp(e:MouseEvent):void{
        this.stopDrag();
        this.dispatchEvent(new Event("stopRefresh"));
        this.removeEventListener(MouseEvent.MOUSE_UP, onUp);
        this.stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
    }
}

import flash.geom.Point;
class GeomUtil {
	// 垂点座標計算メソッド
	public static function getSuiten(Ax:Number, Ay:Number, Bx:Number, By:Number, Cx:Number, Cy:Number):Point{
		var A:Point = new Point(Ax, Ay); // 直線上の点A
		var B:Point = new Point(Bx, By); // 直線上の点B
		var C:Point = new Point(Cx, Cy); // 直線外の点C
		var AB:Point = B.subtract(A); // ベクトルAB
		var unitAB:Point = AB.clone(); // ABの単位ベクトル
		unitAB.normalize(1);
		var AC:Point = C.subtract(A); // ベクトルAC
		
		// ACのAB方向の成分を取得
		var unitABxAC:Number = unitAB.x*AC.x+unitAB.y*AC.y;
		
		// ACのAB軸への射影を計算
		var ret:Point = new Point(unitAB.x*unitABxAC, unitAB.y*unitABxAC);
		return ret.add(A); // A+上の射影が垂点の位置
	}
	// 直線ABと直線CDの交点座標計算メソッド
	public static function getKoten(Ax:Number, Ay:Number, Bx:Number, By:Number, Cx:Number, Cy:Number, Dx:Number, Dy:Number):Point {
		var mat:Matrix = new Matrix(By - Ay, Dy - Cy, Ax - Bx, Cx - Dx);
		var XY:Point = mat.transformPoint(new Point(Cx - Ax, Cy - Ay));
		var abcd:Number = mat.a * mat.d - mat.b * mat.c;
		XY.x /= abcd;
		return new Point(Cx + XY.x * (Dx - Cx), Cy + XY.x * (Dy - Cy));
	}
	// 線分ABの中点座標計算メソッド
	public static function getChuten(Ax:Number, Ay:Number, Bx:Number, By:Number):Point {
		return new Point(Ax + 0.5 * (Bx - Ax), Ay + 0.5 * (By - Ay));
	}
	// 線分ABをs:1-sに内分する点の座標計算メソッド
	public static function getNaibunten(Ax:Number, Ay:Number, Bx:Number, By:Number, s:Number):Point {
		return new Point(Ax + s * (Bx - Ax), Ay + s * (By - Ay));
	}
}