Пример #1
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);
        }
Пример #2
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;
            }
        }