垂線

by keno42
♥2 | Line 89 | Modified 2010-02-06 14:25:58 | MIT License
play

ActionScript3 source code

/**
 * Copyright keno42 ( http://wonderfl.net/user/keno42 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/dHVI
 */

package {
    import flash.display.Sprite;
    import flash.geom.Point;
    import flash.events.Event;
    public class FlashTest extends Sprite {
        // ドラッグ移動できる点の宣言
        private var mpA:MovablePoint = new MovablePoint(3, 0xFFFF0000, true);
        private var mpB:MovablePoint = new MovablePoint(3, 0xFFFF0000, true);
        private var mpC:MovablePoint = new MovablePoint(3, 0xFF00FF00, true);
        private var result:MovablePoint = new MovablePoint(3, 0xFF0000FF, false);
        // コンストラクタ
        public function FlashTest() {
            // write as3 code here..
            // 適当に初期条件
            mpA.x = 200;
            mpA.y = 200;
            addChild(mpA);
            mpB.x = 350;
            mpB.y = 320;
            addChild(mpB);
            mpC.x = 210;
            mpC.y = 320;
            addChild(mpC);
            addChild(result);
            // 点のドラッグ開始と終了をイベント登録
            this.addEventListener("startRefresh", onStartRefresh, true);
            this.addEventListener("stopRefresh", onStopRefresh, true);
            // 画面描画
            _refresh();
        }
        // 点のドラッグ開始で画面描画を開始
        private function onStartRefresh(e:Event):void{
            this.addEventListener(Event.ENTER_FRAME, _onEnter);
        }
        // 点のドラッグ終了で画面描画を停止
        private function onStopRefresh(e:Event):void{
            this.removeEventListener(Event.ENTER_FRAME, _onEnter);
            _refresh();
        }
        // 毎フレーム画面描画
        private function _onEnter(e:Event):void{
            _refresh();
        }
        // 画面描画メソッド
        private function _refresh():void{
            this.graphics.clear();
            this.graphics.lineStyle(0, 0x0);
            // もろもろ計算用のPoint ぴったり重なったときのゼロ除算を避けるためにちょっとだけ加算
            var tempPoint:Point = new Point(mpB.x + 0.0001,mpB.y + 0.0001);
            // 垂点座標の計算
            var p:Point = _calc(mpA.x, mpA.y, tempPoint.x, tempPoint.y, mpC.x-0.0001, mpC.y-0.0001);
            var A:Point = new Point(mpA.x, mpA.y);
            tempPoint = tempPoint.subtract(A);
            tempPoint.normalize(465); // ABの長さを465に伸ばしたベクトル
            // 直線描画
            this.graphics.moveTo(A.x+tempPoint.x, A.y+tempPoint.y);
            this.graphics.lineTo(A.x-tempPoint.x, A.y-tempPoint.y);
            this.graphics.lineStyle(0, 0x0000FF);
            // 垂線描画
            this.graphics.moveTo(mpC.x, mpC.y);
            this.graphics.lineTo(p.x, p.y);
            // 垂点の表示位置を更新
            result.x = p.x;
            result.y = p.y;
        }
        // 垂点座標計算メソッド
        private function _calc(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+上の射影が垂点の位置
        }
    }
}

import flash.display.*;
import flash.events.*;
// ドラッグで移動する点
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);
    }
}

Forked