/// <summary> /// Creates a new <see cref="IntervalTree{T}"/> from the unordered collection of intervals. /// </summary> /// <param name="intervals">An unordered collection of intervals.</param> /// <param name="medianComputation"> /// A function to compute the median between a given start and end point. Some common median computations are /// defined in <see cref="IntervalTreeMedianComputations"/>. /// </param> /// <returns>An <see cref="IntervalTree{T}"/> containing all items from <paramref name="intervals"/></returns> public IntervalTree(IEnumerable <IInterval <T> > intervals, IntervalTreeMedianComputation <T> medianComputation) { var intervalsByStart = intervals.OrderBy(i => i.Start).ThenBy(i => i.End).ToList(); var intervalsByEnd = intervalsByStart.OrderBy(i => i.End).ThenBy(i => i.Start).ToList(); if (intervalsByStart.Count > 0) { _root = new IntervalTreeNode <T>(intervalsByStart, intervalsByEnd, medianComputation); } }
/// <summary> /// Creates a new <see cref="IntervalTreeNode{T}"/> from the given sorted collections of intervals. /// <paramref name="intervalsByStart"/> and <paramref name="intervalsByEnd"/> must contain the same items! /// </summary> /// <param name="intervalsByStart"> /// A collection of items to contain in this node sorted by <see cref="IInterval{T}.Start"/> ASC, /// <see cref="IInterval{T}.End"/> ASC. /// </param> /// <param name="intervalsByEnd"> /// A collection of items to contain in this node sorted by <see cref="IInterval{T}.End"/> ASC, /// <see cref="IInterval{T}.Start"/> ASC. /// </param> /// <param name="medianComputation"> /// A function to compute the median between a given start and end point. Some common median computations are /// defined in <see cref="IntervalTreeMedianComputations"/>. /// </param> public IntervalTreeNode(IList <IInterval <T> > intervalsByStart, IList <IInterval <T> > intervalsByEnd, IntervalTreeMedianComputation <T> medianComputation) { IntervalMin = intervalsByStart.First().Start; IntervalMax = intervalsByEnd.Last().End; Median = medianComputation(IntervalMin, IntervalMax); var leftByStart = new List <IInterval <T> >(); var leftByEnd = new List <IInterval <T> >(); var rightByStart = new List <IInterval <T> >(); var rightByEnd = new List <IInterval <T> >(); var overlappingByStart = new List <IInterval <T> >(); var overlappingByEnd = new List <IInterval <T> >(); foreach (var interval in intervalsByStart) { if (interval.End.CompareTo(Median) < 0) { leftByStart.Add(interval); } else if (interval.Start.CompareTo(Median) > 0) { rightByStart.Add(interval); } else { overlappingByStart.Add(interval); } } foreach (var interval in intervalsByEnd) { if (interval.End.CompareTo(Median) < 0) { leftByEnd.Add(interval); } else if (interval.Start.CompareTo(Median) > 0) { rightByEnd.Add(interval); } else { overlappingByEnd.Add(interval); } } if (overlappingByStart.Count > 0) { OverlappingByStart = overlappingByStart; OverlappingByEnd = overlappingByEnd; } if (leftByStart.Count > 0) { Left = new IntervalTreeNode <T>(leftByStart, leftByEnd, medianComputation); } if (rightByStart.Count > 0) { Right = new IntervalTreeNode <T>(rightByStart, rightByEnd, medianComputation); } }