internal void Siftdown(int startpos, int pos) { var item = _heap[pos]; _EdgeEvent itemAsEdge = null; _SplitEvent itemAsSplit = null; if (item is _EdgeEvent) { itemAsEdge = item as _EdgeEvent; } else if (item is _SplitEvent) { itemAsSplit = item as _SplitEvent; } while (pos > startpos) { var parentpos = (pos - 1) >> 1; var parent = _heap[parentpos]; _EdgeEvent parentAsEdge = null; _SplitEvent parentAsSplit = null; if (parent is _EdgeEvent) { parentAsEdge = parent as _EdgeEvent; } else if (parent is _SplitEvent) { parentAsSplit = parent as _SplitEvent; } if (itemAsEdge != null) { if (parentAsEdge != null) { if (itemAsEdge.Distance < parentAsEdge.Distance) { _heap[pos] = parent; pos = parentpos; continue; } } else if (parentAsSplit != null) { if (itemAsEdge.Distance < parentAsSplit.Distance) { _heap[pos] = parent; pos = parentpos; continue; } } } else if (itemAsSplit != null) { if (parentAsEdge != null) { if (itemAsSplit.Distance < parentAsEdge.Distance) { _heap[pos] = parent; pos = parentpos; continue; } } else if (parentAsSplit != null) { if (itemAsSplit.Distance < parentAsSplit.Distance) { _heap[pos] = parent; pos = parentpos; continue; } } } break; } _heap[pos] = item; }
internal SkeletonEventResult Handle_Split_Event(_SplitEvent splitEvent) { var lav = splitEvent.Vertex.Vertices; //Debug.WriteLine("{0} Split event at intersection {1} from vertex {2}, for edge {3} in {4}", splitEvent.Distance, splitEvent.IntersectionPoint, splitEvent.Vertex, splitEvent.OppositeEdge, lav); var sinks = new List <Vector2>() { splitEvent.Vertex.Point }; var vertices = new List <SkeletonVertex>(); SkeletonVertex x = null; // right vertex SkeletonVertex y = null; // left vertex var norm = splitEvent.OppositeEdge.V.Normalized(); foreach (var childLav in this) { foreach (var v in childLav) { //Debug.WriteLine("{0} in {1}", v, v.LAV); if (norm == v.EdgeLeft.V.Normalized() && splitEvent.OppositeEdge.P == v.EdgeLeft.P) { x = v; y = x.Previous; } else if (norm == v.EdgeRight.V.Normalized() && splitEvent.OppositeEdge.P == v.EdgeRight.P) { y = v; x = y.Next; } if (x != null) { var yIntersectionAsPoint = (new Vector2(splitEvent.IntersectionPoint.X - y.Point.X, splitEvent.IntersectionPoint.Y - y.Point.Y)).Normalized(); var yLeftBiSectorAsPoint = new PointF(y.BiSector.V.Normalized().X, y.BiSector.V.Normalized().Y); var xleft = Helpers.MathHelper.Cross(yLeftBiSectorAsPoint, new PointF(yIntersectionAsPoint.X, yIntersectionAsPoint.Y)) >= 0; var xIntersectionAsPoint = (new Vector2(splitEvent.IntersectionPoint.X - x.Point.X, splitEvent.IntersectionPoint.Y - x.Point.Y)).Normalized(); var xLeftBiSectorAsPoint = new PointF(x.BiSector.V.Normalized().X, x.BiSector.V.Normalized().Y); var xright = Helpers.MathHelper.Cross(xLeftBiSectorAsPoint, new PointF(xIntersectionAsPoint.X, xIntersectionAsPoint.Y)) <= 0; //Debug.WriteLine("Vertex {0} holds edge as {1} edge ({2}, {3})", v, (x == v ? "left" : "right"), xleft, xright); if (xleft && xright) { break; } else { x = null; y = null; } } } } if (x == null) { //Debug.WriteLine("Failed split event {0} (equivalent edge event is expected to follow)", splitEvent); return(new SkeletonEventResult(null, null)); } var v1 = new SkeletonVertex(splitEvent.IntersectionPoint, splitEvent.Vertex.EdgeLeft, splitEvent.OppositeEdge); var v2 = new SkeletonVertex(splitEvent.IntersectionPoint, splitEvent.OppositeEdge, splitEvent.Vertex.EdgeRight); v1.Previous = splitEvent.Vertex.Previous; v1.Next = x; splitEvent.Vertex.Previous.Next = v1; x.Previous = v1; v2.Previous = y; v2.Next = splitEvent.Vertex.Next; splitEvent.Vertex.Next.Previous = v2; y.Next = v2; List <SkeletonVertices> new_lavs = new List <SkeletonVertices>(); this.Remove(lav); if (lav.Count != x.Vertices.Count) { this.Remove(x.Vertices); new_lavs.Add(SkeletonVerticesCollection.FromChain(v1, lav)); } else { new_lavs.Add(SkeletonVerticesCollection.FromChain(v1, lav)); new_lavs.Add(SkeletonVerticesCollection.FromChain(v2, lav)); } foreach (var l in new_lavs) { if (l.Count > 2) { this.Add(l); vertices.Add(l.Head); } else { sinks.Add(l.Head.Next.Point); foreach (var v in l) { v.Invalidate(); } } } var events = new List <IEvent>(); foreach (var vertex in vertices) { var nextEvent = vertex.NextEvent(lav._originalEdges); if (nextEvent != null) { events.Add(nextEvent); } } splitEvent.Vertex.Invalidate(); return(new SkeletonEventResult(new SkeletonSubtree(splitEvent.IntersectionPoint, splitEvent.Distance, sinks), events)); }
void SiftUp(int pos) { var endpos = this._heap.Length; var startpos = pos; var newitem = _heap[pos]; var childpos = 2 * pos + 1; // leftmost child position while (childpos < endpos) { var cmd_gt = false; var rightpos = childpos + 1; if (rightpos < endpos) { _EdgeEvent rightItemAsEdge = null; _SplitEvent rightItemAsSplit = null; if (this._heap[rightpos] is _EdgeEvent) { rightItemAsEdge = this._heap[rightpos] as _EdgeEvent; } else if (this._heap[rightpos] is _SplitEvent) { rightItemAsSplit = this._heap[rightpos] as _SplitEvent; } _EdgeEvent childItemAsEdge = null; _SplitEvent childItemAsSplit = null; if (this._heap[childpos] is _EdgeEvent) { childItemAsEdge = this._heap[childpos] as _EdgeEvent; } else if (this._heap[rightpos] is _SplitEvent) { childItemAsSplit = this._heap[childpos] as _SplitEvent; } if (rightItemAsEdge != null) { if (childItemAsEdge != null) { if (childItemAsEdge.Distance >= rightItemAsEdge.Distance) { cmd_gt = true; } } else if (childItemAsSplit != null) { if (childItemAsSplit.Distance >= rightItemAsEdge.Distance) { cmd_gt = true; } } } else if (rightItemAsSplit != null) { if (childItemAsEdge != null) { if (childItemAsEdge.Distance >= rightItemAsSplit.Distance) { cmd_gt = true; } } else if (childItemAsSplit != null) { if (childItemAsSplit.Distance >= rightItemAsSplit.Distance) { cmd_gt = true; } } } } if (cmd_gt) { childpos = rightpos; } this._heap[pos] = this._heap[childpos]; pos = childpos; childpos = 2 * pos + 1; } this._heap[pos] = newitem; Siftdown(startpos, pos); }