Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BauzoidNET.math
{
    /** Line segment class. */
    public class Line2
    {

            // Constants========================================================================================

            // Embedded Types===================================================================================

            // Fields===========================================================================================
       
            public Vector2 a = new Vector2();
            public Vector2 b = new Vector2();
       
            // parametric form
            private float A = 0.0f;
            private float B = 0.0f;
            private float C = 0.0f;
       
            private Vector2 mTemp = new Vector2();
            private Vector2 mTemp2 = new Vector2();

            // Methods==========================================================================================
       
            public Line2()
            {
                    calcParametric();
            }
       
            public Line2(float ax, float ay, float bx, float by)
            {
                    set(ax, ay, bx, by);
            }
       
            public Line2(Vector2 a, Vector2 b)
            {
                    set(a, b);
            }
       
            public void set(float _ax, float _ay, float _bx, float _by)
            {
                    a.x = _ax; a.y = _ay;
                    b.x = _bx; b.y = _by;
                    calcParametric();
            }
       
            public void set(Vector2 _a, Vector2 _b)
            {
                    a.x = _a.x; a.y = _a.y;
                    b.x = _b.x; b.y = _b.y;
                    calcParametric();          
            }
       
            public void setPointA(float _ax, float _ay)
            {
                    a.x = _ax; a.y = _ay;
                    calcParametric();          
            }
       
            public void setPointB(float _bx, float _by)
            {
                    b.x = _bx; b.y = _by;
                    calcParametric();          
            }
       
            public Line2 copy()
            {
                    return new Line2(a, b);
            }
       
            public Vector2 getMidPoint()
            {
                    return new Vector2(a.x + (b.x - a.x) / 2, a.y + (b.y - a.y) /2);
            }
       
            public Vector2 getLineVector()
            {
                    return new Vector2(b.x - a.x, b.y - a.y);
            }
       
            public void getLineVector(Vector2 result)
            {
                    result.set(b.x - a.x, b.y - a.y);
            }
       
            public void calcParametric()
            {
                    A = getA();
                    B = getB();
                    C = getC();
            }
       
            public float getLengthSqr()
            {
                    float diffX = a.x - b.x;
                    float diffY = a.y - b.y;
                    return (diffX*diffX + diffY*diffY);
            }
       
            public float getLength()
            {
                    float length = getLengthSqr();
                    return (float)(Math.Sqrt(length));
            }
       
            /** Check if x, y (which must be collinear to the line segment) lies within the line segment. */
            public bool isCollinearPointOnSegment(float x, float y)
            {
                    //Gdx.app.log("BLA", "p: " + x + ", " + y + " [" + ax + ", " + ay + " - " + bx + ", " + by);
               
                    float EPSILON = 0.0001f;
               
                    if ((x <= (Math.Max(a.x, b.x) + EPSILON)) && (x >= (Math.Min(a.x, b.x) - EPSILON)) &&
                            (y <= (Math.Max(a.y, b.y) + EPSILON)) && (y >= (Math.Min(a.y, b.y) - EPSILON)))
                    {
                            return true;
                    }
               
                    return false;
            }

            /** Get the A coefficient in the Ax + By = C form. */
            public float getA()
            {
                    return b.y - a.y;
            }
       
            /** Get the B coefficient in the Ax + By = C form. */
            public float getB()
            {
                    return a.x - b.x;
            }
       
            /** Get the C coefficient in the Ax + By = C form. */
            public float getC()
            {
                    return getA() * a.x + getB() * a.y;
            }
       
       
            /** Get intersection point. */
            public Vector2 getLineIntersection(Line2 other)
            {
                    Vector2 result = new Vector2();
                    if (getLineIntersection(other, result))
                            return result;
               
                    return null;
            }
       
            /** Get intersection point (no allocation version). */
            public bool getLineIntersection(Line2 other, Vector2 result)
            {
                    // get Ax + By = C form coefficients               
                    float A1 = A;
                    float B1 = B;
                    float C1 = C;
               
                    float A2 = other.A;
                    float B2 = other.B;
                    float C2 = other.C;
               
                    float delta = A1*B2 - A2*B1;
                    if (delta == 0)
                            return false;
               
                    float x = (B2*C1 - B1*C2)/delta;
                    float y = (A1*C2 - A2*C1)/delta;
                               
                    result.set(x, y);
               
                    return true;
            }
       
       
            /** Get line segment intersection point. */
            public Vector2 getSegmentIntersection(Line2 other)
            {
                    Vector2 result = new Vector2();
               
                    if (getSegmentIntersection(other, result))
                            return result;
               
                    return null;
            }
       
            /** Get line segment intersection point (no allocation version). */
            public bool getSegmentIntersection(Line2 other, Vector2 result)
            {
                    if (!getLineIntersection(other, result))
                            return false;
               
                    if (this.isCollinearPointOnSegment(result.x, result.y) && other.isCollinearPointOnSegment(result.x, result.y))
                            return true;
               
                    return false;
            }
       
       
            /** Check if a segment intersects another. */
        public bool intersectsSegment(Line2 other)
            {
                    return getSegmentIntersection(other, mTemp);
            }
       

            /** Get the smallest perpendicular vector from point to the line. */
            public Vector2 getMinimalVectorFrom(Vector2 point)
            {
                    /*Vector2 closestPoint = getClosestPointFrom(point);
               
                    return new Vector2(closestPoint.x - point.x, closestPoint.y - point.y);*/

                    Vector2 result = new Vector2();
                    getMinimalVectorFrom(point, result);
                    return result;
            }
       
       
            /** Get the smallest perpendicular vector from point to the line (no allocation version). */
            public void getMinimalVectorFrom(Vector2 point, Vector2 result)
            {
                    //Vector2 closestPoint = getClosestPointFrom(point);
                    getClosestPointFrom(point, mTemp);
                    result.set(mTemp.x - point.x, mTemp.y - point.y);
               
                    //return new Vector2(closestPoint.x - point.x, closestPoint.y - point.y);
            }
       
            /** Get the smallest perpendicular vector from point to the line. */
            public Vector2 getMinimalVectorFrom(float px, float py)
            {
                    return getMinimalVectorFrom(new Vector2(px, py));
            }
       
       
            /** Get the closest point on line from a given point. */
            public Vector2 getClosestPointFrom(Vector2 point)
            {
                    return getClosestPointFrom(point.x, point.y);
            }
       
            /** Get the closest point on line from a given point (no allocation version). */
            public void getClosestPointFrom(Vector2 point, Vector2 result)
            {
                    getClosestPointFrom(point.x, point.y, result);
            }
       
            /** Get the closest point on line from a given point. */
            public Vector2 getClosestPointFrom(float px, float py)
            {
                    Vector2 result = new Vector2();
                    getClosestPointFrom(px, py, result);
                    return result;
            }
       
            /** Get the closest point on line from a given point (no allocation version). */
            public void getClosestPointFrom(float px, float py, Vector2 result)
            {
                    getLineVector(mTemp);
               
                    mTemp2.set(px - a.x, py - a.y);
               
                    float t = Vector2.dotProduct(mTemp, mTemp2) / mTemp.squaredLength();
               
                    t = MathUtil.clamp(t, 0, 1);
                    result.set(a.x + t * mTemp.x, a.y + t * mTemp.y);
            }
       
       
            /** Get the closest distance from a given point. */
            public float getClosestDistanceFrom(Vector2 point)
            {
                    return getClosestDistanceFrom(point.x, point.y);
            }
       
            /** Get the closest distance from a given point. */
            public float getClosestDistanceFrom(float px, float py)
            {
                    return (float)Math.Sqrt(getClosestSquaredDistanceFrom(px, py));
            }
       
            /** Get the closest distance from a given point. */
            public float getClosestSquaredDistanceFrom(float px, float py)
            {
                    getClosestPointFrom(px, py, mTemp);
               
                    float dx = mTemp.x - px;
                    float dy = mTemp.y - py;
               
                    return (dx*dx + dy*dy);
            }
    }
}