usdrt/gf/range.h
File members: usdrt/gf/range.h
// Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#pragma once
#include <carb/Defines.h>
#include <usdrt/gf/vec.h>
namespace omni
{
namespace math
{
namespace linalg
{
// specializing range for 1 dimensions to use float and match GfRange1(d|f)
template <typename T>
class range1
{
public:
static const size_t dimension = 1;
using MinMaxType = T;
using ScalarType = T;
using ThisType = range1<T>;
// TODO check whether this can be deprecated.
void inline SetEmpty()
{
_min = std::numeric_limits<ScalarType>::max();
_max = -std::numeric_limits<ScalarType>::max();
}
range1()
{
SetEmpty();
}
constexpr range1(const ThisType&) = default;
constexpr explicit range1(ScalarType size) : _min(-size), _max(size)
{
}
constexpr range1(ScalarType min, ScalarType max) : _min(min), _max(max)
{
}
ScalarType GetMin() const
{
return _min;
}
ScalarType GetMax() const
{
return _max;
}
ScalarType GetSize() const
{
return _max - _min;
}
ScalarType GetMidpoint() const
{
return static_cast<ScalarType>(0.5) * _min + static_cast<ScalarType>(0.5) * _max;
}
void SetMin(ScalarType min)
{
_min = min;
}
void SetMax(ScalarType max)
{
_max = max;
}
bool IsEmpty() const
{
return _min > _max;
}
void ExtendBy(ScalarType point)
{
UnionWith(point);
}
void ExtendBy(const ThisType& range)
{
UnionWith(range);
}
bool Contains(const ScalarType& point) const
{
return (point >= _min && point <= _max);
}
bool Contains(const ThisType& range) const
{
return Contains(range._min) && Contains(range._max);
}
bool IsInside(ScalarType point) const
{
return Contains(point);
}
bool IsInside(const ThisType& range) const
{
return Contains(range);
}
bool IsOutside(const ThisType& range) const
{
return (range._max < _min || range._min > _max);
}
static ThisType GetUnion(const ThisType& a, const ThisType& b)
{
auto res = a;
_FindMin(res._min, b._min);
_FindMax(res._max, b._max);
return res;
}
const ThisType& UnionWith(const ThisType& b)
{
_FindMin(_min, b._min);
_FindMax(_max, b._max);
return *this;
}
const ThisType& UnionWith(const ScalarType& b)
{
_FindMin(_min, b);
_FindMax(_max, b);
return *this;
}
static ThisType Union(const ThisType& a, const ThisType& b)
{
return GetUnion(a, b);
}
const ThisType& Union(const ThisType& b)
{
return UnionWith(b);
}
const ThisType& Union(ScalarType b)
{
return UnionWith(b);
}
static ThisType GetIntersection(const ThisType& a, const ThisType& b)
{
auto res = a;
_FindMax(res._min, b._min);
_FindMin(res._max, b._max);
return res;
}
static ThisType Intersection(const ThisType& a, const ThisType& b)
{
return GetIntersection(a, b);
}
const ThisType& IntersectWith(const ThisType& b)
{
_FindMax(_min, b._min);
_FindMin(_max, b._max);
return *this;
}
const ThisType& Intersection(const ThisType& b)
{
return IntersectWith(b);
}
ThisType operator+=(const ThisType& b)
{
_min += b._min;
_max += b._max;
return *this;
}
ThisType operator-=(const ThisType& b)
{
_min -= b._max;
_max -= b._min;
return *this;
}
ThisType operator*=(double m)
{
if (m > 0)
{
_min *= m;
_max *= m;
}
else
{
float tmp = _min;
_min = _max * m;
_max = tmp * m;
}
return *this;
}
ThisType operator/=(double m)
{
return *this *= (1.0 / m);
}
ThisType operator+(const ThisType& b) const
{
return ThisType(_min + b._min, _max + b._max);
}
ThisType operator-(const ThisType& b) const
{
return ThisType(_min - b._max, _max - b._min);
}
friend ThisType operator*(double m, const ThisType& r)
{
return (m > 0 ? ThisType(r._min * m, r._max * m) : ThisType(r._max * m, r._min * m));
}
friend ThisType operator*(const ThisType& r, double m)
{
return (m > 0 ? ThisType(r._min * m, r._max * m) : ThisType(r._max * m, r._min * m));
}
friend ThisType operator/(const ThisType& r, double m)
{
return r * (1.0 / m);
}
inline bool operator==(const ThisType& other) const
{
return _min == static_cast<ScalarType>(other.GetMin()) && _max == static_cast<ScalarType>(other.GetMax());
}
inline bool operator!=(const ThisType& other) const
{
return !(*this == other);
}
double GetDistanceSquared(ScalarType p) const
{
double dist = 0.0;
if (p < _min)
{
// p is left of box
dist += GfSqr(_min - p);
}
else if (p > _max)
{
// p is right of box
dist += GfSqr(p - _max);
}
return dist;
}
private:
ScalarType _min, _max;
static void _FindMin(ScalarType& dest, ScalarType point)
{
if (point < dest)
{
dest = point;
}
}
static void _FindMax(ScalarType& dest, ScalarType point)
{
if (point > dest)
{
dest = point;
}
}
};
template <typename T>
class range2
{
public:
static const size_t dimension = 2;
using ScalarType = T;
using MinMaxType = omni::math::linalg::vec2<T>;
using ThisType = range2<T>;
range2()
{
SetEmpty();
}
constexpr range2(const ThisType&) = default;
constexpr explicit range2(ScalarType size) : _min(-size), _max(size)
{
}
// TODO check whether this can be deprecated.
constexpr void inline SetEmpty()
{
_min = MinMaxType(std::numeric_limits<ScalarType>::max());
_max = MinMaxType(-std::numeric_limits<ScalarType>::max());
}
constexpr range2(const MinMaxType& min, const MinMaxType& max) : _min(min), _max(max)
{
}
const MinMaxType& GetMin() const
{
return _min;
}
const MinMaxType& GetMax() const
{
return _max;
}
MinMaxType GetSize() const
{
return _max - _min;
}
MinMaxType GetMidpoint() const
{
return static_cast<ScalarType>(0.5) * _min + static_cast<ScalarType>(0.5) * _max;
}
void SetMin(const MinMaxType& min)
{
_min = min;
}
void SetMax(const MinMaxType& max)
{
_max = max;
}
bool IsEmpty() const
{
return _min[0] > _max[0] || _min[1] > _max[1];
}
void ExtendBy(const MinMaxType& point)
{
UnionWith(point);
}
void ExtendBy(const ThisType& range)
{
UnionWith(range);
}
bool Contains(const MinMaxType& point) const
{
return (point[0] >= _min[0] && point[0] <= _max[0] && point[1] >= _min[1] && point[1] <= _max[1]);
}
bool Contains(const ThisType& range) const
{
return Contains(range._min) && Contains(range._max);
}
bool IsInside(const MinMaxType& point) const
{
return Contains(point);
}
bool IsInside(const ThisType& range) const
{
return Contains(range);
}
bool IsOutside(const ThisType& range) const
{
return ((range._max[0] < _min[0] || range._min[0] > _max[0]) ||
(range._max[1] < _min[1] || range._min[1] > _max[1]));
}
static ThisType GetUnion(const ThisType& a, const ThisType& b)
{
auto res = a;
_FindMin(res._min, b._min);
_FindMax(res._max, b._max);
return res;
}
const ThisType& UnionWith(const ThisType& b)
{
_FindMin(_min, b._min);
_FindMax(_max, b._max);
return *this;
}
const ThisType& UnionWith(const MinMaxType& b)
{
_FindMin(_min, b);
_FindMax(_max, b);
return *this;
}
static ThisType Union(const ThisType& a, const ThisType& b)
{
return GetUnion(a, b);
}
const ThisType& Union(const ThisType& b)
{
return UnionWith(b);
}
const ThisType& Union(const MinMaxType& b)
{
return UnionWith(b);
}
static ThisType GetIntersection(const ThisType& a, const ThisType& b)
{
auto res = a;
_FindMax(res._min, b._min);
_FindMin(res._max, b._max);
return res;
}
static ThisType Intersection(const ThisType& a, const ThisType& b)
{
return GetIntersection(a, b);
}
const ThisType& IntersectWith(const ThisType& b)
{
_FindMax(_min, b._min);
_FindMin(_max, b._max);
return *this;
}
const ThisType& Intersection(const ThisType& b)
{
return IntersectWith(b);
}
ThisType& operator+=(const ThisType& b)
{
_min += b._min;
_max += b._max;
return *this;
}
ThisType& operator-=(const ThisType& b)
{
_min -= b._max;
_max -= b._min;
return *this;
}
ThisType& operator*=(double m)
{
if (m > 0)
{
_min *= m;
_max *= m;
}
else
{
auto tmp = _min;
_min = _max * m;
_max = tmp * m;
}
return *this;
}
ThisType& operator/=(double m)
{
return *this *= (1.0 / m);
}
ThisType operator+(const ThisType& b) const
{
return ThisType(_min + b._min, _max + b._max);
}
ThisType operator-(const ThisType& b) const
{
return ThisType(_min - b._max, _max - b._min);
}
friend ThisType operator*(double m, const ThisType& r)
{
return (m > 0 ? ThisType(r._min * m, r._max * m) : ThisType(r._max * m, r._min * m));
}
friend ThisType operator*(const ThisType& r, double m)
{
return (m > 0 ? ThisType(r._min * m, r._max * m) : ThisType(r._max * m, r._min * m));
}
friend ThisType operator/(const ThisType& r, double m)
{
return r * (1.0 / m);
}
bool operator==(const ThisType& b) const
{
return (_min == b._min && _max == b._max);
}
bool operator!=(const ThisType& b) const
{
return !(*this == b);
}
double GetDistanceSquared(const MinMaxType& p) const
{
double dist = 0.0;
if (p[0] < _min[0])
{
// p is left of box
dist += GfSqr(_min[0] - p[0]);
}
else if (p[0] > _max[0])
{
// p is right of box
dist += GfSqr(p[0] - _max[0]);
}
if (p[1] < _min[1])
{
// p is front of box
dist += GfSqr(_min[1] - p[1]);
}
else if (p[1] > _max[1])
{
// p is back of box
dist += GfSqr(p[1] - _max[1]);
}
return dist;
}
MinMaxType GetCorner(size_t i) const
{
if (i > 3)
{
return _min;
}
return MinMaxType((i & 1 ? _max : _min)[0], (i & 2 ? _max : _min)[1]);
}
ThisType GetQuadrant(size_t i) const
{
if (i > 3)
{
return {};
}
auto a = GetCorner(i);
auto b = .5 * (_min + _max);
return ThisType(
MinMaxType(GfMin(a[0], b[0]), GfMin(a[1], b[1])), MinMaxType(GfMax(a[0], b[0]), GfMax(a[1], b[1])));
}
static constexpr ThisType UnitSquare()
{
return ThisType(MinMaxType(0), MinMaxType(1));
}
private:
MinMaxType _min, _max;
static void _FindMin(MinMaxType& dest, const MinMaxType& point)
{
if (point[0] < dest[0])
{
dest[0] = point[0];
}
if (point[1] < dest[1])
{
dest[1] = point[1];
}
}
static void _FindMax(MinMaxType& dest, const MinMaxType& point)
{
if (point[0] > dest[0])
{
dest[0] = point[0];
}
if (point[1] > dest[1])
{
dest[1] = point[1];
}
}
};
template <typename T>
class range3
{
public:
static const size_t dimension = 3;
using ScalarType = T;
using MinMaxType = omni::math::linalg::vec3<T>;
using ThisType = range3<T>;
range3()
{
SetEmpty();
}
constexpr range3(const ThisType&) = default;
constexpr explicit range3(ScalarType size) : _min(-size), _max(size)
{
}
// TODO check whether this can be deprecated.
constexpr void inline SetEmpty()
{
_min = MinMaxType(std::numeric_limits<ScalarType>::max());
_max = MinMaxType(-std::numeric_limits<ScalarType>::max());
}
constexpr range3(const MinMaxType& min, const MinMaxType& max) : _min(min), _max(max)
{
}
const MinMaxType& GetMin() const
{
return _min;
}
const MinMaxType& GetMax() const
{
return _max;
}
MinMaxType GetSize() const
{
return _max - _min;
}
MinMaxType GetMidpoint() const
{
return static_cast<ScalarType>(0.5) * _min + static_cast<ScalarType>(0.5) * _max;
}
void SetMin(const MinMaxType& min)
{
_min = min;
}
void SetMax(const MinMaxType& max)
{
_max = max;
}
bool IsEmpty() const
{
return _min[0] > _max[0] || _min[1] > _max[1] || _min[2] > _max[2];
}
void ExtendBy(const MinMaxType& point)
{
UnionWith(point);
}
void ExtendBy(const ThisType& range)
{
UnionWith(range);
}
bool Contains(const MinMaxType& point) const
{
return (point[0] >= _min[0] && point[0] <= _max[0] && point[1] >= _min[1] && point[1] <= _max[1] &&
point[2] >= _min[2] && point[2] <= _max[2]);
}
bool Contains(const ThisType& range) const
{
return Contains(range._min) && Contains(range._max);
}
bool IsInside(const MinMaxType& point) const
{
return Contains(point);
}
bool IsInside(const ThisType& range) const
{
return Contains(range);
}
bool IsOutside(const ThisType& range) const
{
return ((range._max[0] < _min[0] || range._min[0] > _max[0]) ||
(range._max[1] < _min[1] || range._min[1] > _max[1]) ||
(range._max[2] < _min[2] || range._min[2] > _max[2]));
}
static ThisType GetUnion(const ThisType& a, const ThisType& b)
{
ThisType res = a;
_FindMin(res._min, b._min);
_FindMax(res._max, b._max);
return res;
}
const ThisType& UnionWith(const ThisType& b)
{
_FindMin(_min, b._min);
_FindMax(_max, b._max);
return *this;
}
const ThisType& UnionWith(const MinMaxType& b)
{
_FindMin(_min, b);
_FindMax(_max, b);
return *this;
}
static ThisType Union(const ThisType& a, const ThisType& b)
{
return GetUnion(a, b);
}
const ThisType& Union(const ThisType& b)
{
return UnionWith(b);
}
const ThisType& Union(const MinMaxType& b)
{
return UnionWith(b);
}
static ThisType GetIntersection(const ThisType& a, const ThisType& b)
{
ThisType res = a;
_FindMax(res._min, b._min);
_FindMin(res._max, b._max);
return res;
}
static ThisType Intersection(const ThisType& a, const ThisType& b)
{
return GetIntersection(a, b);
}
const ThisType& IntersectWith(const ThisType& b)
{
_FindMax(_min, b._min);
_FindMin(_max, b._max);
return *this;
}
const ThisType& Intersection(const ThisType& b)
{
return IntersectWith(b);
}
ThisType& operator+=(const ThisType& b)
{
_min += b._min;
_max += b._max;
return *this;
}
ThisType& operator-=(const ThisType& b)
{
_min -= b._max;
_max -= b._min;
return *this;
}
ThisType& operator*=(double m)
{
if (m > 0)
{
_min *= m;
_max *= m;
}
else
{
MinMaxType tmp = _min;
_min = _max * m;
_max = tmp * m;
}
return *this;
}
ThisType& operator/=(double m)
{
return *this *= (1.0 / m);
}
ThisType operator+(const ThisType& b) const
{
return ThisType(_min + b._min, _max + b._max);
}
ThisType operator-(const ThisType& b) const
{
return ThisType(_min - b._max, _max - b._min);
}
friend ThisType operator*(double m, const ThisType& r)
{
return (m > 0 ? ThisType(r._min * m, r._max * m) : ThisType(r._max * m, r._min * m));
}
friend ThisType operator*(const ThisType& r, double m)
{
return (m > 0 ? ThisType(r._min * m, r._max * m) : ThisType(r._max * m, r._min * m));
}
friend ThisType operator/(const ThisType& r, double m)
{
return r * (1.0 / m);
}
bool operator==(const ThisType& b) const
{
return (_min == b._min && _max == b._max);
}
bool operator!=(const ThisType& b) const
{
return !(*this == b);
}
double GetDistanceSquared(const MinMaxType& p) const
{
double dist = 0.0;
if (p[0] < _min[0])
{
// p is left of box
dist += GfSqr(_min[0] - p[0]);
}
else if (p[0] > _max[0])
{
// p is right of box
dist += GfSqr(p[0] - _max[0]);
}
if (p[1] < _min[1])
{
// p is front of box
dist += GfSqr(_min[1] - p[1]);
}
else if (p[1] > _max[1])
{
// p is back of box
dist += GfSqr(p[1] - _max[1]);
}
if (p[2] < _min[2])
{
// p is below of box
dist += GfSqr(_min[2] - p[2]);
}
else if (p[2] > _max[2])
{
// p is above of box
dist += GfSqr(p[2] - _max[2]);
}
return dist;
}
MinMaxType GetCorner(size_t i) const
{
if (i > 7)
{
return _min;
}
return MinMaxType((i & 1 ? _max : _min)[0], (i & 2 ? _max : _min)[1], (i & 4 ? _max : _min)[2]);
}
ThisType GetOctant(size_t i) const
{
if (i > 7)
{
return {};
}
auto a = GetCorner(i);
auto b = .5 * (_min + _max);
return ThisType(MinMaxType(GfMin(a[0], b[0]), GfMin(a[1], b[1]), GfMin(a[2], b[2])),
MinMaxType(GfMax(a[0], b[0]), GfMax(a[1], b[1]), GfMax(a[2], b[2])));
}
static constexpr const ThisType UnitCube()
{
return ThisType(MinMaxType(0), MinMaxType(1));
}
private:
MinMaxType _min, _max;
static void _FindMin(MinMaxType& dest, const MinMaxType& point)
{
if (point[0] < dest[0])
{
dest[0] = point[0];
}
if (point[1] < dest[1])
{
dest[1] = point[1];
}
if (point[2] < dest[2])
{
dest[2] = point[2];
}
}
static void _FindMax(MinMaxType& dest, const MinMaxType& point)
{
if (point[0] > dest[0])
{
dest[0] = point[0];
}
if (point[1] > dest[1])
{
dest[1] = point[1];
}
if (point[2] > dest[2])
{
dest[2] = point[2];
}
}
};
}
}
}
namespace usdrt
{
using GfRange1d = omni::math::linalg::range1<double>;
using GfRange1f = omni::math::linalg::range1<float>;
using GfRange2d = omni::math::linalg::range2<double>;
using GfRange2f = omni::math::linalg::range2<float>;
using GfRange3d = omni::math::linalg::range3<double>;
using GfRange3f = omni::math::linalg::range3<float>;
template <>
struct GfIsGfRange<GfRange1d>
{
static const bool value = true;
};
template <>
struct GfIsGfRange<GfRange1f>
{
static const bool value = true;
};
template <>
struct GfIsGfRange<GfRange2d>
{
static const bool value = true;
};
template <>
struct GfIsGfRange<GfRange2f>
{
static const bool value = true;
};
template <>
struct GfIsGfRange<GfRange3d>
{
static const bool value = true;
};
template <>
struct GfIsGfRange<GfRange3f>
{
static const bool value = true;
};
}