Esempio n. 1
0
        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);
        }