private ContourPolygon ConnectEdges() { var result = new ContourPolygon(); var resultEvents = ResultEvents .Where(it => (it.IsStart && it.InResult) || (!it.IsStart && it.OtherEvent.InResult)).ToList(); // Due to overlapping edges the resultEvents list can be not wholly sorted var sorted = false; while (!sorted) { sorted = true; for (int i = 0; i < resultEvents.Count; i++) { if (i + 1 < resultEvents.Count && SweepEvent.CompareTo(resultEvents[i], resultEvents[i + 1]) == 1) { var tmp = resultEvents[i]; resultEvents[i] = resultEvents[i + 1]; resultEvents[i + 1] = tmp; sorted = false; } } } // We cannot do a foreach because we need to set PositionInResult for (int i = 0; i < resultEvents.Count; i++) { var resultEvent = resultEvents[i]; resultEvent.PositionInResult = i; } foreach (var resultEvent in resultEvents) { if (!resultEvent.IsStart) { var tmp = resultEvent.PositionInResult; resultEvent.PositionInResult = resultEvent.OtherEvent.PositionInResult; resultEvent.OtherEvent.PositionInResult = tmp; } } var processed = new BitArray(resultEvents.Count); var depth = new List <int>(); var holeOf = new List <int>(); for (int i = 0; i < resultEvents.Count; i++) { if (processed[i]) { continue; } var contour = new Contour(); result.Add(contour); var contourId = result.NumberOfContours - 1; depth.Add(0); holeOf.Add(-1); if (resultEvents[i].PreviousInResult != null) { var lowerContourId = resultEvents[i].PreviousInResult.ContourId; if (!resultEvents[i].PreviousInResult.ResultInOut) { result[lowerContourId].AddHole(contourId); holeOf[contourId] = lowerContourId; depth[contourId] = depth[lowerContourId] + 1; contour.External = false; } else if (!result[lowerContourId].External) { result[holeOf[lowerContourId]].AddHole(contourId); holeOf[contourId] = holeOf[lowerContourId]; depth[contourId] = depth[lowerContourId]; contour.External = false; } } var pos = i; var initial = resultEvents[i].Point; contour.AddVertex(initial); while (pos >= i) { processed[pos] = true; if (resultEvents[pos].IsStart) { resultEvents[pos].ResultInOut = false; resultEvents[pos].ContourId = contourId; } else { resultEvents[pos].OtherEvent.ResultInOut = true; resultEvents[pos].OtherEvent.ContourId = contourId; } pos = resultEvents[pos].PositionInResult; processed[pos] = true; contour.AddVertex(resultEvents[pos].Point); pos = NextPos(pos, resultEvents, processed, i); } pos = pos == -1 ? i : pos; processed[pos] = processed[resultEvents[pos].PositionInResult] = true; resultEvents[pos].OtherEvent.ResultInOut = true; resultEvents[pos].OtherEvent.ContourId = contourId; if ((depth[contourId] & 1) != 0) { contour.ChangeOrientation(); } } return(result); }