Exemplo n.º 1
0
        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;
        }
Exemplo n.º 2
0
        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));
        }
Exemplo n.º 3
0
        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);
        }