예제 #1
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Insert a new parabola into the beachline when the beachline spans the X axis. </summary>
        /// <remarks>
        ///     This is the normal case.  We insert our new parabola and split the parabola above our site in
        ///     two. This means one new leaf node is created for leftmost of the two nodes in the split (the
        ///     old lfn is recycled to become the right node of the split).  Also a new internal node to
        ///     parent all this.
        /// </remarks>
        /// <param name="lfnOld">			Parabola above the new site. </param>
        /// <param name="lfnNewParabola">	parabola for the new site. </param>
        /// <param name="innSubRoot">
        ///     Parent node of both lfnOld and lfnNewParabola represneting
        ///     the breakpoint between them.
        /// </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private static void InsertAtDifferentY(LeafNode lfnOld, LeafNode lfnNewParabola, InternalNode innSubRoot)
        {
            // The old lfn will become the new right half of the split but we need a new leaf node
            // for the left half of the split...
            var lfnLeftHalf         = new LeafNode(lfnOld.Poly);
            var innSubRootLeftChild = new InternalNode(lfnOld.Poly, lfnNewParabola.Poly);
            var edge = new FortuneEdge();

            // This is all fairly straightforward (albeit dense) insertion of a node into a binary tree.
            innSubRoot.RightChild = lfnOld;
            innSubRoot.LeftChild  = innSubRootLeftChild;
            innSubRoot.SetEdge(edge);
            innSubRoot.AddEdgeToPolygons(edge);
            innSubRootLeftChild.LeftChild  = lfnLeftHalf;
            innSubRootLeftChild.RightChild = lfnNewParabola;
            innSubRootLeftChild.SetEdge(edge);
            lfnNewParabola.LeftAdjacentLeaf  = lfnLeftHalf;
            lfnNewParabola.RightAdjacentLeaf = lfnOld;
            lfnLeftHalf.LeftAdjacentLeaf     = lfnOld.LeftAdjacentLeaf;
            lfnLeftHalf.RightAdjacentLeaf    = lfnNewParabola;

            if (lfnOld.LeftAdjacentLeaf != null)
            {
                lfnOld.LeftAdjacentLeaf.RightAdjacentLeaf = lfnLeftHalf;
            }

            lfnOld.LeftAdjacentLeaf = lfnNewParabola;
            edge.SetPolys(innSubRoot.PolyRight, innSubRoot.PolyLeft);
        }
예제 #2
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Handle the top N nodes located on a single horizontal line. </summary>
        /// <remarks>
        ///     This only handles the corner case where the top N nodes are on the same horizontal
        ///     line.  In that case the parabolas from previous points are vertically straight up and only
        ///     project to a single point on the x axis so that the beachline is a series of points rather
        ///     than a series of parabolas.  When that is the case we can't "intersect" new points with
        ///     parabolas that span the x axis.  After the scanline passes that initial set of topmost points,
        ///     there will always be a parabola which projects to the entire x axis so no need for this
        ///     special handling. Normally, we produce two new parabolas at a site event like this - the new
        ///     parabola for the site itself and the new parabola produced when we split the parabola above
        ///     us.  In this case there is no parabola above us so we only produce one new parabola - the one
        ///     inserted by the site.
        /// </remarks>
        /// <param name="lfn">				LeafNode of the (degenerate) parabola nearest us. </param>
        /// <param name="lfnNewParabola">	LeafNode we're inserting. </param>
        /// <param name="innParent">		Parent of lfnOld. </param>
        /// <param name="innSubRoot">		Root of the tree. </param>
        /// <param name="fLeftChild">		Left child of innParent. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private static void NdInsertAtSameY(
            LeafNode lfn,
            LeafNode lfnNewParabola,
            InternalNode innParent,
            InternalNode innSubRoot,
            bool fLeftChild)
        {
            // Locals
            LeafNode lfnLeft, lfnRight;
            var      lfnAdjacentParabolaLeft  = lfn.LeftAdjacentLeaf;
            var      lfnAdjacentParabolaRight = lfn.RightAdjacentLeaf;

            if (lfnNewParabola.Poly.VoronoiPoint.X < lfn.Poly.VoronoiPoint.X)
            {
                lfnLeft  = lfnNewParabola;
                lfnRight = lfn;
            }
            else
            {
                //! Note: I don't think this case ever occurs in practice since we pull events off with higher
                //! x coordinates before events with lower x coordinates
                lfnLeft  = lfn;
                lfnRight = lfnNewParabola;
            }

            innSubRoot.PolyLeft  = lfnLeft.Poly;
            innSubRoot.PolyRight = lfnRight.Poly;

            innSubRoot.LeftChild  = lfnLeft;
            innSubRoot.RightChild = lfnRight;

            var edge = new FortuneEdge();

            innSubRoot.SetEdge(edge);
            innSubRoot.AddEdgeToPolygons(edge);
            lfnLeft.LeftAdjacentLeaf   = lfnAdjacentParabolaLeft;
            lfnLeft.RightAdjacentLeaf  = lfnRight;
            lfnRight.LeftAdjacentLeaf  = lfnLeft;
            lfnRight.RightAdjacentLeaf = lfnAdjacentParabolaRight;

            if (innParent != null)
            {
                if (fLeftChild)
                {
                    innParent.PolyLeft = lfnRight.Poly;
                }
                else
                {
                    innParent.PolyRight = lfnLeft.Poly;
                }
            }

            edge.SetPolys(innSubRoot.PolyRight, innSubRoot.PolyLeft);
        }
예제 #3
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Insert a new LeafNode into the tree. </summary>
        /// <remarks>	Darrellp, 2/19/2011. </remarks>
        /// <param name="lfn">	Place to put the new leaf node. </param>
        /// <param name="evt">	The event to insert. </param>
        /// <returns>	. </returns>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        private static InternalNode NdCreateInsertionSubtree(LeafNode lfn, SiteEvent evt)
        {
            // Initialize locals
            var innParent      = lfn.NdParent;
            var lfnNewParabola = new LeafNode(evt.Poly);
            var innSubRoot     = new InternalNode(evt.Poly, lfn.Poly);
            var fLeftChild     = true;

            // If this isn't on the root node, shuffle things around a bit
            if (innParent != null)
            {
                fLeftChild = lfn.IsLeftChild;

                lfn.SnipFromParent();
                if (fLeftChild)
                {
                    innParent.LeftChild = innSubRoot;
                }
                else
                {
                    innParent.RightChild = innSubRoot;
                }
            }

            // Watch for the odd corner case of the top n generators having the same y coordinate.  See comments
            // on NdInsertAtSameY().
            if (Geometry2D.FCloseEnough(evt.Pt.Y, lfn.Poly.VoronoiPoint.Y))
            {
                NdInsertAtSameY(lfn, lfnNewParabola, innParent, innSubRoot, fLeftChild);
            }
            else
            {
                InsertAtDifferentY(lfn, lfnNewParabola, innSubRoot);
            }

            return(innSubRoot);
        }