|
roentgen |
edd579 |
#ifndef TOONZ_PLUGIN_HELPER_UTILS_AFFINE_HPP__
|
|
roentgen |
edd579 |
#define TOONZ_PLUGIN_HELPER_UTILS_AFFINE_HPP__
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <cmath></cmath>
|
|
Toshihiro Shimizu |
890ddd |
#include <cfloat></cfloat>
|
|
Toshihiro Shimizu |
890ddd |
#include <cassert></cassert>
|
|
roentgen |
edd579 |
#include <toonz_hostif.h></toonz_hostif.h>
|
|
roentgen |
edd579 |
#include "rect.hpp"
|
|
roentgen |
edd579 |
|
|
Toshihiro Shimizu |
890ddd |
class ToonzAffine
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
double a11, a12, a13;
|
|
Toshihiro Shimizu |
890ddd |
double a21, a22, a23;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine() : a11(1), a12(0), a13(0), a21(0), a22(1), a23(0) {}
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine(double a11, double a12, double a13,
|
|
Toshihiro Shimizu |
890ddd |
double a21, double a22, double a23)
|
|
Toshihiro Shimizu |
890ddd |
: a11(a11), a12(a12), a13(a13), a21(a21), a22(a22), a23(a23) {}
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine(const toonz_affine_t &affine) : a11(affine.a11), a12(affine.a12), a13(affine.a13), a21(affine.a21), a22(affine.a22), a23(affine.a23) {}
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine(const ToonzAffine &toonzAffine)
|
|
Toshihiro Shimizu |
890ddd |
: a11(toonzAffine.a11), a12(toonzAffine.a12), a13(toonzAffine.a13),
|
|
Toshihiro Shimizu |
890ddd |
a21(toonzAffine.a21), a22(toonzAffine.a22), a23(toonzAffine.a23) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static bool equals(double a, double b, double err = 1e-9)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return std::abs(a - b) < err;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine operator*(const ToonzAffine &toonzAffine) const;
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine &operator=(const ToonzAffine &toonzAffine);
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine &operator*=(const ToonzAffine &toonzAffine);
|
|
Toshihiro Shimizu |
890ddd |
bool operator==(const ToonzAffine &toonzAffine) const;
|
|
Toshihiro Shimizu |
890ddd |
bool operator!=(const ToonzAffine &toonzAffine) const;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzPoint operator*(const ToonzPoint &p) const;
|
|
Toshihiro Shimizu |
890ddd |
ToonzRect operator*(const ToonzRect &p) const;
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine inv() const;
|
|
Toshihiro Shimizu |
890ddd |
double det() const;
|
|
Toshihiro Shimizu |
890ddd |
bool isIdentity(double err = 1e-9) const;
|
|
Toshihiro Shimizu |
890ddd |
bool isTranslation(double err = 1e-9) const;
|
|
Toshihiro Shimizu |
890ddd |
bool isIsotropic(double err = 1e-9) const;
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine place(double u, double v, double x, double y) const;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline ToonzPoint ToonzAffine::operator*(const ToonzPoint &pt) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return ToonzPoint(pt.x * a11 + pt.y * a12 + a13, pt.x * a21 + pt.y * a22 + a23);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline ToonzRect ToonzAffine::operator*(const ToonzRect &r) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (r.x0 == -std::numeric_limits<double>::max() ||</double>
|
|
Toshihiro Shimizu |
890ddd |
r.y0 == -std::numeric_limits<double>::max() ||</double>
|
|
Toshihiro Shimizu |
890ddd |
r.x1 == std::numeric_limits<double>::max() ||</double>
|
|
Toshihiro Shimizu |
890ddd |
r.y1 == std::numeric_limits<double>::max())</double>
|
|
Toshihiro Shimizu |
890ddd |
return ToonzRect(-std::numeric_limits<double>::max(), -std::numeric_limits<double>::max(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max());</double></double></double></double>
|
|
Toshihiro Shimizu |
890ddd |
ToonzPoint p0 = this->operator*(ToonzPoint(r.x0, r.y0));
|
|
Toshihiro Shimizu |
890ddd |
ToonzPoint p1 = this->operator*(ToonzPoint(r.x1, r.y0));
|
|
Toshihiro Shimizu |
890ddd |
ToonzPoint p2 = this->operator*(ToonzPoint(r.x0, r.y1));
|
|
Toshihiro Shimizu |
890ddd |
ToonzPoint p3 = this->operator*(ToonzPoint(r.x1, r.y1));
|
|
Toshihiro Shimizu |
890ddd |
return ToonzRect(std::min(std::min(p0.x, p1.x), std::min(p2.x, p3.x)), std::min(std::min(p0.y, p1.y), std::min(p2.y, p3.y)),
|
|
Toshihiro Shimizu |
890ddd |
std::max(std::max(p0.x, p1.x), std::max(p2.x, p3.x)), std::max(std::max(p0.y, p1.y), std::max(p2.y, p3.y)));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine ToonzAffine::operator*(const ToonzAffine &toonzAffine) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return ToonzAffine(
|
|
Toshihiro Shimizu |
890ddd |
a11 * toonzAffine.a11 + a12 * toonzAffine.a21,
|
|
Toshihiro Shimizu |
890ddd |
a11 * toonzAffine.a12 + a12 * toonzAffine.a22,
|
|
Toshihiro Shimizu |
890ddd |
a11 * toonzAffine.a13 + a12 * toonzAffine.a23 + a13,
|
|
Toshihiro Shimizu |
890ddd |
a21 * toonzAffine.a11 + a22 * toonzAffine.a21,
|
|
Toshihiro Shimizu |
890ddd |
a21 * toonzAffine.a12 + a22 * toonzAffine.a22,
|
|
Toshihiro Shimizu |
890ddd |
a21 * toonzAffine.a13 + a22 * toonzAffine.a23 + a23);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine &ToonzAffine::operator=(const ToonzAffine &toonzAffine)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
a11 = toonzAffine.a11;
|
|
Toshihiro Shimizu |
890ddd |
a12 = toonzAffine.a12;
|
|
Toshihiro Shimizu |
890ddd |
a13 = toonzAffine.a13;
|
|
Toshihiro Shimizu |
890ddd |
a21 = toonzAffine.a21;
|
|
Toshihiro Shimizu |
890ddd |
a22 = toonzAffine.a22;
|
|
Toshihiro Shimizu |
890ddd |
a23 = toonzAffine.a23;
|
|
Toshihiro Shimizu |
890ddd |
return *this;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine &ToonzAffine::operator*=(const ToonzAffine &toonzAffine)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return *this = *this * toonzAffine;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool ToonzAffine::operator==(const ToonzAffine &toonzAffine) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return equals(a11, toonzAffine.a11) && equals(a12, toonzAffine.a12) &&
|
|
Toshihiro Shimizu |
890ddd |
equals(a13, toonzAffine.a13) && equals(a21, toonzAffine.a21) &&
|
|
Toshihiro Shimizu |
890ddd |
equals(a22, toonzAffine.a22) && equals(a23, toonzAffine.a23);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool ToonzAffine::operator!=(const ToonzAffine &toonzAffine) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return !(*this == toonzAffine);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine ToonzAffine::inv() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (equals(a12, 0.0) && equals(a21, 0.0)) {
|
|
Toshihiro Shimizu |
890ddd |
assert(!equals(a11, 0.0, DBL_EPSILON));
|
|
Toshihiro Shimizu |
890ddd |
assert(!equals(a22, 0.0, DBL_EPSILON));
|
|
Toshihiro Shimizu |
890ddd |
double inv_a11 = 1.0 / a11;
|
|
Toshihiro Shimizu |
890ddd |
double inv_a22 = 1.0 / a22;
|
|
Toshihiro Shimizu |
890ddd |
return ToonzAffine(
|
|
Toshihiro Shimizu |
890ddd |
inv_a11, 0.0, -a13 * inv_a11,
|
|
Toshihiro Shimizu |
890ddd |
0.0, inv_a22, -a23 * inv_a22);
|
|
Toshihiro Shimizu |
890ddd |
} else if (equals(a11, 0.0) && equals(a22, 0.0)) {
|
|
Toshihiro Shimizu |
890ddd |
assert(!equals(a12, 0.0, DBL_EPSILON));
|
|
Toshihiro Shimizu |
890ddd |
assert(!equals(a21, 0.0, DBL_EPSILON));
|
|
Toshihiro Shimizu |
890ddd |
double inv_a21 = 1.0 / a21;
|
|
Toshihiro Shimizu |
890ddd |
double inv_a12 = 1.0 / a12;
|
|
Toshihiro Shimizu |
890ddd |
return ToonzAffine(
|
|
Toshihiro Shimizu |
890ddd |
0.0, inv_a21, -a23 * inv_a21,
|
|
Toshihiro Shimizu |
890ddd |
inv_a12, 0.0, -a13 * inv_a12);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
double inv_det = 1.0 / det();
|
|
Toshihiro Shimizu |
890ddd |
return ToonzAffine(
|
|
Toshihiro Shimizu |
890ddd |
a22 * inv_det, -a12 * inv_det, (a12 * a23 - a22 * a13) * inv_det,
|
|
Toshihiro Shimizu |
890ddd |
-a21 * inv_det, a11 * inv_det, (a21 * a13 - a11 * a23) * inv_det);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double ToonzAffine::det() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return a11 * a22 - a12 * a21;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool ToonzAffine::isIdentity(double err) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double value =
|
|
Toshihiro Shimizu |
890ddd |
(a11 - 1.0) * (a11 - 1.0) +
|
|
Toshihiro Shimizu |
890ddd |
(a22 - 1.0) * (a22 - 1.0) +
|
|
Toshihiro Shimizu |
890ddd |
a12 * a12 + a13 * a13 +
|
|
Toshihiro Shimizu |
890ddd |
a21 * a21 + a23 * a23;
|
|
Toshihiro Shimizu |
890ddd |
return value < err;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool ToonzAffine::isTranslation(double err) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double value =
|
|
Toshihiro Shimizu |
890ddd |
(a11 - 1.0) * (a11 - 1.0) +
|
|
Toshihiro Shimizu |
890ddd |
(a22 - 1.0) * (a22 - 1.0) +
|
|
Toshihiro Shimizu |
890ddd |
a12 * a12 + a21 * a21;
|
|
Toshihiro Shimizu |
890ddd |
return value < err;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool ToonzAffine::isIsotropic(double err) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (equals(a11, a22, err) && equals(a12, -a21, err)) {
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ToonzAffine ToonzAffine::place(double u, double v, double x, double y) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return ToonzAffine(
|
|
Toshihiro Shimizu |
890ddd |
a11, a12, x - (a11 * u + a12 * v),
|
|
Toshihiro Shimizu |
890ddd |
a21, a22, y - (a21 * u + a22 * v));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|