/// <summary> /// finds the closest point on a line segment to a given point /// </summary> /// <param name="point">given point</param> /// <param name="edge">line segment</param> /// <returns>closest point on line segment</returns> public static Vector2 ClosestPointOnEdge(Vector2 point, LineSegment edge) { // vector of edge Vector2 a = edge.Point2 - edge.Point1; // vector from initial point of edge to our point Vector2 b = point - edge.Point1; // scalar projection of b onto a float compBOntoA = Vector2.Dot(a, b) / a.Length(); if (compBOntoA < 0) return edge.Point1; if (compBOntoA > a.Length()) return edge.Point2; // unit vector of a a.Normalize(); //a = a / a.Length(); // vector projection of b onto a Vector2 projBontoA = a * compBOntoA; // vector projection plus initial point of edge Vector2 pointOnEdge = edge.Point1 + projBontoA; //pointOnEdge.X = MathHelper.Clamp(pointOnEdge.X, edge.Point1.X, edge.Point2.X); //pointOnEdge.Y = MathHelper.Clamp(pointOnEdge.Y, edge.Point1.Y, edge.Point2.Y); return pointOnEdge; }
public bool ContainsPoint(Vector2 p) { if (p.X < MinX || p.X > MaxX || p.Y < MinY || p.Y > MaxY) return false; Vector2 rayStart = new Vector2(MinX - epsilon, p.Y); Vector2 rayEnd = p; LineSegment ray = new LineSegment(rayStart, rayEnd); // Test the ray against all sides int intersections = 0; foreach (LineSegment side in sides) { if (Geometry.LineSegmentIntersect(ray, side)) intersections++; } // if odd return true if ((intersections & 1) == 1) return true; // if even return false else return false; }
// maybe not working /*public static bool LineSegmentIntersect(LineSegment line1, LineSegment line2) { float v1x1 = line1.Point1.X; float v1x2 = line1.Point2.X; float v1y1 = line1.Point1.Y; float v1y2 = line1.Point2.Y; float v2x1 = line2.Point1.X; float v2x2 = line2.Point2.X; float v2y1 = line2.Point1.Y; float v2y2 = line2.Point2.Y; float d1, d2; float a1, a2, b1, b2, c1, c2; // Convert vector 1 to a line (line 1) of infinite length. // We want the line in linear equation standard form: A*x + B*y + C = 0 // See: http://en.wikipedia.org/wiki/Linear_equation a1 = v1y2 - v1y1; //a1 = line1.Point2.Y - line1.Point1.Y; b1 = v1x1 - v1x2; //b1 = line1.Point1.X - line1.Point2.X; c1 = (v1x2 * v1y1) - (v1x1 * v1y2); //c1 = (line1.Point2.X * line1.Point1.Y) - (line1.Point1.X * line1.Point2.Y); // Every point (x,y), that solves the equation above, is on the line, // every point that does not solve it, is either above or below the line. // We insert (x1,y1) and (x2,y2) of vector 2 into the equation above. d1 = (a1 * v2x1) + (b1 * v2y1) + c1; //d1 = (a1 * line2.Point1.X) + (b1 * line2.Point1.Y) + c1; d2 = (a1 * v2x2) + (b1 * v2y2) + c1; //d2 = (a1 * line2.Point2.X) + (b1 * line2.Point2.Y) + c1; // If d1 and d2 both have the same sign, they are both on the same side of // our line 1 and in that case no intersection is possible. Careful, 0 is // a special case, that's why we don't test ">=" and "<=", but "<" and ">". if (d1 > 0 && d2 > 0) return false; if (d1 < 0 && d2 < 0) return false; // We repeat everything above for vector 2. // We start by calculating line 2 in linear equation standard form. a2 = v2y2 - v2y1; //a2 = line2.Point2.Y - line2.Point1.Y; b2 = v2x1 - v2x2; //b2 = line2.Point1.X - line2.Point2.X; c2 = (v2x2 * v1y1) - (v2x1 * v2y2); //c2 = (line2.Point2.X * line1.Point1.Y) - (line2.Point1.X * line2.Point2.Y); // Calulate d1 and d2 again, this time using points of vector 1 d1 = (a2 * v1x1) + (b2 * v1y1) + c2; //d1 = (a2 * line1.Point1.X) + (b2 * line1.Point1.Y) + c2; d2 = (a2 * v1x2) + (b2 * v1y2) + c2; //d2 = (a2 * line1.Point2.X) + (b2 * line1.Point2.Y) + c2; // Again, if both have the same sign (and neither one is 0), // no intersection is possible. if (d1 > 0 && d2 > 0) return false; if (d1 < 0 && d2 < 0) return false; // If we get here, only three possibilities are left. Either the two // vectors intersect in exactly one point or they are collinear // (they both lie both on the same infinite line), in which case they // may intersect in an infinite number of points or not at all. //if ((a1 * b2) - (a2 * b1) == 0.0f) return COLLINEAR; // If they are not collinear, they must intersect in exactly one point. return true; }*/ // might work public static bool LineSegmentIntersect(LineSegment line1, LineSegment line2) { // Find the four orientations needed for general and // special cases int o1 = orientation(line1.Point1, line1.Point2, line2.Point1); int o2 = orientation(line1.Point1, line1.Point2, line2.Point2); int o3 = orientation(line2.Point1, line2.Point2, line1.Point1); int o4 = orientation(line2.Point1, line2.Point2, line1.Point2); // General case if (o1 != o2 && o3 != o4) return true; return false; }
public static LineSegment PointLinePerpendicular(Vector2 point, LineSegment line) { // vector of line Vector2 a = line.Point2 - line.Point1; // vector of point from initial point on line Vector2 b = point - line.Point1; // scalar projection of b onto a float compBOntoA = Vector2.Dot(a, b) / a.Length(); // unit vector of a a = a / a.Length(); // vector projection of b onto a Vector2 projBontoA = a * compBOntoA; // vector projection plus initial point of edge Vector2 pointOnEdge = line.Point1 + projBontoA; // return line from point on line to given point return new LineSegment(pointOnEdge, point); }
/// <summary> /// finds the closest point on a polygon to a given point /// </summary> /// <param name="point">given point</param> /// <param name="polygon">polygon</param> /// <param name="closestEdge">edge the point is on</param> /// <returns>closest point on polygon</returns> public static Vector2 ClosestPointOnPolygon(Vector2 point, Polygon polygon, ref LineSegment closestEdge) { Vector2 closestPoint = Vector2.Zero; float closestDistance = float.MaxValue; foreach (LineSegment side in polygon.Sides) { Vector2 pointOnEdge = ClosestPointOnEdge(point, side); float distance = Vector2.DistanceSquared(point, pointOnEdge); if (distance < closestDistance) { closestPoint = pointOnEdge; closestDistance = distance; closestEdge = side; } } return closestPoint; }