Beispiel #1
0
            /// <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);
            }
Beispiel #2
0
            /// <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));
            }
Beispiel #3
0
            /// <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));
            }
Beispiel #4
0
            /// <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;
        }
Beispiel #6
0
            /// <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));
            }
Beispiel #7
0
        /// <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;
            }
        }
Beispiel #8
0
        /// <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);
                        }
                    }
                }
            }
        }
Beispiel #9
0
        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));
        }
Beispiel #10
0
        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));
        }