public static void InitializeHoles(List <Contour> holes, ITriangulatable parent, ConstrainedPointSet cps) { int numHoles = holes.Count; int holeIdx = 0; // pass 1 - remove duplicates while (holeIdx < numHoles) { int hole2Idx = holeIdx + 1; while (hole2Idx < numHoles) { bool bSamePolygon = PolygonUtil.PolygonsAreSame2D(holes [holeIdx], holes [hole2Idx]); if (bSamePolygon) { // remove one of them holes.RemoveAt(hole2Idx); --numHoles; } else { ++hole2Idx; } } ++holeIdx; } // pass 2: Intersections and Containment holeIdx = 0; while (holeIdx < numHoles) { bool bIncrementHoleIdx = true; int hole2Idx = holeIdx + 1; while (hole2Idx < numHoles) { if (PolygonUtil.PolygonContainsPolygon(holes [holeIdx], holes [holeIdx].Bounds, holes [hole2Idx], holes [hole2Idx].Bounds, false)) { holes [holeIdx].AddHole(holes [hole2Idx]); holes.RemoveAt(hole2Idx); --numHoles; } else if (PolygonUtil.PolygonContainsPolygon(holes [hole2Idx], holes [hole2Idx].Bounds, holes [holeIdx], holes [holeIdx].Bounds, false)) { holes [hole2Idx].AddHole(holes [holeIdx]); holes.RemoveAt(holeIdx); --numHoles; bIncrementHoleIdx = false; break; } else { bool bIntersect = PolygonUtil.PolygonsIntersect2D(holes [holeIdx], holes [holeIdx].Bounds, holes [hole2Idx], holes [hole2Idx].Bounds); if (bIntersect) { // this is actually an error condition // fix by merging hole1 and hole2 into hole1 (including the holes inside hole2!) and delete hole2 // Then, because hole1 is now changed, restart it's check. PolygonOperationContext ctx = new PolygonOperationContext(); if (!ctx.Init(PolygonUtil.PolyOperation.Union | PolygonUtil.PolyOperation.Intersect, holes [holeIdx], holes [hole2Idx])) { if (ctx.mError == PolygonUtil.PolyUnionError.Poly1InsidePoly2) { holes [hole2Idx].AddHole(holes [holeIdx]); holes.RemoveAt(holeIdx); --numHoles; bIncrementHoleIdx = false; break; } else { throw new Exception("PolygonOperationContext.Init had an error during initialization"); } } PolygonUtil.PolyUnionError pue = PolygonUtil.PolygonOperation(ctx); if (pue == PolygonUtil.PolyUnionError.None) { Point2DList union = ctx.Union; Point2DList intersection = ctx.Intersect; // create a new contour for the union Contour c = new Contour(parent); c.AddRange(union); c.Name = "(" + holes [holeIdx].Name + " UNION " + holes [hole2Idx].Name + ")"; c.WindingOrder = Point2DList.WindingOrderType.Default; // add children from both of the merged contours int numChildHoles = holes [holeIdx].GetNumHoles(); for (int i = 0; i < numChildHoles; ++i) { c.AddHole(holes [holeIdx].GetHole(i)); } numChildHoles = holes [hole2Idx].GetNumHoles(); for (int i = 0; i < numChildHoles; ++i) { c.AddHole(holes [hole2Idx].GetHole(i)); } // make sure we preserve the contours of the intersection Contour cInt = new Contour(c); cInt.AddRange(intersection); cInt.Name = "(" + holes [holeIdx].Name + " INTERSECT " + holes [hole2Idx].Name + ")"; cInt.WindingOrder = Point2DList.WindingOrderType.Default; c.AddHole(cInt); // replace the current contour with the merged contour holes [holeIdx] = c; // toss the second contour holes.RemoveAt(hole2Idx); --numHoles; // current hole is "examined", so move to the next one hole2Idx = holeIdx + 1; } else { throw new Exception("PolygonOperation had an error!"); } } else { ++hole2Idx; } } } if (bIncrementHoleIdx) { ++holeIdx; } } numHoles = holes.Count; holeIdx = 0; while (holeIdx < numHoles) { int numPoints = holes [holeIdx].Count; for (int i = 0; i < numPoints; ++i) { int j = holes [holeIdx].NextIndex(i); uint constraintCode = TriangulationConstraint.CalculateContraintCode(holes [holeIdx] [i], holes [holeIdx] [j]); TriangulationConstraint tc = null; if (!cps.TryGetConstraint(constraintCode, out tc)) { tc = new TriangulationConstraint(holes [holeIdx] [i], holes [holeIdx] [j]); cps.AddConstraint(tc); } // replace the points in the holes with valid points if (holes [holeIdx] [i].VertexCode == tc.P.VertexCode) { holes [holeIdx] [i] = tc.P; } else if (holes [holeIdx] [j].VertexCode == tc.P.VertexCode) { holes [holeIdx] [j] = tc.P; } if (holes [holeIdx] [i].VertexCode == tc.Q.VertexCode) { holes [holeIdx] [i] = tc.Q; } else if (holes [holeIdx] [j].VertexCode == tc.Q.VertexCode) { holes [holeIdx] [j] = tc.Q; } } ++holeIdx; } }