Line -> LineSegment
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4707 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.util {
|
||||
|
||||
import flash.geom.Point;
|
||||
import flash.geom.Matrix;
|
||||
|
||||
/**
|
||||
* Merely a typed container for two Points.
|
||||
*/
|
||||
public class LineSegment implements Equalable
|
||||
{
|
||||
public static const INTERSECTION_NORTH :int = 1;
|
||||
public static const INTERSECTION_SOUTH :int = 2;
|
||||
public static const DOES_NOT_INTERSECT :int = 3;
|
||||
|
||||
public var start :Point;
|
||||
public var stop :Point;
|
||||
|
||||
public function LineSegment (start :Point, stop :Point)
|
||||
{
|
||||
this.start = start;
|
||||
this.stop = stop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of this line.
|
||||
*/
|
||||
public function getLength () :Number
|
||||
{
|
||||
return Point.distance(start, stop);
|
||||
}
|
||||
|
||||
public function isIntersected (line :LineSegment) :Boolean
|
||||
{
|
||||
return getIntersectionType(line) != DOES_NOT_INTERSECT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the point at which the other line intersects us.
|
||||
*/
|
||||
public function getIntersectionPoint (line :LineSegment) :Point
|
||||
{
|
||||
return getIntersection(line, true) as Point;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the given line intersects this line. This method rotates both lines so that the
|
||||
* start point of this line is on the left, at (0, 0). If the lines do intersect, it then
|
||||
* returns INTERSECTION_NORTH if the end point of <code>line</code> is north of this line,
|
||||
* INTERSECTION_SOUTH otherwise.
|
||||
*
|
||||
* Intersections are inclusive. If one or both points lands on this line, interects will not
|
||||
* return DOES_NOT_INTERSECT.
|
||||
*/
|
||||
public function getIntersectionType (line :LineSegment) :int
|
||||
{
|
||||
return getIntersection(line, false) as int;
|
||||
}
|
||||
|
||||
// from interface Equalable
|
||||
public function equals (o :Object) :Boolean
|
||||
{
|
||||
var other :LineSegment = o as LineSegment; // or null if not a line
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// both end points must be the same, in the same order
|
||||
return start.equals(other.start) && stop.equals(other.stop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method that calculates whether the other line intersects
|
||||
* and returns either the intersected point or merely the intersection
|
||||
* type.
|
||||
*/
|
||||
protected function getIntersection (line :LineSegment, returnPoint :Boolean) :*
|
||||
{
|
||||
// rotate so that this line is horizontal, with the start on the left, at (0, 0)
|
||||
var trans :Matrix = new Matrix();
|
||||
trans.translate(-start.x, -start.y);
|
||||
trans.rotate(-Math.atan2(stop.y - start.y, stop.x - start.x));
|
||||
var thisLineStop :Point = trans.transformPoint(stop);
|
||||
var thatLineStart :Point = trans.transformPoint(line.start);
|
||||
var thatLineStop :Point = trans.transformPoint(line.stop);
|
||||
var interp :Point;
|
||||
var type :int;
|
||||
|
||||
if (thatLineStart.y >= 0 && thatLineStop.y <= 0) {
|
||||
interp = Point.interpolate(thatLineStart, thatLineStop, thatLineStop.y /
|
||||
(thatLineStop.y + (-thatLineStart.y)));
|
||||
type = INTERSECTION_NORTH;
|
||||
|
||||
} else if (thatLineStart.y <= 0 && thatLineStop.y >= 0) {
|
||||
interp = Point.interpolate(thatLineStop, thatLineStart, thatLineStart.y /
|
||||
(thatLineStart.y + (-thatLineStop.y)));
|
||||
type = INTERSECTION_SOUTH;
|
||||
}
|
||||
|
||||
// see if we have a potential hit...
|
||||
if (interp != null && interp.x >= 0 && interp.x <= thisLineStop.x) {
|
||||
if (returnPoint) {
|
||||
// transform the intersection point back into "real" coordinates
|
||||
trans.invert();
|
||||
return trans.transformPoint(interp);
|
||||
|
||||
} else {
|
||||
return type
|
||||
}
|
||||
}
|
||||
|
||||
return returnPoint ? null : DOES_NOT_INTERSECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user