public override void Insert(T data) { RBNode <T> node = new RBNode <T>(data); root = InsertNode(node, root) as RBNode <T>; FixViolation(node); }
private int Size(RBNode x) { if (x == null) { return(0); } return(x.Size); }
private bool IsRed(RBNode x) { if (x == null) { return(false); } return(x.Color == RED); }
private int Count(RBNode root) { if (root == sentinelNode) { return(0); } return(1 + Count(root.Left) + Count(root.Right)); }
/// <summary> /// deleting elem with its key /// </summary> /// <param name="elem"></param> public void RBDelete(TKey elem) { RBNode node = SearchKey(elem); RBDelete(node); count--; entries.Remove(node); }
/// <summary> /// searching minimum element in tree. /// </summary> /// <param name="elem"></param> /// <returns></returns> private RBNode RBMin(RBNode elem) { while (elem.left != RBLeaf.Instance()) { elem = elem.right; } return(elem); }
public RBNode() { value = 0; color = Color.RED; parent = null; left = null; right = null; }
//Default comparison function //internal int? defaultCompare<T>(T a, T b) //{ // if ( a is long && b is long) // { // long a1 = (long)Convert.ChangeType(a, typeof(long)); // long b1 = (long)Convert.ChangeType(b, typeof(long)); // return ((a1 < b1) ? -1 : ((a1 > b1) ? 1 : 0)); // } // return null; //} internal RedBlackTree(Comporator _compare, RBNode _root) { //if( _compare != null ) this.compare = _compare; //else // this.compare = defaultCompare; this.root = _root; }
void CreateConeOnPortLocation(SweepEvent sweepEvent) { var cone = new Cone(sweepEvent.Site, this); RBNode <ConeSide> leftNode = InsertToTree(leftConeSides, cone.LeftSide = new ConeLeftSide(cone)); RBNode <ConeSide> rightNode = InsertToTree(rightConeSides, cone.RightSide = new ConeRightSide(cone)); LookForIntersectionWithConeRightSide(rightNode); LookForIntersectionWithConeLeftSide(leftNode); }
//Swaps two nodes internal void swapNode(RBNode n, RBNode v) { n.key = v.key; n.value = v.value; n.left = v.left; n.right = v.right; n.color = v.color; n.count = v.count; }
public static RBNode Instance() { if (node == null) { node = new RBNode(); node.color = Color.black; } return(node); }
internal RBNode(RBTreeNodeColor color, SweepEvent key, SweepEvent value, RBNode left, RBNode right, long count) { this.color = color; this.key = key; this.value = value; this.left = left; this.right = right; this.count = count; }
//Build a tree internal RedBlackTree(Comporator _compare) { //*if (_compare != null) this.compare = _compare; ///*else // this.compare = defaultCompare; this.root = null; }
internal RBNode <T> remove_r(RBNode <T> root, T data, ref bool done) { if (root == null) { done = true; } else { int dir; if (root.value.CompareTo(data) == 0) { if (root.link[0] == null || root.link[1] == null) { int id = (root.link[0] == null ? 1 : 0); RBNode <T> save = root.link[id]; /* case 0 */ if (is_red(root)) { done = true; } else if (is_red(save)) { save.red = false; done = true; } /* delete root; */ return(save); } else { RBNode <T> heir = root.link[0]; while (heir.link[1] != null) { heir = heir.link[1]; } root.value = heir.value; data = heir.value; } } dir = (root.value.CompareTo(data) < 0 ? 1 : 0); root.link[dir] = remove_r(root.link[dir], data, ref done); if (!done) { root = remove_balance(root, dir, ref done); } } return(root); }
protected override ValueTreeNode Find(T item) { RBNode node = (RBNode)base.Find(item); if (node.IsLeaf) { return(null); } return(node); }
public RBNode RB() { if (lexer.GetToken().Id == 4) { var result = new RBNode(lexer.GetText()); lexer.NextToken(); return(result); } throw new ParserException("Got unxpected token from lexer"); }
private RBNode NewRBNode(T data) { var node = new RBNode(data); node.Parent = NullNode; node.LeftChild = NullNode; node.RightChild = NullNode; node.ColorRed(); return(node); }
internal RBNode <BasicReflectionEvent> FindNextInRange(RBNode <BasicReflectionEvent> prev, Point high) { RBNode <BasicReflectionEvent> nextNode = eventTree.Next(prev); if ((null != nextNode) && (Compare(nextNode.Item.Site, high) <= 0)) { return(nextNode); } return(null); }
internal void RemoveSitesForFlatBottom(Point low, Point high) { for (RBNode <BasicReflectionEvent> node = FindFirstInRange(low, high); null != node; node = FindNextInRange(node, high)) { MarkStaleSite(node.Item); } RemoveStaleSites(); }
private RBNode MoveRedRight(RBNode h) { FlipColors(h); if (IsRed(h.Left.Left)) { h = RotateRight(h); FlipColors(h); } return(h); }
protected override KeyValueTreeNode Find(TKey key) { RBNode node = (RBNode)base.Find(key); if (node.IsLeaf) { return(null); } return(node); }
/// <summary> /// Removes the first occurrence of a specific object from the RedBlackTree<T>. /// </summary> /// <param name="item">The object to be removed.</param> /// <returns>true if item was successfully removed from the RedBlackTree<T>; otherwise, false.</returns> public override bool Remove(T item) { RBNode current = (RBNode)this.root; while (!current.IsLeaf) { int c = item.CompareTo(current.Value); if (c < 0) { current = current.Left; } else if (c > 0) { current = current.Right; } else { break; } } if (current.IsLeaf) { return(false); } if (current.Count > 1) { current.Count--; this.Count--; return(true); } if (current.Left.IsLeaf || current.Right.IsLeaf) { this.Delete(current); } else { RBNode replace = (RBNode)this.Predecessor(current); if (replace == null) { replace = (RBNode)this.Successor(current); } current.Value = replace.Value; current.Count = replace.Count; this.Delete(replace); } this.Count--; return(true); }
private void DeleteCorrectCase1(RBNode n) { if (n.parent == null) { _root = n; } else { DeleteCorrectCase2(n); } }
public int ActualFrom(RBNode r) { if (r == sentinelNode) { return(0); } else { return(r.Value + ActualFrom(r.Left) + ActualFrom(r.Right)); } }
private RBNode Minimum(RBNode node) { if (node != NullNode) { while (node.LeftChild != NullNode) { node = node.LeftChild; } } return(node); }
CdtSite MiddleCase(CdtSite pi, RBNode <CdtFrontElement> hittedFrontElementNode, out CdtSite rightSite) { // if(db) // ShowFrontWithSite(pi, new LineSegment(pi.Point, hittedFrontElementNode.Item.Edge.upperSite.Point), new LineSegment(pi.Point, hittedFrontElementNode.Item.Edge.lowerSite.Point)); var leftSite = hittedFrontElementNode.Item.LeftSite; rightSite = hittedFrontElementNode.Item.RightSite; InsertAndLegalizeTriangle(pi, hittedFrontElementNode.Item); front.DeleteNodeInternal(hittedFrontElementNode); return(leftSite); }
private RBNode Maximum(RBNode node) { if (node != NullNode) { while (node.RightChild != NullNode) { node = node.RightChild; } } return(node); }
/// <summary> /// fixing violations /// </summary> /// <param name="elem"></param> /// <returns></returns> private RBNode RBFixInsertion(RBNode elem) { RBNode temp = new RBNode(); while (elem.parent.color == Color.red) { if (elem.parent == elem.parent.parent.left) { temp = elem.parent.parent.right; if (temp.color == Color.red) { elem.parent.color = Color.black; temp.color = Color.black; elem.parent.parent.color = Color.red; elem = elem.parent.parent; } else { if (elem == elem.parent.right) { elem = elem.parent; RBLeftRotate(elem); } elem.parent.color = Color.black; elem.parent.parent.color = Color.black; RBRightRotate(elem.parent.parent); } } else { temp = elem.parent.parent.left; if (temp.color == Color.red) { elem.parent.color = Color.black; temp.color = Color.black; elem.parent.parent.color = Color.red; elem = elem.parent.parent; } else { if (elem == elem.parent.left) { elem = elem.parent; RBRightRotate(elem); } elem.parent.color = Color.black; elem.parent.parent.color = Color.red; RBLeftRotate(elem.parent.parent); } } } RBroot.color = Color.black; return(elem); }
// the smallest key in subtree rooted at x; null if no such key private RBNode Min(RBNode x) { if (x.Left == null) { return(x); } else { return(Min(x.Left)); } }
private RBNode MoveRedLeft(RBNode h) { FlipColors(h); if (IsRed(h.Right.Left)) { h.Right = RotateRight(h.Right); h = RotateLeft(h); FlipColors(h); } return(h); }
internal void SetSides(Directions dir, RBNode<BasicObstacleSide> neighborNode, RBNode<BasicObstacleSide> overlapEndNode, BasicObstacleSide interveningGroupSide) { if (StaticGraphUtility.IsAscending(dir)) { HighNeighbor = neighborNode; HighOverlapEnd = overlapEndNode; this.GroupSideInterveningBeforeHighNeighbor = interveningGroupSide; return; } LowNeighbor = neighborNode; LowOverlapEnd = overlapEndNode; this.GroupSideInterveningBeforeLowNeighbor = interveningGroupSide; }
void FindPiercedTriangle(RBNode<CdtFrontElement> v) { var e = v.Item.Edge; var t = e.CcwTriangle ?? e.CwTriangle; var eIndex = t.Edges.Index(e); for (int i = 1; i <= 2; i++) { var ei = t.Edges[i + eIndex]; var signedArea0 = ApproximateComparer.Sign(Point.SignedDoubledTriangleArea(ei.lowerSite.Point, a.Point, b.Point)); var signedArea1 = ApproximateComparer.Sign(Point.SignedDoubledTriangleArea(ei.upperSite.Point, a.Point, b.Point)); if (signedArea1 * signedArea0 <= 0) { piercedTriangle = t; piercedEdge = ei; break; } } }
void ProcessLeftFrontPiercedElement() { // CdtSweeper.ShowFront(triangles, front,new []{new LineSegment(a.Point, b.Point),new LineSegment(piercedToTheLeftFrontElemNode.Item.Edge.lowerSite.Point,piercedToTheLeftFrontElemNode.Item.Edge.upperSite.Point)},null); var v = piercedToTheLeftFrontElemNode; do { elementsToBeRemovedFromFront.Add(v.Item); AddSiteToLeftPolygon(v.Item.LeftSite); v = front.Previous(v); } while (Point.PointToTheLeftOfLine(v.Item.LeftSite.Point, a.Point, b.Point)); //that is why we are adding to the left polygon elementsToBeRemovedFromFront.Add(v.Item); AddSiteToRightPolygon(v.Item.LeftSite); if (v.Item.LeftSite == b) { piercedToTheLeftFrontElemNode = v; //this will stop the traversal return; } FindPiercedTriangle(v); piercedToTheLeftFrontElemNode = null; }
void ProcessRightFrontPiercedElement() { var v = piercedToTheRightFrontElemNode; do { elementsToBeRemovedFromFront.Add(v.Item); AddSiteToRightPolygon(v.Item.RightSite); v = front.Next(v); } while (Point.PointToTheRightOfLine(v.Item.RightSite.Point, a.Point, b.Point)); //that is why we are adding to the right polygon elementsToBeRemovedFromFront.Add(v.Item); AddSiteToLeftPolygon(v.Item.RightSite); if (v.Item.RightSite == b) { piercedToTheRightFrontElemNode = v; //this will stop the traversal return; } FindPiercedTriangle(v); piercedToTheRightFrontElemNode = null; }
void Init() { // if (CdtSweeper.D) // CdtSweeper.ShowFront(triangles, front, new[] {new LineSegment(a.Point, b.Point)},null); //new[] {new LineSegment(piercedEdge.upperSite.Point, piercedEdge.lowerSite.Point)}); var frontElemNodeRightOfA = CdtSweeper.FindNodeInFrontBySite(front, a); var frontElemNodeLeftOfA = front.Previous(frontElemNodeRightOfA); if (Point.PointToTheLeftOfLine(b.Point, frontElemNodeLeftOfA.Item.LeftSite.Point, frontElemNodeLeftOfA.Item.RightSite.Point)) piercedToTheLeftFrontElemNode = frontElemNodeLeftOfA; else if (Point.PointToTheRightOfLine(b.Point, frontElemNodeRightOfA.Item.RightSite.Point, frontElemNodeRightOfA.Item.LeftSite.Point)) piercedToTheRightFrontElemNode = frontElemNodeRightOfA; else { foreach (var e in a.Edges) { var t = e.CcwTriangle; if (t == null) continue; if (Point.PointToTheLeftOfLine(b.Point, e.lowerSite.Point, e.upperSite.Point)) continue; var eIndex = t.Edges.Index(e); var site = t.Sites[eIndex + 2]; if (Point.PointToTheLeftOfLineOrOnLine(b.Point, site.Point, e.upperSite.Point)) { piercedEdge = t.Edges[eIndex + 1]; piercedTriangle = t; // CdtSweeper.ShowFront(triangles, front, new[] { new LineSegment(e.upperSite.Point, e.lowerSite.Point) }, // new[] { new LineSegment(piercedEdge.upperSite.Point, piercedEdge.lowerSite.Point) }); break; } } } }
private void CreateScanSegmentFromLowSide(RBNode<BasicObstacleSide> lowSideNode, BasicVertexEvent vertexEvent) { // Create one or more segments from low to high using the neighbors of the LowObstacleSide. this.CreateScanSegments(lowSideNode.Item.Obstacle, this.LowNeighborSides, vertexEvent); }
void PrepareNextStateAfterPiercedEdge() { var t = piercedEdge.CwTriangle ?? piercedEdge.CcwTriangle; var eIndex = t.Edges.Index(piercedEdge); for (int i = 1; i <= 2; i++) { var e = t.Edges[i + eIndex]; var signedArea0 = ApproximateComparer.Sign(Point.SignedDoubledTriangleArea(e.lowerSite.Point, a.Point, b.Point)); var signedArea1 = ApproximateComparer.Sign(Point.SignedDoubledTriangleArea(e.upperSite.Point, a.Point, b.Point)); if (signedArea1 * signedArea0 <= 0) { if (e.CwTriangle != null && e.CcwTriangle != null) { piercedTriangle = t; piercedEdge = e; break; } //e has to belong to the front, and its triangle has to be removed piercedTriangle = null; piercedEdge = null; var leftSite = e.upperSite.Point.X < e.lowerSite.Point.X ? e.upperSite : e.lowerSite; var frontElem = CdtSweeper.FindNodeInFrontBySite(front, leftSite); Debug.Assert(frontElem != null); if (leftSite.Point.X < a.Point.X) piercedToTheLeftFrontElemNode = frontElem; else piercedToTheRightFrontElemNode = frontElem; RemovePiercedTriangle(e.CwTriangle ?? e.CcwTriangle); break; } } }
void CreateScanSegmentFromHighSide(RBNode<BasicObstacleSide> highSideNode, BasicVertexEvent vertexEvent) { // Create one or more segments from low to high using the neighbors of the HighObstacleSide. this.CreateScanSegments(highSideNode.Item.Obstacle, this.HighNeighborSides, vertexEvent); }
/// <summary> /// /// </summary> /// <param name="obstSideEndVertex"></param> /// <param name="rbNode">represents a node of the right cone side</param> /// <param name="obstSideStartVertex"></param> void FixConeRightSideIntersections(PolylinePoint obstSideStartVertex, PolylinePoint obstSideEndVertex, RBNode<ConeSide> rbNode) { if (rbNode != null) { Point intersection; var seg = rbNode.Item as ConeRightSide; if (seg != null && Point.IntervalIntersectsRay(obstSideStartVertex.Point, obstSideEndVertex.Point, seg.Start, seg.Direction, out intersection)) { EnqueueEvent(CreateRightIntersectionEvent(seg, intersection, obstSideEndVertex)); } } }
private bool ProcessGroupSideEncounteredOnTraversalToNeighbor(RBNode<BasicObstacleSide> nborNode, Point sideReferencePoint, Directions nborSearchDir) { if (!this.ScanLineCrossesObstacle(sideReferencePoint, nborNode.Item.Obstacle)) { return false; } // We don't stop overlap or neighbor-traversal for groups, because we must go through the boundary; // neither do we create overlapped edges (unless we're inside a non-group obstacle). Instead we turn // the boundary crossing on or off based on group membership at ShortestPath-time. Directions dirToInsideOfGroup = ((nborNode.Item is LowObstacleSide) == StaticGraphUtility.IsAscending(nborSearchDir)) ? nborSearchDir : CompassVector.OppositeDir(nborSearchDir); var intersect = this.ScanLineIntersectSide(sideReferencePoint, nborNode.Item); this.CurrentGroupBoundaryCrossingMap.AddIntersection(intersect, nborNode.Item.Obstacle, dirToInsideOfGroup); return true; }
/// <summary> /// /// </summary> /// <param name="rightSide"></param> /// <param name="rbNode">represents a node of the right cone side</param> void FixConeRightSideIntersections(BrokenConeSide rightSide, RBNode<ConeSide> rbNode) { //the first intersection can happen only with predecessors of rightSide Debug.Assert(rbNode != null); do { //this loop usually works only once rbNode = rightConeSides.Previous(rbNode); } while (rbNode != null && Point.PointToTheLeftOfLineOrOnLine(rightSide.Start, rbNode.Item.Start, rbNode.Item.Start + rbNode.Item.Direction)); if (rbNode != null) { Point intersection; var seg = rbNode.Item as ConeRightSide; if (seg != null && Point.IntervalIntersectsRay(rightSide.Start, rightSide.End, seg.Start, seg.Direction, out intersection)) { EnqueueEvent(CreateRightIntersectionEvent(seg, intersection, rightSide.EndVertex)); // Show(CurveFactory.CreateDiamond(3, 3, intersection)); } } }
void FindInitialNeighborSides(RBNode<BasicObstacleSide> sideNode, out RBNode<BasicObstacleSide> lowNborSideNode, out RBNode<BasicObstacleSide> highNborSideNode) { lowNborSideNode = this.scanLine.NextLow(sideNode); highNborSideNode = this.scanLine.NextHigh(sideNode); }
protected void FindNeighbors(BasicVertexEvent vertexEvent, RBNode<BasicObstacleSide> sideNode, NeighborSides neighborSides) { // vertexEvent.Site is on one of vertexEvent.Obstacle.Active(Low|High)Side, so we must get the // appropriate vertex on whichever one of those Active*Sides is sideNode. var sideReferencePoint = (vertexEvent is OpenVertexEvent) ? sideNode.Item.Start : sideNode.Item.End; RBNode<BasicObstacleSide> initialLowNbor, initialHighNbor; this.FindInitialNeighborSides(sideNode, out initialLowNbor, out initialHighNbor); this.SkipToNeighbor(this.ScanDirection.OppositeDirection, sideNode.Item, sideReferencePoint, initialLowNbor, neighborSides); this.SkipToNeighbor(this.ScanDirection.Direction, sideNode.Item, sideReferencePoint, initialHighNbor, neighborSides); }
void LookForIntersectionWithConeLeftSide(RBNode<ConeSide> leftNode) { //Show(new Ellipse(1, 1, leftNode.item.Start)); var coneLeftSide = leftNode.Item as ConeLeftSide; if (coneLeftSide != null) { //leftNode = leftSegmentTree.TreePredecessor(leftNode); //if (leftNode != null) { // var seg = leftNode.item as ObstacleSideSegment; // if (seg != null) // TryIntersectionOfConeLeftSideAndObstacleConeSide(coneLeftSide, seg); //} RightObstacleSide rightObstacleSide = FindFirstObstacleSideToTheLeftOfPoint(coneLeftSide.Start); if (rightObstacleSide != null) TryIntersectionOfConeLeftSideAndObstacleSide(coneLeftSide, rightObstacleSide); } else { var seg = (BrokenConeSide)leftNode.Item; leftNode = leftConeSides.Next(leftNode); if (leftNode != null) { coneLeftSide = leftNode.Item as ConeLeftSide; if (coneLeftSide != null) TryIntersectionOfConeLeftSideAndObstacleConeSide(coneLeftSide, seg); } } }
void TriangulateEmptySpaceToTheLeft(RBNode<CdtFrontElement> leftLegNode) { var peakSite = leftLegNode.Item.RightSite; var previousNode = front.Previous(leftLegNode); while (previousNode != null) { var prevElement = previousNode.Item; var rp = prevElement.LeftSite; var r=prevElement.RightSite; if ((r.Point - peakSite.Point) * (rp.Point - r.Point) < 0) { //see figures 9(a) and 9(b) of the paper leftLegNode=ShortcutTwoFrontElements(previousNode, leftLegNode); previousNode = front.Previous(leftLegNode); } else { TryTriangulateBasinToTheLeft(leftLegNode); break; } } }
CdtSite MiddleCase(CdtSite pi, RBNode<CdtFrontElement> hittedFrontElementNode, out CdtSite rightSite) { // if(db) // ShowFrontWithSite(pi, new LineSegment(pi.Point, hittedFrontElementNode.Item.Edge.upperSite.Point), new LineSegment(pi.Point, hittedFrontElementNode.Item.Edge.lowerSite.Point)); var leftSite = hittedFrontElementNode.Item.LeftSite; rightSite = hittedFrontElementNode.Item.RightSite; InsertAndLegalizeTriangle(pi, hittedFrontElementNode.Item); front.DeleteNodeInternal(hittedFrontElementNode); return leftSite; }
void LookForIntersectionWithConeRightSide(RBNode<ConeSide> rightNode) { //Show(new Ellipse(10, 5, rightNode.item.Start)); var coneRightSide = rightNode.Item as ConeRightSide; if (coneRightSide != null) { //rightNode = rightSegmentTree.TreeSuccessor(rightNode); //if (rightNode != null) { // var seg = rightNode.item as ObstacleSideSegment; // if (seg != null) // TryIntersectionOfConeRightSideAndObstacleConeSide(coneRightSide, seg); //} LeftObstacleSide leftObstacleSide = FindFirstObstacleSideToToTheRightOfPoint(coneRightSide.Start); if (leftObstacleSide != null) TryIntersectionOfConeRightSideAndObstacleSide(coneRightSide, leftObstacleSide); } else { var seg = (BrokenConeSide)rightNode.Item; rightNode = rightConeSides.Previous(rightNode); if (rightNode != null) { coneRightSide = rightNode.Item as ConeRightSide; if (coneRightSide != null) TryIntersectionOfConeRightSideAndObstacleConeSide(coneRightSide, seg); } } }
protected override void ProcessVertexEvent(RBNode<BasicObstacleSide> lowSideNode, RBNode<BasicObstacleSide> highSideNode, BasicVertexEvent vertexEvent) { // Create the scan segment from the low side. CreateScanSegmentFromLowSide(lowSideNode, vertexEvent); // If the low segment covered up to our high neighbor, we're done. Otherwise, there were overlaps // inside a flat boundary and now we need to come in from the high side. In this case there's a chance // that we're redoing a single subsegment in the event of two obstacles' outside edges crossing // the middle of a flat boundary of the event obstacle, but that should be sufficiently rare that // we don't need to optimize it away as the segments will be merged by ScanSegmentTree.MergeSegments. // TODOgroup TODOperf: currentGroupBoundaryCrossingMap still has the Low-side stuff in it but it shouldn't // matter much - profile to see how much time GetOrderedIndexBetween takes. if (LowNeighborSides.HighNeighbor.Item != HighNeighborSides.HighNeighbor.Item) { CreateScanSegmentFromHighSide(highSideNode, vertexEvent); } }
/// <summary> /// aNode is to the left of bNode, and they are consecutive /// </summary> /// <param name="aNode"></param> /// <param name="bNode"></param> RBNode<CdtFrontElement> ShortcutTwoFrontElements(RBNode<CdtFrontElement> aNode, RBNode<CdtFrontElement> bNode) { var aElem = aNode.Item; var bElem = bNode.Item; Debug.Assert(aElem.RightSite == bElem.LeftSite); CdtTriangle t = new CdtTriangle(aElem.LeftSite, aElem.RightSite, bElem.RightSite, aElem.Edge, bElem.Edge, createEdgeDelegate); Triangles.Insert(t); front.DeleteNodeInternal(aNode); //now bNode might b not valid anymore front.Remove(bElem); var newEdge = t.Edges[2]; Debug.Assert(newEdge.IsAdjacent( aElem.LeftSite) && newEdge.IsAdjacent(bElem.RightSite)); LegalizeEdge(aElem.LeftSite, t.OppositeEdge(aElem.LeftSite)); t=newEdge.CcwTriangle ?? newEdge.CwTriangle; LegalizeEdge(bElem.RightSite, t.OppositeEdge(bElem.RightSite)); return front.Insert(new CdtFrontElement(aElem.LeftSite, newEdge)); }
protected abstract void ProcessVertexEvent(RBNode<BasicObstacleSide> lowSideNode, RBNode<BasicObstacleSide> highSideNode, BasicVertexEvent vertexEvent);
void RemoveSideFromScanLine(RBNode<BasicObstacleSide> sideNode, Point scanPos) { scanLine.Remove(sideNode.Item, scanPos); }
void TryTriangulateBasinToTheLeft(RBNode<CdtFrontElement> leftLegNode) { if (!DropsSharpEnoughToTheLeft(leftLegNode.Item)) return; //ShowFrontWithSite(leftLegNode.Item.LeftSite); var stack = new Stack<CdtSite>(); stack.Push(leftLegNode.Item.LeftSite); while (true) { var site = stack.Pop(); leftLegNode = FindNodeInFrontBySite(front, site); var prev = front.Previous(leftLegNode); if (prev == null) return; if (Point.GetTriangleOrientationWithNoEpsilon(prev.Item.LeftSite.Point, leftLegNode.Item.LeftSite.Point, leftLegNode.Item.RightSite.Point) == TriangleOrientation.Counterclockwise) { stack.Push(prev.Item.LeftSite); ShortcutTwoFrontElements(prev, leftLegNode); // ShowFrontWithSite(site); } else { if (leftLegNode.Item.LeftSite.Point.Y > leftLegNode.Item.RightSite.Point.Y) { stack.Push(prev.Item.LeftSite); } else { if (prev.Item.LeftSite.Point.Y <= prev.Item.RightSite.Point.Y) return; stack.Push(prev.Item.LeftSite); } } } }
// As described in the doc, we stop at the first neighbor of the appropriate side type that we touch // the border of, even if that's just skimming along the extreme vertex of it, because those will // continue the chain of open/close+addSegment, and we don't want to follow the full length of the // segment each time if there are a lot of collinear obstacle open/close events. protected void FindNeighbors(BasicVertexEvent vertexEvent, RBNode<BasicObstacleSide> lowSideNode, RBNode<BasicObstacleSide> highSideNode) { LowNeighborSides.Clear(); HighNeighborSides.Clear(); // Find the first HighObstacleSide in the low (scanline-decreasing) direction (this may be the low // sentinel) and the lowest LowObstacleSide toward that that we cross *through*, if any. Then do // the same thing in the high direction. If we are not overlapped, then we'll jump out immediately // from SkipToNeighbor, so there won't be a lot of redundant effort in that case. FindNeighbors(vertexEvent, lowSideNode, LowNeighborSides); FindNeighbors(vertexEvent, highSideNode, HighNeighborSides); }
void TriangulateEmptySpaceToTheRight(RBNode<CdtFrontElement> piNode) { var piSite=piNode.Item.LeftSite; var piPoint=piSite.Point; var piNext = front.Next(piNode); while (piNext != null) { var frontElem=piNext.Item; var r=frontElem.LeftSite; var rp = frontElem.RightSite; if ((r.Point - piPoint) * (rp.Point - r.Point) < 0) { //see figures 9(a) and 9(b) of the paper piNode = ShortcutTwoFrontElements(piNode, piNext); piNext = front.Next(piNode); } else { TryTriangulateBasinToTheRight(piNode); break; } } }
void SkipToNeighbor(Directions nborSearchDir, BasicObstacleSide side, Point sideReferencePoint, RBNode<BasicObstacleSide> nborNode, NeighborSides neighborSides) { // Find the first neighbor side (LowObstacleSide if going high, HighObstacleSide if going low) and // the side of opposite type (which would potentially end overlap), that that we cross *through*, if any. RBNode<BasicObstacleSide> overlapSideNode = null; BasicObstacleSide interveningGroupSide = null; for (; ; nborNode = scanLine.Next(nborSearchDir, nborNode)) { // Ignore the opposite side of the current obstacle. if (nborNode.Item.Obstacle == side.Obstacle) { continue; } if (nborNode.Item.Obstacle.IsGroup) { if (ProcessGroupSideEncounteredOnTraversalToNeighbor(nborNode, sideReferencePoint, nborSearchDir)) { // Keep the first one (outermost) encountered. if (null == interveningGroupSide) { interveningGroupSide = nborNode.Item; } } continue; } // Check for overlap-ending obstacle. if ((nborNode.Item is HighObstacleSide) == StaticGraphUtility.IsAscending(nborSearchDir)) { if (ScanLineCrossesObstacle(sideReferencePoint, nborNode.Item.Obstacle)) { overlapSideNode = nborNode; interveningGroupSide = null; } continue; } // If we're here, we found the neighbor we were looking for. break; } neighborSides.SetSides(nborSearchDir, nborNode, overlapSideNode, interveningGroupSide); }
void TryTriangulateBasinToTheRight(RBNode<CdtFrontElement> piNode) { if (!DropsSharpEnoughToTheRight(piNode.Item)) return; // ShowFrontWithSite(piNode.Item.LeftSite); var stack = new Stack<CdtSite>(); stack.Push(piNode.Item.LeftSite); while(true) { var site = stack.Pop(); piNode = FindNodeInFrontBySite(front, site); var next = front.Next(piNode); if (next == null) return; if (Point.GetTriangleOrientationWithNoEpsilon(piNode.Item.LeftSite.Point, piNode.Item.RightSite.Point, next.Item.RightSite.Point) == TriangleOrientation.Counterclockwise) { ShortcutTwoFrontElements(piNode, next); stack.Push(site); } else { if (piNode.Item.LeftSite.Point.Y > piNode.Item.RightSite.Point.Y) { stack.Push(piNode.Item.RightSite); } else { if (next.Item.LeftSite.Point.Y >= next.Item.RightSite.Point.Y) return; stack.Push(piNode.Item.RightSite); } } } }
void FindNeighborsAndProcessVertexEvent(RBNode<BasicObstacleSide> lowSideNode , RBNode<BasicObstacleSide> highSideNode , BasicVertexEvent vertexEvent) { CurrentGroupBoundaryCrossingMap.Clear(); FindNeighbors(vertexEvent, lowSideNode, highSideNode); this.ProcessVertexEvent(lowSideNode, highSideNode, vertexEvent); // Clear this again because we don't want Reflections to access stale values. CurrentGroupBoundaryCrossingMap.Clear(); }
void ProjectToFront(CdtSite site, out RBNode<CdtFrontElement> frontElement) { frontElement = front.FindLast(s => s.X <= site.Point.X); }
CdtSite LeftCase(CdtSite pi, RBNode<CdtFrontElement> hittedFrontElementNode, out CdtSite rightSite) { //left case // if(db)ShowFrontWithSite(pi, new LineSegment(pi.Point, hittedFrontElementNode.Item.Edge.upperSite.Point), new LineSegment(pi.Point, hittedFrontElementNode.Item.Edge.lowerSite.Point)); Debug.Assert(ApproximateComparer.Close(pi.Point.X, hittedFrontElementNode.Item.X)); var hittedFrontElement = hittedFrontElementNode.Item; InsertAndLegalizeTriangle(pi, hittedFrontElement); var prevToHitted = front.Previous(hittedFrontElementNode); var leftSite = prevToHitted.Item.LeftSite; rightSite = hittedFrontElementNode.Item.RightSite; // if(db)ShowFrontWithSite(pi, new LineSegment(pi.Point, leftSite.Point), new LineSegment(pi.Point, prevToHitted.Item.RightSite.Point)); InsertAndLegalizeTriangle(pi, prevToHitted.Item); front.DeleteNodeInternal(prevToHitted); var d = front.Remove(hittedFrontElement); Debug.Assert(d != null); return leftSite; }
RBNode<ConeSide> GetRbNodeEmergency(RBNode<ConeSide> rbNode, ConeSide leftConeSide) { for (var node = leftConeSides.TreeMinimum(); node != null; node = leftConeSides.Next(node)) if (node.Item == leftConeSide) { rbNode = node; break; } return rbNode; }