/// <summary> /// Initializes a new instance of the <see cref="PresortedEventQueue" /> class. /// </summary> /// <param name="source">The source coordinates representing multiple line strings.</param> /// <exception cref="System.ArgumentNullException">The source is null.</exception> public PresortedEventQueue(IEnumerable <IList <Coordinate> > source) { // source: http://geomalgorithms.com/a09-_intersect-3.html if (source == null) { throw new ArgumentNullException("source", "The source is null."); } _comparer = new CoordinateComparer(); _eventIndex = 0; _eventList = new List <EndPointEvent>(); Int32 index = 0, compare; foreach (IList <Coordinate> coordinateList in source) { if (coordinateList == null || coordinateList.Count < 2) { continue; } for (Int32 i = 0; i < coordinateList.Count - 1; i++) { var firstEvent = new EndPointEvent { Edge = index, Vertex = coordinateList[i] }; var secondEvent = new EndPointEvent { Edge = index, Vertex = coordinateList[i + 1] }; compare = _comparer.Compare(coordinateList[i], coordinateList[i + 1]); if (compare == 0) { continue; } if (compare < 0) { firstEvent.Type = EventType.Left; secondEvent.Type = EventType.Right; } else { firstEvent.Type = EventType.Right; secondEvent.Type = EventType.Left; } _eventList.Add(firstEvent); _eventList.Add(secondEvent); index++; } index++; } _eventList.Sort(new EventComparer()); }
/// <summary> /// Adds a new endpoint event to the sweep line. /// </summary> /// <param name="e">The event.</param> /// <returns>The sweep line segment created by addition of <paramref name="e" />.</returns> /// <exception cref="System.ArgumentNullException">e;The event is null.</exception> /// <exception cref="System.ArgumentException"> /// The edge of the event is less than 0.;e /// or /// The edge of the event is greater than the number of edges in the source.;e /// </exception> public SweepLineSegment Add(EndPointEvent e) { // source: http://geomalgorithms.com/a09-_intersect-3.html if (e == null) { throw new ArgumentNullException("e", "The event is null."); } if (e.Edge < 0) { throw new ArgumentException("The edge of the event is less than 0.", "e"); } if (e.Edge >= _source.Count - 1) { throw new ArgumentException("The edge of the event is greater than the number of edges in the source.", "e"); } SweepLineSegment segment = new SweepLineSegment { Edge = e.Edge }; Coordinate c1 = _source[e.Edge]; Coordinate c2 = _source[e.Edge + 1]; if (_coordinateComparer.Compare(c1, c2) <= 0) { segment.LeftCoordinate = c1; segment.RightCoordinate = c2; } else { segment.LeftCoordinate = c2; segment.RightCoordinate = c1; } _tree.Insert(segment); SweepLineSegment segmentAbove = _tree.GetNext(); SweepLineSegment segmentBelow = _tree.GetPrev(); if (segmentAbove != null) { segment.Above = segmentAbove; segment.Above.Below = segment; } if (segmentBelow != null) { segment.Below = segmentBelow; segment.Below.Above = segment; } return(segment); }
/// <summary> /// Searches the sweep line for an endpoint event. /// </summary> /// <param name="e">The event.</param> /// <returns>The segment associated with the event.</returns> /// <exception cref="System.ArgumentNullException">e;The event is null.</exception> /// <exception cref="System.ArgumentException"> /// The edge of the event is less than 0. /// or /// The edge of the event is greater than the number of edges in the source. /// </exception> public SweepLineSegment Search(EndPointEvent e) { if (e == null) { throw new ArgumentNullException("e", "The event is null."); } if (e.Edge < 0) { throw new ArgumentException("The edge of the event is less than 0.", "e"); } if (e.Edge >= _source.Count - 1) { throw new ArgumentException("The edge of the event is greater than the number of edges in the source.", "e"); } SweepLineSegment segment = new SweepLineSegment() { Edge = e.Edge }; Coordinate c1 = _source[e.Edge]; Coordinate c2 = _source[e.Edge + 1]; if (_coordinateComparer.Compare(c1, c2) < 0) { segment.LeftCoordinate = c1; segment.RightCoordinate = c2; } else { segment.LeftCoordinate = c2; segment.RightCoordinate = c1; } SweepLineSegment segmentResult; if (_tree.TrySearch(segment, out segmentResult)) { return(segmentResult); } else { return(null); } }
/// <summary> /// Initializes a new instance of the <see cref="EventQueue" /> class. /// </summary> /// <param name="source">The source coordinates representing a single line string.</param> /// <exception cref="System.ArgumentNullException">The source is null.</exception> public EventQueue(IList <Coordinate> source) { // source: http://geomalgorithms.com/a09-_intersect-3.html if (source == null) { throw new ArgumentNullException("source", "The source is null."); } _comparer = new CoordinateComparer(); _eventHeap = new EventHeap(); Int32 compare; for (Int32 i = 0; i < source.Count - 1; i++) { EndPointEvent firstEvent = new EndPointEvent { Edge = i, Vertex = source[i] }; EndPointEvent secondEvent = new EndPointEvent { Edge = i, Vertex = source[i + 1] }; compare = _comparer.Compare(source[i], source[i + 1]); if (compare == 0) { continue; } if (compare < 0) { firstEvent.Type = EventType.Left; secondEvent.Type = EventType.Right; } else { firstEvent.Type = EventType.Right; secondEvent.Type = EventType.Left; } _eventHeap.Insert(firstEvent); _eventHeap.Insert(secondEvent); } }
/// <summary> /// Compares two <see cref="Event"/> instances and returns a value indicating whether one is less than, equal to, or greater than the other. /// </summary> /// <remarks> /// Events primarily compared by their vertex coordinate, secondarily by their type. /// </remarks> /// <param name="x">The first <see cref="Event"/> to compare.</param> /// <param name="y">The second <see cref="Event"/> to compare.</param> /// <returns>A signed integer that indicates the relative values of <paramref name="x"/> and <paramref name="y"/>.</returns> public Int32 Compare(Event x, Event y) { Int32 result = _coordinateComparer.Compare(x.Vertex, y.Vertex); if (result != 0) { return(result); } if (x is EndPointEvent && y is EndPointEvent) { EndPointEvent ex = (EndPointEvent)x; EndPointEvent ey = (EndPointEvent)y; result = ex.Type.CompareTo(ey.Type); if (result == 0) { result = ex.Edge.CompareTo(ey.Edge); } } else if (x is IntersectionEvent && y is IntersectionEvent) { IntersectionEvent ix = (IntersectionEvent)x; IntersectionEvent iy = (IntersectionEvent)y; if (result == 0) { result = _coordinateComparer.Compare(ix.Below.LeftCoordinate, iy.Below.LeftCoordinate); } if (result == 0) { result = _coordinateComparer.Compare(ix.Above.LeftCoordinate, iy.Above.LeftCoordinate); } if (result == 0) { result = _coordinateComparer.Compare(ix.Below.RightCoordinate, iy.Below.RightCoordinate); } if (result == 0) { result = _coordinateComparer.Compare(ix.Above.RightCoordinate, iy.Above.RightCoordinate); } if (result == 0) { result = ix.Below.Edge.CompareTo(iy.Below.Edge); } if (result == 0) { result = ix.Above.Edge.CompareTo(iy.Above.Edge); } if (result == 0) { result = ix.IsClose.CompareTo(iy.IsClose); } } else if (x is EndPointEvent && y is IntersectionEvent) { result = ((EndPointEvent)x).Type == EventType.Left ? -1 : 1; } else if (y is EndPointEvent && x is IntersectionEvent) { result = ((EndPointEvent)y).Type == EventType.Left ? 1 : -1; } return(result); }