Exemple #1
0
        private void ProcessSiteEvent(FortunesAlgorithmState state, SiteEvent e)
        {
            var sweepY           = e.Y;
            var newParabolaFocus = e.Point;

            if (state.Root == null)
            {
                state.Root = new Node(new ParabolaData(newParabolaFocus));
                return;
            }

            var cutNode = state.Root.FindDeepestNodeAtX(newParabolaFocus.X, newParabolaFocus.Y);

            if (!cutNode.IsLeaf())
            {
                throw new NotSupportedException("Cutting edge node not supported.");
            }

            var cutParabolaFocus = ((ParabolaData)cutNode.Data).Focus;

            Node leftParabola, centerParabola, rightParabola;
            Node newNode = BeachlineNodeOperations.ComputeThreeParabolasFromDifferentYParabolaNodeCut(
                cutParabolaFocus, newParabolaFocus,
                out leftParabola, out centerParabola, out rightParabola);

            NodeOperations.ReplaceNode(cutNode, newNode, ref state.Root);

            state.DelanayEdges.Add(new VoronoiEdge(newParabolaFocus, true, cutParabolaFocus, true));

            Node leftLeftParabola;

            if (leftParabola.TryGetLeftLeaf(out leftLeftParabola))
            {
                HandleAddCircleEvent(state, leftLeftParabola, leftParabola, centerParabola, sweepY);
            }

            Node rightRightParabola;

            if (rightParabola.TryGetRightLeaf(out rightRightParabola))
            {
                HandleAddCircleEvent(state, centerParabola, rightParabola, rightRightParabola, sweepY);
            }
        }
Exemple #2
0
        void ProcessCircleEvent(FortunesAlgorithmState state, CircleEvent e)
        {
            var sweepY = e.Y;
            var swallowedParabolaNode = e.SwallowedParabolaNode;

            if (swallowedParabolaNode.Parent == null)
            {
                return;
            }

            Node leftAncestor, rightAncestor;

            swallowedParabolaNode.FindDirectionalAncestors(out leftAncestor, out rightAncestor);

            var leftAncestorEdgeRayData  = (EdgeRayData)leftAncestor.Data;
            var rightAncestorEdgeRayData = (EdgeRayData)rightAncestor.Data;

            state.VoronoiEdges.Add(new VoronoiEdge(
                                       leftAncestorEdgeRayData.Origin, leftAncestorEdgeRayData.IsOriginBounded, e.Circumcenter, true));
            state.VoronoiEdges.Add(new VoronoiEdge(
                                       rightAncestorEdgeRayData.Origin, leftAncestorEdgeRayData.IsOriginBounded, e.Circumcenter, true));

            var leftParabolaNode  = leftAncestor.Left.GetRightmost();
            var leftParabolaFocus = ((ParabolaData)leftParabolaNode.Data).Focus;

            var rightParabolaNode  = rightAncestor.Right.GetLeftmost();
            var rightParabolaFocus = ((ParabolaData)rightParabolaNode.Data).Focus;

            state.DelanayEdges.Add(new VoronoiEdge(leftParabolaFocus, true, rightParabolaFocus, true));

            // One ancestor will become the edge shared by the left/right parabolas,
            // the other will be deleted. It's guranteed our parent is one of these
            // ancestors and that the other ancestor is above it (that is, it has a
            // parent) so opt to delete our parent.
            var nodeParent  = swallowedParabolaNode.Parent;
            var nodeSibling = nodeParent.Left == swallowedParabolaNode ? nodeParent.Right : nodeParent.Left;

            NodeOperations.ReplaceNode(nodeParent, nodeSibling, ref state.Root);
            nodeParent.Left = nodeParent.Right = null;

            var olderAncestor        = nodeParent == leftAncestor ? rightAncestor : leftAncestor;
            var leftFocusRightFocus  = rightParabolaFocus - leftParabolaFocus; // x is positive
            var edgeDirection        = new TVector2(-leftFocusRightFocus.Y, leftFocusRightFocus.X);
            var leftRightFocusCenter = new TVector2(
                MathUtil.Average(leftParabolaFocus.X, rightParabolaFocus.X),
                MathUtil.Average(leftParabolaFocus.Y, rightParabolaFocus.Y));
            var dy        = sweepY - leftRightFocusCenter.Y;
            var edgeStart = e.Circumcenter;

            olderAncestor.Data = new EdgeRayData(true, edgeStart, edgeDirection);

            // add new potential circle events
            Node leftLeftLeaf;

            if (leftParabolaNode.TryGetLeftLeaf(out leftLeftLeaf))
            {
                HandleAddCircleEvent(state, leftLeftLeaf, leftParabolaNode, rightParabolaNode, sweepY);
            }

            Node rightRightLeaf;

            if (rightParabolaNode.TryGetRightLeaf(out rightRightLeaf))
            {
                HandleAddCircleEvent(state, leftParabolaNode, rightParabolaNode, rightRightLeaf, sweepY);
            }
        }