示例#1
0
        private void CheckIntersection(StatusItem left, StatusItem right, IBST <SweepEvent> events)
        {
            Vector2?intersect = left.LineObject.Intersect(right.LineObject);

            if (intersect != null)
            {
                Vector2?otherIntersect = right.LineObject.Intersect(left.LineObject);
                if (intersect != null)
                {
                    float y = ((Vector2)intersect).y;
                    if (y < Line.Point1.y)
                    {
                        if (y > left.LineObject.YInterval.Min && y < left.LineObject.YInterval.Max &&
                            y > right.LineObject.YInterval.Min && y < right.LineObject.YInterval.Max)
                        {
                            SweepEvent ev = new SweepEvent(EventType.INTERSECT);
                            ev.StatusItem             = left;
                            ev.IntersectingStatusItem = right;
                            if (!events.Contains(ev))
                            {
                                events.Insert(ev);
                            }
                        }
                    }
                }
            }
        }
示例#2
0
        private void DivideSegment(SweepEvent ev, Vector2D pos, IBST <SweepEvent> events)
        {
            // "Right event" of the "left line segment" resulting from dividing ev.Segment
            var r = new SweepEvent(pos, false, ev, ev.PolygonType);
            // "Left event" of the "right line segment" resulting from dividing ev.Segment
            var l = new SweepEvent(pos, true, ev.OtherEvent, ev.PolygonType);

            if (SweepEvent.CompareTo(l, ev.OtherEvent) > 0
                ) // Avoid a rounding error. The left event would be processed after the right event
            {
                ev.OtherEvent.IsStart = true;
                l.IsStart             = false;
            }

            ev.OtherEvent.OtherEvent = l;
            ev.OtherEvent            = r;
            events.Insert(l);
            events.Insert(r);
        }
示例#3
0
        /// <summary>
        /// Initialize the status tree with the given items.
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        public IBST <T> InitializeStatus(IEnumerable <T> items)
        {
            Status.Clear();

            foreach (var item in items)
            {
                Status.Insert(item);
            }

            return(Status);
        }
示例#4
0
        /// <summary>
        /// Initialize the event queue with the given items.
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        public IBST <ISweepEvent <T> > InitializeEvents(IEnumerable <ISweepEvent <T> > items)
        {
            Events.Clear();

            foreach (var item in items)
            {
                Events.Insert(item);
            }

            return(Events);
        }
示例#5
0
        /// <summary>
        /// Initialize the event queue with the given items.
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        public IBST <E> InitializeEvents(IEnumerable <E> items)
        {
            Events.Clear();

            foreach (var item in items)
            {
                if (!Events.Insert(item))
                {
                    throw new ArgumentException(string.Format("Failed to insert event {0}", item));
                }
            }

            return(Events);
        }
示例#6
0
        private void HandleEvent(IBST <SweepEvent> events, IBST <StatusItem> status, SweepEvent ev)
        {
            ResultEvents.Add(ev);

            // Optimization 2
            if ((Operation == OperationType.Intersection && ev.Point.x > RightBound) ||
                (Operation == OperationType.Difference && ev.Point.x > SubjectBoundingBox.xMax))
            {
                // We need to connect edges now, so just clear all events. This will result in us immediately
                // going to ConnectEdges() since there are no more events to handle.
                InitializeEvents(new List <SweepEvent>());
                return;
            }

            if (ev.IsStart) // The line segment must be inserted into status
            {
                ev.StatusItem = new StatusItem(ev);
                if (!status.Insert(ev.StatusItem))
                {
                    throw new ArgumentException("Failed to insert into state");
                }

                StatusItem prev;
                var        prevFound = status.FindNextSmallest(ev.StatusItem, out prev);

                ComputeFields(ev, prev, prevFound);

                StatusItem next;
                if (status.FindNextBiggest(ev.StatusItem, out next))
                {
                    // Process a possible intersection between "ev" and its next neighbor in status
                    if (PossibleIntersection(ev, next.SweepEvent, events) == 2)
                    {
                        ComputeFields(ev, prev, prevFound);
                        ComputeFields(next.SweepEvent, ev.StatusItem, true);
                    }
                }

                // Process a possible intersection between "ev" and its previous neighbor in status
                if (prevFound)
                {
                    if (PossibleIntersection(prev.SweepEvent, ev, events) == 2)
                    {
                        StatusItem prevprev;
                        var        prevprevFound = status.FindNextSmallest(prev, out prevprev);

                        ComputeFields(prev.SweepEvent, prevprev, prevprevFound);
                        ComputeFields(ev, prev, prevFound);
                    }
                }
            }
            else
            {
                // The line segment must be removed from status
                ev = ev.OtherEvent; // We work with the left event

                StatusItem prev, next;
                var        prevFound = status.FindNextSmallest(ev.StatusItem, out prev);
                var        nextFound = status.FindNextBiggest(ev.StatusItem, out next);

                // Delete line segment associated to "ev" from status and check for intersection between the neighbors of "ev" in status
                status.Delete(ev.StatusItem);

                if (nextFound && prevFound)
                {
                    PossibleIntersection(prev.SweepEvent, next.SweepEvent, events);
                }
            }
        }
        public void HandleEvent(IBST <IntersectionSweepEvent> events, IBST <IntersectionStatusItem> status,
                                IntersectionSweepEvent ev)
        {
            if (ev.IsStart)
            {
                ev.StatusItem = new IntersectionStatusItem(ev);
                status.Insert(ev.StatusItem);

                IntersectionStatusItem prev, next;
                bool prevFound = status.FindNextSmallest(ev.StatusItem, out prev);
                bool nextFound = status.FindNextBiggest(ev.StatusItem, out next);

                if (prevFound)
                {
                    LineSegment otherSegment = prev.SweepEvent.Segment;
                    Vector2?    intersection = ev.Segment.IntersectProper(otherSegment);
                    if (intersection != null)
                    {
                        events.Insert(new IntersectionSweepEvent(intersection.Value, false, false,
                                                                 ev.Segment, otherSegment));
                    }
                }

                if (nextFound)
                {
                    LineSegment otherSegment = next.SweepEvent.Segment;
                    Vector2?    intersection = ev.Segment.IntersectProper(otherSegment);
                    if (intersection != null)
                    {
                        events.Insert(new IntersectionSweepEvent(intersection.Value, false, false,
                                                                 ev.Segment, otherSegment));
                    }
                }
            }
            else if (ev.IsEnd)
            {
                ev = ev.OtherEvent;
                if (ev.StatusItem == null)
                {
                    return;
                }

                IntersectionStatusItem prev, next;
                bool prevFound = status.FindNextSmallest(ev.StatusItem, out prev);
                bool nextFound = status.FindNextBiggest(ev.StatusItem, out next);

                status.Delete(ev.StatusItem);

                if (nextFound && prevFound)
                {
                    LineSegment segment      = prev.SweepEvent.Segment;
                    LineSegment otherSegment = next.SweepEvent.Segment;
                    Vector2?    intersection = segment.IntersectProper(otherSegment);
                    if (intersection != null)
                    {
                        events.Insert(new IntersectionSweepEvent(intersection.Value, false, false,
                                                                 segment, otherSegment));
                    }
                }
            }
            else if (ev.IsIntersection)
            {
                // stop on first intersection
                intersected = new List <Edge>
                {
                    new Edge(new Vertex(ev.Segment.Point1), new Vertex(ev.Segment.Point2)),
                    new Edge(new Vertex(ev.OtherSegment.Point1), new Vertex(ev.OtherSegment.Point2))
                };
                events.Clear();
                status.Clear();
            }
            else
            {
                throw new Exception("Invalid event type");
            }
        }
示例#8
0
        public new void HandleEvent(IBST <SweepEvent> events, IBST <StatusItem> status, SweepEvent ev)
        {
            // keep track of added events for visualization
            producedEvents.Add(ev);

            if (ev.IsStart)
            {
                ComparePreEvent = true;
                if (!status.Insert(ev.StatusItem))
                {
                    throw new ArgumentException("Failed to insert into state");
                }

                StatusItem prev;
                if (status.FindNextSmallest(ev.StatusItem, out prev))
                {
                    CheckIntersection(prev, ev.StatusItem, events);
                }

                StatusItem next;
                if (status.FindNextBiggest(ev.StatusItem, out next))
                {
                    CheckIntersection(ev.StatusItem, next, events);
                }
            }
            else if (ev.IsEnd)
            {
                ComparePreEvent = false;
                StatusItem prev;
                bool       hasPrev = status.FindNextSmallest(ev.StatusItem, out prev);

                StatusItem next;
                bool       hasNext = status.FindNextBiggest(ev.StatusItem, out next);
                if (!status.Delete(ev.StatusItem))
                {
                    throw new InvalidInitialGeneralPosition("Could not delete from status : (");
                }

                if (hasPrev && hasNext)
                {
                    CheckIntersection(prev, next, events);
                }
            }
            else if (ev.IsIntersection)
            {
                StatusItem left  = ev.StatusItem;
                StatusItem right = ev.IntersectingStatusItem;
                this.intersections.Add(new Intersection(left.LineObject, right.LineObject));
                // Remove
                ComparePreEvent = true;
                if (!status.Delete(left))
                {
                    throw new InvalidInitialGeneralPosition(left + " not deleted.");
                }
                if (!status.Delete(right))
                {
                    throw new InvalidInitialGeneralPosition(right + " not deleted.");
                }

                // Swap
                ComparePreEvent = false;

                // Add
                status.Insert(left);
                status.Insert(right);

                // NOTE: At this point, ComparePreEvent = false implies that right PRECEDES left now

                StatusItem prev;
                if (status.FindNextSmallest(right, out prev))
                {
                    CheckIntersection(prev, right, events);
                }

                StatusItem next;
                if (status.FindNextBiggest(left, out next))
                {
                    CheckIntersection(left, next, events);
                }
            }
        }