181 lines
No EOL
4.2 KiB
C#
181 lines
No EOL
4.2 KiB
C#
using System;
|
|
|
|
namespace JD.Kernel.Structs
|
|
{
|
|
/// <summary>
|
|
/// A range (a max and a min).
|
|
/// </summary>
|
|
public struct Range<T> : IEquatable<Range<T>>
|
|
// JD : Avoid Boxing when comparing values.
|
|
where T : struct, IComparable<T>
|
|
{
|
|
#region Variables
|
|
|
|
private readonly T m_min;
|
|
private readonly T m_max;
|
|
|
|
#endregion
|
|
|
|
#region Constructor
|
|
|
|
public Range(T min, T max)
|
|
{
|
|
m_min = ComputeMin(min, max);
|
|
m_max = ComputeMax(min, max);
|
|
}
|
|
|
|
static Range()
|
|
{
|
|
Range<int>.Infinite = new Range<int>(int.MinValue, int.MaxValue);
|
|
Range<float>.Infinite = new Range<float>(float.MinValue, float.MaxValue);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
public static Range<T> Infinite;
|
|
|
|
public T Min
|
|
{
|
|
get { return m_min; }
|
|
}
|
|
|
|
public T Max
|
|
{
|
|
get { return m_max; }
|
|
}
|
|
|
|
public static Range<T> Empty
|
|
{
|
|
get
|
|
{
|
|
return new Range<T>(default(T), default(T));
|
|
}
|
|
}
|
|
|
|
public bool IsEmpty
|
|
{
|
|
get { return Compare(Min, Max) == 0; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Functions
|
|
|
|
private static int Compare(T a, T b)
|
|
{
|
|
return a.CompareTo(b);
|
|
}
|
|
|
|
private static T ComputeMin(T a, T b)
|
|
{
|
|
return Compare(a, b) <= 0 ? a : b;
|
|
}
|
|
|
|
private static T ComputeMax(T a, T b)
|
|
{
|
|
return Compare(a, b) >= 0 ? a : b;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Makes the value fits the actual range.
|
|
/// </summary>
|
|
public T Clamp(T value)
|
|
{
|
|
return ComputeMax(ComputeMin(value, m_max), m_min);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Makes the range fits into the range.
|
|
/// </summary>
|
|
public Range<T> ClampRange(Range<T> other)
|
|
{
|
|
return new Range<T>(Clamp(other.Min), Clamp(other.Max));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a range that contains both.
|
|
/// </summary>
|
|
public Range<T> Union(Range<T> other)
|
|
{
|
|
return new Range<T>(ComputeMin(Min, other.Min), ComputeMax(Max, other.Max));
|
|
}
|
|
|
|
/// <summary>
|
|
/// True if the value is included in the Range.
|
|
/// </summary>
|
|
public bool Contains(T value)
|
|
{
|
|
return Compare(value, m_min) >= 0 && Compare(value, m_max) <= 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// True if this range contains the other one.
|
|
/// </summary>
|
|
/// <param name="other"></param>
|
|
public bool Contains(Range<T> other)
|
|
{
|
|
return Compare(m_min, other.m_min) <= 0 && Compare(m_max, other.m_max) >= 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// True if there is a common section between the two ranges.
|
|
/// </summary>
|
|
public bool Intersects(T min, T max)
|
|
{
|
|
if (min.CompareTo(Min) < 0)
|
|
{
|
|
return max.CompareTo(Min) > 0;
|
|
}
|
|
|
|
return min.CompareTo(Max) < 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// True if there is a common section between the two ranges.
|
|
/// </summary>
|
|
/// <param name="other"></param>
|
|
/// <returns></returns>
|
|
public bool Intersects(Range<T> other)
|
|
{
|
|
return Intersects(other.Min, other.Max);
|
|
}
|
|
|
|
#region Equality
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
return obj is Range<T> && Equals((Range<T>) obj);
|
|
}
|
|
|
|
public bool Equals(Range<T> other)
|
|
{
|
|
return Equals(Min, other.Min) && Equals(Max, other.Max);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return Min.GetHashCode() ^ Max.GetHashCode();
|
|
}
|
|
|
|
public static bool operator ==(Range<T> a, Range<T> b)
|
|
{
|
|
return a.Equals(b);
|
|
}
|
|
|
|
public static bool operator !=(Range<T> a, Range<T> b)
|
|
{
|
|
return !(a == b);
|
|
}
|
|
|
|
#endregion
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"[{Min} - {Max}]";
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |