Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

package com.gebauz.bauzoid2.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 boolean isCollinearPointOnSegment(float x, float y)
        {
                //Gdx.app.log("BLA", "p: " + x + ", " + y + " [" + ax + ", " + ay + " - " + bx + ", " + by);
               
                final 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 final float getA()
        {
                return b.y - a.y;
        }
       
        /** Get the B coefficient in the Ax + By = C form. */
        public final float getB()
        {
                return a.x - b.x;
        }
       
        /** Get the C coefficient in the Ax + By = C form. */
        public final 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 boolean 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 boolean 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 boolean 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);
        }
       
       
        /*     
        (P-A).D == |X-A|

                        X == A + ((P-A).D)D
                        Desired perpendicular: X-P
                       
                       
                          Returns the closest point x on segment ab to point p
   (x-p).(b-a) = 0, x = a + t(b-a)
   => (a + t(b-a) - p).(b-a) = 0
   => t(b-a).(b-a) = (p-a).(b-a)
   => t = (p-a).(b-a) / |b-a|^2
   
   Ogre::Vector3 closestPointOnLineSegment(const Ogre::Vector3 &p,const Ogre::Vector3 &a,const Ogre::Vector3 b)
   {
      Ogre::Vector3 ab = b-a;
      float t = (p-a).dotProduct(ab) / (ab).squaredLength();
      t = Ogre::Math::Clamp(t,0.f,1.f);
      return a + t*ab;
   }
                       
                        *
                        *
                        *
                        */


        // Getters/Setters==================================================================================

}