示例#1
0
    private static void CheckCircle(RedBlackTreeNode <BeachSection> section, MinHeap <FortuneEvent> eventQueue)
    {
        RedBlackTreeNode <BeachSection> left  = section.previous;
        RedBlackTreeNode <BeachSection> right = section.next;

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

        FortuneSite leftSite   = left.data.site;
        FortuneSite centerSite = section.data.site;
        FortuneSite rightSite  = right.data.site;

        if (leftSite == rightSite)
        {
            return;
        }


        double bX = centerSite.x;
        double bY = centerSite.y;
        double aX = leftSite.x - bX;
        double aY = leftSite.y - bY;
        double cX = rightSite.x - bX;
        double cY = rightSite.y - bY;

        double delta = aX * cY - aY * cX;

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

        double magnitudeA = aX * aX + aY * aY;
        double magnitudeC = cX * cX + cY * cY;

        double x = (cY * magnitudeA - aY * magnitudeC) / (2 * delta);
        double y = (aX * magnitudeC - cX * magnitudeA) / (2 * delta);

        double yCenter = y + bY;

        FortuneCircleEvent circleEvent = new FortuneCircleEvent(
            new Point(x + bX, yCenter + Math.Sqrt(x * x + y * y)),
            yCenter, section
            );

        section.data.circleEvent = circleEvent;
        eventQueue.Insert(circleEvent);
    }
示例#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 Point(x + bx, ycenter + Math.Sqrt(x * x + y * y)),
                ycenter, section
                );

            section.Data.CircleEvent = circleEvent;
            eventQueue.Insert(circleEvent);
        }
示例#3
0
        internal void RemoveBeachSection(FortuneCircleEvent circle, MinHeap <FortuneEvent> eventQueue, HashSet <FortuneCircleEvent> deleted, LinkedList <VoronoiEdge> edges)
        {
            var section = circle.ToDelete;
            var x       = circle.X;
            var y       = circle.YCenter;
            var vertex  = new Point(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.EndPoint      = vertex;
            section.Next.Data.Edge.EndPoint = 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.EndPoint      = vertex;
                remove.Next.Data.Edge.EndPoint = 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 VoronoiEdge(vertex, next.Data.Site, prev.Data.Site);

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

            //add neighbors for delaunay
            prev.Data.Site.Neighbours.Add(next.Data.Site);
            next.Data.Site.Neighbours.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);
        }
示例#4
0
 internal BeachSection(FSite site)
 {
     Site        = site;
     CircleEvent = null;
 }
示例#5
0
    public void RemoveBeachSection(FortuneCircleEvent circle, MinHeap <FortuneEvent> eventQueue, HashSet <FortuneCircleEvent> deleted, LinkedList <Edge> edges)
    {
        RedBlackTreeNode <BeachSection> section = circle.toDelete;
        double x      = circle.x;
        double y      = circle.yCenter;
        Point  vertex = new Point(x, y);

        List <RedBlackTreeNode <BeachSection> > toBeRemoved = new List <RedBlackTreeNode <BeachSection> >();

        RedBlackTreeNode <BeachSection> previous = section.previous;

        while (previous.data.circleEvent != null && (x - previous.data.circleEvent.x).ApproxEqual(0) && (y - previous.data.circleEvent.y).ApproxEqual(0))
        {
            toBeRemoved.Add(previous);
            previous = previous.previous;
        }

        RedBlackTreeNode <BeachSection> 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;

        foreach (RedBlackTreeNode <BeachSection> toRemove in toBeRemoved)
        {
            toRemove.data.edge.end      = vertex;
            toRemove.next.data.edge.end = vertex;
            deleted.Add(toRemove.data.circleEvent);
            toRemove.data.circleEvent = null;
        }

        if (previous.data.circleEvent != null)
        {
            deleted.Add(previous.data.circleEvent);
            previous.data.circleEvent = null;
        }
        if (next.data.circleEvent != null)
        {
            deleted.Add(next.data.circleEvent);
            next.data.circleEvent = null;
        }

        Edge newEdge = new Edge(vertex, next.data.site, previous.data.site);

        next.data.edge = newEdge;
        edges.AddFirst(newEdge);

        previous.data.site.neighbours.Add(next.data.site);
        next.data.site.neighbours.Add(previous.data.site);

        sections.Remove(section);
        foreach (RedBlackTreeNode <BeachSection> toRemove in toBeRemoved)
        {
            sections.Remove(toRemove);
        }

        CheckCircle(previous, eventQueue);
        CheckCircle(next, eventQueue);
    }
示例#6
0
 public BeachSection(FortuneSite site)
 {
     this.site        = site;
     this.circleEvent = null;
 }