Exemple #1
0
        /// <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);
            }
        }
Exemple #4
0
        /// <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);
        }