//******************************************************************************************************
// Range.cs - Gbtc
//
// Copyright © 2015, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 06/30/2015 - Stephen C. Wills
// Generated original version of source code.
//
//******************************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
namespace GSF
{
///
/// Represents a range of values with a start and end value.
///
public class Range
{
#region [ Members ]
// Fields
private readonly T m_start;
private readonly T m_end;
#endregion
#region [ Constructors ]
///
/// Creates a new instance of the class using the default comparer.
///
/// The start value of the range.
/// The end value of the range.
public Range(T start, T end)
{
m_start = start;
m_end = end;
}
#endregion
#region [ Properties ]
///
/// Gets the start value of the range.
///
public T Start
{
get
{
return m_start;
}
}
///
/// Gets the end value of the range.
///
public T End
{
get
{
return m_end;
}
}
#endregion
#region [ Methods ]
///
/// Determines whether the range overlaps with the given range.
///
/// The range to be compared with.
/// True if the ranges overlap; false otherwise.
public bool Overlaps(Range range)
{
return Overlaps(range, Comparer.Default);
}
///
/// Determines whether the range overlaps with the given range.
///
/// The range to be compared with.
/// The comparer used to compare objects of type .
/// True if the ranges overlap; false otherwise.
public bool Overlaps(Range range, IComparer comparer)
{
return Overlaps(range, comparer.Compare);
}
///
/// Determines whether the range overlaps with the given range.
///
/// The range to be compared with.
/// The comparison used to compare objects of type .
/// True if the ranges overlap; false otherwise.
public bool Overlaps(Range range, Comparison comparison)
{
return comparison(m_start, range.m_end) <= 0 && comparison(range.m_start, m_end) <= 0;
}
///
/// Merges two ranges into one range that fully encompasses both ranges.
///
/// The range to be merged with this one.
/// The range that fully encompasses the merged ranges.
public Range Merge(Range range)
{
return Merge(range, Comparer.Default);
}
///
/// Merges two ranges into one range that fully encompasses both ranges.
///
/// The range to be merged with this one.
/// The comparer used to compare objects of type .
/// The range that fully encompasses the merged ranges.
public Range Merge(Range range, IComparer comparer)
{
return Merge(range, comparer.Compare);
}
///
/// Merges two ranges into one range that fully encompasses both ranges.
///
/// The range to be merged with this one.
/// The comparison used to compare objects of type .
/// The range that fully encompasses the merged ranges.
public Range Merge(Range range, Comparison comparison)
{
T start = comparison(m_start, range.m_start) <= 0 ? m_start : range.m_start;
T end = comparison(m_end, range.m_end) >= 0 ? m_end : range.m_end;
return new Range(start, end);
}
#endregion
#region [ Static ]
// Static Methods
///
/// Merges all ranges in a collection of ranges.
///
/// The collection of ranges to be merged.
/// A range that is the result of merging all ranges in the collection.
public static Range Merge(IEnumerable> ranges)
{
return Merge(ranges, Comparer.Default);
}
///
/// Merges all ranges in a collection of ranges.
///
/// The collection of ranges to be merged.
/// The comparer used to compare objects of type .
/// A range that is the result of merging all ranges in the collection.
public static Range Merge(IEnumerable> ranges, Comparer comparer)
{
return Merge(ranges, comparer.Compare);
}
///
/// Merges all ranges in a collection of ranges.
///
/// The collection of ranges to be merged.
/// The comparison used to compare objects of type .
/// A range that is the result of merging all ranges in the collection.
public static Range Merge(IEnumerable> ranges, Comparison comparison)
{
return ranges.Aggregate((range1, range2) => range1.Merge(range2, comparison));
}
///
/// Merges all consecutive groups of overlapping ranges in a
/// collection and returns the resulting collection of ranges.
///
/// The collection of ranges.
/// The collection of merged ranges.
public static IEnumerable> MergeConsecutiveOverlapping(IEnumerable> ranges)
{
return MergeConsecutiveOverlapping(ranges, Comparer.Default);
}
///
/// Merges all consecutive groups of overlapping ranges in a
/// collection and returns the resulting collection of ranges.
///
/// The collection of ranges.
/// The comparer used to compare objects of type .
/// The collection of merged ranges.
public static IEnumerable> MergeConsecutiveOverlapping(IEnumerable> ranges, IComparer comparer)
{
return MergeConsecutiveOverlapping(ranges, comparer.Compare);
}
///
/// Merges all consecutive groups of overlapping ranges in a
/// collection and returns the resulting collection of ranges.
///
/// The collection of ranges.
/// The comparison used to compare objects of type .
/// The collection of merged ranges.
public static IEnumerable> MergeConsecutiveOverlapping(IEnumerable> ranges, Comparison comparison)
{
Range currentRange = null;
foreach (Range range in ranges)
{
if ((object)currentRange == null)
{
currentRange = range;
}
else if (currentRange.Overlaps(range, comparison))
{
currentRange = currentRange.Merge(range, comparison);
}
else
{
yield return currentRange;
currentRange = range;
}
}
if ((object)currentRange != null)
yield return currentRange;
}
///
/// Merges all consecutive groups of overlapping ranges in a
/// collection and returns the resulting collection of ranges.
///
/// The collection of ranges.
/// The collection of merged ranges.
/// This method does not preserve the order of the source collection.
public static IEnumerable> MergeAllOverlapping(IEnumerable> ranges)
{
return MergeAllOverlapping(ranges, Comparer.Default);
}
///
/// Merges all consecutive groups of overlapping ranges in a
/// collection and returns the resulting collection of ranges.
///
/// The collection of ranges.
/// The comparison used to compare objects of type .
/// The collection of merged ranges.
/// This method does not preserve the order of the source collection.
public static IEnumerable> MergeAllOverlapping(IEnumerable> ranges, Comparison comparison)
{
return MergeAllOverlapping(ranges, Comparer.Create(comparison));
}
///
/// Merges all consecutive groups of overlapping ranges in a
/// collection and returns the resulting collection of ranges.
///
/// The collection of ranges.
/// The comparer used to compare objects of type .
/// The collection of merged ranges.
/// This method does not preserve the order of the source collection.
public static IEnumerable> MergeAllOverlapping(IEnumerable> ranges, IComparer comparer)
{
return MergeConsecutiveOverlapping(ranges.OrderBy(range => range.Start, comparer));
}
#endregion
}
}