#ifndef TOONZ_PLUGIN_HELPER_RECT_H__
#define TOONZ_PLUGIN_HELPER_RECT_H__
#include <algorithm>
#include <cmath>
#include <cfloat>
class ToonzRect
{
public:
double x0, y0;
double x1, y1;
ToonzRect()
: x0(0), y0(0), x1(0), y1(0) {}
ToonzRect(double x0, double y0, double x1, double y1)
: x0(x0), y0(y0), x1(x1), y1(y1) {}
ToonzRect(const ToonzRect &toonzRect)
: x0(toonzRect.x0), y0(toonzRect.y0), x1(toonzRect.x1), y1(toonzRect.y1) {}
bool equals(double a, double b, double err = DBL_EPSILON) const
{
return fabs(a - b) < err;
}
ToonzRect operator+(const ToonzRect &toonzRect) const;
ToonzRect operator*(const ToonzRect &toonzRect) const;
ToonzRect &operator+=(const ToonzRect &toonzRect);
ToonzRect &operator*=(const ToonzRect &toonzRect);
bool operator==(const ToonzRect &toonzRect) const;
bool isEmpty() const;
bool isContained(const ToonzRect &toonzRect) const;
bool isOverlapped(const ToonzRect &toonzRect) const;
ToonzRect enlarge(double x, double y) const;
};
ToonzRect ToonzRect::operator+(const ToonzRect &toonzRect) const
{
if (isEmpty()) {
return toonzRect;
} else if (toonzRect.isEmpty()) {
return *this;
}
return ToonzRect(std::min(x0, toonzRect.x0), std::min(y0, toonzRect.y0),
std::max(x1, toonzRect.x1), std::max(y1, toonzRect.y1));
}
ToonzRect ToonzRect::operator*(const ToonzRect &toonzRect) const
{
if (isEmpty() ||
toonzRect.isEmpty() ||
toonzRect.x1 < x0 ||
x1 < toonzRect.x0 ||
toonzRect.y1 < y0 ||
y1 < toonzRect.y0) {
return ToonzRect();
}
return ToonzRect(std::max(x0, toonzRect.x0), std::max(y0, toonzRect.y0),
std::min(x1, toonzRect.x1), std::min(y1, toonzRect.y1));
}
ToonzRect &ToonzRect::operator+=(const ToonzRect &toonzRect)
{
return *this = *this + toonzRect;
}
ToonzRect &ToonzRect::operator*=(const ToonzRect &toonzRect)
{
return *this = *this * toonzRect;
}
bool ToonzRect::operator==(const ToonzRect &toonzRect) const
{
return equals(x0, toonzRect.x0) &&
equals(y0, toonzRect.y0) &&
equals(x1, toonzRect.x1) &&
equals(y1, toonzRect.y1);
}
bool ToonzRect::isEmpty() const
{
if ((equals(x0, x1) && equals(y0, y1)) ||
x0 > x1 ||
y0 > y1) {
return true;
}
return false;
}
bool ToonzRect::isContained(const ToonzRect &toonzRect) const
{
return toonzRect.x0 <= x0 && x1 <= toonzRect.x1 &&
toonzRect.y0 <= y0 && y1 <= toonzRect.y1;
}
bool ToonzRect::isOverlapped(const ToonzRect &toonzRect) const
{
return x0 <= toonzRect.x1 && x1 >= toonzRect.x0 &&
y0 <= toonzRect.y1 && y1 >= toonzRect.y0;
}
ToonzRect ToonzRect::enlarge(double x, double y) const
{
if (isEmpty()) {
return *this;
}
return ToonzRect(x0 - x, y0 - y, x1 + x, y1 + y);
}
class ToonzPoint
{
public:
double x, y;
ToonzPoint() : x(0), y(0) {}
ToonzPoint(double x, double y) : x(x), y(y) {}
};
#endif