// // Is a point intersecting with a polygon? // //The list describing the polygon has to be sorted either clockwise or counter-clockwise because we have to identify its edges //TODO: May sometimes fail because of floating point precision issues public static bool PointPolygon(List <MyVector2> polygonPoints, MyVector2 point) { //Step 1. Find a point outside of the polygon //Pick a point with a x position larger than the polygons max x position, which is always outside MyVector2 maxXPosVertex = polygonPoints[0]; for (int i = 1; i < polygonPoints.Count; i++) { if (polygonPoints[i].x > maxXPosVertex.x) { maxXPosVertex = polygonPoints[i]; } } //The point should be outside so just pick a number to move it outside //Should also move it up a little to minimize floating point precision issues //This is where it fails if this line is exactly on a vertex MyVector2 pointOutside = maxXPosVertex + new MyVector2(1f, 0.01f); //Step 2. Create an edge between the point we want to test with the point thats outside MyVector2 l1_p1 = point; MyVector2 l1_p2 = pointOutside; //Debug.DrawLine(l1_p1.XYZ(), l1_p2.XYZ()); //Step 3. Find out how many edges of the polygon this edge is intersecting with int numberOfIntersections = 0; for (int i = 0; i < polygonPoints.Count; i++) { //Line 2 MyVector2 l2_p1 = polygonPoints[i]; int iPlusOne = MathUtility.ClampListIndex(i + 1, polygonPoints.Count); MyVector2 l2_p2 = polygonPoints[iPlusOne]; //Are the lines intersecting? if (Intersections.LineLine(l1_p1, l1_p2, l2_p1, l2_p2, shouldIncludeEndPoints: true)) { numberOfIntersections += 1; } } //Step 4. Is the point inside or outside? bool isInside = true; //The point is outside the polygon if number of intersections is even or 0 if (numberOfIntersections == 0 || numberOfIntersections % 2 == 0) { isInside = false; } return(isInside); }
//Is an edge crossing another edge? private static bool IsEdgeCrossingEdge(MyVector2 e1_p1, MyVector2 e1_p2, MyVector2 e2_p1, MyVector2 e2_p2) { //We will here run into floating point precision issues so we have to be careful //To solve that you can first check the end points //and modify the line-line intersection algorithm to include a small epsilon //First check if the edges are sharing a point, if so they are not crossing if (e1_p1.Equals(e2_p1) || e1_p1.Equals(e2_p2) || e1_p2.Equals(e2_p1) || e1_p2.Equals(e2_p2)) { return(false); } //Then check if the lines are intersecting if (!Intersections.LineLine(e1_p1, e1_p2, e2_p1, e2_p2, shouldIncludeEndPoints: false)) { return(false); } return(true); }
public static List <List <MyVector2> > ClipPolygons(List <MyVector2> polyVector2, List <MyVector2> clipPolyVector2, BooleanOperation booleanOperation) { List <List <MyVector2> > finalPoly = new List <List <MyVector2> >(); //Step 0. Create the data structure needed List <ClipVertex> poly = InitDataStructure(polyVector2); List <ClipVertex> clipPoly = InitDataStructure(clipPolyVector2); //Step 1. Find intersection points //Need to test if we have found an intersection point, //if none is found, the polygons dont intersect, or one polygon is inside the other bool hasFoundIntersection = false; for (int i = 0; i < poly.Count; i++) { ClipVertex currentVertex = poly[i]; //Important to use iPlusOne because poly.next may change int iPlusOne = MathUtility.ClampListIndex(i + 1, poly.Count); MyVector2 a = poly[i].coordinate; MyVector2 b = poly[iPlusOne].coordinate; //Gizmos.DrawWireSphere(poly[i].coordinate, 0.02f); //Gizmos.DrawWireSphere(poly[i].next.coordinate, 0.02f); for (int j = 0; j < clipPoly.Count; j++) { int jPlusOne = MathUtility.ClampListIndex(j + 1, clipPoly.Count); MyVector2 c = clipPoly[j].coordinate; MyVector2 d = clipPoly[jPlusOne].coordinate; //Are these lines intersecting? if (Intersections.LineLine(a, b, c, d, true)) { hasFoundIntersection = true; MyVector2 intersectionPoint2D = Intersections.GetLineLineIntersectionPoint(a, b, c, d); //Vector3 intersectionPoint = new Vector3(intersectionPoint2D.x, 0f, intersectionPoint2D.y); //Gizmos.color = Color.red; //Gizmos.DrawWireSphere(intersectionPoint, 0.04f); //We need to insert this intersection vertex into both polygons //Insert into the polygon ClipVertex vertexOnPolygon = InsertIntersectionVertex(a, b, intersectionPoint2D, currentVertex); //Insert into the clip polygon ClipVertex vertexOnClipPolygon = InsertIntersectionVertex(c, d, intersectionPoint2D, clipPoly[j]); //Also connect the intersection vertices with each other vertexOnPolygon.neighbor = vertexOnClipPolygon; vertexOnClipPolygon.neighbor = vertexOnPolygon; } } } //Debug in which order the vertices are in the linked list //InWhichOrderAreVerticesAdded(poly); //InWhichOrderAreVerticesAdded(clipPoly); //If the polygons are intersecting if (hasFoundIntersection) { //Step 2. Trace each polygon and mark entry and exit points to the other polygon's interior MarkEntryExit(poly, clipPolyVector2); MarkEntryExit(clipPoly, polyVector2); //Debug entry exit points DebugEntryExit(poly); //DebugEntryExit(clipPoly); //Step 3. Create the desired clipped polygon if (booleanOperation == BooleanOperation.Intersection) { //Where the two polygons intersect List <ClipVertex> intersectionVertices = GetClippedPolygon(poly, true); //Debug.Log(intersectionVertices.Count); AddPolygonToList(intersectionVertices, finalPoly, false); //Debug.Log(); } else if (booleanOperation == BooleanOperation.Difference) { //Whats outside of the polygon that doesnt intersect List <ClipVertex> outsidePolyVertices = GetClippedPolygon(poly, false); AddPolygonToList(outsidePolyVertices, finalPoly, true); } else if (booleanOperation == BooleanOperation.ExclusiveOr) { //Whats outside of the polygon that doesnt intersect List <ClipVertex> outsidePolyVertices = GetClippedPolygon(poly, false); AddPolygonToList(outsidePolyVertices, finalPoly, true); //Whats outside of the polygon that doesnt intersect List <ClipVertex> outsideClipPolyVertices = GetClippedPolygon(clipPoly, false); AddPolygonToList(outsideClipPolyVertices, finalPoly, true); } else if (booleanOperation == BooleanOperation.Union) { //Where the two polygons intersect List <ClipVertex> intersectionVertices = GetClippedPolygon(poly, true); AddPolygonToList(intersectionVertices, finalPoly, false); //Whats outside of the polygon that doesnt intersect List <ClipVertex> outsidePolyVertices = GetClippedPolygon(poly, false); AddPolygonToList(outsidePolyVertices, finalPoly, true); //Whats outside of the polygon that doesnt intersect List <ClipVertex> outsideClipPolyVertices = GetClippedPolygon(clipPoly, false); AddPolygonToList(outsideClipPolyVertices, finalPoly, true); } //Where the two polygons intersect //List<ClipVertex> intersectionVertices = GetClippedPolygon(poly, true); //Whats outside of the polygon that doesnt intersect //These will be in clockwise order so remember to change to counter clockwise //List<ClipVertex> outsidePolyVertices = GetClippedPolygon(poly, false); //List<ClipVertex> outsideClipPolyVertices = GetClippedPolygon(clipPoly, false); } //Check if one polygon is inside the other else { //Is the polygon inside the clip polygon? //Depending on the type of boolean operation, we might get a hole if (IsPolygonInsidePolygon(polyVector2, clipPolyVector2)) { Debug.Log("Poly is inside clip poly"); } else if (IsPolygonInsidePolygon(clipPolyVector2, polyVector2)) { Debug.Log("Clip poly is inside poly"); } else { Debug.Log("Polygons are not intersecting"); } } return(finalPoly); }