예제 #1
0
        /// <summary>
        /// Returns the difference of one interval to another.
        /// </summary>
        /// <typeparam name="T">The type of values included in the intervals.</typeparam>
        /// <param name="interval">The source interval.</param>
        /// <param name="other">The interval to exclude.</param>
        /// <returns>A set that contains every part of <paramref name="interval"/> that is not also contained by <paramref name="other"/>.</returns>
        public static IList <IInterval <T> > DifferenceWith <T>(this IInterval <T> interval, IInterval <T> other) where T : IComparable <T>
        {
            if (interval.IsEmpty())
            {
                return(null);
            }

            var intersection = interval.IntersectWith(other);

            if (intersection.IsEmpty())
            {
                return(new[] { interval });
            }
            else if (intersection == interval)
            {
                return(null);
            }

            var intervals = new List <IInterval <T> >();

            var startToStart = interval.Start.CompareTo(intersection.Start);

            if (startToStart != 0 ||
                (interval.StartInclusive && !intersection.StartInclusive))
            {
                intervals.Add(interval.Clone(
                                  interval.Start,
                                  interval.StartInclusive,
                                  intersection.Start,
                                  !intersection.StartInclusive));
            }

            var endToEnd = interval.End.CompareTo(intersection.End);

            if (endToEnd != 0 ||
                (interval.EndInclusive && !intersection.EndInclusive))
            {
                intervals.Add(interval.Clone(
                                  intersection.End,
                                  !intersection.EndInclusive,
                                  interval.End,
                                  interval.EndInclusive));
            }

            return(intervals);
        }
        /// <summary>
        /// Add a list of objects to a given interval.
        /// </summary>
        /// <param name = "interval">The interval to store the object in.</param>
        /// <param name = "values">The list of objects to store.</param>
        public void Add(IInterval <TMath> interval, IList <TObject> values)
        {
            // Check for intersections with existing intervals.
            IList <IntervalValues> intersecting = FindIntersections(interval);

            if (intersecting.Count > 0)
            {
                // A list used to find remnants after cutting intersections.
                var remnants = new List <IInterval <TMath> >
                {
                    (IInterval <TMath>)interval.Clone()
                };

                // Split up all intersecting intervals.
                foreach (IntervalValues intersectingRange in intersecting)
                {
                    IInterval <TMath> intersection = intersectingRange.Interval.Intersection(interval);

                    SplitRemoveIntersection(intersectingRange, intersection);

                    // Add intersection with objects of both intervals.
                    var mergedObjects = new List <TObject>(intersectingRange.Values);
                    mergedObjects.AddRange(values);
                    _rangedObjects.Add(new IntervalValues(mergedObjects, intersection));

                    // Remove intersections from remnants.
                    var newRemnants = new List <IInterval <TMath> >();
                    foreach (IInterval <TMath> remnant in remnants)
                    {
                        newRemnants.AddRange(remnant.Subtract(intersection));
                    }
                    remnants = newRemnants;
                }

                // Add remnants of the newly added interval.
                foreach (IInterval <TMath> remnant in remnants)
                {
                    _rangedObjects.Add(new IntervalValues(values, remnant));
                }
            }
            else
            {
                // No intersections, just add.
                _rangedObjects.Add(new IntervalValues(values, interval));
            }
        }
예제 #3
0
        /// <summary>
        /// Returns the union of two intervals.
        /// </summary>
        /// <typeparam name="T">The type of values included in the intervals.</typeparam>
        /// <param name="interval">The first interval.</param>
        /// <param name="other">The second interval.</param>
        /// <returns>A set that contains both intervals.</returns>
        /// <remarks>
        /// If the intervals intersect, the result will be a set with a single interval.
        /// </remarks>
        public static IList <IInterval <T> > UnionWith <T>(this IInterval <T> interval, IInterval <T> other) where T : IComparable <T>
        {
            var intervalEmpty = interval.IsEmpty();
            var otherEmpty    = other.IsEmpty();

            if (intervalEmpty && otherEmpty)
            {
                return(null);
            }
            else if (intervalEmpty)
            {
                return(new[] { other });
            }
            else if (otherEmpty)
            {
                return(new[] { interval });
            }

            int  startToStart, endToEnd, startToEnd;
            T    start, end;
            bool startInclusive, endInclusive;

            startToStart = interval.Start.CompareTo(other.Start);
            if (startToStart > 0)
            {
                start          = interval.Start;
                startInclusive = interval.StartInclusive;
            }
            else if (startToStart < 0)
            {
                start          = other.Start;
                startInclusive = other.StartInclusive;
            }
            else
            {
                start          = interval.Start;
                startInclusive = interval.StartInclusive && other.StartInclusive;
            }

            endToEnd = interval.End.CompareTo(other.End);
            if (endToEnd < 0)
            {
                end          = interval.End;
                endInclusive = interval.EndInclusive;
            }
            else if (endToEnd > 0)
            {
                end          = other.End;
                endInclusive = other.EndInclusive;
            }
            else
            {
                end          = interval.End;
                endInclusive = interval.EndInclusive && other.EndInclusive;
            }

            startToEnd = start.CompareTo(end);
            if (startToEnd > 0)
            {
                return(new[] { interval, other });
            }
            else if (startToEnd == 0 && !(startInclusive || endInclusive))
            {
                return(new[] { interval, other });
            }

            bool startMatchesInterval = false,
                 startMatchesOther    = false,
                 endMatchesInterval   = false,
                 endMatchesOther      = false;

            if (startToStart < 0)
            {
                start                = interval.Start;
                startInclusive       = interval.StartInclusive;
                startMatchesInterval = true;
            }
            else if (startToStart > 0)
            {
                start             = other.Start;
                startInclusive    = other.StartInclusive;
                startMatchesOther = true;
            }
            else
            {
                start                = interval.Start;
                startInclusive       = interval.StartInclusive || other.StartInclusive;
                startMatchesInterval = startInclusive == interval.StartInclusive;
                startMatchesOther    = startInclusive == other.StartInclusive;
            }

            if (endToEnd > 0)
            {
                end                = interval.End;
                endInclusive       = interval.EndInclusive;
                endMatchesInterval = true;
            }
            else if (endToEnd < 0)
            {
                end             = other.End;
                endInclusive    = other.EndInclusive;
                endMatchesOther = true;
            }
            else
            {
                end                = interval.End;
                endInclusive       = interval.EndInclusive || other.EndInclusive;
                endMatchesInterval = endInclusive == interval.EndInclusive;
                endMatchesOther    = endInclusive == other.EndInclusive;
            }

            if (startMatchesInterval && endMatchesInterval)
            {
                return(new[] { interval });
            }
            else if (startMatchesOther && endMatchesOther)
            {
                return(new[] { other });
            }

            return(new[]
            {
                interval.Clone(
                    start,
                    startInclusive,
                    end,
                    endInclusive)
            });
        }
예제 #4
0
        /// <summary>
        /// Returns the intersection of two intervals.
        /// </summary>
        /// <typeparam name="T">The type of values included in the intervals.</typeparam>
        /// <param name="interval">The first interval.</param>
        /// <param name="other">The second interval.</param>
        /// <returns>An interval that represents the intersection of the intervals.</returns>
        public static IInterval <T> IntersectWith <T>(this IInterval <T> interval, IInterval <T> other) where T : IComparable <T>
        {
            if (interval.IsEmpty() ||
                other.IsEmpty())
            {
                return(null);
            }

            T    start, end;
            bool startInclusive, endInclusive;

            bool startMatchesInterval = false,
                 startMatchesOther    = false,
                 endMatchesInterval   = false,
                 endMatchesOther      = false;

            var startToStart = interval.Start.CompareTo(other.Start);

            if (startToStart > 0)
            {
                start                = interval.Start;
                startInclusive       = interval.StartInclusive;
                startMatchesInterval = true;
            }
            else if (startToStart < 0)
            {
                start             = other.Start;
                startInclusive    = other.StartInclusive;
                startMatchesOther = true;
            }
            else
            {
                start                = interval.Start;
                startInclusive       = interval.StartInclusive && other.StartInclusive;
                startMatchesInterval = startInclusive == interval.StartInclusive;
                startMatchesOther    = startInclusive == other.StartInclusive;
            }

            var endToEnd = interval.End.CompareTo(other.End);

            if (endToEnd < 0)
            {
                end                = interval.End;
                endInclusive       = interval.EndInclusive;
                endMatchesInterval = true;
            }
            else if (endToEnd > 0)
            {
                end             = other.End;
                endInclusive    = other.EndInclusive;
                endMatchesOther = true;
            }
            else
            {
                end                = interval.End;
                endInclusive       = interval.EndInclusive && other.EndInclusive;
                endMatchesInterval = endInclusive == interval.EndInclusive;
                endMatchesOther    = endInclusive == other.EndInclusive;
            }

            var startToEnd = start.CompareTo(end);

            if (startToEnd > 0)
            {
                return(null);
            }
            else if (startToEnd == 0 && (!startInclusive || !endInclusive))
            {
                return(null);
            }

            if (startMatchesInterval && endMatchesInterval)
            {
                return(interval);
            }
            else if (startMatchesOther && endMatchesOther)
            {
                return(other);
            }

            return(interval.Clone(
                       start,
                       startInclusive,
                       end,
                       endInclusive));
        }