/// <summary> /// Gets the intersection type between the two given sweep line segments. /// </summary> /// <param name="x">First sweep line segment.</param> /// <param name="y">Second sweep line segment.</param> /// <returns>The type of intersection that exists between the two sweep line segments, considering the position of the sweepline.</returns> public SweepLineIntersection GetIntersection(SweepLineSegment x, SweepLineSegment y) { IList <Coordinate> intersections = LineAlgorithms.Intersection(x.LeftCoordinate, x.RightCoordinate, y.LeftCoordinate, y.RightCoordinate, _precisionModel); if (intersections.Count == 0) { return(SweepLineIntersection.NotExists); } if (intersections[0].X < _sweepLinePosition) { return(SweepLineIntersection.Passed); } if (intersections[0].X > _sweepLinePosition) { return(SweepLineIntersection.NotPassed); } return((_intersections.Contains(Tuple.Create(x, y)) || _intersections.Contains(Tuple.Create(y, x))) ? SweepLineIntersection.Passed : SweepLineIntersection.NotPassed); }
/// <summary> /// Registers a passed intersection point by the sweep line between the two given arguments. /// </summary> /// <remarks> /// The position of the sweep line is updated when necessary. /// </remarks> /// <param name="x">First sweep line segment.</param> /// <param name="y">Second sweep line segment.</param> public void PassIntersection(SweepLineSegment x, SweepLineSegment y) { Intersection intersection = LineAlgorithms.Intersection(x.LeftCoordinate, x.RightCoordinate, y.LeftCoordinate, y.RightCoordinate, this.precisionModel); if (intersection == null) { return; } if (intersection.Coordinate.X > this.sweepLinePosition) { this.sweepLinePosition = intersection.Coordinate.X; this.intersections.Clear(); } this.intersections.Add(Tuple.Create(x, y)); this.intersections.Add(Tuple.Create(y, x)); }
/// <summary> /// Registers a passed intersection point by the sweep line between the two given arguments. /// </summary> /// <remarks> /// The position of the sweep line is updated when necessary. /// </remarks> /// <param name="x">First sweep line segment.</param> /// <param name="y">Second sweep line segment.</param> public void PassIntersection(SweepLineSegment x, SweepLineSegment y) { IList <Coordinate> intersections = LineAlgorithms.Intersection(x.LeftCoordinate, x.RightCoordinate, y.LeftCoordinate, y.RightCoordinate, _precisionModel); if (intersections.Count == 0) { return; } if (intersections[0].X > _sweepLinePosition) { _sweepLinePosition = intersections[0].X; _intersections.Clear(); } _intersections.Add(Tuple.Create(x, y)); _intersections.Add(Tuple.Create(y, x)); }
/// <summary> /// Gets the intersection type between the two given sweep line segments. /// </summary> /// <param name="x">First sweep line segment.</param> /// <param name="y">Second sweep line segment.</param> /// <returns>The type of intersection that exists between the two sweep line segments, considering the position of the sweep line.</returns> public SweepLineIntersection GetIntersection(SweepLineSegment x, SweepLineSegment y) { Intersection intersection = LineAlgorithms.Intersection(x.LeftCoordinate, x.RightCoordinate, y.LeftCoordinate, y.RightCoordinate, this.precisionModel); if (intersection == null || intersection.Type == IntersectionType.None) { return(SweepLineIntersection.NotExists); } if (intersection.Coordinate.X < this.sweepLinePosition) { return(SweepLineIntersection.Passed); } if (intersection.Coordinate.X > this.sweepLinePosition) { return(SweepLineIntersection.NotPassed); } return((this.intersections.Contains(Tuple.Create(x, y)) || this.intersections.Contains(Tuple.Create(y, x))) ? SweepLineIntersection.Passed : SweepLineIntersection.NotPassed); }
/// <summary> /// Computes the intersection of one or more line strings. /// </summary> public void Compute() { // source: http://geomalgorithms.com/a09-_intersect-3.html _intersections = new List <Coordinate>(); _edgeIndices = new List <Tuple <Int32, Int32> >(); Event currentEvent = _eventQueue.Next(); SweepLineSegment segment; IList <Coordinate> intersections; while (currentEvent != null) { if (currentEvent is EndPointEvent) { EndPointEvent endPointEvent = (EndPointEvent)currentEvent; switch (endPointEvent.Type) { // Left endpoint event: check for possible intersection with below and / or above segments. case EventType.Left: segment = _sweepLine.Add(endPointEvent); if (segment.Above != null) { intersections = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate, segment.Above.LeftCoordinate, segment.Above.RightCoordinate, PrecisionModel); if (intersections.Count > 0) { IntersectionEvent intersectionEvent = new IntersectionEvent { Vertex = intersections[0], Below = segment, Above = segment.Above }; _eventQueue.Add(intersectionEvent); } } if (segment.Below != null) { intersections = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate, segment.Below.LeftCoordinate, segment.Below.RightCoordinate, PrecisionModel); if (intersections.Count > 0) { IntersectionEvent intersectionEvent = new IntersectionEvent { Vertex = intersections[0], Below = segment.Below, Above = segment }; _eventQueue.Add(intersectionEvent); } } break; // Right endpoint event: check for possible intersection of the below and above segments. case EventType.Right: segment = _sweepLine.Search(endPointEvent); if (segment != null) { if (segment.Above != null && segment.Below != null) { intersections = LineAlgorithms.Intersection(segment.Above.LeftCoordinate, segment.Above.RightCoordinate, segment.Below.LeftCoordinate, segment.Below.RightCoordinate, PrecisionModel); if (intersections.Count > 0) { IntersectionEvent intersectionEvent = new IntersectionEvent { Vertex = intersections[0], Below = segment.Below, Above = segment.Above }; if (!_eventQueue.Contains(intersectionEvent)) { _eventQueue.Add(intersectionEvent); } } } _sweepLine.Remove(segment); } break; } } // Intersection point event: switch the two concerned segments and check for possible intersection with their below and above segments. else if (currentEvent is IntersectionEvent) { IntersectionEvent intersectionEvent = (IntersectionEvent)currentEvent; /* * Segment order before intersection: segmentBelow <-> segmentAbove <-> segment <-> segmentAboveAbove * Segment order after intersection: segmentBelow <-> segment <-> segmentAbove <-> segmentAboveAbove */ segment = intersectionEvent.Above; SweepLineSegment segmentAbove = intersectionEvent.Below; // Handle closing intersection points when segments (partially) overlap each other. if (intersectionEvent.IsClose) { if (!_sweepLine.IsAdjacent(segment.Edge, segmentAbove.Edge)) { _intersections.Add(currentEvent.Vertex); _edgeIndices.Add(Tuple.Create(Math.Min(segment.Edge, segmentAbove.Edge), Math.Max(segment.Edge, segmentAbove.Edge))); } } // It is possible that the previously detected intersection point is not a real intersection, because a new segment started between them, // therefore a repeated check is necessary to carry out. else if (_sweepLine.Add(intersectionEvent)) { if (!_sweepLine.IsAdjacent(segment.Edge, segmentAbove.Edge)) { _intersections.Add(currentEvent.Vertex); _edgeIndices.Add(Tuple.Create(Math.Min(segment.Edge, segmentAbove.Edge), Math.Max(segment.Edge, segmentAbove.Edge))); intersections = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate, segmentAbove.LeftCoordinate, segmentAbove.RightCoordinate, PrecisionModel); if (intersections.Count > 1 && !intersections[1].Equals(intersections[0])) { IntersectionEvent newIntersectionEvent = new IntersectionEvent { Vertex = intersections[1], Below = segment, Above = segmentAbove, IsClose = true, }; _eventQueue.Add(newIntersectionEvent); } } if (segmentAbove.Above != null) { intersections = LineAlgorithms.Intersection(segmentAbove.LeftCoordinate, segmentAbove.RightCoordinate, segmentAbove.Above.LeftCoordinate, segmentAbove.Above.RightCoordinate, PrecisionModel); if (intersections.Count > 0 && intersections[0].X >= intersectionEvent.Vertex.X) { IntersectionEvent newIntersectionEvent = new IntersectionEvent { Vertex = intersections[0], Below = segmentAbove, Above = segmentAbove.Above }; if (!_eventQueue.Contains(newIntersectionEvent)) { _eventQueue.Add(newIntersectionEvent); } } } if (segment.Below != null) { intersections = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate, segment.Below.LeftCoordinate, segment.Below.RightCoordinate, PrecisionModel); if (intersections.Count > 0 && intersections[0].X >= intersectionEvent.Vertex.X) { IntersectionEvent newIntersectionEvent = new IntersectionEvent { Vertex = intersections[0], Below = segment.Below, Above = segment }; if (!_eventQueue.Contains(newIntersectionEvent)) { _eventQueue.Add(newIntersectionEvent); } } } } } currentEvent = _eventQueue.Next(); } _hasResult = true; }
/// <summary> /// Compares two <see cref="SweepLineSegment" /> instances and returns a value indicating whether one is less than, equal to, or greater than the other. /// </summary> /// <remarks> /// The comparator applies a above-below relationship between the arguments, where a "greater" segment is above the another one. /// </remarks> /// <param name="first">The first <see cref="SweepLineSegment" /> to compare.</param> /// <param name="second">The second <see cref="SweepLineSegment" /> to compare.</param> /// <returns>A signed integer that indicates the relative values of <paramref name="first" /> and <paramref name="second" />.</returns> /// <exception cref="System.InvalidOperationException">Cannot compare non-overlapping sweep line segments.</exception> public Int32 Compare(SweepLineSegment first, SweepLineSegment second) { // Comparing non-overlapping segments is not supported. if (first.RightCoordinate.X < second.LeftCoordinate.X || first.LeftCoordinate.X > second.RightCoordinate.X) { throw new InvalidOperationException("Cannot compare non-overlapping sweep line segments."); } // The segments intersect. SweepLineIntersection intersection = GetIntersection(first, second); if (intersection != SweepLineIntersection.NotExists) { CoordinateVector xDiff = first.RightCoordinate - first.LeftCoordinate; Double xGradient = xDiff.X == 0 ? Double.MaxValue : xDiff.Y / xDiff.X; CoordinateVector yDiff = second.RightCoordinate - second.LeftCoordinate; Double yGradient = yDiff.X == 0 ? Double.MaxValue : yDiff.Y / yDiff.X; Int32 result = yGradient.CompareTo(xGradient); if (result == 0) { result = first.LeftCoordinate.X.CompareTo(second.LeftCoordinate.X); } if (result == 0) { result = second.LeftCoordinate.Y.CompareTo(first.LeftCoordinate.Y); } if (result == 0) { result = first.RightCoordinate.X.CompareTo(second.RightCoordinate.X); } if (result == 0) { result = second.RightCoordinate.Y.CompareTo(first.RightCoordinate.Y); } if (result == 0) { result = second.Edge.CompareTo(first.Edge); } if (intersection == SweepLineIntersection.Passed) { result *= -1; } return(result); } // The segments do not intersect. if (first.LeftCoordinate.X < second.LeftCoordinate.X) { Double[] verticalCollection = new[] { first.LeftCoordinate.Y, first.RightCoordinate.Y }; var verticalLineStart = new Coordinate(second.LeftCoordinate.X, verticalCollection.Min()); var verticalLineEnd = new Coordinate(second.LeftCoordinate.X, verticalCollection.Max()); IList <Coordinate> startIntersections = LineAlgorithms.Intersection(first.LeftCoordinate, first.RightCoordinate, verticalLineStart, verticalLineEnd, _precisionModel); // due to precision tolerance degeneracy we might not found the intersection return(startIntersections.Count > 0 ? startIntersections[0].Y.CompareTo(second.LeftCoordinate.Y) : ((first.LeftCoordinate.Y + first.RightCoordinate.Y) / 2.0).CompareTo(second.LeftCoordinate.Y)); } if (first.LeftCoordinate.X > second.LeftCoordinate.X) { Double[] verticalCollection = new[] { second.LeftCoordinate.Y, second.RightCoordinate.Y }; var verticalLineStart = new Coordinate(first.LeftCoordinate.X, verticalCollection.Min()); var verticalLineEnd = new Coordinate(first.LeftCoordinate.X, verticalCollection.Max()); IList <Coordinate> startIntersections = LineAlgorithms.Intersection(verticalLineStart, verticalLineEnd, second.LeftCoordinate, second.RightCoordinate, _precisionModel); return(startIntersections.Count > 0 ? first.LeftCoordinate.Y.CompareTo(startIntersections[0].Y) : first.LeftCoordinate.Y.CompareTo((second.LeftCoordinate.Y + second.RightCoordinate.Y) / 2.0)); } // first.LeftCoordinate.X == second.LeftCoordinate.X return(first.LeftCoordinate.Y.CompareTo(second.LeftCoordinate.Y)); }
/// <summary> /// Processes the end point event. /// </summary> /// <param name="endPointEvent">The end point event.</param> private void ProcessEndPointEvent(EndPointEvent endPointEvent) { SweepLineSegment segment; Intersection intersection; switch (endPointEvent.Type) { // left endpoint event: check for possible intersection with below and / or above segments case EventType.Left: segment = this.sweepLine.Add(endPointEvent); if (segment.Above != null) { intersection = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate, segment.Above.LeftCoordinate, segment.Above.RightCoordinate, this.PrecisionModel); if (intersection != null) { IntersectionEvent intersectionEvent = new IntersectionEvent { Vertex = intersection.Coordinate, Below = segment, Above = segment.Above }; this.eventQueue.Add(intersectionEvent); } } if (segment.Below != null) { intersection = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate, segment.Below.LeftCoordinate, segment.Below.RightCoordinate, this.PrecisionModel); if (intersection != null) { IntersectionEvent intersectionEvent = new IntersectionEvent { Vertex = intersection.Coordinate, Below = segment.Below, Above = segment }; this.eventQueue.Add(intersectionEvent); } } break; // right endpoint event: check for possible intersection of the below and above segments case EventType.Right: segment = this.sweepLine.Search(endPointEvent); if (segment != null) { if (segment.Above != null && segment.Below != null) { intersection = LineAlgorithms.Intersection(segment.Above.LeftCoordinate, segment.Above.RightCoordinate, segment.Below.LeftCoordinate, segment.Below.RightCoordinate, this.PrecisionModel); if (intersection != null) { IntersectionEvent intersectionEvent = new IntersectionEvent { Vertex = intersection.Coordinate, Below = segment.Below, Above = segment.Above }; if (!this.eventQueue.Contains(intersectionEvent)) { this.eventQueue.Add(intersectionEvent); } } } this.sweepLine.Remove(segment); } break; } }
/// <summary> /// Processes the intersection event. /// </summary> /// <param name="intersectionEvent">The intersection event.</param> private void ProcessIntersectionEvent(IntersectionEvent intersectionEvent) { SweepLineSegment segment; Intersection intersection; /* * segment order before intersection: segmentBelow <-> segmentAbove <-> segment <-> segmentAboveAbove * segment order after intersection: segmentBelow <-> segment <-> segmentAbove <-> segmentAboveAbove */ segment = intersectionEvent.Above; SweepLineSegment segmentAbove = intersectionEvent.Below; // dandle closing intersection points when segments (partially) overlap each other if (intersectionEvent.IsClosing) { if (!this.sweepLine.IsAdjacent(segment.Edge, segmentAbove.Edge)) { this.intersections.Add(intersectionEvent.Vertex); this.edgeIndexes.Add(Tuple.Create(Math.Min(segment.Edge, segmentAbove.Edge), Math.Max(segment.Edge, segmentAbove.Edge))); } } // it is possible that the previously detected intersection point is not a real intersection, because a new segment started between them, // therefore a repeated check is necessary to carry out else if (this.sweepLine.Add(intersectionEvent)) { if (!this.sweepLine.IsAdjacent(segment.Edge, segmentAbove.Edge)) { this.intersections.Add(intersectionEvent.Vertex); this.edgeIndexes.Add(Tuple.Create(Math.Min(segment.Edge, segmentAbove.Edge), Math.Max(segment.Edge, segmentAbove.Edge))); intersection = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate, segmentAbove.LeftCoordinate, segmentAbove.RightCoordinate, this.PrecisionModel); if (intersection.Type == IntersectionType.Interval) { IntersectionEvent newIntersectionEvent = new IntersectionEvent { Vertex = intersection.End, Below = segment, Above = segmentAbove, IsClosing = true, }; this.eventQueue.Add(newIntersectionEvent); } } if (segmentAbove.Above != null) { intersection = LineAlgorithms.Intersection(segmentAbove.LeftCoordinate, segmentAbove.RightCoordinate, segmentAbove.Above.LeftCoordinate, segmentAbove.Above.RightCoordinate, this.PrecisionModel); if (intersection != null && intersection.Coordinate.X >= intersectionEvent.Vertex.X) { IntersectionEvent newIntersectionEvent = new IntersectionEvent { Vertex = intersection.Coordinate, Below = segmentAbove, Above = segmentAbove.Above }; if (!this.eventQueue.Contains(newIntersectionEvent)) { this.eventQueue.Add(newIntersectionEvent); } } } if (segment.Below != null) { intersection = LineAlgorithms.Intersection(segment.LeftCoordinate, segment.RightCoordinate, segment.Below.LeftCoordinate, segment.Below.RightCoordinate, this.PrecisionModel); if (intersection != null && intersection.Coordinate.X >= intersectionEvent.Vertex.X) { IntersectionEvent newIntersectionEvent = new IntersectionEvent { Vertex = intersection.Coordinate, Below = segment.Below, Above = segment }; if (!this.eventQueue.Contains(newIntersectionEvent)) { this.eventQueue.Add(newIntersectionEvent); } } } } }
public void LineAlgorithmsIntersectionTest() { // coinciding lines Coordinate firstLineStart = new Coordinate(1, 1); Coordinate firstLineEnd = new Coordinate(4, 1); Coordinate secondLineStart = new Coordinate(1, 1); Coordinate secondLineEnd = new Coordinate(4, 1); IList <Coordinate> expectedResult = new List <Coordinate> { new Coordinate(1, 1), new Coordinate(4, 1) }; Assert.AreEqual(expectedResult, LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd)); // lines intersecting in one point firstLineStart = new Coordinate(1, 1); firstLineEnd = new Coordinate(1, 4); secondLineStart = new Coordinate(4, 2); secondLineEnd = new Coordinate(0, 2); expectedResult = new List <Coordinate> { new Coordinate(1, 2) }; Assert.AreEqual(expectedResult, LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd)); firstLineStart = new Coordinate(-1, 6); firstLineEnd = new Coordinate(1, 2); secondLineStart = new Coordinate(4, 0); secondLineEnd = new Coordinate(0, 4); expectedResult = new List <Coordinate> { new Coordinate(0, 4) }; Assert.AreEqual(expectedResult, LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd)); firstLineStart = new Coordinate(2, 2); firstLineEnd = new Coordinate(2, 2); secondLineStart = new Coordinate(2, 2); secondLineEnd = new Coordinate(2, 2); expectedResult = new List <Coordinate> { new Coordinate(2, 2) }; Assert.AreEqual(expectedResult, LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd)); // lines intersecting in more than one point firstLineStart = new Coordinate(2, 2); firstLineEnd = new Coordinate(2, 8); secondLineStart = new Coordinate(2, 5); secondLineEnd = new Coordinate(2, 10); expectedResult = new List <Coordinate> { new Coordinate(2, 5), new Coordinate(2, 8) }; Assert.AreEqual(expectedResult, LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd)); firstLineStart = new Coordinate(4, 1); firstLineEnd = new Coordinate(1, 4); secondLineStart = new Coordinate(3, 2); secondLineEnd = new Coordinate(2, 3); expectedResult = new List <Coordinate> { new Coordinate(3, 2), new Coordinate(2, 3) }; Assert.AreEqual(expectedResult, LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd)); // parallel lines firstLineStart = new Coordinate(1.3, 1.3); firstLineEnd = new Coordinate(1.3, 4.3); secondLineStart = new Coordinate(2.3, 1.3); secondLineEnd = new Coordinate(2.3, 4.3); expectedResult = new List <Coordinate> { }; Assert.AreEqual(expectedResult, LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd)); // not intersecting lines firstLineStart = new Coordinate(2, 2); firstLineEnd = new Coordinate(2, 8); secondLineStart = new Coordinate(2.1, 1); secondLineEnd = new Coordinate(10, 8); expectedResult = new List <Coordinate> { }; Assert.AreEqual(expectedResult, LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd)); // coinciding infinite lines firstLineStart = new Coordinate(2, 4); CoordinateVector firstVector = new CoordinateVector(0, 1); secondLineStart = new Coordinate(2, 5); CoordinateVector secondVector = new CoordinateVector(0, 4); Assert.AreEqual(new Coordinate(2, 4), LineAlgorithms.Intersection(firstLineStart, firstVector, secondLineStart, secondVector)); // intersecting infinite lines firstLineStart = new Coordinate(1, 2); firstVector = new CoordinateVector(1, -2); secondLineStart = new Coordinate(4, 0); secondVector = new CoordinateVector(1, -1); Assert.AreEqual(new Coordinate(0, 4), LineAlgorithms.Intersection(firstLineStart, firstVector, secondLineStart, secondVector)); firstLineStart = new Coordinate(1, 1); firstVector = new CoordinateVector(0, 1); secondLineStart = new Coordinate(1, 1); secondVector = new CoordinateVector(1, 0); Assert.AreEqual(new Coordinate(1, 1), LineAlgorithms.Intersection(firstLineStart, firstVector, secondLineStart, secondVector)); // not intersecting infinite lines firstLineStart = new Coordinate(1, 1); firstVector = new CoordinateVector(0, 1); secondLineStart = new Coordinate(2, 2); secondVector = new CoordinateVector(0, 1); Assert.IsFalse(LineAlgorithms.Intersection(firstLineStart, firstVector, secondLineStart, secondVector).IsValid); // internally intersecting lines firstLineStart = new Coordinate(1, 4); firstLineEnd = new Coordinate(4, 1); secondLineStart = new Coordinate(3, 2); secondLineEnd = new Coordinate(2, 3); expectedResult = new List <Coordinate> { new Coordinate(3, 2), new Coordinate(2, 3) }; Assert.AreEqual(expectedResult, LineAlgorithms.InternalIntersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd)); firstLineStart = new Coordinate(1, 4); firstLineEnd = new Coordinate(4, 1); secondLineStart = new Coordinate(1, 2); secondLineEnd = new Coordinate(200, 2); expectedResult = new List <Coordinate> { new Coordinate(3, 2) }; Assert.AreEqual(expectedResult, LineAlgorithms.InternalIntersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd)); firstLineStart = new Coordinate(10.58, 4); firstLineEnd = new Coordinate(4, 1); secondLineStart = new Coordinate(10.58, 4); secondLineEnd = new Coordinate(4, 1); expectedResult = new List <Coordinate> { new Coordinate(10.58, 4), new Coordinate(4, 1) }; Assert.AreEqual(expectedResult, LineAlgorithms.InternalIntersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd)); // not internally intersecting lines firstLineStart = new Coordinate(1, 1); firstLineEnd = new Coordinate(10, 1); secondLineStart = new Coordinate(1, 4); secondLineEnd = new Coordinate(1, 1); expectedResult = new List <Coordinate> { }; Assert.AreEqual(expectedResult, LineAlgorithms.InternalIntersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd)); // intersecting lines with fixed precision PrecisionModel precision = new PrecisionModel(0.001); firstLineStart = new Coordinate(1000, 1000); firstLineEnd = new Coordinate(1000, 4000); secondLineStart = new Coordinate(4000, 2000); secondLineEnd = new Coordinate(-2000, 1000); expectedResult = new List <Coordinate> { new Coordinate(1000, 2000) }; Assert.AreEqual(expectedResult, LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd, precision)); secondLineEnd = new Coordinate(-2000, 0); expectedResult = new List <Coordinate> { new Coordinate(1000, 1000) }; Assert.AreEqual(expectedResult, LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd, precision)); }
public void LineAlgorithmsIntersectionTest() { // coinciding lines Coordinate firstLineStart = new Coordinate(1, 1); Coordinate firstLineEnd = new Coordinate(4, 1); Coordinate secondLineStart = new Coordinate(1, 1); Coordinate secondLineEnd = new Coordinate(4, 1); Intersection intersection = LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd); intersection.Type.ShouldBe(IntersectionType.Interval); intersection.Start.ShouldBe(new Coordinate(1, 1)); intersection.End.ShouldBe(new Coordinate(4, 1)); // lines intersecting in one point firstLineStart = new Coordinate(1, 1); firstLineEnd = new Coordinate(1, 4); secondLineStart = new Coordinate(4, 2); secondLineEnd = new Coordinate(0, 2); intersection = LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd); intersection.Type.ShouldBe(IntersectionType.Coordinate); intersection.Coordinate.ShouldBe(new Coordinate(1, 2)); firstLineStart = new Coordinate(0, 0); firstLineEnd = new Coordinate(10, 0); secondLineStart = new Coordinate(0, 0); secondLineEnd = new Coordinate(0, 3); intersection = LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd); intersection.Type.ShouldBe(IntersectionType.Coordinate); intersection.Coordinate.ShouldBe(new Coordinate(0, 0)); firstLineStart = new Coordinate(-1, 6); firstLineEnd = new Coordinate(1, 2); secondLineStart = new Coordinate(4, 0); secondLineEnd = new Coordinate(0, 4); intersection = LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd); intersection.Type.ShouldBe(IntersectionType.Coordinate); intersection.Coordinate.ShouldBe(new Coordinate(0, 4)); firstLineStart = new Coordinate(2, 2); firstLineEnd = new Coordinate(2, 2); secondLineStart = new Coordinate(2, 2); secondLineEnd = new Coordinate(2, 2); intersection = LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd); intersection.Type.ShouldBe(IntersectionType.Coordinate); intersection.Coordinate.ShouldBe(new Coordinate(2, 2)); // lines intersecting in more than one point firstLineStart = new Coordinate(2, 2); firstLineEnd = new Coordinate(2, 8); secondLineStart = new Coordinate(2, 5); secondLineEnd = new Coordinate(2, 10); intersection = LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd); intersection.Type.ShouldBe(IntersectionType.Interval); intersection.Start.ShouldBe(new Coordinate(2, 5)); intersection.End.ShouldBe(new Coordinate(2, 8)); firstLineStart = new Coordinate(4, 1); firstLineEnd = new Coordinate(1, 4); secondLineStart = new Coordinate(3, 2); secondLineEnd = new Coordinate(2, 3); intersection = LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd); intersection.Type.ShouldBe(IntersectionType.Interval); intersection.Start.ShouldBe(new Coordinate(3, 2)); intersection.End.ShouldBe(new Coordinate(2, 3)); firstLineStart = new Coordinate(2, 8); firstLineEnd = new Coordinate(6, 8); secondLineStart = new Coordinate(0, 8); secondLineEnd = new Coordinate(8, 8); intersection = LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd); intersection.Type.ShouldBe(IntersectionType.Interval); intersection.Start.ShouldBe(new Coordinate(2, 8)); intersection.End.ShouldBe(new Coordinate(6, 8)); // parallel lines firstLineStart = new Coordinate(1.3, 1.3); firstLineEnd = new Coordinate(1.3, 4.3); secondLineStart = new Coordinate(2.3, 1.3); secondLineEnd = new Coordinate(2.3, 4.3); LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd).ShouldBeNull(); // not intersecting lines firstLineStart = new Coordinate(2, 2); firstLineEnd = new Coordinate(2, 8); secondLineStart = new Coordinate(2.1, 1); secondLineEnd = new Coordinate(10, 8); LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd).ShouldBeNull(); // coinciding infinite lines firstLineStart = new Coordinate(2, 4); CoordinateVector firstVector = new CoordinateVector(0, 1); secondLineStart = new Coordinate(2, 5); CoordinateVector secondVector = new CoordinateVector(0, 4); intersection = LineAlgorithms.Intersection(firstLineStart, firstVector, secondLineStart, secondVector); intersection.Type.ShouldBe(IntersectionType.Coordinate); intersection.Coordinate.ShouldBe(new Coordinate(2, 4)); // intersecting infinite lines firstLineStart = new Coordinate(1, 2); firstVector = new CoordinateVector(1, -2); secondLineStart = new Coordinate(4, 0); secondVector = new CoordinateVector(1, -1); intersection = LineAlgorithms.Intersection(firstLineStart, firstVector, secondLineStart, secondVector); intersection.Type.ShouldBe(IntersectionType.Coordinate); intersection.Coordinate.ShouldBe(new Coordinate(0, 4)); firstLineStart = new Coordinate(1, 1); firstVector = new CoordinateVector(0, 1); secondLineStart = new Coordinate(1, 1); secondVector = new CoordinateVector(1, 0); intersection = LineAlgorithms.Intersection(firstLineStart, firstVector, secondLineStart, secondVector); intersection.Type.ShouldBe(IntersectionType.Coordinate); intersection.Coordinate.ShouldBe(new Coordinate(1, 1)); // not intersecting infinite lines firstLineStart = new Coordinate(1, 1); firstVector = new CoordinateVector(0, 1); secondLineStart = new Coordinate(2, 2); secondVector = new CoordinateVector(0, 1); LineAlgorithms.Intersection(firstLineStart, firstVector, secondLineStart, secondVector).ShouldBeNull(); // internally intersecting lines firstLineStart = new Coordinate(1, 4); firstLineEnd = new Coordinate(4, 1); secondLineStart = new Coordinate(3, 2); secondLineEnd = new Coordinate(2, 3); intersection = LineAlgorithms.InternalIntersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd); intersection.Type.ShouldBe(IntersectionType.Interval); intersection.Start.ShouldBe(new Coordinate(3, 2)); intersection.End.ShouldBe(new Coordinate(2, 3)); firstLineStart = new Coordinate(1, 4); firstLineEnd = new Coordinate(4, 1); secondLineStart = new Coordinate(1, 2); secondLineEnd = new Coordinate(200, 2); intersection = LineAlgorithms.InternalIntersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd); intersection.Type.ShouldBe(IntersectionType.Coordinate); intersection.Coordinate.ShouldBe(new Coordinate(3, 2)); firstLineStart = new Coordinate(10.58, 4); firstLineEnd = new Coordinate(4, 1); secondLineStart = new Coordinate(10.58, 4); secondLineEnd = new Coordinate(4, 1); intersection = LineAlgorithms.InternalIntersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd); intersection.Type.ShouldBe(IntersectionType.Interval); intersection.Start.ShouldBe(new Coordinate(10.58, 4)); intersection.End.ShouldBe(new Coordinate(4, 1)); // not internally intersecting lines firstLineStart = new Coordinate(1, 1); firstLineEnd = new Coordinate(10, 1); secondLineStart = new Coordinate(1, 4); secondLineEnd = new Coordinate(1, 1); LineAlgorithms.InternalIntersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd).ShouldBeNull(); // intersecting lines with fixed precision PrecisionModel precisionModel = new PrecisionModel(0.001); firstLineStart = new Coordinate(1000, 1000); firstLineEnd = new Coordinate(1000, 4000); secondLineStart = new Coordinate(4000, 2000); secondLineEnd = new Coordinate(-2000, 1000); intersection = LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd, precisionModel); intersection.Type.ShouldBe(IntersectionType.Coordinate); intersection.Coordinate.ShouldBe(new Coordinate(1000, 2000)); secondLineEnd = new Coordinate(-2000, 0); intersection = LineAlgorithms.Intersection(firstLineStart, firstLineEnd, secondLineStart, secondLineEnd, precisionModel); intersection.Type.ShouldBe(IntersectionType.Coordinate); intersection.Coordinate.ShouldBe(new Coordinate(1000, 1000)); }