///Returns whether a line segment intersects a polygon (given a list of vertices) public static bool LineSegIntersectsPoly(LineSeg lns, List <Vector2> verts) { //Check to see if either end of the segment is in the polygon if (PointInPoly(lns.CenterA, verts) || PointInPoly(lns.CenterB, verts)) { return(true); } int j = verts.Count - 1; LineSeg lnsCheck = new LineSeg(); //checks every line segment in the polygon until an intersection is found for (int i = 0; i < verts.Count; i++) { lnsCheck.SetA(verts[i]); lnsCheck.SetB(verts[j]); if (LineSegIntersectsLineSeg(lns, lnsCheck)) { return(true); } j = i; } return(false); }
///Returns whether a line segment intersects a circle public static bool LineSegIntersectsCircle(LineSeg lns, Circle c) { //for efficiency, check if either end of the line is in the circle first if (PointInCircle(lns.CenterA, c) || PointInCircle(lns.CenterB, c)) { return(true); } Vector2 point = Vector2.zero; //do checks to see whether the slope is 0 or infinite if (Mathf.Approximately(lns.Slope, 0f)) { point = new Vector2(c.WorldCenter.x, lns.CenterA.y); } else if (lns.Slope == float.PositiveInfinity) { point = new Vector2(lns.CenterA.x, c.WorldCenter.y); } else { //get negative reciprocal of slope of line segment to find a new perpendicular line float slope = -1f / lns.Slope; //find the offset that the new line needs to also contain the center of the circle float offset = -slope * c.WorldCenter.x + c.WorldCenter.y; //calculate point of intersection between the perpendicular lines point.x = (lns.Offset - offset) / (slope - lns.Slope); point.y = slope * point.x + offset; } //check if the calculated point is on the line segment and in the circle return(PointInCircle(point, c) && PointOnLineSeg(point, lns)); }
/* Poly methods */ #region ///Returns whether a polygon intersects another polygon (given a list of vertices) public static bool PolyIntersectsPoly(List <Vector2> verts1, List <Vector2> verts2) { //check to see if any vertices exist inside either polygon (more efficient and catches most cases) for (int i = 0; i < verts1.Count; i++) { Vector2 vert = verts1[i]; if (PointInPoly(vert, verts2)) { return(true); } } for (int i = 0; i < verts2.Count; i++) { Vector2 vert = verts2[i]; if (PointInPoly(vert, new List <Vector2>(verts1))) { return(true); } } //check to see if any of the edges of a polygon intersect with the edges of the other //this code ensures concave shapes work too but it's potentially slow LineSeg lnsCheck = new LineSeg(); int j = verts1.Count - 1; for (int i = 0; i < verts1.Count; i++) { lnsCheck.SetA(verts1[i]); lnsCheck.SetB(verts1[j]); if (LineSegIntersectsPoly(lnsCheck, verts2)) { return(true); } j = i; } return(false); }
///Returns whether a point lies on the perimeter of a polygon given its vertices public static bool PointOnPolyPerimeter(Vector2 p, List <Vector2> verts) { LineSeg lineCheck = new LineSeg(); int j = verts.Count - 1; //checks every line segment of the polygon to see if the point lies on any segment for (int i = 0; i < verts.Count; i++) { lineCheck.SetA(verts[i]); lineCheck.SetB(verts[j]); if (PointOnLineSeg(p, lineCheck)) { return(true); } j = i; } return(false); }
///Returns whether a circle intersects a polygon (given a list of vertices) public static bool CircleIntersectsPoly(Circle c, List <Vector2> verts) { //check to see if the center of the circle is in the poly if (PointInPoly(c.WorldCenter, verts)) { return(true); } //check to see if any points are in the circle for (int i = 0; i < verts.Count; i++) { Vector2 vert = verts[i]; if (PointInCircle(vert, c)) { return(true); } } LineSeg lnsCheck = new LineSeg(); int j = verts.Count - 1; //check each line segment of the polygon until an intersection is found for (int i = 0; i < verts.Count; i++) { lnsCheck.SetA(verts[i]); lnsCheck.SetB(verts[j]); if (LineSegIntersectsCircle(lnsCheck, c)) { return(true); } j = i; } return(false); }
/* LineSeg methods */ #region ///Returns whether a line segment intersects another line segment public static bool LineSegIntersectsLineSeg(LineSeg lns1, LineSeg lns2) { //if lines have the same slope (i.e. parallel or collinear) if (Mathf.Approximately(lns1.Slope, lns2.Slope)) { //returns whether the ends of either segment lies on either segment return(PointOnLineSeg(lns1.CenterA, lns2) || PointOnLineSeg(lns1.CenterB, lns2) || PointOnLineSeg(lns2.CenterA, lns1) || PointOnLineSeg(lns2.CenterB, lns1)); } Vector2 p; //check to see if either line 1 or 2 are vertical (slope would be infinite) //slope and offset are needed for slope intercept form calculation (y = mx + b) if (lns1.Slope == float.PositiveInfinity) { p.x = lns1.Offset; p.y = lns2.Slope * p.x + lns2.Offset; } else if (lns2.Slope == float.PositiveInfinity) { p.x = lns2.Offset; p.y = lns1.Slope * p.x + lns1.Offset; } else { //find point of intersection for line equations p.x = (lns2.Offset - lns1.Offset) / (lns1.Slope - lns2.Slope); p.y = lns1.Slope * p.x + lns1.Offset; } //return whether the calculated point is on both line segments return(PointOnLineSeg(p, lns1) && PointOnLineSeg(p, lns2)); }
///Returns whether a line segment intersects a polygon public static bool LineSegIntersectsPoly(LineSeg lns, Poly p) { return(LineSegIntersectsPoly(lns, p.GetOffsetVerts())); }
///Returns whether a point lies on a line segment public static bool PointOnLineSeg(Vector2 p, LineSeg lns) { //if the distance between p and the segment ends is equal to the length of the segment, then point is on the segment return(Mathf.Approximately(Vector2.Distance(p, lns.CenterA) + Vector2.Distance(p, lns.CenterB), lns.Length)); }