/// <summary> /// Appends the coordinates to the queue. /// </summary> /// <param name="coordinates">The collection of coordinates.</param> private void AppendCoordinates(IEnumerable <Coordinate> coordinates) { if (coordinates == null) { return; } IEnumerator <Coordinate> enumerator = coordinates.GetEnumerator(); if (!enumerator.MoveNext()) { return; } Coordinate previous, current = enumerator.Current; while (enumerator.MoveNext()) { if (enumerator.Current == null) { continue; } previous = current; current = enumerator.Current; EndPointEvent firstEvent = new EndPointEvent { Edge = this.coordinateCount, Vertex = previous }; EndPointEvent secondEvent = new EndPointEvent { Edge = this.coordinateCount, Vertex = current }; Int32 compare = this.comparer.Compare(previous, current); if (compare == 0) { continue; } if (compare < 0) { firstEvent.Type = EventType.Left; secondEvent.Type = EventType.Right; } else { firstEvent.Type = EventType.Right; secondEvent.Type = EventType.Left; } this.eventHeap.Insert(firstEvent); this.eventHeap.Insert(secondEvent); this.coordinateCount++; } this.coordinateCount++; }
/// <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">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 Add(EndPointEvent e) { if (e == null) { throw new ArgumentNullException(nameof(e)); } if (e.Edge < 0) { throw new ArgumentException(CoreMessages.EventEdgeIsLessThan0, nameof(e)); } if (e.Edge >= this.source.Count - 1) { throw new ArgumentException(CoreMessages.EventEdgeIsGreaterThanNumberOfEdges, nameof(e)); } SweepLineSegment segment = new SweepLineSegment { Edge = e.Edge }; if (this.coordinateComparer.Compare(this.source[e.Edge], this.source[e.Edge + 1]) <= 0) { segment.LeftCoordinate = this.source[e.Edge]; segment.RightCoordinate = this.source[e.Edge + 1]; } else { segment.LeftCoordinate = this.source[e.Edge + 1]; segment.RightCoordinate = this.source[e.Edge]; } this.tree.Insert(segment); SweepLineSegment segmentAbove = this.tree.GetNext(); SweepLineSegment segmentBelow = this.tree.GetPrevious(); 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">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(nameof(e)); } if (e.Edge < 0) { throw new ArgumentException(CoreMessages.EventEdgeIsLessThan0, nameof(e)); } if (e.Edge >= this.source.Count - 1) { throw new ArgumentException(CoreMessages.EventEdgeIsGreaterThanNumberOfEdges, nameof(e)); } SweepLineSegment segment = new SweepLineSegment() { Edge = e.Edge }; if (this.coordinateComparer.Compare(this.source[e.Edge], this.source[e.Edge + 1]) < 0) { segment.LeftCoordinate = this.source[e.Edge]; segment.RightCoordinate = this.source[e.Edge + 1]; } else { segment.LeftCoordinate = this.source[e.Edge + 1]; segment.RightCoordinate = this.source[e.Edge]; } SweepLineSegment segmentResult; if (this.tree.TrySearch(segment, out segmentResult)) { return(segmentResult); } else { return(null); } }
/// <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) { if (x == null || y == null) { return(0); } Int32 result = this.coordinateComparer.Compare(x.Vertex, y.Vertex); if (result != 0) { return(result); } EndPointEvent ex = x as EndPointEvent; EndPointEvent ey = y as EndPointEvent; IntersectionEvent ix = x as IntersectionEvent; IntersectionEvent iy = y as IntersectionEvent; if (ex != null && ey != null) { result = ex.Type.CompareTo(ey.Type); if (result == 0) { result = ex.Edge.CompareTo(ey.Edge); } } else if (ix != null && iy != null) { if (result == 0) { result = this.coordinateComparer.Compare(ix.Below.LeftCoordinate, iy.Below.LeftCoordinate); } if (result == 0) { result = this.coordinateComparer.Compare(ix.Above.LeftCoordinate, iy.Above.LeftCoordinate); } if (result == 0) { result = this.coordinateComparer.Compare(ix.Below.RightCoordinate, iy.Below.RightCoordinate); } if (result == 0) { result = this.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.IsClosing.CompareTo(iy.IsClosing); } } else if (ex != null && iy != null) { result = ex.Type == EventType.Left ? -1 : 1; } else if (ix != null && ey != null) { result = ey.Type == EventType.Left ? 1 : -1; } return(result); }