public ChainEnd(CurveLink first, ChainEnd partner)
 {
     _head    = first;
     _tail    = first;
     _partner = partner;
     _etag    = first.GetEdgeTag();
 }
Exemple #2
0
 public ChainEnd(CurveLink first, ChainEnd partner)
 {
     _head = first;
     _tail = first;
     _partner = partner;
     _etag = first.GetEdgeTag();
 }
Exemple #3
0
        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();
        }
Exemple #4
0
 public void AddLink(CurveLink newlink)
 {
     if (_etag == AreaOp.ETAG_ENTER)
     {
         _tail.SetNext(newlink);
         _tail = newlink;
     }
     else
     {
         newlink.SetNext(_head);
         _head = newlink;
     }
 }
 public void AddLink(CurveLink newlink)
 {
     if (_etag == AreaOp.ETAG_ENTER)
     {
         _tail.SetNext(newlink);
         _tail = newlink;
     }
     else
     {
         newlink.SetNext(_head);
         _head = newlink;
     }
 }
Exemple #6
0
 public bool Absorb(CurveLink link)
 {
     return(Absorb(link._curve, link._ytop, link._ybot, link._etag));
 }
Exemple #7
0
 public void SetNext(CurveLink link)
 {
     _next = link;
 }
Exemple #8
0
        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];
                }
            }
        }
Exemple #9
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);
        }
Exemple #10
0
 public bool Absorb(CurveLink link)
 {
     return Absorb(link._curve, link._ytop, link._ybot, link._etag);
 }
Exemple #11
0
 public void SetNext(CurveLink link)
 {
     _next = link;
 }
Exemple #12
0
        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];
                }
            }
        }