public ChainEnd(CurveLink first, ChainEnd partner) { _head = first; _tail = first; _partner = partner; _etag = first.GetEdgeTag(); }
public static void FinalizeSubCurves(ArrayList subcurves, ArrayList chains) { int numchains = chains.Count; if (numchains == 0) { return; } if ((numchains & 1) != 0) { throw new SystemException("Odd number of chains!"); } var tempArray = chains.ToArray(); ChainEnd[] endlist = new ChainEnd[tempArray.Length]; for (int i = 0; i < tempArray.Length; i++) { endlist[i] = tempArray[i] as ChainEnd; } for (int i = 1; i < numchains; i += 2) { ChainEnd open = endlist[i - 1]; ChainEnd close = endlist[i]; CurveLink subcurve = open.LinkTo(close); if (subcurve != null) { subcurves.Add(subcurve); } } chains.Clear(); }
public void AddLink(CurveLink newlink) { if (_etag == AreaOp.ETAG_ENTER) { _tail.SetNext(newlink); _tail = newlink; } else { newlink.SetNext(_head); _head = newlink; } }
public bool Absorb(CurveLink link) { return(Absorb(link._curve, link._ytop, link._ybot, link._etag)); }
public void SetNext(CurveLink link) { _next = link; }
public static void ResolveLinks(ArrayList subcurves, ArrayList chains, ArrayList links) { int numlinks = links.Count; CurveLink[] linklist; if (numlinks == 0) { linklist = EmptyLinkList; } else { if ((numlinks & 1) != 0) { throw new SystemException("Odd number of new curves!"); } var tempArray = links.ToArray(); linklist = new CurveLink[numlinks + 2]; for (int i = 0; i < tempArray.Length; i++) { linklist[i] = tempArray[i] as CurveLink; } } int numchains = chains.Count; ChainEnd[] endlist; if (numchains == 0) { endlist = EmptyChainList; } else { if ((numchains & 1) != 0) { throw new SystemException("Odd number of chains!"); } var tempArray = chains.ToArray(); endlist = new ChainEnd[numchains + 2]; for (int i = 0; i < tempArray.Length; i++) { endlist[i] = tempArray[i] as ChainEnd; } } int curchain = 0; int curlink = 0; chains.Clear(); ChainEnd chain = endlist[0]; ChainEnd nextchain = endlist[1]; CurveLink link = linklist[0]; CurveLink nextlink = linklist[1]; while (chain != null || link != null) { /* * Strategy 1: * Connect chains or links if they are the only things left... */ bool connectchains = (link == null); bool connectlinks = (chain == null); if (!connectchains && !connectlinks) { // assert(link != null && chain != null); /* * Strategy 2: * Connect chains or links if they close off an open area... */ if (nextchain != null) { connectchains = ((curchain & 1) == 0 && chain.GetX() == nextchain.GetX()); } if (nextlink != null) { connectlinks = ((curlink & 1) == 0 && link.GetX() == nextlink.GetX()); if (!connectchains && !connectlinks) { /* * Strategy 3: * Connect chains or links if their successor is * between them and their potential connectee... */ double cx = chain.GetX(); double lx = link.GetX(); connectchains = (nextchain != null && cx < lx && Obstructs(nextchain.GetX(), lx, curchain)); connectlinks = (lx < cx && Obstructs(nextlink.GetX(), cx, curlink)); } } } if (connectchains) { CurveLink subcurve = chain.LinkTo(nextchain); if (subcurve != null) { subcurves.Add(subcurve); } curchain += 2; chain = endlist[curchain]; nextchain = endlist[curchain + 1]; } if (connectlinks) { ChainEnd openend = new ChainEnd(link, null); ChainEnd closeend = new ChainEnd(nextlink, openend); openend.SetOtherEnd(closeend); chains.Add(openend); chains.Add(closeend); curlink += 2; link = linklist[curlink]; nextlink = linklist[curlink + 1]; } if (!connectchains && !connectlinks) { // assert(link != null); // assert(chain != null); // assert(chain.getEtag() == link.getEtag()); chain.AddLink(link); chains.Add(chain); curchain++; chain = nextchain; nextchain = endlist[curchain + 1]; curlink++; link = nextlink; nextlink = linklist[curlink + 1]; } } }
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); }
public bool Absorb(CurveLink link) { return Absorb(link._curve, link._ytop, link._ybot, link._etag); }
public static void ResolveLinks(ArrayList subcurves, ArrayList chains, ArrayList links) { int numlinks = links.Count; CurveLink[] linklist; if (numlinks == 0) { linklist = EmptyLinkList; } else { if ((numlinks & 1) != 0) { throw new SystemException("Odd number of new curves!"); } var tempArray = links.ToArray(); linklist = new CurveLink[numlinks + 2]; for (int i = 0; i < tempArray.Length; i++) { linklist[i] = tempArray[i] as CurveLink; } } int numchains = chains.Count; ChainEnd[] endlist; if (numchains == 0) { endlist = EmptyChainList; } else { if ((numchains & 1) != 0) { throw new SystemException("Odd number of chains!"); } var tempArray = chains.ToArray(); endlist = new ChainEnd[numchains+2]; for (int i = 0; i < tempArray.Length; i++) { endlist[i] = tempArray[i] as ChainEnd; } } int curchain = 0; int curlink = 0; chains.Clear(); ChainEnd chain = endlist[0]; ChainEnd nextchain = endlist[1]; CurveLink link = linklist[0]; CurveLink nextlink = linklist[1]; while (chain != null || link != null) { /* * Strategy 1: * Connect chains or links if they are the only things left... */ bool connectchains = (link == null); bool connectlinks = (chain == null); if (!connectchains && !connectlinks) { // assert(link != null && chain != null); /* * Strategy 2: * Connect chains or links if they close off an open area... */ if (nextchain != null) connectchains = ((curchain & 1) == 0 && chain.GetX() == nextchain.GetX()); if (nextlink != null) { connectlinks = ((curlink & 1) == 0 && link.GetX() == nextlink.GetX()); if (!connectchains && !connectlinks) { /* * Strategy 3: * Connect chains or links if their successor is * between them and their potential connectee... */ double cx = chain.GetX(); double lx = link.GetX(); connectchains = (nextchain != null && cx < lx && Obstructs(nextchain.GetX(), lx, curchain)); connectlinks = (lx < cx && Obstructs(nextlink.GetX(), cx, curlink)); } } } if (connectchains) { CurveLink subcurve = chain.LinkTo(nextchain); if (subcurve != null) { subcurves.Add(subcurve); } curchain += 2; chain = endlist[curchain]; nextchain = endlist[curchain + 1]; } if (connectlinks) { ChainEnd openend = new ChainEnd(link, null); ChainEnd closeend = new ChainEnd(nextlink, openend); openend.SetOtherEnd(closeend); chains.Add(openend); chains.Add(closeend); curlink += 2; link = linklist[curlink]; nextlink = linklist[curlink + 1]; } if (!connectchains && !connectlinks) { // assert(link != null); // assert(chain != null); // assert(chain.getEtag() == link.getEtag()); chain.AddLink(link); chains.Add(chain); curchain++; chain = nextchain; nextchain = endlist[curchain + 1]; curlink++; link = nextlink; nextlink = linklist[curlink + 1]; } } }