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); } } } } } }
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); }
/// <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); }
/// <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); }
/// <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); }
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"); } }
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); } } }