/// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)">
        /// </seealso>
        public override int Collide(Contact[] contacts, Body bodyA, Body bodyB)
        {
            Polygon poly = (Polygon) bodyA.Shape;
            Box box = (Box) bodyB.Shape;

            // TODO: this can be optimized using matrix multiplications and moving only one shape
            // specifically the box, because it has fewer vertices.
            Vector2f[] vertsA = poly.GetVertices(bodyA.GetPosition(), bodyA.Rotation);
            Vector2f[] vertsB = box.GetPoints(bodyB.GetPosition(), bodyB.Rotation);

            // TODO: use a sweepline that has the smallest projection of the box
            // now we use just an arbitrary one
            Vector2f sweepline = new Vector2f(vertsB[1]);
            sweepline.Sub(vertsB[2]);

            EdgeSweep sweep = new EdgeSweep(sweepline);

            sweep.AddVerticesToSweep(true, vertsA);
            sweep.AddVerticesToSweep(false, vertsB);

            int[][] collEdgeCands = sweep.OverlappingEdges;
            //		FeaturePair[] featurePairs = getFeaturePairs(contacts.Length, vertsA, vertsB, collEdgeCands);
            //		return PopulateContacts(contacts, vertsA, vertsB, featurePairs);

            Intersection[][] intersections = GetIntersectionPairs(vertsA, vertsB, collEdgeCands);
            return PopulateContacts(contacts, vertsA, vertsB, intersections);
        }
Example #2
0
        /// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)">
        /// </seealso>
        public virtual int Collide(Contact[] contacts, Body bodyA, Body bodyB)
        {
            int count = collider.Collide(contacts, bodyB, bodyA);

            // Reverse the collision results by inverting normals
            for (int i = 0; i < count; i++)
            {
                Vector2f vec = MathUtil.Scale(contacts[i].Normal, - 1);
                contacts[i].Normal = vec;
            }

            return count;
        }
        /// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)">
        /// </seealso>
        public override int Collide(Contact[] contacts, Body bodyA, Body bodyB)
        {
            Polygon polyA = (Polygon) bodyA.Shape;
            Circle circle = (Circle) bodyB.Shape;

            // TODO: this can be optimized using matrix multiplications and moving only the circle
            Vector2f[] vertsA = polyA.GetVertices(bodyA.GetPosition(), bodyA.Rotation);

            Vector2f centroidA = new Vector2f(polyA.GetCentroid());
            centroidA.Add(bodyA.GetPosition());

            int[][] collPairs = GetCollisionCandidates(vertsA, centroidA, circle.Radius, bodyB.GetPosition());

            int noContacts = 0;
            for (int i = 0; i < collPairs.Length; i++)
            {
                if (noContacts >= contacts.Length)
                    return contacts.Length;

                Vector2f lineStartA = vertsA[collPairs[i][0]];
                Vector2f lineEndA = vertsA[(collPairs[i][0] + 1) % vertsA.Length];
                Line line = new Line(lineStartA, lineEndA);

                float dis2 = line.distanceSquared(bodyB.GetPosition());
                float r2 = circle.Radius * circle.Radius;

                if (dis2 < r2)
                {
                    Vector2f pt = new Vector2f();

                    line.getClosestPoint(bodyB.GetPosition(), pt);
                    Vector2f normal = new Vector2f(bodyB.GetPosition());
                    normal.Sub(pt);
                    float sep = circle.Radius - normal.Length();
                    normal.Normalise();

                    contacts[noContacts].Separation = - sep;
                    contacts[noContacts].Position = pt;
                    contacts[noContacts].Normal = normal;
                    contacts[noContacts].Feature = new FeaturePair();
                    noContacts++;
                }
            }

            return noContacts;
        }
        /// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)">
        /// </seealso>
        public override int Collide(Contact[] contacts, Body bodyA, Body bodyB)
        {
            Line line = (Line) bodyA.Shape;
            Polygon poly = (Polygon) bodyB.Shape;

            // TODO: this can be optimized using matrix multiplications and moving only one shape
            // specifically the line, because it has only two vertices
            Vector2f[] vertsA = line.getVertices(bodyA.GetPosition(), bodyA.Rotation);
            Vector2f[] vertsB = poly.GetVertices(bodyB.GetPosition(), bodyB.Rotation);

            Vector2f pos = poly.GetCentroid(bodyB.GetPosition(), bodyB.Rotation);

            // using the z axis of a 3d Cross product we determine on what side B is
            bool isLeftOf = 0 > (pos.x - vertsA[0].x) * (vertsA[1].y - vertsA[0].y) - (vertsA[1].x - vertsA[0].x) * (pos.y - vertsA[0].y);

            // to get the proper intersection pairs we make sure
            // the line's normal is pointing towards the polygon
            // TODO: verify that it's not actually pointing in the opposite direction
            if (isLeftOf)
            {
                Vector2f tmp = vertsA[0];
                vertsA[0] = vertsA[1];
                vertsA[1] = tmp;
            }

            // we use the line's normal for our sweepline projection
            Vector2f normal = new Vector2f(vertsA[1]);
            normal.Sub(vertsA[0]);
            normal.Reconfigure(normal.y, - normal.x);
            EdgeSweep sweep = new EdgeSweep(normal);
            sweep.Insert(0, true, vertsA[0].Dot(normal));
            sweep.Insert(0, true, vertsA[1].Dot(normal));
            sweep.AddVerticesToSweep(false, vertsB);
            int[][] collEdgeCands = sweep.OverlappingEdges;

            IntersectionGatherer intGath = new IntersectionGatherer(vertsA, vertsB);
            for (int i = 0; i < collEdgeCands.Length; i++)
                intGath.Intersect(collEdgeCands[i][0], collEdgeCands[i][1]);

            Intersection[] intersections = intGath.Intersections;

            return PopulateContacts(contacts, vertsA, vertsB, intersections);
        }
        /// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)">
        /// </seealso>
        public override int Collide(Contact[] contacts, Body circleBody, Body boxBody)
        {
            int count = base.Collide(contacts, boxBody, circleBody);

            // Reverse the collision results by inverting normals
            // and projecting the results onto the circle
            for (int i = 0; i < count; i++)
            {
                Vector2f vec = MathUtil.Scale(contacts[i].Normal, - 1);
                contacts[i].Normal = vec;

                Vector2f pt = MathUtil.Sub(contacts[i].Position, circleBody.GetPosition());
                pt.Normalise();
                pt.Scale(((Circle) circleBody.Shape).Radius);
                pt.Add(circleBody.GetPosition());
                contacts[i].Position = pt;
            }

            return count;
        }
        /// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)">
        /// </seealso>
        public virtual int Collide(Contact[] contacts, Body bodyA, Body bodyB)
        {
            float x1 = bodyA.GetPosition().X;
            float y1 = bodyA.GetPosition().Y;
            float x2 = bodyB.GetPosition().X;
            float y2 = bodyB.GetPosition().Y;

            bool touches = bodyA.Shape.Bounds.Touches(x1, y1, bodyB.Shape.Bounds, x2, y2);
            if (!touches)
            {
                return 0;
            }

            Circle circleA = (Circle) bodyA.Shape;
            Circle circleB = (Circle) bodyB.Shape;

            touches = circleA.Touches(x1, y1, circleB, x2, y2);
            if (!touches)
            {
                return 0;
            }

            Vector2f normal = MathUtil.Sub(bodyB.GetPosition(), bodyA.GetPosition());
            float sep = (circleA.Radius + circleB.Radius) - normal.Length();

            normal.Normalise();
            Vector2f pt = MathUtil.Scale(normal, circleA.Radius);
            pt.Add(bodyA.GetPosition());

            contacts[0].Separation = - sep;
            contacts[0].Position = pt;
            contacts[0].Normal = normal;

            FeaturePair fp = new FeaturePair();
            contacts[0].Feature = fp;

            return 1;
        }
        /// <summary> Create a collider for two bodies. The decision depends on
        /// the body's shapes.
        /// 
        /// </summary>
        /// <param name="bodyA">First body in the collision test
        /// </param>
        /// <param name="bodyB">Second body in the collision test
        /// </param>
        /// <returns> A collider that can test wether the two bodies actually Collide
        /// </returns>
        /// <throws>  ColliderUnavailableException  </throws>
        /// <summary>         This exception will be thrown if no suitable collider can be found. 
        /// </summary>
        public virtual Collider CreateCollider(Body bodyA, Body bodyB)
        {
            Shape shapeA = bodyA.Shape;
            Shape shapeB = bodyB.Shape;

            if (shapeA is Circle)
            {
                return CreateColliderFor((Circle) shapeA, shapeB);
            }
            else if (shapeA is Box)
            {
                return CreateColliderFor((Box) shapeA, shapeB);
            }
            else if (shapeA is Line)
            {
                return CreateColliderFor((Line) shapeA, shapeB);
            }
            else if (shapeA is Polygon)
            {
                return CreateColliderFor((Polygon) shapeA, shapeB);
            }

            throw new ColliderUnavailableException(shapeA, shapeB);
        }
 /// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)">
 /// </seealso>
 public virtual int Collide(Contact[] contacts, Body bodyA, Body bodyB)
 {
     // TODO: function disabled until we can remember on what side of A,
     // B used to be, which is crucial to determine a proper collision normal
     return 0;
     //		Line lineA = (Line) bodyA.getShape();
     //		Line lineB = (Line) bodyB.getShape();
     //
     //		Vector2f[] vertsA = lineA.GetVertices(bodyA.GetPosition(), bodyA.getRotation());
     //		Vector2f[] vertsB = lineB.GetVertices(bodyB.GetPosition(), bodyB.getRotation());
     //
     //		Vector2f startA = vertsA[0];
     //		Vector2f endA = vertsA[1];
     //		Vector2f startB = vertsB[0];
     //		Vector2f endB = vertsB[1];
     //
     //		//TODO: reuse mathutil.Intersect?
     //		float d = (endB.y - startB.y) * (endA.x - startA.x) - (endB.x - startB.x) * (endA.y - startA.y);
     //
     //		if ( d == 0 ) // parallel lines
     //			return 0;
     //
     //		float uA = (endB.x - startB.x) * (startA.y - startB.y) - (endB.y - startB.y) * (startA.x - startB.x);
     //		uA /= d;
     //		float uB = (endA.x - startA.x) * (startA.y - startB.y) - (endA.y - startA.y) * (startA.x - startB.x);
     //		uB /= d;
     //
     //		if ( uA < 0 || uA > 1 || uB < 0 || uB > 1 )
     //			return 0; // intersection point isn't between the start and endpoints
     //
     //		// there must be a collision, let's determine our contact information
     //		// we're searching for a contact with the smallest penetration depth
     //		Vector2f[][] closestPoints = {
     //				{startB, GetClosestPoint(startA, endA, startB)},
     //				{endB, GetClosestPoint(startA, endA, endB)},
     //				{startA, GetClosestPoint(startB, endB, startA)},
     //				{endA, GetClosestPoint(startB, endB, endA)}
     //		};
     //
     //		float distSquared = Float.MAX_VALUE;
     //		Vector2f position = null;
     //		Vector2f normal = new Vector2f();
     //
     //		for ( int i = 0; i < 4; i++ ) {
     //			Vector2f l;
     //			if ( i < 2 ) {
     //				l = closestPoints[i][1];
     //				l.Sub(closestPoints[i][0]);
     //			} else {
     //				l = closestPoints[i][0];
     //				l.Sub(closestPoints[i][1]);
     //			}
     //
     //			float newDistSquared = l.LengthSquared();
     //			if ( newDistSquared < distSquared ) {
     //				distSquared = newDistSquared;
     //				position = closestPoints[i][0];
     //				normal.set(l);
     //			}
     //		}
     //
     //		normal.Normalise();
     //		contacts[0].setNormal(normal);
     //		contacts[0].SetPosition(position);
     //		if ( Math.sqrt(distSquared) > 10f )
     //			System.out.println(Math.sqrt(distSquared));
     //		contacts[0].setSeparation((float) -Math.sqrt(distSquared));
     //
     //		return 1;
 }
 /// <summary> Add a pody to the space
 /// 
 /// </summary>
 /// <param name="body">The body to Add to the space
 /// </param>
 public virtual void AddBody(Body body)
 {
     Add(body);
 }
        /// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)">
        /// </seealso>
        public virtual int Collide(Contact[] contacts, Body boxBody, Body circleBody)
        {
            float x1 = boxBody.GetPosition().X;
            float y1 = boxBody.GetPosition().Y;
            float x2 = circleBody.GetPosition().X;
            float y2 = circleBody.GetPosition().Y;

            bool touches = boxBody.Shape.Bounds.Touches(x1, y1, circleBody.Shape.Bounds, x2, y2);
            if (!touches)
            {
                return 0;
            }

            Box box = (Box) boxBody.Shape;
            Circle circle = (Circle) circleBody.Shape;

            Vector2f[] pts = box.GetPoints(boxBody.GetPosition(), boxBody.Rotation);
            Line[] lines = new Line[4];
            lines[0] = new Line(pts[0], pts[1]);
            lines[1] = new Line(pts[1], pts[2]);
            lines[2] = new Line(pts[2], pts[3]);
            lines[3] = new Line(pts[3], pts[0]);

            float r2 = circle.Radius * circle.Radius;
            int closest = - 1;
            float closestDistance = System.Single.MaxValue;

            for (int i = 0; i < 4; i++)
            {
                float dis = lines[i].distanceSquared(circleBody.GetPosition());
                if (dis < r2)
                {
                    if (closestDistance > dis)
                    {
                        closestDistance = dis;
                        closest = i;
                    }
                }
            }

            if (closest > - 1)
            {
                float dis = (float) System.Math.Sqrt(closestDistance);
                contacts[0].Separation = dis - circle.Radius;

                // this should really be where the edge and the line
                // between the two elements Cross?
                Vector2f contactPoint = new Vector2f();
                lines[closest].getClosestPoint(circleBody.GetPosition(), contactPoint);

                Vector2f normal = MathUtil.Sub(circleBody.GetPosition(), contactPoint);
                normal.Normalise();
                contacts[0].Normal = normal;
                contacts[0].Position = contactPoint;
                contacts[0].Feature = new FeaturePair();

                return 1;
            }

            return 0;
        }
        /// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)">
        /// </seealso>
        public virtual int Collide(Contact[] contacts, Body bodyA, Body bodyB)
        {
            Line line = (Line) bodyA.Shape;
            Circle circle = (Circle) bodyB.Shape;

            Vector2f[] vertsA = line.getVertices(bodyA.GetPosition(), bodyA.Rotation);

            // compute intersection of the line A and a line parallel to
            // the line A's normal passing through the origin of B
            Vector2f startA = vertsA[0];
            Vector2f endA = vertsA[1];
            ROVector2f startB = bodyB.GetPosition();
            Vector2f endB = new Vector2f(endA);
            endB.Sub(startA);
            endB.Reconfigure(endB.y, - endB.x);
            //		endB.Add(startB);// TODO: inline endB into equations below, this last operation will be useless..

            //TODO: reuse mathutil.Intersect
            //		float d = (endB.y - startB.getY()) * (endA.x - startA.x);
            //		d -= (endB.x - startB.getX()) * (endA.y - startA.y);
            //
            //		float uA = (endB.x - startB.getX()) * (startA.y - startB.getY());
            //		uA -= (endB.y - startB.getY()) * (startA.x - startB.getX());
            //		uA /= d;
            float d = endB.y * (endA.x - startA.x);
            d -= endB.x * (endA.y - startA.y);

            float uA = endB.x * (startA.y - startB.Y);
            uA -= endB.y * (startA.x - startB.X);
            uA /= d;

            Vector2f position = null;

            if (uA < 0)
            {
                // the intersection is somewhere before startA
                position = startA;
            }
            else if (uA > 1)
            {
                // the intersection is somewhere after endA
                position = endA;
            }
            else
            {
                position = new Vector2f(startA.x + uA * (endA.x - startA.x), startA.y + uA * (endA.y - startA.y));
            }

            Vector2f normal = endB; // reuse of vector object
            normal.Reconfigure(startB);
            normal.Sub(position);
            float distSquared = normal.LengthSquared();
            float radiusSquared = circle.Radius * circle.Radius;

            if (distSquared < radiusSquared)
            {
                contacts[0].Position = position;
                contacts[0].Feature = new FeaturePair();

                normal.Normalise();
                contacts[0].Normal = normal;

                float separation = (float) System.Math.Sqrt(distSquared) - circle.Radius;
                contacts[0].Separation = separation;

                return 1;
            }

            return 0;
        }
Example #12
0
        /// <seealso cref="Silver.Weight.Raw.Collide.Collider.Collide(Silver.Weight.Raw.Contact[], Silver.Weight.Raw.Body, Silver.Weight.Raw.Body)">
        /// </seealso>
        public virtual int Collide(Contact[] contacts, Body bodyA, Body bodyB)
        {
            int numContacts = 0;

            Line line = (Line) bodyA.Shape;
            Box box = (Box) bodyB.Shape;

            Vector2f lineVec = new Vector2f(line.DX, line.DY);
            lineVec.Normalise();
            Vector2f axis = new Vector2f(- line.DY, line.DX);
            axis.Normalise();

            Vector2f res = new Vector2f();
            line.Start.ProjectOntoUnit(axis, res);
            float linePos = GetProp(res, axis);

            Vector2f c = MathUtil.Sub(bodyB.GetPosition(), bodyA.GetPosition());
            c.ProjectOntoUnit(axis, res);
            float centre = GetProp(res, axis);

            Vector2f[] pts = box.GetPoints(bodyB.GetPosition(), bodyB.Rotation);
            float[] tangent = new float[4];
            float[] proj = new float[4];

            int outOfRange = 0;

            for (int i = 0; i < 4; i++)
            {
                pts[i].Sub(bodyA.GetPosition());
                pts[i].ProjectOntoUnit(axis, res);
                tangent[i] = GetProp(res, axis);
                pts[i].ProjectOntoUnit(lineVec, res);
                proj[i] = GetProp(res, new Vector2f(line.DX, line.DY));

                if ((proj[i] >= 1) || (proj[i] <= 0))
                {
                    outOfRange++;
                }
            }
            if (outOfRange == 4)
            {
                return 0;
            }

            Vector2f normal = new Vector2f(axis);

            if (centre < linePos)
            {
                if (!line.BlocksInnerEdge)
                {
                    return 0;
                }

                normal.Scale(- 1);
                for (int i = 0; i < 4; i++)
                {
                    if (tangent[i] > linePos)
                    {
                        if (proj[i] < 0)
                        {
                            Vector2f onAxis = new Vector2f();
                            Line leftLine = new Line(GetPt(pts, i - 1), pts[i]);
                            Line rightLine = new Line(GetPt(pts, i + 1), pts[i]);
                            leftLine.getClosestPoint(line.Start, res);
                            res.ProjectOntoUnit(axis, onAxis);
                            float left = GetProp(onAxis, axis);
                            rightLine.getClosestPoint(line.Start, res);
                            res.ProjectOntoUnit(axis, onAxis);
                            float right = GetProp(onAxis, axis);

                            if ((left > 0) && (right > 0))
                            {
                                Vector2f pos = new Vector2f(bodyA.GetPosition());
                                pos.Add(line.Start);

                                ResolveEndPointCollision(pos, bodyA, bodyB, normal, leftLine, rightLine, contacts[numContacts], i);
                                numContacts++;
                            }
                        }
                        else if (proj[i] > 1)
                        {
                            Vector2f onAxis = new Vector2f();
                            Line leftLine = new Line(GetPt(pts, i - 1), pts[i]);
                            Line rightLine = new Line(GetPt(pts, i + 1), pts[i]);
                            leftLine.getClosestPoint(line.End, res);
                            res.ProjectOntoUnit(axis, onAxis);
                            float left = GetProp(onAxis, axis);
                            rightLine.getClosestPoint(line.End, res);
                            res.ProjectOntoUnit(axis, onAxis);
                            float right = GetProp(onAxis, axis);

                            if ((left > 0) && (right > 0))
                            {
                                Vector2f pos = new Vector2f(bodyA.GetPosition());
                                pos.Add(line.End);

                                ResolveEndPointCollision(pos, bodyA, bodyB, normal, leftLine, rightLine, contacts[numContacts], i);
                                numContacts++;
                            }
                        }
                        else
                        {
                            pts[i].ProjectOntoUnit(lineVec, res);
                            res.Add(bodyA.GetPosition());
                            contacts[numContacts].Separation = - (tangent[i] - linePos);
                            contacts[numContacts].Position = new Vector2f(res);
                            contacts[numContacts].Normal = normal;
                            contacts[numContacts].Feature = new FeaturePair(i);
                            numContacts++;
                        }
                    }
                }
            }
            else
            {
                if (!line.BlocksOuterEdge)
                {
                    return 0;
                }

                for (int i = 0; i < 4; i++)
                {
                    if (tangent[i] < linePos)
                    {
                        if (proj[i] < 0)
                        {
                            Vector2f onAxis = new Vector2f();
                            Line leftLine = new Line(GetPt(pts, i - 1), pts[i]);
                            Line rightLine = new Line(GetPt(pts, i + 1), pts[i]);
                            leftLine.getClosestPoint(line.Start, res);
                            res.ProjectOntoUnit(axis, onAxis);
                            float left = GetProp(onAxis, axis);
                            rightLine.getClosestPoint(line.Start, res);
                            res.ProjectOntoUnit(axis, onAxis);
                            float right = GetProp(onAxis, axis);

                            if ((left < 0) && (right < 0))
                            {
                                Vector2f pos = new Vector2f(bodyA.GetPosition());
                                pos.Add(line.Start);

                                ResolveEndPointCollision(pos, bodyA, bodyB, normal, leftLine, rightLine, contacts[numContacts], i);
                                numContacts++;
                            }
                        }
                        else if (proj[i] > 1)
                        {
                            Vector2f onAxis = new Vector2f();
                            Line leftLine = new Line(GetPt(pts, i - 1), pts[i]);
                            Line rightLine = new Line(GetPt(pts, i + 1), pts[i]);
                            leftLine.getClosestPoint(line.End, res);
                            res.ProjectOntoUnit(axis, onAxis);
                            float left = GetProp(onAxis, axis);
                            rightLine.getClosestPoint(line.End, res);
                            res.ProjectOntoUnit(axis, onAxis);
                            float right = GetProp(onAxis, axis);

                            if ((left < 0) && (right < 0))
                            {
                                Vector2f pos = new Vector2f(bodyA.GetPosition());
                                pos.Add(line.End);

                                ResolveEndPointCollision(pos, bodyA, bodyB, normal, leftLine, rightLine, contacts[numContacts], i);
                                numContacts++;
                            }
                        }
                        else
                        {
                            pts[i].ProjectOntoUnit(lineVec, res);
                            res.Add(bodyA.GetPosition());
                            contacts[numContacts].Separation = - (linePos - tangent[i]);
                            contacts[numContacts].Position = new Vector2f(res);
                            contacts[numContacts].Normal = normal;
                            contacts[numContacts].Feature = new FeaturePair();
                            numContacts++;
                        }
                    }
                }
            }

            if (numContacts > 2)
            {
                throw new System.SystemException("LineBoxCollision: > 2 contacts");
            }

            return numContacts;
        }
Example #13
0
        /// <summary> Resolve the collision math around an end point
        /// 
        /// </summary>
        /// <param name="pos">The position of the contact
        /// </param>
        /// <param name="bodyA">The first body in the collision
        /// </param>
        /// <param name="bodyB">The second body in the collision
        /// </param>
        /// <param name="leftLine">The line to the left of the vertex of collision
        /// </param>
        /// <param name="rightLine">The line to the right of the vertex of collision
        /// </param>
        /// <param name="contact">The contact to populate
        /// </param>
        /// <param name="norm">The normal determined for the line
        /// </param>
        /// <param name="i">The index of teh face we're resolving for feature ID
        /// </param>
        private void ResolveEndPointCollision(Vector2f pos, Body bodyA, Body bodyB, Vector2f norm, Line leftLine, Line rightLine, Contact contact, int i)
        {
            Vector2f start = new Vector2f(pos);
            Vector2f end = new Vector2f(start);
            end.Add(norm);

            rightLine.move(bodyA.GetPosition());
            leftLine.move(bodyA.GetPosition());
            Line normLine = new Line(start, end);
            Vector2f rightPoint = normLine.intersect(rightLine);
            Vector2f leftPoint = normLine.intersect(leftLine);

            float dis1 = System.Single.MaxValue;
            if (rightPoint != null)
            {
                dis1 = rightPoint.Distance(start) - norm.Length();
            }
            float dis2 = System.Single.MaxValue;
            if (leftPoint != null)
            {
                dis2 = leftPoint.Distance(start) - norm.Length();
            }

            norm.Normalise();
            float dis = System.Math.Min(dis1, dis2);

            contact.Separation = - dis;
            contact.Position = pos;
            contact.Normal = norm;
            contact.Feature = new FeaturePair(i);
        }