private ArrayList PruneEdges(ArrayList edges) { var numedges = edges.Count; if (numedges < 2) { return(edges); } var temp = edges.ToArray(); Edge[] edgelist = new Edge[temp.Length]; for (int i = 0; i < temp.Length; i++) { edgelist[i] = temp[i] as Edge; } Array.Sort(edgelist, YXTopComparator); Edge e; var left = 0; var right = 0; var yrange = new double[2]; var subcurves = new ArrayList(); var chains = new ArrayList(); var links = new ArrayList(); // Active edges are between left (inclusive) and right (exclusive) while (left < numedges) { double y = yrange[0]; // Prune active edges that fall off the top of the active y range int next; int cur; for (cur = next = right - 1; cur >= left; cur--) { e = edgelist[cur]; if (e.GetCurve().GetYBot() > y) { if (next > cur) { edgelist[next] = e; } next--; } } left = next + 1; // Grab a new "top of Y range" if the active edges are empty if (left >= right) { if (right >= numedges) { break; } y = edgelist[right].GetCurve().GetYTop(); if (y > yrange[0]) { FinalizeSubCurves(subcurves, chains); } yrange[0] = y; } // Incorporate new active edges that enter the active y range while (right < numedges) { e = edgelist[right]; if (e.GetCurve().GetYTop() > y) { break; } right++; } // Sort the current active edges by their X values and // determine the maximum valid Y range where the X ordering // is correct yrange[1] = edgelist[left].GetCurve().GetYBot(); if (right < numedges) { y = edgelist[right].GetCurve().GetYTop(); if (yrange[1] > y) { yrange[1] = y; } } // Note: We could start at left+1, but we need to make // sure that edgelist[left] has its equivalence set to 0. int nexteq = 1; for (cur = left; cur < right; cur++) { e = edgelist[cur]; e.SetEquivalence(0); for (next = cur; next > left; next--) { Edge prevedge = edgelist[next - 1]; int ordering = e.CompareTo(prevedge, yrange); if (yrange[1] <= yrange[0]) { throw new SystemException("backstepping to " + yrange[1] + " from " + yrange[0]); } if (ordering >= 0) { if (ordering == 0) { // If the curves are equal, mark them to be // deleted later if they cancel each other // out so that we avoid having extraneous // curve segments. int eq = prevedge.GetEquivalence(); if (eq == 0) { eq = nexteq++; prevedge.SetEquivalence(eq); } e.SetEquivalence(eq); } break; } edgelist[next] = prevedge; } edgelist[next] = e; } // Now prune the active edge list. // For each edge in the list, determine its classification // (entering shape, exiting shape, ignore - no change) and // record the current Y range and its classification in the // Edge object for use later in constructing the new outline. NewRow(); double ystart = yrange[0]; double yend = yrange[1]; for (cur = left; cur < right; cur++) { e = edgelist[cur]; int etag; int eq = e.GetEquivalence(); if (eq != 0) { // Find one of the segments in the "equal" range // with the right transition state and prefer an // edge that was either active up until ystart // or the edge that extends the furthest downward // (i.e. has the most potential for continuation) int origstate = GetState(); etag = (origstate == RSTAG_INSIDE ? ETAG_EXIT : ETAG_ENTER); Edge activematch = null; Edge longestmatch = e; double furthesty = yend; do { // Note: classify() must be called // on every edge we consume here. Classify(e); if (activematch == null && e.IsActiveFor(ystart, etag)) { activematch = e; } y = e.GetCurve().GetYBot(); if (y > furthesty) { longestmatch = e; furthesty = y; } } while (++cur < right && (e = edgelist[cur]).GetEquivalence() == eq); --cur; if (GetState() == origstate) { etag = ETAG_IGNORE; } else { e = (activematch != null ? activematch : longestmatch); } } else { etag = Classify(e); } if (etag != ETAG_IGNORE) { e.Record(yend, etag); links.Add(new CurveLink(e.GetCurve(), ystart, yend, etag)); } } // assert(getState() == AreaOp.RSTAG_OUTSIDE); if (GetState() != RSTAG_OUTSIDE) { for (cur = left; cur < right; cur++) { e = edgelist[cur]; if (e != null) { e.GetEquivalence(); } } } ResolveLinks(subcurves, chains, links); links.Clear(); // Finally capture the bottom of the valid Y range as the top // of the next Y range. yrange[0] = yend; } FinalizeSubCurves(subcurves, chains); ArrayList ret = new ArrayList(); IEnumerator enumerator = subcurves.GetEnumerator(); while (enumerator.MoveNext()) { CurveLink link = (CurveLink)enumerator.Current; ret.Add(link.GetMoveto()); CurveLink nextlink = link; while ((nextlink = nextlink.GetNext()) != null) { if (!link.Absorb(nextlink)) { ret.Add(link.GetSubCurve()); link = nextlink; } } ret.Add(link.GetSubCurve()); } return(ret); }