15 #ifndef MOTIVE_MATH_RANGE_H_
16 #define MOTIVE_MATH_RANGE_H_
19 #include "mathfu/utilities.h"
26 enum ModularDirection {
39 template <
size_t kMaxLen>
45 template <
size_t kMaxLen>
52 RangeT() : start_(static_cast<T>(1)), end_(static_cast<T>(0)) {}
53 explicit RangeT(
const T point) : start_(point), end_(point) {}
54 RangeT(
const T
start,
const T end) : start_(start), end_(end) {}
57 bool Valid()
const {
return start_ <= end_; }
61 T
Middle()
const {
return (start_ + end_) /
static_cast<T
>(2); }
65 T
Length()
const {
return end_ - start_; }
70 T
Clamp(
const T x)
const {
return mathfu::Clamp(x, start_, end_); }
87 T
Lerp(
const float percent)
const {
88 return mathfu::Lerp(start_, end_, percent);
98 return mathfu::Clamp(
Percent(x), 0.0f, 1.0f);
124 static const int kMaxAdjustments = 4;
127 const bool below = x <= start_;
128 const bool above = x > end_;
129 if (!below && !above)
return x;
133 const T length =
Length();
134 int num_adjustments = 0;
141 }
while (x <= start_);
158 const T length =
Length();
159 const T units = (x - start_) / length;
160 const T whole_units = floor(units);
165 const T close = x - whole_units * length;
176 const T length =
Length();
177 const T adjustment = x <= start_ ? length : x > end_ ? -length : 0.0f;
188 const float length =
Length();
190 return close >= 0.0f ? close - length : close + length;
196 const float length =
Length();
198 return close >= 0.0f ? close : close + length;
204 const float length =
Length();
206 return close >= 0.0f ? close - length : close;
211 float ModDiff(T a, T b, ModularDirection direction)
const {
213 case kDirectionClosest:
215 case kDirectionFarthest:
217 case kDirectionPositive:
219 case kDirectionNegative:
221 case kDirectionDirect:
229 bool Contains(
const T x)
const {
return start_ <= x && x <= end_; }
234 return start_ < x && x <= end_;
247 const float tolerance =
Length() * percent;
248 return start_ - tolerance <= x && x <= end_ + tolerance;
259 const T extra =
static_cast<T
>(
Length() * percent * 0.5f);
260 return RangeT(start_ - extra, end_ + extra);
266 return RangeT(std::min<T>(start_, x), std::max<T>(end_, x));
271 return start_ == rhs.start_ && end_ == rhs.end_;
280 T end()
const {
return end_; }
281 void set_start(
const T
start) { start_ =
start; }
282 void set_end(
const T end) { end_ = end; }
305 return RangeT(std::max(a.start_, b.start_), std::min(a.end_, b.end_));
325 return RangeT(std::min(a.start_, b.start_), std::max(a.end_, b.end_));
338 size_t num_returned = 0;
339 for (
size_t i = 0; i < num_values; ++i) {
340 const T value = values[i];
341 const T clamped = range.
Clamp(value);
342 const T dist = fabs(value - clamped);
345 if (dist <= epsilon) {
346 values[num_returned++] = clamped;
352 template <
size_t kMaxLen>
354 TArray<kMaxLen>* values) {
355 values->len =
ValuesInRange(range, epsilon, values->len, values->arr);
362 size_t len_b,
RangeT* intersections,
364 size_t* len_gaps =
nullptr) {
365 size_t num_intersections = 0;
368 for (
size_t i = 0; i < len_a; ++i) {
369 for (
size_t j = 0; j < len_b; ++j) {
371 if (intersection.
Valid()) {
372 intersections[num_intersections++] = intersection;
374 }
else if (gaps !=
nullptr) {
377 gaps[num_gaps++] = intersection.
Invert();
383 if (len_gaps !=
nullptr) {
384 *len_gaps = num_gaps;
386 return num_intersections;
389 template <
size_t kMaxLen>
391 const RangeArray<kMaxLen>& b,
392 RangeArray<kMaxLen * kMaxLen>* intersections,
393 RangeArray<kMaxLen * kMaxLen>* gaps =
nullptr) {
394 const bool use_gaps = gaps !=
nullptr;
396 a.arr, a.len, b.arr, b.len, intersections->arr,
397 use_gaps ? gaps->arr :
nullptr, use_gaps ? &gaps->len :
nullptr);
402 T longest_length = -1.0f;
403 size_t longest_index = 0;
404 for (
size_t i = 0; i < len; ++i) {
405 const T length = ranges[i].
Length();
406 if (length > longest_length) {
407 longest_length = length;
411 return longest_index;
414 template <
size_t kMaxLen>
421 T shortest_length = std::numeric_limits<T>::infinity();
422 size_t shortest_index = 0;
423 for (
size_t i = 0; i < len; ++i) {
424 const T length = ranges[i].
Length();
425 if (length < shortest_length) {
426 shortest_length = length;
430 return shortest_index;
433 template <
size_t kMaxLen>
440 T closest_dist = std::numeric_limits<T>::infinity();
442 for (
size_t i = 0; i < len; ++i) {
443 const T clamp = ranges[i].
Clamp(x);
444 const T dist = fabs(x - clamp);
445 if (dist < closest_dist) {
447 closest_clamp = clamp;
450 return closest_clamp;
453 template <
size_t kMaxLen>
464 template <
typename S,
typename F>
467 for (
size_t i = 0; i < len; ++i) {
475 return CoversLambda(array, len, [](
const T& t) {
return t; });
480 return RangeT<T>(-std::numeric_limits<T>::infinity(),
481 std::numeric_limits<T>::infinity());
489 return RangeT<T>(std::numeric_limits<T>::infinity(),
490 -std::numeric_limits<T>::infinity());
495 return RangeT<T>(0.0f, std::numeric_limits<T>::infinity());
500 return RangeT<T>(-std::numeric_limits<T>::infinity(), 0.0f);
511 RangeT<T> CreateValidRange(
const T a,
const T b) {
512 return RangeT<T>(std::min<T>(a, b), std::max<T>(a, b));
516 typedef RangeT<float> RangeFloat;
517 typedef RangeT<double> RangeDouble;
518 typedef RangeT<int> RangeInt;
519 typedef RangeT<unsigned int> RangeUInt;
522 typedef RangeFloat Range;
525 static const Range kAngleRange(-static_cast<float>(M_PI),
526 static_cast<float>(M_PI));
527 static const Range kInvalidRange;
531 #endif // MOTIVE_MATH_RANGE_H_
float Percent(const T x) const
Definition: range.h:93
static RangeT Union(const RangeT &a, const RangeT &b)
Return the smallest range that covers all of 'a' and 'b'.
Definition: range.h:309
float ModDiffNegative(T a, T b) const
Definition: range.h:203
bool ContainsExcludingEnd(const T x) const
Definition: range.h:239
float ModDiffClose(T a, T b) const
Definition: range.h:184
static size_t IndexOfLongest(const RangeT *ranges, size_t len)
Return the index of the longest range in ranges.
Definition: range.h:401
T ClampBeforeEnd(const T x) const
Definition: range.h:78
static T ClampToClosest(T x, const RangeT *ranges, size_t len)
Return the index of the shortest range in ranges.
Definition: range.h:439
static RangeT< T > Positive()
Returns the range of positive numbers: [0, +infinity].
Definition: range.h:494
bool ContainsExcludingStart(const T x) const
Definition: range.h:233
RangeT Invert() const
Definition: range.h:254
RangeT Include(const T x) const
Definition: range.h:265
static RangeT Intersect(const RangeT &a, const RangeT &b)
Definition: range.h:288
static size_t IntersectRanges(const RangeT *a, size_t len_a, const RangeT *b, size_t len_b, RangeT *intersections, RangeT *gaps=nullptr, size_t *len_gaps=nullptr)
Definition: range.h:361
T Lerp(const float percent) const
Definition: range.h:87
T NormalizeWildValue(T x) const
Definition: range.h:155
bool Contains(const T x) const
Return true if x is in [start_, end_], i.e. the inclusive range.
Definition: range.h:229
RangeT operator*(const float s) const
Scale by multiplying by a scalar.
Definition: range.h:276
float ModDiffPositive(T a, T b) const
Definition: range.h:195
float ModDiff(T a, T b, ModularDirection direction) const
Definition: range.h:211
T ClampAfterStart(const T x) const
Definition: range.h:74
T NormalizeCloseValue(T x) const
Definition: range.h:123
static RangeT< T > CoversLambda(const S *array, size_t len, const F &f)
Definition: range.h:465
float ModDiffFar(T a, T b) const
Return the farthest difference from 'a' to 'b' under modular arithmetic.
Definition: range.h:187
T DistanceFrom(const T x) const
Definition: range.h:82
bool operator==(const RangeT &rhs) const
Equality is strict. No epsilon checking here.
Definition: range.h:270
static RangeT< T > Full()
Returns the complete range. Every T is contained in this range.
Definition: range.h:479
T PercentClamped(const T x) const
Definition: range.h:97
T Middle() const
Definition: range.h:61
static size_t ValuesInRange(const RangeT &range, T epsilon, size_t num_values, T *values)
Definition: range.h:336
T Normalize(T x) const
Definition: range.h:107
T start() const
Accessors.
Definition: range.h:279
static RangeT< T > Negative()
Returns the range of negative numbers.: [-infinity, 0].
Definition: range.h:499
static size_t IndexOfShortest(const RangeT *ranges, size_t len)
Return the index of the shortest range in ranges.
Definition: range.h:420
T ModularAdjustment(T x) const
Definition: range.h:175
static RangeT< T > Empty()
Definition: range.h:488
RangeT Lengthen(const float percent) const
Definition: range.h:258
bool StrictlyContains(const T x) const
Return true if x is in (start_, end_), i.e. the exclusive range.
Definition: range.h:242
bool ContainsWithTolerance(const T x, const T percent) const
Definition: range.h:246
static RangeT< T > Covers(const T *array, size_t len)
Return the range that covers all values in array.
Definition: range.h:474
T Clamp(const T x) const
Definition: range.h:70
T Length() const
Definition: range.h:65
Represent an interval on a number line.
Definition: range.h:37
bool Valid() const
A range is valid if it contains at least one number.
Definition: range.h:57