//////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> Insert a new polygon arising from a site event. </summary> /// <remarks> Darrellp, 2/19/2011. </remarks> /// <param name="evt"> Site event causing the new polygon. </param> /// <param name="evq"> Event queue. </param> //////////////////////////////////////////////////////////////////////////////////////////////////// internal void PolyInsertNode(SiteEvent evt, EventQueue evq) { // If there's no tree yet if (NdRoot == null) { // Create a leaf node and make it the tree root NdRoot = new LeafNode(evt.Poly); return; } // Get the parabola above this site and the parabolas to its left and right var lfn = LfnSearchNode(evt.Pt.X, evt.Pt.Y); var lfnLeft = lfn.LeftAdjacentLeaf; var lfnRight = lfn.RightAdjacentLeaf; // Remove the circle event associated with the parabola we intersect // // We are inserting ourselves into this parabola which means it's old circle event is defunct // so toss it. lfn.DeleteAssociatedCircleEvent(evq); // Create a new subtree to hold the new leaf node var innSubRoot = NdCreateInsertionSubtree(lfn, evt); // If the root node is a leaf if (NdRoot.IsLeaf) { // Replace it with the new inner node we just created NdRoot = innSubRoot; } // TODO: Rebalancing the tree //Rebalance(innSubRoot); // For every circle event // // Remove any circle events that this generator is inside since it will be closer to the center // of the circle than any of the three points which lie on the circle // TODO: Is there a good way to optimize this? var lln = evq.CircleEvents.First; while (lln != null) { var cevt = lln.Value; var llnNext = lln.Next; if (cevt.Contains(evt.Pt)) { // Delete the circle event evq.CircleEvents.Remove(lln); cevt.LinkedListNode = null; } lln = llnNext; } // Create any circle events which this site causes CreateCircleEventsFromSiteEvent(lfnLeft, lfnRight, evt.Pt.Y, evq); }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <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); }