API Docs for: 1.1.0
Show:

File: src\geom\Intersect.ts

/**
*  
* @module Kiwi
* @submodule Geom
*/ 

module Kiwi.Geom {

    /**
    * Contains a collection of STATIC methods to help determine and return intersection between geometric objects.
    *
    * @class Intersect
    * @namespace Kiwi.Geom
    * @static
    */
    export class Intersect {

        /**
        * The type of this object.
        * @method objType
        * @return {String}
        * @public
        */
        public objType() {
            return "Intersect";
        }

        /**
	    * -------------------------------------------------------------------------------------------
	    * Distance
	    * -------------------------------------------------------------------------------------------
	    **/

        /** 
	    * Returns the distance between two sets of coordinates that you specify. 
	    * @method distance
        * @param x1 {Number} The x position of the first coordinate.
        * @param y1 {Number} The y position of the first coordinate.
        * @param x2 {Number} The x position of the second coordinate.
        * @param y2 {Number} The y position of the second coordinate.
        * @return {Number} The distance between the two points.
        * @public
        * @static
	    **/
        static distance(x1: number, y1: number, x2: number, y2: number) {
            return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
        }

        /** 
	    * Returns the distance squared between two sets of coordinates that you specify. 
	    * @method distanceSquared
        * @param x1 {Number} The x position of the first coordinate.
        * @param y1 {Number} The y position of the first coordinate.
        * @param x2 {Number} The x position of the second coordinate.
        * @param y2 {Number} The y position of the second coordinate.
        * @return {Number} The distance between the two points squared.
        * @public
        * @static
	    */
        static distanceSquared(x1: number, y1: number, x2: number, y2: number) {
            return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
        }

        /**
	    * -------------------------------------------------------------------------------------------
	    * Lines
	    * -------------------------------------------------------------------------------------------
	    **/

        /**
	    * Check to see if any two Lines intersect at any point. 
        * Both lines are treated as if they extend infintely through space.
	    * @method lineToLine
	    * @param line1 {Line} The first line object to check
	    * @param line2 {Line} The second line object to check
	    * @param [output=IntersectResult] {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in. (One is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection in x/y
        * @public
        * @static
	    */
        static lineToLine(line1: Line, line2: Line, output: IntersectResult = new IntersectResult): IntersectResult {

            var denom = (line1.x1 - line1.x2) * (line2.y1 - line2.y2) - (line1.y1 - line1.y2) * (line2.x1 - line2.x2);

            if (denom !== 0)
            {
                output.result = true;
                output.x = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (line2.x1 - line2.x2) - (line1.x1 - line1.x2) * (line2.x1 * line2.y2 - line2.y1 * line2.x2)) / denom;
                output.y = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (line2.y1 - line2.y2) - (line1.y1 - line1.y2) * (line2.x1 * line2.y2 - line2.y1 * line2.x2)) / denom;
            }

            return output;
        }

        /**
	    * Check to see if a Line and a Line Segment intersect at any point. 
        * Note: The first line passed is treated as if it extends infinately though space, 
        * The second is treated as if it only exists between its two points.
	    * @method lineToLineSegment
	    * @param line1 {Kiwi.Geom.Line} The first line to check. This is the one that will extend through space infinately.
	    * @param seg {Kiwi.Geom.Line} The second line to check. This is the one that will only exist between its two coordinates.
	    * @param [output=IntersectResult] {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection.
        * @public
        * @static
	    */
        static lineToLineSegment(line1: Line, seg: Line, output: IntersectResult = new IntersectResult): IntersectResult {

            var denom = (line1.x1 - line1.x2) * (seg.y1 - seg.y2) - (line1.y1 - line1.y2) * (seg.x1 - seg.x2);

            if (denom !== 0)
            {
                output.x = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (seg.x1 - seg.x2) - (line1.x1 - line1.x2) * (seg.x1 * seg.y2 - seg.y1 * seg.x2)) / denom;
                output.y = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (seg.y1 - seg.y2) - (line1.y1 - line1.y2) * (seg.x1 * seg.y2 - seg.y1 * seg.x2)) / denom;

                var maxX = Math.max(seg.x1, seg.x2);
                var minX = Math.min(seg.x1, seg.x2);
                var maxY = Math.max(seg.y1, seg.y2);
                var minY = Math.min(seg.y1, seg.y2);

                //if (!(output.x <= maxX && output.x >= minX) || !(output.y <= maxY && output.y >= minY))
                if ((output.x <= maxX && output.x >= minX) === true || (output.y <= maxY && output.y >= minY) === true)
                {
                    output.result = true;
                }

            }

            return output;

        }

        /**
	    * Checks to see if a Line that is passed, intersects at any point another Line that is made by passing a set of coordinates to this method. 
        * Note: The first line will extend infinately through space. 
        * And the second line will only exist between the two points passed.
	    * @method lineToRawSegment
	    * @param line {Kiwi.Geom.Line} The line object that extends infinatly through space.
	    * @param x1 {number} The x coordinate of the first point in the second line.
	    * @param y1 {number} The y coordinate of the first point in the second line.
	    * @param x2 {number} The x coordinate of the second point in the second line.
	    * @param y2 {number} The y coordinate of the second point in the second line.
	    * @param [output=IntersectResult] {IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {IntersectResult} An IntersectResult object containing the results of this intersection in x/y
	    * @static
        * @public
        */
        static lineToRawSegment(line: Line, x1: number, y1: number, x2: number, y2: number, output: IntersectResult = new IntersectResult): IntersectResult {

            var denom = (line.x1 - line.x2) * (y1 - y2) - (line.y1 - line.y2) * (x1 - x2);

            if (denom !== 0)
            {
                output.x = ((line.x1 * line.y2 - line.y1 * line.x2) * (x1 - x2) - (line.x1 - line.x2) * (x1 * y2 - y1 * x2)) / denom;
                output.y = ((line.x1 * line.y2 - line.y1 * line.x2) * (y1 - y2) - (line.y1 - line.y2) * (x1 * y2 - y1 * x2)) / denom;

                var maxX = Math.max(x1, x2);
                var minX = Math.min(x1, x2);
                var maxY = Math.max(y1, y2);
                var minY = Math.min(y1, y2);

                if ((output.x <= maxX && output.x >= minX) === true || (output.y <= maxY && output.y >= minY) === true)
                {
                    output.result = true;
                }

            }

            return output;

        }

        /**
	    * Checks to see if a Line and Ray object intersects at any point. 
        * Note: The line in this case extends infinately through space. 
	    * @method lineToRay
	    * @param line1 {Kiwi.Geom.Line} The Line object that extends infinatly through space.
	    * @param ray {Kiwi.Geom.Ray} The Ray object that you want to check it against.
	    * @param {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection in x/y
	    * @public
        * @static
        */
        static lineToRay(line1: Line, ray: Ray, output: IntersectResult = new IntersectResult): IntersectResult {

            var denom = (line1.x1 - line1.x2) * (ray.y1 - ray.y2) - (line1.y1 - line1.y2) * (ray.x1 - ray.x2);

            if (denom !== 0)
            {
                output.x = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (ray.x1 - ray.x2) - (line1.x1 - line1.x2) * (ray.x1 * ray.y2 - ray.y1 * ray.x2)) / denom;
                output.y = ((line1.x1 * line1.y2 - line1.y1 * line1.x2) * (ray.y1 - ray.y2) - (line1.y1 - line1.y2) * (ray.x1 * ray.y2 - ray.y1 * ray.x2)) / denom;
                output.result = true; // true unless either of the 2 following conditions are met

                if (!(ray.x1 >= ray.x2) && output.x < ray.x1)
                {
                    output.result = false;
                }

                if (!(ray.y1 >= ray.y2) && output.y < ray.y1)
                {
                    output.result = false;
                }
            }

            return output;

        }

        /**
	    * Checks to see if a Line and a Circle intersect at any point.
        * Note: The line passed is assumed to extend infinately through space. 
	    * @method lineToCircle
	    * @param line {Kiwi.Geom.Line} The Line object that you want to check it against.
	    * @param circle {Kiwi.Geom.Circle} The Circle object to check.
	    * @param [output=Intersect] {IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection
	    * @public
        * @static
        */
        static lineToCircle(line: Line, circle: Circle, output: IntersectResult = new IntersectResult): IntersectResult {

            //  Get a perpendicular line running to the center of the circle
            if (line.perp(circle.x, circle.y).length <= circle.radius)
            {
                output.result = true;
            }

            return output;

        }

        /**
	    * Check if the Line intersects with each side of a Rectangle.
        * Note: The Line is assumned to extend infinately through space.
	    * @method lineToRectangle
	    * @param line {Kiwi.Geom.Line} The Line object to check
	    * @param rectangle {Kiwi.Geom.Rectangle} The Rectangle object to check
	    * @param [output=IntersectResult] {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection
        * @public
        * @static
	    */
        static lineToRectangle(line: any, rect: Rectangle, output: IntersectResult = new IntersectResult): IntersectResult {

            //  Top of the Rectangle vs the Line
            Intersect.lineToRawSegment(line, rect.x, rect.y, rect.right, rect.y, output);

            if (output.result === true)
            {
                return output;
            }

            //  Left of the Rectangle vs the Line
            Intersect.lineToRawSegment(line, rect.x, rect.y, rect.x, rect.bottom, output);

            if (output.result === true)
            {
                return output;
            }

            //  Bottom of the Rectangle vs the Line
            Intersect.lineToRawSegment(line, rect.x, rect.bottom, rect.right, rect.bottom, output);

            if (output.result === true)
            {
                return output;
            }

            //  Right of the Rectangle vs the Line
            Intersect.lineToRawSegment(line, rect.right, rect.y, rect.right, rect.bottom, output);

            return output;

        }

        /**
	    * -------------------------------------------------------------------------------------------
	    * Line Segment
	    * -------------------------------------------------------------------------------------------
	    **/

        /**
	    * Checks to see if two Line Segments intersect at any point in space. 
        * Note: Both lines are treated as if they only exist between their two line coordinates.
	    * @method lineSegmentToLineSegment
	    * @param line1 {Kiwi.Geom.Line} The first line object to check.
	    * @param line2 {Kiwi.Geom.Line} The second line object to check.
	    * @param [output=IntersectResult]{Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection in x/y.
	    * @public
        * @static
        */
        static lineSegmentToLineSegment(line1: Line, line2: Line, output: IntersectResult = new IntersectResult): IntersectResult {

            Intersect.lineToLineSegment(line1, line2, output);

            if (output.result === true)
            {
                if (!(output.x >= Math.min(line1.x1, line1.x2) && output.x <= Math.max(line1.x1, line1.x2)
                    && output.y >= Math.min(line1.y1, line1.y2) && output.y <= Math.max(line1.y1, line1.y2)))
                {
                    output.result = false;
                }
            }

            return output;
        }

        /**
	    * Check if the Line Segment intersects with the Ray.
        * Note: The Line only exists between its two points.
	    * @method lineSegmentToRay
	    * @param line1 {Kiwi.Geom.Line} The Line object to check.
	    * @param ray {Kiwi.Geom.Line} The Ray object to check.
	    * @param [output=IntersectResult] {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection in x/y
        * @public
        * @static
	    */
        static lineSegmentToRay(line1: Line, ray: Ray, output: IntersectResult = new IntersectResult): IntersectResult {

            Intersect.lineToRay(line1, ray, output);

            if (output.result === true)
            {
                if (!(output.x >= Math.min(line1.x1, line1.x2) && output.x <= Math.max(line1.x1, line1.x2)
                    && output.y >= Math.min(line1.y1, line1.y2) && output.y <= Math.max(line1.y1, line1.y2)))
                {
                    output.result = false;
                }
            }

            return output;

        }

        /**
	    * Check if the Line Segment intersects with the Circle.
        * Note the Line only exists between its point points.
	    * @method lineSegmentToCircle
	    * @param seg {Kiwi.Geom.Line} The Line object to check
	    * @param circle {Kiwi.Geom.Circle} The Circle object to check
	    * @param [ouput=IntersectResult] {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection in x/y
        * @public
        * @static
	    */
        static lineSegmentToCircle(seg: Line, circle: Circle, output: IntersectResult = new IntersectResult): IntersectResult {

            var perp = seg.perp(circle.x, circle.y);

            if (perp.length <= circle.radius)
            {
                //  Line intersects circle - check if segment does
                var maxX = Math.max(seg.x1, seg.x2);
                var minX = Math.min(seg.x1, seg.x2);
                var maxY = Math.max(seg.y1, seg.y2);
                var minY = Math.min(seg.y1, seg.y2);

                if ((perp.x2 <= maxX && perp.x2 >= minX) && (perp.y2 <= maxY && perp.y2 >= minY))
                {
                    output.result = true;
                }
                else
                {
                    //  Worst case - segment doesn't traverse center, so no perpendicular connection.
                    if (Intersect.circleContainsPoint(circle, <Point> { x: seg.x1, y: seg.y1 }) || Intersect.circleContainsPoint(circle, <Point> { x: seg.x2, y: seg.y2 }))
                    {
                        output.result = true;
                    }
                }

            }

            return output;
        }

        /**
	    * Check if the Line Segment intersects with any side of a Rectangle.
        * Note: The Line only exists between its two points.
	    * @method lineSegmentToCircle
	    * @param seg {Kiwi.Geom.Line} The Line object to check.
	    * @param rect {Kiwi.Geom.Rectangle} The Rectangle object to check.
	    * @param [output=IntersectResult] {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given).
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection in x/y.
	    * @public
        * @static
        */ 
        static lineSegmentToRectangle(seg: Line, rect: Rectangle, output: IntersectResult = new IntersectResult): IntersectResult {

            if (rect.contains(seg.x1, seg.y1) && rect.contains(seg.x2, seg.y2))
            {
                output.result = true;
            }
            else
            {
                //  Top of the Rectangle vs the Line
                Intersect.lineToRawSegment(seg, rect.x, rect.y, rect.right, rect.bottom, output);

                if (output.result === true)
                {
                    return output;
                }

                //  Left of the Rectangle vs the Line
                Intersect.lineToRawSegment(seg, rect.x, rect.y, rect.x, rect.bottom, output);

                if (output.result === true)
                {
                    return output;
                }

                //  Bottom of the Rectangle vs the Line
                Intersect.lineToRawSegment(seg, rect.x, rect.bottom, rect.right, rect.bottom, output);

                if (output.result === true)
                {
                    return output;
                }

                //  Right of the Rectangle vs the Line
                Intersect.lineToRawSegment(seg, rect.right, rect.y, rect.right, rect.bottom, output);

                return output;

            }

            return output;

        }

        /**
	    * -------------------------------------------------------------------------------------------
	    * Ray
	    * -------------------------------------------------------------------------------------------
	    **/

        /**
	    * Check to see if a Ray intersects at any point with a Rectangle.
	    * @method rayToRectangle
	    * @param ray {Kiwi.Geom.Ray} The Ray object to check. 
	    * @param rect {Kiwi.Geom.Rectangle} The Rectangle to check.
	    * @param [output=IntersectResult] {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection
	    * @public
        * @static
        */
        static rayToRectangle(ray: Ray, rect: Rectangle, output: IntersectResult = new IntersectResult): IntersectResult {

            //  Currently just finds first intersection - might not be closest to ray pt1
            Intersect.lineToRectangle(ray, rect, output);

            return output;

        }

        /**
        * Check whether a Ray intersects a Line segment, returns the parametric value where the intersection occurs.
        * Note: The Line only exists between its two points.
        * @method rayToLineSegment
        * @static
        * @param rayx1 {Number} The origin point of the ray on the x axis.
        * @param rayy1 {Number} The origin point of the ray on the y axis.
        * @param rayx2 {Number} The direction of the ray on the x axis. 
        * @param rayy2 {Number} The direction of the ray on the y axis.
        * @param linex1 {Number} The x of the first point of the line segment.
        * @param liney1 {Number} The y of the first point of the line segment.
        * @param linex2 {Number} The x of the second point of the line segment.
        * @param liney2 {Number} The y of the second point of the line segment.
	    * @param [output=IntersectResult] {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection stored in x
        * @public
        */
        static rayToLineSegment(rayx1, rayy1, rayx2, rayy2, linex1, liney1, linex2, liney2, output: IntersectResult = new IntersectResult): IntersectResult {

            var r, s, d;

            // Check lines are not parallel
            if ((rayy2 - rayy1) / (rayx2 - rayx1) != (liney2 - liney1) / (linex2 - linex1))
            {
                d = (((rayx2 - rayx1) * (liney2 - liney1)) - (rayy2 - rayy1) * (linex2 - linex1));

                if (d != 0)
                {
                    r = (((rayy1 - liney1) * (linex2 - linex1)) - (rayx1 - linex1) * (liney2 - liney1)) / d;
                    s = (((rayy1 - liney1) * (rayx2 - rayx1)) - (rayx1 - linex1) * (rayy2 - rayy1)) / d;

                    if (r >= 0)
                    {
                        if (s >= 0 && s <= 1)
                        {
                            output.result = true;
                            output.x = rayx1 + r * (rayx2 - rayx1), rayy1 + r * (rayy2 - rayy1);
                        }
                    }
                }
            }

            return output;

        }

        /**
	    * -------------------------------------------------------------------------------------------
	    * Circle
	    * -------------------------------------------------------------------------------------------
	    **/

        /**
	    * Check if the two given Circle objects intersect at any point.
	    * @method circleToCircle
	    * @param circle1 {Kiwi.Geom.Circle} The first circle object to check.
	    * @param circle2 {Kiwi.Geom.Circle} The second circle object to check.
	    * @param [output=IntersectResult] {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection
	    * @public
        * @static
        */
        static circleToCircle(circle1: Circle, circle2: Circle, output: IntersectResult = new IntersectResult): IntersectResult {

            output.result = ((circle1.radius + circle2.radius) * (circle1.radius + circle2.radius)) >= Intersect.distanceSquared(circle1.x, circle1.y, circle2.x, circle2.y);

            return output;

        }

        /**
	    * Check if a Circle and a Rectangle intersect with each other at any point. 
	    * @method circleToRectangle
	    * @param circle {Kiwi.Geom.Circle} The circle object to check.
	    * @param rect {Kiwi.Geom.Rectangle} The Rectangle object to check.
	    * @param [output=IntersectResult] {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection
	    * @public
        * @static
        */
        static circleToRectangle(circle: Circle, rect: Rectangle, output: IntersectResult = new IntersectResult): IntersectResult {

            var inflatedRect: Rectangle = rect.clone();

            inflatedRect.inflate(circle.radius, circle.radius);

            output.result = inflatedRect.contains(circle.x, circle.y);

            return output;

        }

        /**
	    * Check if the given Point is found within the given Circle.
	    * @method circleContainsPoint
	    * @param circle {Kiwi.Geom.Circle} The circle object to check
	    * @param point {Kiwi.Geom.Point} The point object to check
	    * @param [output=IntersectResult] {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection
	    * @public
        * @static
        */
        static circleContainsPoint(circle: Circle, point: Point, output: IntersectResult = new IntersectResult): IntersectResult {

            output.result = circle.radius * circle.radius >= Intersect.distanceSquared(circle.x, circle.y, point.x, point.y);

            return output;

        }

        /**
	    * -------------------------------------------------------------------------------------------
	    * Rectangles
	    * -------------------------------------------------------------------------------------------
	    **/

        /**
        * Determines whether the specified point is contained within a given Rectangle object.
        * @method pointToRectangle
        * @param point {Kiwi.Geom.Point} The point object being checked.
        * @param rect {Kiwi.Geom.Rectangle} The rectangle object being checked.
	    * @param [output=Intersect] {Kiwi.Geom.IntersectResult}  An optional IntersectResult object to store the intersection values in (one is created if none given)
        * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection in x/y/result
        * @public
        * @static
        */
        static pointToRectangle(point: Point, rect: Rectangle, output: IntersectResult = new IntersectResult): IntersectResult {

            output.setTo(point.x, point.y);

            output.result = rect.containsPoint(point);

            return output;

        }

        /**
	    * Check whether two axis aligned rectangles intersect. Return the intersecting rectangle dimensions if they do.
	    * @method rectangleToRectangle
	    * @param rect1 {Kiwi.Geom.Rectangle} The first Rectangle object.
	    * @param rect2 {Kiwi.Geom.Rectangle} The second Rectangle object.
	    * @param [output=IntersectResult] {Kiwi.Geom.IntersectResult} An optional IntersectResult object to store the intersection values in (one is created if none given)
	    * @return {Kiwi.Geom.IntersectResult} An IntersectResult object containing the results of this intersection in x/y/width/height
	    * @public
        * @static
        */
        static rectangleToRectangle(rect1: Rectangle, rect2: Rectangle, output: IntersectResult = new IntersectResult): IntersectResult {

            var leftX = Math.max(rect1.x, rect2.x);
            var rightX = Math.min(rect1.right, rect2.right);
            var topY = Math.max(rect1.y, rect2.y);
            var bottomY = Math.min(rect1.bottom, rect2.bottom);

            output.setTo(leftX, topY, rightX - leftX, bottomY - topY, rightX - leftX, bottomY - topY);

            var cx = output.x + output.width * .5;
            var cy = output.y + output.height * .5;

            if ((cx > rect1.x && cx < rect1.right) && (cy > rect1.y && cy < rect1.bottom))
            {
                output.result = true;
            }

            return output;

        }

    }

}