예제 #1
0
        public static double LeftBreakPoint(RedBlackTree arc, double directrix)
        {
            var site  = arc.Site;
            var rfocx = site.X;
            var rfocy = site.Y;
            var pby2  = rfocy - directrix;

            if (pby2 == 0)
            {
                return(rfocx);
            }

            var lArc = arc.P;

            if (lArc == null)
            {
                return(double.MinValue);
            }

            site = lArc.Site;
            var lfocx = site.X;
            var lfocy = site.Y;
            var plby2 = lfocy - directrix;

            if (plby2 == 0)
            {
                return(lfocx);
            }

            var hl   = lfocx - rfocx;
            var aby2 = 1 / pby2 - 1 / plby2;
            var b    = hl / plby2;

            if (aby2 != 0)
            {
                return((-b + Math.Sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx);
            }

            return((rfocx + lfocx) / 2);
        }
예제 #2
0
        public static void AddBeach(ref Dictionary <int, Cell> cells, ref RedBlackTree circles, ref RedBlackTree beaches, ref List <Edge> edges, Point site)
        {
            var          x         = site.X;
            var          directrix = site.Y;
            RedBlackTree lArc      = null;
            RedBlackTree rArc      = null;
            var          dxl       = 0d;
            var          dxr       = 0d;
            var          node      = beaches._;

            while (node != null)
            {
                dxl = LeftBreakPoint(node, directrix) - x;
                if (dxl > Diagram.Epsilon)
                {
                    node = node.L;
                }
                else
                {
                    dxr = x - RightBreakPoint(node, directrix);
                    if (dxr > Diagram.Epsilon)
                    {
                        if (node.R == null)
                        {
                            lArc = node;
                            break;
                        }
                        node = node.R;
                    }
                    else
                    {
                        if (dxl > -Diagram.Epsilon)
                        {
                            lArc = node.P;
                            rArc = node;
                        }
                        else if (dxr > -Diagram.Epsilon)
                        {
                            lArc = node;
                            rArc = node.N;
                        }
                        else
                        {
                            lArc = rArc = node;
                        }
                        break;
                    }
                }
            }

            Cell.CreateCell(ref cells, site);
            var newArc = CreateBeach(site);

            beaches.Insert(lArc, newArc);

            if (lArc == null && rArc == null)
            {
                return;
            }

            if (lArc == rArc)
            {
                Circle.DetachCircle(ref circles, lArc);
                rArc = CreateBeach(lArc.Site);
                beaches.Insert(newArc, rArc);
                newArc.Edge = rArc.Edge = Edge.CreateEdge(ref cells, ref edges, lArc.Site, newArc.Site);
                Circle.AttachCircle(ref circles, lArc);
                Circle.AttachCircle(ref circles, rArc);
                return;
            }

            if (rArc == null)
            { // && lArc
                newArc.Edge = Edge.CreateEdge(ref cells, ref edges, lArc.Site, newArc.Site);
                return;
            }

            // else lArc !== rArc
            Circle.DetachCircle(ref circles, lArc);
            Circle.DetachCircle(ref circles, rArc);

            var lSite  = lArc.Site;
            var ax     = lSite.X;
            var ay     = lSite.Y;
            var bx     = site.X - ax;
            var by     = site.Y - ay;
            var rSite  = rArc.Site;
            var cx     = rSite.X - ax;
            var cy     = rSite.Y - ay;
            var d      = 2 * (bx * cy - by * cx);
            var hb     = bx * bx + by * by;
            var hc     = cx * cx + cy * cy;
            var vertex = new Point((cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay);

            rArc.Edge   = Edge.SetEdgeEnd(rArc.Edge, lSite, rSite, vertex);
            newArc.Edge = Edge.CreateEdge(ref cells, ref edges, lSite, site, null, vertex);
            rArc.Edge   = Edge.CreateEdge(ref cells, ref edges, site, rSite, null, vertex);
            Circle.AttachCircle(ref circles, lArc);
            Circle.AttachCircle(ref circles, rArc);
        }
예제 #3
0
        public static void RemoveBeach(ref Dictionary <int, Cell> cells, ref List <Edge> edges, ref RedBlackTree beaches, ref RedBlackTree circles, RedBlackTree beach)
        {
            var circle       = beach.Circle;
            var x            = circle.X;
            var y            = circle.CY;
            var vertex       = new Point(x, y);
            var previous     = beach.P;
            var next         = beach.N;
            var disappearing = new List <RedBlackTree>()
            {
                beach
            };

            DetachBeach(ref circles, ref beaches, beach);

            var lArc = previous;

            while (lArc.Circle != null && Math.Abs(x - lArc.Circle.X) < Diagram.Epsilon && Math.Abs(y - lArc.Circle.CY) < Diagram.Epsilon)
            {
                previous = lArc.P;
                disappearing.Insert(0, lArc);
                DetachBeach(ref circles, ref beaches, lArc);
                lArc = previous;
            }

            disappearing.Insert(0, lArc);
            Circle.DetachCircle(ref circles, lArc);

            var rArc = next;

            while (rArc.Circle != null && Math.Abs(x - rArc.Circle.X) < Diagram.Epsilon && Math.Abs(y - rArc.Circle.CY) < Diagram.Epsilon)
            {
                next = rArc.N;
                disappearing.Add(rArc);
                DetachBeach(ref circles, ref beaches, rArc);
                rArc = next;
            }

            disappearing.Add(rArc);
            Circle.DetachCircle(ref circles, rArc);

            int nArcs = disappearing.Count;
            int iArc;

            for (iArc = 1; iArc < nArcs; ++iArc)
            {
                rArc      = disappearing[iArc];
                lArc      = disappearing[iArc - 1];
                rArc.Edge = Edge.SetEdgeEnd(rArc.Edge, lArc.Site, rArc.Site, vertex);
            }

            lArc      = disappearing[0];
            rArc      = disappearing[nArcs - 1];
            rArc.Edge = Edge.CreateEdge(ref cells, ref edges, lArc.Site, rArc.Site, null, vertex);

            Circle.AttachCircle(ref circles, lArc);
            Circle.AttachCircle(ref circles, rArc);
        }
예제 #4
0
 public static void DetachBeach(ref RedBlackTree circles, ref RedBlackTree beaches, RedBlackTree beach)
 {
     Circle.DetachCircle(ref circles, beach);
     beaches.Remove(beach);
     Beach.BeachPool.Add(beach);
     beach.Reset();
 }
예제 #5
0
        public void Insert(RedBlackTree after, RedBlackTree node)
        {
            RedBlackTree parent  = null;
            RedBlackTree grandpa = null;
            RedBlackTree uncle   = null;

            if (after != null)
            {
                node.P = after;
                node.N = after.N;
                if (after.N != null)
                {
                    after.N.P = node;
                }
                after.N = node;
                if (after.R != null)
                {
                    after = after.R;
                    while (after.L != null)
                    {
                        after = after.L;
                    }
                    after.L = node;
                }
                else
                {
                    after.R = node;
                }
                parent = after;
            }
            else if (this._ != null)
            {
                after   = RedBlackFirst(this._);
                node.P  = null;
                node.N  = after;
                after.P = after.L = node;
                parent  = after;
            }
            else
            {
                node.P = node.N = null;
                this._ = node;
                parent = null;
            }
            node.L = node.R = null;
            node.U = parent;
            node.C = true;

            after = node;
            while (parent != null && parent.C)
            {
                grandpa = parent.U;
                if (parent == grandpa.L)
                {
                    uncle = grandpa.R;
                    if (uncle != null && uncle.C)
                    {
                        parent.C  = uncle.C = false;
                        grandpa.C = true;
                        after     = grandpa;
                    }
                    else
                    {
                        if (after == parent.R)
                        {
                            RedBlackRotateLeft(this, parent);
                            after  = parent;
                            parent = after.U;
                        }
                        parent.C  = false;
                        grandpa.C = true;
                        RedBlackRotateRight(this, grandpa);
                    }
                }
                else
                {
                    uncle = grandpa.L;
                    if (uncle != null && uncle.C)
                    {
                        parent.C  = uncle.C = false;
                        grandpa.C = true;
                        after     = grandpa;
                    }
                    else
                    {
                        if (after == parent.L)
                        {
                            RedBlackRotateRight(this, parent);
                            after  = parent;
                            parent = after.U;
                        }
                        parent.C  = false;
                        grandpa.C = true;
                        RedBlackRotateLeft(this, grandpa);
                    }
                }
                parent = after.U;
            }
            this._.C = false;
        }
예제 #6
0
 public void Reset()
 {
     U = L = R = P = N = null;
     C = false;
 }
예제 #7
0
        public void Remove(RedBlackTree node)
        {
            if (node.N != null)
            {
                node.N.P = node.P;
            }
            if (node.P != null)
            {
                node.P.N = node.N;
            }
            node.N = node.P = null;

            RedBlackTree parent  = node.U;
            RedBlackTree sibling = null;
            RedBlackTree left    = node.L;
            RedBlackTree right   = node.R;
            RedBlackTree next    = null;
            bool         red     = false;

            if (left == null)
            {
                next = right;
            }
            else if (right == null)
            {
                next = left;
            }
            else
            {
                next = RedBlackFirst(right);
            }

            if (parent != null)
            {
                if (parent.L == node)
                {
                    parent.L = next;
                }
                else
                {
                    parent.R = next;
                }
            }
            else
            {
                this._ = next;
            }

            if (left != null && right != null)
            {
                red    = next.C;
                next.C = node.C;
                next.L = left;
                left.U = next;
                if (next != right)
                {
                    parent   = next.U;
                    next.U   = node.U;
                    node     = next.R;
                    parent.L = node;
                    next.R   = right;
                    right.U  = next;
                }
                else
                {
                    next.U = parent;
                    parent = next;
                    node   = next.R;
                }
            }
            else
            {
                red  = node.C;
                node = next;
            }

            if (node != null)
            {
                node.U = parent;
            }
            if (red)
            {
                return;
            }
            if (node != null && node.C)
            {
                node.C = false; return;
            }

            do
            {
                if (node == this._)
                {
                    break;
                }
                if (node == parent.L)
                {
                    sibling = parent.R;
                    if (sibling.C)
                    {
                        sibling.C = false;
                        parent.C  = true;
                        RedBlackRotateLeft(this, parent);
                        sibling = parent.R;
                    }
                    if ((sibling.L != null && sibling.L.C) ||
                        (sibling.R != null && sibling.R.C))
                    {
                        if (sibling.R == null || !sibling.R.C)
                        {
                            sibling.L.C = false;
                            sibling.C   = true;
                            RedBlackRotateRight(this, sibling);
                            sibling = parent.R;
                        }
                        sibling.C = parent.C;
                        parent.C  = sibling.R.C = false;
                        RedBlackRotateLeft(this, parent);
                        node = this._;
                        break;
                    }
                }
                else
                {
                    sibling = parent.L;
                    if (sibling.C)
                    {
                        sibling.C = false;
                        parent.C  = true;
                        RedBlackRotateRight(this, parent);
                        sibling = parent.L;
                    }
                    if ((sibling.L != null && sibling.L.C) ||
                        (sibling.R != null && sibling.R.C))
                    {
                        if (sibling.L == null || !sibling.L.C)
                        {
                            sibling.R.C = false;
                            sibling.C   = true;
                            RedBlackRotateLeft(this, sibling);
                            sibling = parent.L;
                        }
                        sibling.C = parent.C;
                        parent.C  = sibling.L.C = false;
                        RedBlackRotateRight(this, parent);
                        node = this._;
                        break;
                    }
                }
                sibling.C = true;
                node      = parent;
                parent    = parent.U;
            } while (!node.C);

            if (node != null)
            {
                node.C = false;
            }
        }
예제 #8
0
        public static void AttachCircle(ref RedBlackTree circles, RedBlackTree arc)
        {
            var lArc = arc.P;
            var rArc = arc.N;

            if (lArc == null || rArc == null)
            {
                return;
            }

            var lSite = lArc.Site;
            var cSite = arc.Site;
            var rSite = rArc.Site;

            if (lSite == rSite)
            {
                return;
            }

            var bx = cSite.X;
            var by = cSite.Y;
            var ax = lSite.X - bx;
            var ay = lSite.Y - by;
            var cx = rSite.X - bx;
            var cy = rSite.Y - by;

            var d = 2 * (ax * cy - ay * cx);

            if (d >= -Diagram.Epsilon2)
            {
                return;
            }

            var ha = ax * ax + ay * ay;
            var hc = cx * cx + cy * cy;
            var x  = (cy * ha - ay * hc) / d;
            var y  = (ax * hc - cx * ha) / d;

            RedBlackTree circle = null;

            if (Circle.CirclePool.Any())
            {
                circle = Circle.CirclePool.Last();
                Circle.CirclePool.Remove(circle);
            }
            else
            {
                circle = new RedBlackTree();
            }

            circle.Arc  = arc;
            circle.Site = cSite;
            circle.X    = x + bx;
            circle.Y    = (circle.CY = y + by) + Math.Sqrt(x * x + y * y); // y bottom

            arc.Circle = circle;

            RedBlackTree before = null;
            var          node   = circles._;

            while (node != null)
            {
                if (circle.Y < node.Y || (circle.Y == node.Y && circle.X <= node.X))
                {
                    if (node.L != null)
                    {
                        node = node.L;
                    }
                    else
                    {
                        before = node.P; break;
                    }
                }
                else
                {
                    if (node.R != null)
                    {
                        node = node.R;
                    }
                    else
                    {
                        before = node; break;
                    }
                }
            }

            circles.Insert(before, circle);
            if (before == null)
            {
                FirstCircle = circle;
            }
        }