Line -> LineSegment

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4707 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Nathan Curtis
2007-05-10 22:00:24 +00:00
parent 96dd2deba3
commit 01b43deb6e
+135
View File
@@ -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;
}
}
}