I created the class ContinuousDimensionInterval, to model an interval of a continuous dimension interval, presented below.
namespace Minotaur.Math.Dimensions {
using System;
public sealed class ContinuousDimensionInterval: IDimensionInterval {
public int DimensionIndex { get; }
public readonly DimensionBound Start;
public readonly DimensionBound End;
public ContinuousDimensionInterval(
int dimensionIndex,
DimensionBound start,
DimensionBound end
) {
if (dimensionIndex < 0)
throw new ArgumentOutOfRangeException(nameof(dimensionIndex) + " must be >= 0.");
DimensionIndex = dimensionIndex;
Start = start;
End = end;
}
public bool Contains(float value) {
if (float.IsNaN(value))
throw new ArgumentOutOfRangeException(nameof(value));
if (value > Start.Value && value < End.Value)
return true;
if (Start.IsInclusive && value == Start.Value)
return true;
if (End.IsInclusive && value == End.Value)
return true;
return false;
}
}
}
I felt the need to create a struct, DimensionBound, to represent the bounds of an interval, since they may be inclusive or exclusive.
namespace Minotaur.Math.Dimensions {
using System;
public readonly struct DimensionBound {
public readonly float Value;
public readonly bool IsInclusive;
public DimensionBound(float value, bool isInclusive) {
if (float.IsNaN(value))
throw new ArgumentOutOfRangeException(nameof(value) + " can't be NaN.");
Value = value;
IsInclusive = isInclusive;
}
}
}
I'd like to receive some feedback on the implementation of both classes.
- Should I disallow the construction of
DimensionBound
with value=infinity and inclusive=true? - Is my decision to make
DimensionBound
astruct
reasonable? It feels struct-like to me... - Should
DimensionBound
implementIEquatable<DimensionBound>
? - Am I over-engineering the whole thing by creating a class to represent the bounds of an interval?
Here an example of how the class is used:
private static bool IntersectsContinuous(ContinuousDimensionInterval lhs, ContinuousDimensionInterval rhs) {
// @Improve performance?
// @Verify correctness
var aStart= lhs.Start;
var aEnd = lhs.End;
var bStart = rhs.Start;
var bEnd = rhs.End;
if (aStart.Value > bEnd.Value)
return false;
if (aStart.Value == bEnd.Value)
return aStart.IsInclusive && bEnd.IsInclusive;
if (bStart.Value > aEnd.Value)
return false;
if (bStart.Value == aEnd.Value)
return bStart.IsInclusive && aEnd.IsInclusive;
return true;
}
DimensionIndex
? \$\endgroup\$