public static void PolygonSubtractInternal(PolygonOperationContext ctx) { Point2DList subtract = ctx.Subtract; if (ctx.mStartingIndex == -1) { switch (ctx.mError) { case PolygonUtil.PolyUnionError.NoIntersections: case PolygonUtil.PolyUnionError.InfiniteLoop: case PolygonUtil.PolyUnionError.Poly1InsidePoly2: return; } } Point2DList currentPoly = ctx.mPoly1; Point2DList otherPoly = ctx.mPoly2; List<int> currentPolyVectorAngles = ctx.mPoly1VectorAngles; // Store the starting vertex so we can refer to it later. Point2D startingVertex = ctx.mPoly1[ctx.mStartingIndex]; int currentIndex = ctx.mStartingIndex; subtract.Clear(); // Trace direction bool forward = true; do { // Add the current vertex to the final union subtract.Add(currentPoly[currentIndex]); foreach (EdgeIntersectInfo intersect in ctx.mIntersections) { // If the current point is an intersection point if (currentPoly[currentIndex].Equals(intersect.IntersectionPoint, currentPoly.Epsilon)) { // Make sure we want to swap polygons here. int otherIndex = otherPoly.IndexOf(intersect.IntersectionPoint); //Point2D otherVertex; if (forward) { // If the next vertex, if we do swap, is inside the current polygon, // then its safe to swap, otherwise, just carry on with the current poly. int compareIndex = otherPoly.PreviousIndex(otherIndex); Point2D compareVertex = otherPoly[compareIndex]; bool bPointInPolygonAngle = false; if (currentPolyVectorAngles[compareIndex] == -1) { bPointInPolygonAngle = ctx.PointInPolygonAngle(compareVertex, currentPoly); currentPolyVectorAngles[compareIndex] = bPointInPolygonAngle ? 1 : 0; } else { bPointInPolygonAngle = (currentPolyVectorAngles[compareIndex] == 1) ? true : false; } if (bPointInPolygonAngle) { // switch polygons if (currentPoly == ctx.mPoly1) { currentPoly = ctx.mPoly2; currentPolyVectorAngles = ctx.mPoly2VectorAngles; otherPoly = ctx.mPoly1; } else { currentPoly = ctx.mPoly1; currentPolyVectorAngles = ctx.mPoly1VectorAngles; otherPoly = ctx.mPoly2; } // set currentIndex currentIndex = otherIndex; // Reverse direction forward = !forward; // Stop checking ctx.mIntersections for this point. break; } } else { // If the next vertex, if we do swap, is outside the current polygon, // then its safe to swap, otherwise, just carry on with the current poly. int compareIndex = otherPoly.NextIndex(otherIndex); Point2D compareVertex = otherPoly[compareIndex]; bool bPointInPolygonAngle = false; if (currentPolyVectorAngles[compareIndex] == -1) { bPointInPolygonAngle = ctx.PointInPolygonAngle(compareVertex, currentPoly); currentPolyVectorAngles[compareIndex] = bPointInPolygonAngle ? 1 : 0; } else { bPointInPolygonAngle = (currentPolyVectorAngles[compareIndex] == 1) ? true : false; } if (!bPointInPolygonAngle) { // switch polygons if (currentPoly == ctx.mPoly1) { currentPoly = ctx.mPoly2; currentPolyVectorAngles = ctx.mPoly2VectorAngles; otherPoly = ctx.mPoly1; } else { currentPoly = ctx.mPoly1; currentPolyVectorAngles = ctx.mPoly1VectorAngles; otherPoly = ctx.mPoly2; } // set currentIndex currentIndex = otherIndex; // Reverse direction forward = !forward; // Stop checking intersections for this point. break; } } } } if (forward) { // Move to next index currentIndex = currentPoly.NextIndex(currentIndex); } else { currentIndex = currentPoly.PreviousIndex(currentIndex); } } while ((currentPoly[currentIndex] != startingVertex) && (subtract.Count <= (ctx.mPoly1.Count + ctx.mPoly2.Count))); // If the number of vertices in the union is more than the combined vertices // of the input polygons, then something is wrong and the algorithm will // loop forever. Luckily, we check for that. if (subtract.Count > (ctx.mPoly1.Count + ctx.mPoly2.Count)) { ctx.mError = PolygonUtil.PolyUnionError.InfiniteLoop; } return; }
protected static void PolygonIntersectInternal(PolygonOperationContext ctx) { Point2DList intersectOut = ctx.Intersect; if (ctx.mStartingIndex == -1) { switch (ctx.mError) { case PolygonUtil.PolyUnionError.NoIntersections: case PolygonUtil.PolyUnionError.InfiniteLoop: return; case PolygonUtil.PolyUnionError.Poly1InsidePoly2: intersectOut.AddRange(ctx.mOriginalPolygon2); return; } } Point2DList currentPoly = ctx.mPoly1; Point2DList otherPoly = ctx.mPoly2; List<int> currentPolyVectorAngles = ctx.mPoly1VectorAngles; // Store the starting vertex so we can refer to it later. int currentIndex = ctx.mPoly1.IndexOf(ctx.mIntersections[0].IntersectionPoint); Point2D startingVertex = ctx.mPoly1[currentIndex]; int firstPoly1Index = currentIndex; int firstPoly2Index = -1; intersectOut.Clear(); do { // Add the current vertex to the final intersection if (intersectOut.Contains(currentPoly[currentIndex])) { // This can happen when the two polygons only share a single edge, and neither is inside the other break; } intersectOut.Add(currentPoly[currentIndex]); foreach (EdgeIntersectInfo intersect in ctx.mIntersections) { // If the current point is an intersection point if (currentPoly[currentIndex].Equals(intersect.IntersectionPoint, currentPoly.Epsilon)) { // Make sure we want to swap polygons here. int otherIndex = otherPoly.IndexOf(intersect.IntersectionPoint); // If the next vertex, if we do swap, is inside the current polygon, // then its safe to swap, otherwise, just carry on with the current poly. int comparePointIndex = otherPoly.NextIndex(otherIndex); Point2D comparePoint = otherPoly[comparePointIndex]; bool bPointInPolygonAngle = false; if (currentPolyVectorAngles[comparePointIndex] == -1) { bPointInPolygonAngle = ctx.PointInPolygonAngle(comparePoint, currentPoly); currentPolyVectorAngles[comparePointIndex] = bPointInPolygonAngle ? 1 : 0; } else { bPointInPolygonAngle = (currentPolyVectorAngles[comparePointIndex] == 1) ? true : false; } if (bPointInPolygonAngle) { // switch polygons if (currentPoly == ctx.mPoly1) { currentPoly = ctx.mPoly2; currentPolyVectorAngles = ctx.mPoly2VectorAngles; otherPoly = ctx.mPoly1; if (firstPoly2Index < 0) { firstPoly2Index = otherIndex; } } else { currentPoly = ctx.mPoly1; currentPolyVectorAngles = ctx.mPoly1VectorAngles; otherPoly = ctx.mPoly2; } // set currentIndex currentIndex = otherIndex; // Stop checking intersections for this point. break; } } } // Move to next index currentIndex = currentPoly.NextIndex(currentIndex); if (currentPoly == ctx.mPoly1) { if (currentIndex == firstPoly1Index) { break; } } else { if (firstPoly2Index >= 0 && currentIndex == firstPoly2Index) { break; } } } while ((currentPoly[currentIndex] != startingVertex) && (intersectOut.Count <= (ctx.mPoly1.Count + ctx.mPoly2.Count))); // If the number of vertices in the union is more than the combined vertices // of the input polygons, then something is wrong and the algorithm will // loop forever. Luckily, we check for that. if (intersectOut.Count > (ctx.mPoly1.Count + ctx.mPoly2.Count)) { ctx.mError = PolygonUtil.PolyUnionError.InfiniteLoop; } return; }