Ejemplo n.º 1
0
        /// <summary>
        /// Tests an interval to see if it wholly contains another interval.
        /// </summary>
        /// <typeparam name="T">The type of values included in the intervals.</typeparam>
        /// <param name="interval">The interval to test.</param>
        /// <param name="other">The other interval.</param>
        /// <returns>true, if <paramref name="interval"/> contains <paramref name="other"/>; false, otherwise.</returns>
        /// <remarks>
        /// All intervals (including empty ones) contain every other empty interval.  So, if <paramref name="other"/> is empty, this method always returns true.
        /// Otherwise, this method only returns true if the start and end values of <paramref name="interval"/> surround the values of <paramref name="other"/>.
        /// </remarks>
        public static bool Contains <T>(this IInterval <T> interval, IInterval <T> other) where T : IComparable <T>
        {
            if (other.IsEmpty())
            {
                return(true);
            }

            var intersection = other.IntersectWith(interval);

            return(!intersection.IsEmpty() &&
                   intersection == other);
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Tests an interval to see if it contains a given value.
        /// </summary>
        /// <typeparam name="T">The type of values included in the interval.</typeparam>
        /// <param name="interval">The interval to test.</param>
        /// <param name="value">The value to test.</param>
        /// <returns>true, if the interval is non-empty and contains the value; false, otherwise.</returns>
        public static bool Contains <T>(this IInterval <T> interval, T value) where T : IComparable <T>
        {
            if (interval.IsEmpty())
            {
                return(false);
            }

            var start = interval.Start.CompareTo(value);
            var end   = interval.End.CompareTo(value);

            if ((interval.StartInclusive && start == 0) ||
                (interval.EndInclusive && end == 0))
            {
                return(true);
            }

            if (start >= 0 ||
                end <= 0)
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 4
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)
            });
        }
Ejemplo n.º 5
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));
        }