Пример #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
        private int PossibleIntersection(SweepEvent ev1, SweepEvent ev2, IBST <SweepEvent> events)
        {
            Vector2D intersectionPoint;
            var      nIntersections = FindIntersections(ev1.Point, ev1.OtherEvent.Point, ev2.Point, ev2.OtherEvent.Point,
                                                        out intersectionPoint);

            if (nIntersections == 0)
            {
                return(0); // no intersection
            }

            // If the intersection is between two endpoints
            if (nIntersections == 1 && (ev1.Point.Equals(ev2.Point) ||
                                        ev1.OtherEvent.Point.Equals(ev2.OtherEvent.Point)))
            {
                return(0); // the line segments intersect at an endpoint of both line segments
            }

            if (nIntersections == 2 && ev1.PolygonType == ev2.PolygonType)
            {
                // The line segments overlap, but they belong to the same polygon
                throw new ArgumentException(string.Format("Sorry, edges of the same polygon overlap ({0} and {1})", ev1,
                                                          ev2));
            }

            // The line segments associated to ev1 and ev2 intersect
            if (nIntersections == 1)
            {
                if (!ev1.Point.Equals(intersectionPoint) && !ev1.OtherEvent.Point.Equals(intersectionPoint)
                    ) // If the intersection point is not an endpoint of ev1.Segment
                {
                    DivideSegment(ev1, intersectionPoint, events);
                }

                if (!ev2.Point.Equals(intersectionPoint) && !ev2.OtherEvent.Point.Equals(intersectionPoint)
                    ) // If the intersection point is not an endpoint of ev2.Segment
                {
                    DivideSegment(ev2, intersectionPoint, events);
                }

                return(1);
            }

            // The line segments associated to ev1 and ev2 overlap
            var sortedEvents = new List <SweepEvent>();
            var leftEqual    = false;
            var rightEqual   = false;

            if (ev1.Point.Equals(ev2.Point))
            {
                leftEqual = true;
            }
            else if (SweepEvent.CompareTo(ev1, ev2) == 1)
            {
                sortedEvents.Add(ev2);
                sortedEvents.Add(ev1);
            }
            else
            {
                sortedEvents.Add(ev1);
                sortedEvents.Add(ev2);
            }

            if (ev1.OtherEvent.Point.Equals(ev2.OtherEvent.Point))
            {
                rightEqual = true;
            }
            else if (SweepEvent.CompareTo(ev1.OtherEvent, ev2.OtherEvent) == 1)
            {
                sortedEvents.Add(ev2.OtherEvent);
                sortedEvents.Add(ev1.OtherEvent);
            }
            else
            {
                sortedEvents.Add(ev1.OtherEvent);
                sortedEvents.Add(ev2.OtherEvent);
            }

            if (leftEqual)
            {
                // Both line segments are equal or share the left endpoint
                ev2.EdgeType = EdgeType.NonContributing;
                ev1.EdgeType = (ev2.InOut == ev1.InOut) ? EdgeType.SameTransition : EdgeType.DifferentTransition;
                if (!rightEqual)
                {
                    DivideSegment(sortedEvents[1].OtherEvent, sortedEvents[0].Point, events);
                }

                return(2);
            }

            if (rightEqual)
            {
                // The line segments share the right endpoint
                DivideSegment(sortedEvents[0], sortedEvents[1].Point, events);
                return(3);
            }

            if (sortedEvents[0] != sortedEvents[3].OtherEvent)
            {
                // No line segment includes totally the other one
                DivideSegment(sortedEvents[0], sortedEvents[1].Point, events);
                DivideSegment(sortedEvents[1], sortedEvents[2].Point, events);
                return(3);
            }

            // One line segment includes the other one
            DivideSegment(sortedEvents[0], sortedEvents[1].Point, events);
            DivideSegment(sortedEvents[3].OtherEvent, sortedEvents[2].Point, events);
            return(3);
        }
Пример #4
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");
            }
        }
Пример #6
0
 public BSTInOrderIterator(IBST <T> bst)
 {
     root = bst;
     Reset();
 }
Пример #7
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);
                }
            }
        }