private static IntervalCollection <T> LowUnionOf <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 result = new List <Interval <T> >(3); result.AddRange(a.DifferenceWith(b)); result.AddRange(b.DifferenceWith(a)); var intersection = default(Interval <T>); if (TryIntersectionOf(a, b, out intersection)) { result.Add(intersection); } result.Sort(); return(new IntervalCollection <T>(result)); }
/// <summary> /// Determines the complement of an <see cref="Interval<T>"/>. /// </summary> /// <typeparam name="T">The value type of the interval.</typeparam> /// <param name="value">An <see cref="Interval<T>"/> reference.</param> /// <returns>An <see cref="IntervalCollection<T>"/> that contains elements not in the specified interval.</returns> /// <seealso href="http://en.wikipedia.org/wiki/Complement_(set_theory)">Complement (set theory)</seealso> public static IntervalCollection <T> ComplementOf <T>(Interval <T> value) { if (Interval.IsNullOrEmpty(value)) { return(new IntervalCollection <T> ( new Interval <T>(Bound <T> .LowestBound, Bound <T> .UpmostBound) )); } var lowerBound = value.LowerBound; var upperBound = value.UpperBound; var result = new List <Interval <T> >(2); if (object.Equals(lowerBound, Bound <T> .LowestBound) && object.Equals(upperBound, Bound <T> .UpmostBound)) { } else if (object.Equals(lowerBound, Bound <T> .LowestBound)) { result.Add(new Interval <T> (new Bound <T>(BoundType.Lower, Bound.Reverse(upperBound.Direction), upperBound.Value) , Bound <T> .UpmostBound)); } else if (object.Equals(upperBound, Bound <T> .UpmostBound)) { result.Add(new Interval <T> (Bound <T> .LowestBound , new Bound <T>(BoundType.Upper, Bound.Reverse(lowerBound.Direction), lowerBound.Value))); } else { var iLower = Bound <T> .LowestBound; var iUpper = new Bound <T>(BoundType.Upper, Bound.Reverse(lowerBound.Direction), lowerBound.Value); var jLower = new Bound <T>(BoundType.Lower, Bound.Reverse(upperBound.Direction), upperBound.Value); var jUpper = Bound <T> .UpmostBound; Interval <T> i; if (Interval.TryParse(iLower, iUpper, out i)) { result.Add(i); } Interval <T> j; if (Interval.TryParse(jLower, jUpper, out j)) { result.Add(j); } } return(new IntervalCollection <T>(result)); }
/// <summary> /// Determines the difference of two intervals. /// </summary> /// <typeparam name="T">The value type of the interval.</typeparam> /// <param name="a">The first interval.</param> /// <param name="b">The second interval.</param> /// <returns>An <see cref="IntervalCollection<T>"/> that contains elements in <paramref name="a"/> but not in <paramref name="b"/>.</returns> /// <seealso href="http://en.wikipedia.org/wiki/Complement_(set_theory)">Relative complement (set theory)</seealso> public static IntervalCollection <T> DifferenceOf <T>(Interval <T> a, Interval <T> b) { if (Interval.IsNullOrEmpty(a)) { return(new IntervalCollection <T>(a)); } if (Interval.IsNullOrEmpty(b)) { return(new IntervalCollection <T>(a)); } // A - B = A ∩ Bc if (object.Equals(a, b)) { return(new IntervalCollection <T>()); } var c = b.Complement; var args = new Interval <T> [c.Count + 1]; args[0] = a; c.CopyTo(args, 1); var result = new List <Interval <T> >(2); foreach (var i in c) { var value = a.IntersectionWith(i); if (!Interval.IsNullOrEmpty(value)) { result.Add(value); } } return(new IntervalCollection <T>(result)); }
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>()); }