usdrt/gf/rect.h

File members: usdrt/gf/rect.h

// Copyright (c) 2021-2022, 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>

#include <float.h>

namespace usdrt
{

struct GfRect2i
{
public:
    // In order to make GfRect2i a POD type we need to give up on non-default constructor
    // pxr::GfRect2i initializes to empty, so we're not 100% compatible here!
    GfRect2i() = default;
    constexpr GfRect2i(const GfRect2i&) = default;

    using MinMaxType = GfVec2i;

    static const size_t dimension = MinMaxType::dimension;
    using ScalarType = MinMaxType::ScalarType;

    constexpr GfRect2i(const GfVec2i& min, const GfVec2i& max) : _min(min), _max(max)
    {
    }

    GfRect2i(const GfVec2i& min, int width, int height) : _min(min), _max(min + GfVec2i(width - 1, height - 1))
    {
    }

    bool IsNull() const
    {
        return GetWidth() == 0 && GetHeight() == 0;
    }

    bool IsEmpty() const
    {
        return GetWidth() <= 0 || GetHeight() <= 0;
    }

    bool IsValid() const
    {
        return !IsEmpty();
    }

    GfRect2i GetNormalized() const
    {
        GfVec2i min, max;

        if (_max[0] < _min[0])
        {
            min[0] = _max[0];
            max[0] = _min[0];
        }
        else
        {
            min[0] = _min[0];
            max[0] = _max[0];
        }

        if (_max[1] < _min[1])
        {
            min[1] = _max[1];
            max[1] = _min[1];
        }
        else
        {
            min[1] = _min[1];
            max[1] = _max[1];
        }

        return GfRect2i(min, max);
    }

    const GfVec2i& GetMin() const
    {
        return _min;
    }

    const GfVec2i& GetMax() const
    {
        return _max;
    }

    int GetMinX() const
    {
        return _min[0];
    }

    void SetMinX(int x)
    {
        _min[0] = x;
    }

    int GetMaxX() const
    {
        return _max[0];
    }

    void SetMaxX(int x)
    {
        _max[0] = x;
    }

    int GetMinY() const
    {
        return _min[1];
    }

    void SetMinY(int y)
    {
        _min[1] = y;
    }

    int GetMaxY() const
    {
        return _max[1];
    }

    void SetMaxY(int y)
    {
        _max[1] = y;
    }

    void SetMin(const GfVec2i& min)
    {
        _min = min;
    }

    void SetMax(const GfVec2i& max)
    {
        _max = max;
    }

    GfVec2i GetCenter() const
    {
        return (_min + _max) / 2;
    }

    void Translate(const GfVec2i& displacement)
    {
        _min += displacement;
        _max += displacement;
    }

    unsigned long GetArea() const
    {
        return (unsigned long)GetWidth() * (unsigned long)GetHeight();
    }

    GfVec2i GetSize() const
    {
        return GfVec2i(GetWidth(), GetHeight());
    }

    int GetWidth() const
    {
        return (_max[0] - _min[0]) + 1;
    }

    int GetHeight() const
    {
        return (_max[1] - _min[1]) + 1;
    }

    GfRect2i GetIntersection(const GfRect2i& that) const
    {
        if (IsEmpty())
            return *this;
        else if (that.IsEmpty())
            return that;
        else
            return GfRect2i(GfVec2i(GfMax(_min[0], that._min[0]), GfMax(_min[1], that._min[1])),
                            GfVec2i(GfMin(_max[0], that._max[0]), GfMin(_max[1], that._max[1])));
    }

    GfRect2i Intersect(const GfRect2i& that) const
    {
        return GetIntersection(that);
    }

    GfRect2i GetUnion(const GfRect2i& that) const
    {
        if (IsEmpty())
            return that;
        else if (that.IsEmpty())
            return *this;
        else
            return GfRect2i(GfVec2i(GfMin(_min[0], that._min[0]), GfMin(_min[1], that._min[1])),
                            GfVec2i(GfMax(_max[0], that._max[0]), GfMax(_max[1], that._max[1])));
    }

    GfRect2i Union(const GfRect2i& that) const
    {
        return GetUnion(that);
    }

    bool Contains(const GfVec2i& p) const
    {
        return ((p[0] >= _min[0]) && (p[0] <= _max[0]) && (p[1] >= _min[1]) && (p[1] <= _max[1]));
    }

    friend bool operator==(const GfRect2i& r1, const GfRect2i& r2)
    {
        return r1._min == r2._min && r1._max == r2._max;
    }

    friend bool operator!=(const GfRect2i& r1, const GfRect2i& r2)
    {
        return !(r1 == r2);
    }

    GfRect2i operator+=(const GfRect2i& that)
    {
        *this = GetUnion(that);
        return *this;
    }

    friend GfRect2i operator+(const GfRect2i r1, const GfRect2i& r2)
    {
        GfRect2i tmp(r1);
        tmp += r2;
        return tmp;
    }

private:
    GfVec2i _min = { 0, 0 };
    GfVec2i _max = { -1, -1 };
};

}