Exemplo n.º 1
0
        //------------------------- DistToLineSegmentSq ----------------------------
        //
        //  as above, but avoiding Math.Sqrt
        //------------------------------------------------------------------------
        public static double DistToLineSegmentSq(Vector2D A,
                                                 Vector2D B,
                                                 Vector2D P)
        {
            //if the angle is obtuse between PA and AB is obtuse then the closest
            //vertex must be A
            double dotA = (P.X - A.X) * (B.X - A.X) + (P.Y - A.Y) * (B.Y - A.Y);

            if (dotA <= 0)
            {
                return(Vector2D.Vec2DDistanceSq(A, P));
            }

            //if the angle is obtuse between PB and AB is obtuse then the closest
            //vertex must be B
            double dotB = (P.X - B.X) * (A.X - B.X) + (P.Y - B.Y) * (A.Y - B.Y);

            if (dotB <= 0)
            {
                return(Vector2D.Vec2DDistanceSq(B, P));
            }

            //calculate the point along AB that is the closest to P
            Vector2D Point = A + ((B - A) * dotA) / (dotA + dotB);

            //calculate the distance P-Point
            return(Vector2D.Vec2DDistanceSq(P, Point));
        }
Exemplo n.º 2
0
        //-------------------- GetEntityLineSegmentIntersections ----------------------
        //
        //  tests a line segment AB against a container of entities. First of all
        //  a test is made to confirm that the entity is within a specified range of
        //  the one_to_ignore (positioned at A). If within range the intersection test
        //  is made.
        //
        //  returns a list of all the entities that tested positive for intersection
        //-----------------------------------------------------------------------------
        public static List <BaseGameEntity> GetEntityLineSegmentIntersections(List <BaseGameEntity> entities,
                                                                              int the_one_to_ignore,
                                                                              Vector2D A,
                                                                              Vector2D B,
                                                                              double range)
        {
            List <BaseGameEntity> hits = new List <BaseGameEntity>();

            //iterate through all entities checking against the line segment AB
            foreach (BaseGameEntity it in entities)
            {
                //if not within range or the entity being checked is the_one_to_ignore
                //just continue with the next entity
                if ((it.ID() == the_one_to_ignore) ||
                    (Vector2D.Vec2DDistanceSq(it.Pos, A) > range * range))
                {
                    continue;
                }

                //if the distance to AB is less than the entities bounding radius then
                //there is an intersection so add it to hits
                if (DistToLineSegment(A, B, it.Pos) < it.BRadius)
                {
                    hits.Add(it);
                }
            }

            return(hits);
        }
Exemplo n.º 3
0
        //------------------- GetLineSegmentCircleClosestIntersectionPoint ------------
        //
        //  given a line segment AB and a circle position and radius, this function
        //  determines if there is an intersection and stores the position of the
        //  closest intersection in the reference IntersectionPoint
        //
        //  returns false if no intersection point is found
        //-----------------------------------------------------------------------------
        public static bool GetLineSegmentCircleClosestIntersectionPoint(Vector2D A,
                                                                        Vector2D B,
                                                                        Vector2D pos,
                                                                        double radius,
                                                                        ref Vector2D IntersectionPoint)
        {
            Vector2D toBNorm = Vector2D.Vec2DNormalize(B - A);

            //move the circle into the local space defined by the vector B-A with origin
            //at A
            Vector2D LocalPos = PointToLocalSpace(pos, toBNorm, toBNorm.Perp(), A);

            bool ipFound = false;

            //if the local position + the radius is negative then the circle lays behind
            //point A so there is no intersection possible. If the local x pos minus the
            //radius is greater than length A-B then the circle cannot intersect the
            //line segment
            if ((LocalPos.X + radius >= 0) &&
                ((LocalPos.X - radius) * (LocalPos.X - radius) <= Vector2D.Vec2DDistanceSq(B, A)))
            {
                //if the distance from the x axis to the object's position is less
                //than its radius then there is a potential intersection.
                if (Math.Abs(LocalPos.Y) < radius)
                {
                    //now to do a line/circle intersection test. The center of the
                    //circle is represented by A, B. The intersection points are
                    //given by the formulae x = A +/-Math.Sqrt(r^2-B^2), y=0. We only
                    //need to look at the smallest positive value of x.
                    double a = LocalPos.X;
                    double b = LocalPos.Y;

                    double ip = a - Math.Sqrt(radius * radius - b * b);

                    if (ip <= 0)
                    {
                        ip = a + Math.Sqrt(radius * radius - b * b);
                    }

                    ipFound = true;

                    IntersectionPoint = A + toBNorm * ip;
                }
            }

            return(ipFound);
        }
Exemplo n.º 4
0
        //------------------------ GetClosestEntityLineSegmentIntersection ------------
        //
        //  tests a line segment AB against a container of entities. First of all
        //  a test is made to confirm that the entity is within a specified range of
        //  the one_to_ignore (positioned at A). If within range the intersection test
        //  is made.
        //
        //  returns the closest entity that tested positive for intersection or NULL
        //  if none found
        //-----------------------------------------------------------------------------
        public static BaseGameEntity GetClosestEntityLineSegmentIntersection(List <BaseGameEntity> entities,
                                                                             int the_one_to_ignore,
                                                                             Vector2D A,
                                                                             Vector2D B,
                                                                             double range)
        {
            BaseGameEntity ClosestEntity = null;

            double ClosestDist = Double.MaxValue;

            //iterate through all entities checking against the line segment AB
            foreach (BaseGameEntity it in entities)
            {
                double distSq = Vector2D.Vec2DDistanceSq(it.Pos, A);

                //if not within range or the entity being checked is the_one_to_ignore
                //just continue with the next entity
                if ((it.ID() == the_one_to_ignore) || (distSq > range * range))
                {
                    continue;
                }

                //if the distance to AB is less than the entities bounding radius then
                //there is an intersection so add it to hits
                if (DistToLineSegment(A, B, it.Pos) < it.BRadius)
                {
                    if (distSq < ClosestDist)
                    {
                        ClosestDist = distSq;

                        ClosestEntity = it;
                    }
                }
            }

            return(ClosestEntity);
        }