private static IntervalCollection <T> HighUnionOf <T>(Interval <T> a, Interval <T> b) { if (Interval.IsNullOrEmpty(a)) { return(new IntervalCollection <T>(b)); } if (Interval.IsNullOrEmpty(b)) { return(new IntervalCollection <T>(a)); } var lowestBound = Bound.Min(a.LowerBound, b.LowerBound); var upmostValue = Bound.Max(a.UpperBound, b.UpperBound); var lowerBound = default(Bound <T>); var upperBound = default(Bound <T>); // a //------------- // b // --------- if (object.Equals(lowestBound, a.LowerBound) && object.Equals(upmostValue, a.UpperBound)) { lowerBound = new Bound <T>(BoundType.Lower , object.Equals(a.LowerBound.Value, b.LowerBound.Value) ? Bound.Max(a.LowerBound.Direction, b.LowerBound.Direction) : a.LowerBound.Direction , a.LowerBound.Value); upperBound = new Bound <T>(BoundType.Upper , object.Equals(a.UpperBound.Value, b.UpperBound.Value) ? Bound.Max(a.UpperBound.Direction, b.UpperBound.Direction) : a.UpperBound.Direction , a.UpperBound.Value); } // a // --------- // b //------------- else if (object.Equals(lowestBound, b.LowerBound) && object.Equals(upmostValue, b.UpperBound)) { lowerBound = new Bound <T>(BoundType.Lower , object.Equals(a.LowerBound.Value, b.LowerBound.Value) ? Bound.Max(a.LowerBound.Direction, b.LowerBound.Direction) : b.LowerBound.Direction , b.LowerBound.Value); upperBound = new Bound <T>(BoundType.Upper , object.Equals(a.UpperBound.Value, b.UpperBound.Value) ? Bound.Max(a.UpperBound.Direction, b.UpperBound.Direction) : b.UpperBound.Direction , b.UpperBound.Value); } // a //--------- // b // ------------- else if (object.Equals(lowestBound, a.LowerBound) && object.Equals(upmostValue, b.UpperBound) && a.UpperBound.UnionCompareTo(b.LowerBound) >= 0) { lowerBound = new Bound <T>(BoundType.Lower , object.Equals(a.LowerBound.Value, b.LowerBound.Value) ? Bound.Max(a.LowerBound.Direction, b.LowerBound.Direction) : a.LowerBound.Direction , a.LowerBound.Value); upperBound = new Bound <T>(BoundType.Upper , object.Equals(a.UpperBound.Value, b.UpperBound.Value) ? Bound.Max(a.UpperBound.Direction, b.UpperBound.Direction) : b.UpperBound.Direction , b.UpperBound.Value); } // a // ------------- // b //--------- else if (object.Equals(lowestBound, b.LowerBound) && object.Equals(upmostValue, a.UpperBound) && b.UpperBound.UnionCompareTo(a.LowerBound) >= 0) { lowerBound = new Bound <T>(BoundType.Lower , object.Equals(a.LowerBound.Value, b.LowerBound.Value) ? Bound.Max(a.LowerBound.Direction, b.LowerBound.Direction) : b.LowerBound.Direction , b.LowerBound.Value); upperBound = new Bound <T>(BoundType.Upper , object.Equals(a.UpperBound.Value, b.UpperBound.Value) ? Bound.Max(a.UpperBound.Direction, b.UpperBound.Direction) : a.UpperBound.Direction , a.UpperBound.Value); } else { return(new IntervalCollection <T>(a, b)); } Interval <T> result; return(TryParse(lowerBound, upperBound, out result) ? new IntervalCollection <T>(result) : new IntervalCollection <T>(a, b)); }
/// <summary> /// Determines the intersection of two intervals. /// </summary> /// <typeparam name="T">The value type of the intervals.</typeparam> /// <param name="a">The first interval.</param> /// <param name="b">The second interval.</param> /// <returns>An <see cref="Interval<T>"/> that contains all elements of <paramref name="a"/> /// that also belong to <paramref name="b"/> (or equivalently, all elements of <paramref name="b"/> /// that also belong to <paramref name="a"/>), but no other elements.</returns> /// <seealso href="http://en.wikipedia.org/wiki/Intersection_(set_theory)">Intersection (set theory)</seealso> private static Interval <T> IntersectionOf <T>(Interval <T> a, Interval <T> b) { if (Interval.IsNullOrEmpty(a)) { return(a); } if (Interval.IsNullOrEmpty(b)) { return(b); } var lowestBound = Bound.Min(a.LowerBound, b.LowerBound); var upmostValue = Bound.Max(a.UpperBound, b.UpperBound); var lowerBound = default(Bound <T>); var upperBound = default(Bound <T>); // a //------------- // b // --------- if (object.Equals(lowestBound, a.LowerBound) && object.Equals(upmostValue, a.UpperBound)) { lowerBound = new Bound <T>(BoundType.Lower , object.Equals(a.LowerBound.Value, b.LowerBound.Value) ? Bound.Min(a.LowerBound.Direction, b.LowerBound.Direction) : b.LowerBound.Direction , b.LowerBound.Value); upperBound = new Bound <T>(BoundType.Upper , object.Equals(a.UpperBound.Value, b.UpperBound.Value) ? Bound.Min(a.UpperBound.Direction, b.UpperBound.Direction) : b.UpperBound.Direction , b.UpperBound.Value); } // a // --------- // b //------------- else if (object.Equals(lowestBound, b.LowerBound) && object.Equals(upmostValue, b.UpperBound)) { lowerBound = new Bound <T>(BoundType.Lower , object.Equals(a.LowerBound.Value, b.LowerBound.Value) ? Bound.Min(a.LowerBound.Direction, b.LowerBound.Direction) : a.LowerBound.Direction , a.LowerBound.Value); upperBound = new Bound <T>(BoundType.Upper , object.Equals(a.UpperBound.Value, b.UpperBound.Value) ? Bound.Min(a.UpperBound.Direction, b.UpperBound.Direction) : a.UpperBound.Direction , a.UpperBound.Value); } // a //--------- // b // ------------- else if (object.Equals(lowestBound, a.LowerBound) && object.Equals(upmostValue, b.UpperBound)) { lowerBound = new Bound <T>(BoundType.Lower , object.Equals(a.LowerBound.Value, b.LowerBound.Value) ? Bound.Min(a.LowerBound.Direction, b.LowerBound.Direction) : b.LowerBound.Direction , b.LowerBound.Value); upperBound = new Bound <T>(BoundType.Upper , object.Equals(a.UpperBound.Value, b.UpperBound.Value) ? Bound.Min(a.UpperBound.Direction, b.UpperBound.Direction) : a.UpperBound.Direction , a.UpperBound.Value); } // a // ------------- // b //--------- else if (object.Equals(lowestBound, b.LowerBound) && object.Equals(upmostValue, a.UpperBound)) { lowerBound = new Bound <T>(BoundType.Lower , object.Equals(a.LowerBound.Value, b.LowerBound.Value) ? Bound.Min(a.LowerBound.Direction, b.LowerBound.Direction) : a.LowerBound.Direction , a.LowerBound.Value); upperBound = new Bound <T>(BoundType.Upper , object.Equals(a.UpperBound.Value, b.UpperBound.Value) ? Bound.Min(a.UpperBound.Direction, b.UpperBound.Direction) : b.UpperBound.Direction , b.UpperBound.Value); } else { return(Interval.Empty <T>()); } Interval <T> result; return(TryParse(lowerBound, upperBound, out result) ? result : Interval.Empty <T>()); }
/// <summary> /// Determines whether two intervals intersect each other. /// </summary> /// <typeparam name="T">The value type of the intervals.</typeparam> /// <param name="a">The first interval.</param> /// <param name="b">The second interval.</param> /// <returns><c>true</c> if the <see cref="Interval<T>"/> <paramref name="a"/> intersects the interval <paramref name="b"/>; otherwise, <c>false</c>.</returns> public static bool Intersect <T>(Interval <T> a, Interval <T> b) { return(!IsNullOrEmpty(IntersectionOf(a, b))); }
/// <summary> /// Determines the intersection of two intervals. /// </summary> /// <typeparam name="T">The value type of the intervals.</typeparam> /// <param name="a">The first interval.</param> /// <param name="b">The second interval.</param> /// <param name="intersection">When this method returns, contains the <see cref="Interval<T>"/> /// that contains all elements of <paramref name="a"/> that also belong to <paramref name="b"/>; /// otherwise, an empty interval.</param> /// <returns><b>true</b> if the intersection is not empty; otherwise, <b>false</b>.</returns> public static bool TryIntersectionOf <T>(Interval <T> a, Interval <T> b, out Interval <T> intersection) { intersection = IntersectionOf(a, b); return(!IsNullOrEmpty(intersection)); }
/// <summary> /// Indicates whether the specified <see cref="Interval<T>"/> object is <c>null</c> or an <see cref="P:Interval´1.Empty"/> interval. /// </summary> /// <typeparam name="T">The value type of the interval.</typeparam> /// <param name="value">An <see cref="Interval<T>"/> reference.</param> /// <returns> /// <c>true</c> if the <paramref name="value"/> parameter is <c>null</c> or an emty interval; otherwise, <c>false</c>. /// </returns> public static bool IsNullOrEmpty <T>(Interval <T> value) { return(object.Equals(value, default(Interval <T>)) || value.IsEmpty); }