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

distancePointSegment

点と線分の距離。
Get Adobe Flash player
by medadotter 20 Jun 2012
/**
 * Copyright medadotter ( http://wonderfl.net/user/medadotter )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/8WCs
 */

package
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    
    /**
     * ...
     * @author DT
     */
    [SWF(width="465",height="465")]
    public class distancePointSegment extends Sprite
    {
        private var counter:int = 0;
        
        public function distancePointSegment()
        {
            //stage.addEventListener(MouseEvent.CLICK, testStar);
            addEventListener(Event.ENTER_FRAME, testPointSegmentDistance);
        }
        
        private function testPointSegmentDistance(event:Event):void {
            var mouse:Point = new Point(mouseX, mouseY);
            var begin:Point = new Point(stage.stageWidth / 2 - 100, stage.stageHeight / 2 - 50);
            var end:Point = new Point(stage.stageWidth / 2 + 100, stage.stageHeight / 2 + 50);
            var segment:Segment = new Segment(begin, end);
            var dVekt:Point = segment.distanceVektor(mouse);
            var dSegment:Segment = new Segment(mouse, new Point(mouse.x + dVekt.x, mouse.y + dVekt.y));
            graphics.clear();
            graphics.lineStyle(0);
            mouse.draw(graphics);
            segment.draw(graphics);
            graphics.lineStyle(0, 0xff0000);
            dSegment.draw(graphics);
            trace(dVekt.norm - segment.distance(mouse));//誤差はe12のオーダなのでまず問題はない。
        }
        
        private function testStarIntersect(event:Event):void {
            var star1:Star = new Star(new Point(stage.stageWidth / 2 - 30, stage.stageHeight / 2), 2.5 * counter, 40);
            var star2:Star = new Star(new Point(stage.stageWidth / 2 + 30, stage.stageHeight / 2), 0, 40);
            ++counter;
            Star.intersect(star1, star2) ? graphics.lineStyle(0, 0xff0000) : graphics.lineStyle(0);
            trace( Star.intersect(star1, star2) );
            graphics.clear();
            star1.draw(graphics);
            star2.draw(graphics);            
        }
        
        private function testIntersect(event:MouseEvent):void {
            
            var seg1:Segment = makeSegment();
            var seg2:Segment = makeSegment();
            graphics.clear();
            if (Segment.intersect(seg1, seg2)) {
                graphics.lineStyle(0, 0xff0000);
            }
            else {
                graphics.lineStyle(0);
            }
            
            seg1.draw(graphics);
            seg2.draw(graphics);
        }

        
        private function makeSegment():Segment {
            var begin:Point = new Point(Math.random() * stage.stageWidth,
                                        Math.random() * stage.stageHeight);
            var end:Point   = new Point(Math.random() * stage.stageWidth,
                                        Math.random() * stage.stageHeight);
            var segment:Segment = new Segment(begin, end);
            return segment;
        }
        
    
    }


}
import flash.display.Graphics;

class Point
{
    private var _x:Number;
    private var _y:Number;
    
    public function Point(x:Number = 0, y:Number = 0)
    {
        this.x = x;
        this.y = y;
    }
    
    /** 
     * ccw:counter clockwise 反時計回り(ただしX軸からY軸への方向を反時計回りのデフォルトとしている)。
     * 三点が同一直線上にない場合:
     *         反時計回り:+1
     *         時計回り  :-1
     * 三点が同一直線上にある場合:
     *         aがbとcの間にあれば:-1
     *         bがcとaの間にあれば:+1
     *         cがaとbの間にあれば:0
     * 参考:sedgwickの本。
     */
    static public function ccwSed(a:Point, b:Point, c:Point):int {
        var ab:Point = new Point(b.x - a.x, b.y - a.y);
        var ac:Point = new Point(c.x - a.x, c.y - a.y);
        //傾きの比較ないしは外積。
        if (ab.x * ac.y > ab.y * ac.x) return +1;
        if (ab.x * ac.y < ab.y * ac.x) return -1;
        //以下、三点は同一直線上にある。
        if ((ab.x * ac.x < 0) || (ab.y * ac.y < 0)) return -1;//abとacは逆方向。
        if ((ab.x * ab.x + ab.y * ab.y) < (ac.x * ac.x + ac.y * ac.y)) return -1;//abとacが同方向でabよりacの方が短い。
        return 0;
    }
    
    /**
     * 上記のccwSedを幾何演算で可読的に書き直したもの。
     * 参考:http://www.prefield.com/algorithm/geometry/ccw.html
     */
    static public function ccw(a:Point, b:Point, c:Point):int {
        var ab:Point = new Point(b.x - a.x, b.y - a.y);
        var ac:Point = new Point(c.x - a.x, c.y - a.y);
        //外積。crossをキャッシュするのは僅かな効率のために可読性を犠牲にする。
        if (cross(ab,ac) > 0) return +1;
        if (cross(ab,ac) < 0) return -1;
        //以下、三点は同一直線上にある。
        if (dot(ab,ac) < 0) return -1;//abとacは逆方向。
        if (ab.normSQ < ac.normSQ) return -1;//abとacが同方向でabよりacの方が短い。
        return 0;
    }
    
    static public function dot(lhs:Point, rhs:Point):Number {
        return lhs.x * rhs.x + lhs.y * rhs.y;
    }
    
    static public function cross(lhs:Point, rhs:Point):Number {
        return lhs.x * rhs.y - lhs.y * rhs.x;        
    }
    
    public function get normSQ():Number {
        return x * x + y * y;
    }
    
    public function get norm():Number {
        return Math.sqrt(normSQ);
    }
    
    public function draw(graphics:Graphics):void {
        graphics.drawCircle(x, y, 1);
    }
    
    public function get x():Number {
        return _x;
    }
    
    public function set x(value:Number):void {
        _x = value;
    }
    
    public function get y():Number {
        return _y;
    }
    
    public function set y(value:Number):void {
        _y = value;
    }
}

class Segment
{
    private var _begin:Point;
    private var _end:Point;
    
    public function Segment(begin:Point, end:Point)
    {
        this.begin = begin;
        this.end = end;
    }
    
    public function draw(graphics:Graphics):void {
        graphics.drawCircle(begin.x, begin.y, 4);
        graphics.moveTo(begin.x, begin.y);
        graphics.lineTo(end.x, end.y);
    }
    
    /**
     * 二線分のそれぞれに対して、一方の線分の両端点がもう一方の線分の異なる側にあれば(Point.ccwによって判定)両線文は交差する。
     * @param    seg1
     * @param    seg2
     * @return  Boolean 交差していればtrue、していなければfalse
     */
    static public function intersect(seg1:Segment, seg2:Segment):Boolean {
        return ((Point.ccw(seg1.begin, seg1.end, seg2.begin)
                *Point.ccw(seg1.begin, seg1.end, seg2.end)) <= 0)
            && ((Point.ccw(seg2.begin, seg2.end, seg1.begin)
                *Point.ccw(seg2.begin, seg2.end, seg1.end)) <= 0);
    }
    
    public function distanceVektor(point:Point):Point {
        var AB:Point = new Point(end.x - begin.x,end.y - begin.y);
        var CA:Point = new Point(begin.x - point.x, begin.y - point.y);
        var CB:Point = new Point(end.x - point.x, end.y -point.y);
        if (Point.dot(AB, CA) > 0) return CA;
        if (Point.dot(AB, CB) < 0) return CB;
        var project:Number = -Point.dot(AB, CA) / AB.normSQ;
        var CH:Point = new Point(CA.x + project * AB.x, CA.y + project * AB.y);
        return CH;
    }
    public function distance(point:Point):Number {
        var AB:Point = new Point(end.x - begin.x,end.y - begin.y);
        var CA:Point = new Point(begin.x - point.x, begin.y - point.y);
        var CB:Point = new Point(end.x - point.x, end.y -point.y);
        if (Point.dot(AB, CA) > 0) return CA.norm;
        if (Point.dot(AB, CB) < 0) return CB.norm;
        return Math.abs(Point.cross(AB,CA)/AB.norm);
    }
    
    public function get begin():Point {
        return _begin;
    }
    
    public function set begin(value:Point):void {
        _begin = value;
    }
    
    public function get end():Point {
        return _end;
    }
    
    public function set end(value:Point):void {
        _end = value;
    }
}

class Star {
    private var center:Point;
    private var points:Vector.<Point> = new Vector.<Point>();
    private var segments:Vector.<Segment> = new Vector.<Segment>();
    
    public function Star(center:Point, degree:int, radius:Number):void {
        this.center = center;
        makePoints(degree, radius);
        makeSegments();
    }
    
    private function makeSegments():void {
        for (var i:int = 0; i < 5; i++) {
            var segment:Segment = new Segment(points[i], points[(i + 2) % 5]);
            segments.push(segment);
        }
        
    }
    
    public function draw(graphics:Graphics):void {
        //drawPoints(graphics);
        drawSegments(graphics);

    }
    
    static public function intersect(star1:Star, star2:Star):Boolean {
        for (var i:int = 0; i < 5; i++) {
            for (var j:int = i; j < 5; j++) {
                if ( Segment.intersect(star1.segments[i], star2.segments[j]) ) return true;
            }
        }
        return false;
    }
    
    private function makePoints(degree:int, radius:Number):void {
        for (var i:int = 0; i < 5; i++) {
            var angle:Number = (degree + 90 + 72 * i) / 180 * Math.PI;
            var point:Point = new Point(center.x + radius * Math.cos(angle),
                                        center.y + radius * Math.sin(angle));
            points.push(point);
        }
    }
    
    private function drawPoints(graphics:Graphics):void {
        for each (var point:Point in points) {
            point.draw(graphics);
        }
    }
    
    private function drawSegments(graphics:Graphics):void {
        for each (var segment:Segment in segments) {
            segment.draw(graphics);
        }
    }
}