Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

package com.gebauz.bauzoid.math;

/** Line segment class. */
public class Line2
{
        // Constants========================================================================================

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

        // Fields===========================================================================================
       
        private float ax = 0;
        private float ay = 0;
       
        private float bx = 0;
        private float by = 0;
       
        // parametric form
        private float A = 0.0f;
        private float B = 0.0f;
        private float C = 0.0f;

        // Methods==========================================================================================
       
        public Line2()
        {
                calcParametric();
        }
       
        public Line2(float _ax, float _ay, float _bx, float _by)
        {
                ax = _ax; ay = _ay;
                bx = _bx; by = _by;
                calcParametric();
        }
       
        public Line2(Vector2 a, Vector2 b)
        {
                ax = a.x; ay = a.y;
                bx = b.x; by = b.y;
                calcParametric();
        }
       
        public Vector2 getLineVector()
        {
                return new Vector2(bx - ax, by - ay);
        }
       
        public void calcParametric()
        {
                A = getA();
                B = getB();
                C = getC();
        }
       
        public float getLengthSqr()
        {
                float diffX = ax - bx;
                float diffY = ay - by;
                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)
        {
                if ((x <= Math.max(ax, bx)) && (x >= Math.min(ax, bx)) &&
                        (y <= Math.max(ay, by)) && (y >= Math.min(ay, by)))
                {
                        return true;
                }
               
                return false;
        }
       
        /** Get the A coefficient in the Ax + By = C form. */
        public final float getA()
        {
                return by - ay;
        }
       
        /** Get the B coefficient in the Ax + By = C form. */
        public final float getB()
        {
                return ax - bx;
        }
       
        /** Get the C coefficient in the Ax + By = C form. */
        public final float getC()
        {
                return getA() * ax + getB() * ay;
        }
       
        public Vector2 getLineIntersection(Line2 other)
        {
                // 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 null;
               
                float x = (B2*C1 - B1*C2)/delta;
                float y = (A1*C2 - A2*C1)/delta;
               
                return new Vector2(x, y);
        }
       
        public Vector2 getSegmentIntersection(Line2 other)
        {
                Vector2 p = getLineIntersection(other);
               
                if (p == null)
                        return null;
               
                if (this.isCollinearPointOnSegment(p.x, p.y) && other.isCollinearPointOnSegment(p.x, p.y))
                        return p;
               
                return null;
        }
       
        public boolean intersectsSegment(Line2 other)
        {
                Vector2 p = getSegmentIntersection(other);
               
                if (p == null)
                        return false;
               
                return true;
        }
       
        /** 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);
        }
       
        /** 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)
        {
                Vector2 ab = getLineVector();
               
                Vector2 ap = new Vector2(point.x - ax, point.y - ay);
               
                float t = Vector2.dotProduct(ap, ab) / ab.squaredLength();
               
                t = MathUtil.clamp(t, 0, 1);
               
                return new Vector2(ax + t * ab.x, ay + t * ab.y);
        }
       
        public Vector2 getClosestPointFrom(float px, float py)
        {
                return getClosestPointFrom(new Vector2(px, py));
        }
       
       
        /*     
        (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==================================================================================

}