Example #1
0
        internal void RemoveBeachSection(FortuneCircleEvent circle, MinHeap <FortuneEvent> eventQueue, HashSet <FortuneCircleEvent> deleted, LinkedList <VEdge> edges)
        {
            var section = circle.ToDelete;
            var x       = circle.X;
            var y       = circle.YCenter;
            var vertex  = new VPoint(x, y);

            //multiple edges could end here
            var toBeRemoved = new List <RBTreeNode <BeachSection> >();

            //look left
            var prev = section.Previous;

            while (prev.Data.CircleEvent != null &&
                   (x - prev.Data.CircleEvent.X).ApproxEqual(0) &&
                   (y - prev.Data.CircleEvent.Y).ApproxEqual(0))
            {
                toBeRemoved.Add(prev);
                prev = prev.Previous;
            }

            var next = section.Next;

            while (next.Data.CircleEvent != null &&
                   (x - next.Data.CircleEvent.X).ApproxEqual(0) &&
                   (y - next.Data.CircleEvent.Y).ApproxEqual(0))
            {
                toBeRemoved.Add(next);
                next = next.Next;
            }

            section.Data.Edge.End      = vertex;
            section.Next.Data.Edge.End = vertex;
            section.Data.CircleEvent   = null;

            //odds are this double writes a few edges but this is clean...
            foreach (var remove in toBeRemoved)
            {
                remove.Data.Edge.End      = vertex;
                remove.Next.Data.Edge.End = vertex;
                deleted.Add(remove.Data.CircleEvent);
                remove.Data.CircleEvent = null;
            }


            //need to delete all upcoming circle events with this node
            if (prev.Data.CircleEvent != null)
            {
                deleted.Add(prev.Data.CircleEvent);
                prev.Data.CircleEvent = null;
            }
            if (next.Data.CircleEvent != null)
            {
                deleted.Add(next.Data.CircleEvent);
                next.Data.CircleEvent = null;
            }


            //create a new edge with start point at the vertex and assign it to next
            var newEdge = new VEdge(vertex, next.Data.Site, prev.Data.Site);

            next.Data.Edge = newEdge;
            edges.AddFirst(newEdge);

            //add neighbors for delaunay
            prev.Data.Site.Neighbors.Add(next.Data.Site);
            next.Data.Site.Neighbors.Add(prev.Data.Site);

            //remove the sectionfrom the tree
            beachLine.RemoveNode(section);
            foreach (var remove in toBeRemoved)
            {
                beachLine.RemoveNode(remove);
            }

            CheckCircle(prev, eventQueue);
            CheckCircle(next, eventQueue);
        }
Example #2
0
        private static void CheckCircle(RBTreeNode <BeachSection> section, MinHeap <FortuneEvent> eventQueue)
        {
            //if (section == null)
            //    return;
            var left  = section.Previous;
            var right = section.Next;

            if (left == null || right == null)
            {
                return;
            }

            var leftSite   = left.Data.Site;
            var centerSite = section.Data.Site;
            var rightSite  = right.Data.Site;

            //if the left arc and right arc are defined by the same
            //focus, the two arcs cannot converge
            if (leftSite == rightSite)
            {
                return;
            }

            // http://mathforum.org/library/drmath/view/55002.html
            // because every piece of this program needs to be demoed in maple >.<

            //MATH HACKS: place center at origin and
            //draw vectors a and c to
            //left and right respectively
            double bx = centerSite.X,
                   by = centerSite.Y,
                   ax = leftSite.X - bx,
                   ay = leftSite.Y - by,
                   cx = rightSite.X - bx,
                   cy = rightSite.Y - by;

            //The center beach section can only dissapear when
            //the angle between a and c is negative
            var d = ax * cy - ay * cx;

            if (d.ApproxGreaterThanOrEqualTo(0))
            {
                return;
            }

            var magnitudeA = ax * ax + ay * ay;
            var magnitudeC = cx * cx + cy * cy;
            var x          = (cy * magnitudeA - ay * magnitudeC) / (2 * d);
            var y          = (ax * magnitudeC - cx * magnitudeA) / (2 * d);

            //add back offset
            var ycenter = y + by;
            //y center is off
            var circleEvent = new FortuneCircleEvent(
                new VPoint(x + bx, ycenter + Math.Sqrt(x * x + y * y)),
                ycenter, section
                );

            section.Data.CircleEvent = circleEvent;
            eventQueue.Insert(circleEvent);
        }
Example #3
0
 internal BeachSection(FortuneSite site)
 {
     Site        = site;
     CircleEvent = null;
 }