public static List <List <Vector2> > Simplify(List <Vector2> vertices, List <List <Vector2> > holes) { var vertexIndexSet = new HashSet <int>(); for (var holeIndex = holes.Count - 1; holeIndex >= 0; holeIndex--) { var holeVertexIndex = 0; if (!TryFindASurgerySegment(vertices, holes, holeIndex, ref holeVertexIndex, new Segment(), vertexIndexSet, out var surgerySegment1)) { continue; } var removedHole = holes[holeIndex]; var surgerySegment = new Segment(removedHole[surgerySegment1.holeVertIndex], vertices[surgerySegment1.vertIndex]); holeVertexIndex++; if (!TryFindASurgerySegment(vertices, holes, holeIndex, ref holeVertexIndex, surgerySegment, vertexIndexSet, out var surgerySegment2)) { continue; } //Create subpolygons var vertexCount = vertices.Count; var holeVertexCount = removedHole.Count; var polygon1 = new List <Vector2>(); var startIndex = surgerySegment1.vertIndex; var endIndex = surgerySegment2.vertIndex; var index = startIndex; while (index != endIndex) { polygon1.Add(vertices[index]); index = (index + 1) % vertexCount; } polygon1.Add(vertices[endIndex]); startIndex = surgerySegment2.holeVertIndex; endIndex = surgerySegment1.holeVertIndex; index = startIndex; while (index != endIndex) { polygon1.Add(removedHole[index]); if (--index < 0) { index += holeVertexCount; } } polygon1.Add(removedHole[endIndex]); var polygon2 = new List <Vector2>(); startIndex = surgerySegment2.vertIndex; endIndex = surgerySegment1.vertIndex; index = startIndex; while (index != endIndex) { polygon2.Add(vertices[index]); index = (index + 1) % vertexCount; } polygon2.Add(vertices[endIndex]); startIndex = surgerySegment1.holeVertIndex; endIndex = surgerySegment2.holeVertIndex; index = startIndex; while (index != endIndex) { polygon2.Add(removedHole[index]); if (--index < 0) { index += holeVertexCount; } } polygon2.Add(removedHole[endIndex]); holes.RemoveAt(holeIndex); var polygon1Holes = new List <List <Vector2> >(); var polygon2Holes = new List <List <Vector2> >(); for (var i = 0; i < holes.Count; i++) { var hole = holes[i]; if (PolygonInclude(polygon1, hole[0])) { polygon1Holes.Add(hole); } else { polygon2Holes.Add(hole); } } var subPolygons = new List <List <Vector2> >(2); if (polygon1Holes.Count > 0) { var innerSubPolygons = Simplify(polygon1, polygon1Holes); for (var i = 0; i < innerSubPolygons.Count; i++) { subPolygons.Add(innerSubPolygons[i]); } } else { subPolygons.Add(polygon1); } if (polygon2Holes.Count > 0) { var innerSubPolygons = Simplify(polygon2, polygon2Holes); for (var i = 0; i < innerSubPolygons.Count; i++) { subPolygons.Add(innerSubPolygons[i]); } } else { subPolygons.Add(polygon2); } return(subPolygons); } throw new Exception("Could not find the " + nameof(SurgerySegment) + " couple!"); }
private static bool TryFindASurgerySegment(List <Vector2> vertices, List <List <Vector2> > holes, int holeIndex, ref int holeVertexIndex, Segment otherSurgerySegment, HashSet <int> vertexIndexSet, out SurgerySegment surgerySegment) { var holeCount = holes.Count; var hole = holes[holeIndex]; var holeVertexCount = hole.Count; for (; holeVertexIndex < holeVertexCount; holeVertexIndex++) { var holeVertex = hole[holeVertexIndex]; var vertexCount = vertices.Count; for (var vertIndex = 0; vertIndex < vertexCount; vertIndex++) { if (vertexIndexSet.Contains(vertIndex)) { continue; } var vertex = vertices[vertIndex]; var segment = new Segment(holeVertex, vertex); var intersection = Segment.Intersect(segment, otherSurgerySegment); if (intersection) { continue; } var nextHoleVertexIndex = (holeVertexIndex + 1) % holeVertexCount; for (var j = 0; j < holeVertexCount - 2; j++) { var index = (nextHoleVertexIndex + j) % holeVertexCount; var comparedSegment = new Segment(hole[index], hole[(index + 1) % holeVertexCount]); if (Segment.Intersect(segment, comparedSegment)) { intersection = true; break; } } if (intersection) { continue; } for (var j = 0; j < holeCount; j++) { if (j == holeIndex) { continue; } var comparedHole = holes[j]; if (Segment.Intersect(segment, comparedHole)) { intersection = true; break; } } if (intersection) { continue; } var nextVertexIndex = (vertIndex + 1) % vertexCount; for (var j = 0; j < vertexCount - 2; j++) { var index = (nextVertexIndex + j) % vertexCount; var comparedSegment = new Segment(vertices[index], vertices[(index + 1) % vertexCount]); if (Segment.Intersect(segment, comparedSegment)) { intersection = true; break; } } if (!intersection) { // Debug.DrawLine(segment.p, segment.q, Color.red, 10); vertexIndexSet.Add(vertIndex); surgerySegment = new SurgerySegment(holeVertexIndex, vertIndex); return(true); } } } surgerySegment = new SurgerySegment(); return(false); }