예제 #1
0
        /// <summary>
        /// Removes the specified sweep line segment.
        /// </summary>
        /// <param name="segment">The segment.</param>
        /// <exception cref="System.ArgumentNullException">The segment is null.</exception>
        public void Remove(SweepLineSegment segment)
        {
            if (segment == null)
            {
                throw new ArgumentNullException(nameof(segment));
            }

            this.tree.SetCurrent(segment);
            if (this.tree.Current == null)
            {
                return;
            }

            SweepLineSegment segmentAbove = this.tree.GetNext();
            SweepLineSegment segmentBelow = this.tree.GetPrevious();

            if (segmentAbove != null)
            {
                segmentAbove.Below = segment.Below;
            }
            if (segmentBelow != null)
            {
                segmentBelow.Above = segment.Above;
            }

            this.tree.Remove(segment);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        /// <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);
            }
        }
예제 #4
0
        /// <summary>
        /// Performs the order modifying effect of a possible intersection point between two directly adjacent segments.
        /// </summary>
        /// <remarks>
        /// An intersection event may become invalid if the order of the segments were altered or the intersection point has been already passed by the sweep line since the enqueuing of the event.
        /// This method is safe to be applied for invalid intersections.
        /// </remarks>
        /// <param name="x">First segment.</param>
        /// <param name="y">Second segment.</param>
        /// <returns><c>true</c> if a new, valid intersection point was found and passed between <paramref name="x" /> and <paramref name="y" />; otherwise <c>false</c>.</returns>
        /// <exception cref="InvalidOperationException">The segments do not intersect each other.</exception>
        public Boolean Intersect(SweepLineSegment x, SweepLineSegment y)
        {
            if (x == null || y == null)
            {
                return(false);
            }

            SweepLineSegmentComparer comparer     = (SweepLineSegmentComparer)this.tree.Comparer;
            SweepLineIntersection    intersection = comparer.GetIntersection(x, y);

            if (intersection == SweepLineIntersection.NotExists)
            {
                throw new InvalidOperationException(CoreMessages.SegmentsDoNotIntersect);
            }
            if (intersection == SweepLineIntersection.Passed)
            {
                return(false);
            }

            /*
             * Segment order before intersection: belowBelow <-> below <-> above <-> aboveAbove
             * Segment order after intersection:  belowBelow <-> above <-> below <-> aboveAbove
             */
            SweepLineSegment below, above;

            if (x.Above == y)
            {
                below = x;
                above = y;
            }
            else if (y.Above == x)
            {
                below = y;
                above = x;
            }
            else
            {
                return(false);
            }

            this.tree.Remove(x);
            this.tree.Remove(y);
            comparer.PassIntersection(x, y);
            this.tree.Insert(x);
            this.tree.Insert(y);

            SweepLineSegment belowBelow = below.Below;
            SweepLineSegment aboveAbove = above.Above;

            below.Above = aboveAbove;
            below.Below = above;
            above.Below = belowBelow;
            above.Above = below;

            if (belowBelow != null)
            {
                belowBelow.Above = above;
            }
            if (aboveAbove != null)
            {
                aboveAbove.Below = below;
            }

            return(true);
        }