Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tgeometry.h"
Rozhuk Ivan 823a31
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const T3DPointD TConsts::nap3d((numeric_limits<double>::max)(),</double>
Shinya Kitaoka 120a6e
                               (numeric_limits<double>::max)(),</double>
Shinya Kitaoka 120a6e
                               (numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const TThickPoint TConsts::natp((numeric_limits<double>::max)(),</double>
Shinya Kitaoka 120a6e
                                (numeric_limits<double>::max)(),</double>
Shinya Kitaoka 120a6e
                                (numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const TPointD TConsts::napd((numeric_limits<double>::max)(),</double>
Shinya Kitaoka 120a6e
                            (numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const TPointI TConsts::nap((numeric_limits<int>::max)(),</int>
Shinya Kitaoka 120a6e
                           (numeric_limits<int>::max)());</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const TRectD TConsts::infiniteRectD(-(numeric_limits<double>::max)(),</double>
Shinya Kitaoka 120a6e
                                    -(numeric_limits<double>::max)(),</double>
Shinya Kitaoka 120a6e
                                    (numeric_limits<double>::max)(),</double>
Shinya Kitaoka 120a6e
                                    (numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const TRectI TConsts::infiniteRectI(-(numeric_limits<int>::max)(),</int>
Shinya Kitaoka 120a6e
                                    -(numeric_limits<int>::max)(),</int>
Shinya Kitaoka 120a6e
                                    (numeric_limits<int>::max)(),</int>
Shinya Kitaoka 120a6e
                                    (numeric_limits<int>::max)());</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// operazioni fra affini
Shinya Kitaoka 120a6e
TAffine &TAffine::operator=(const TAffine &a) {
Shinya Kitaoka 120a6e
  a11 = a.a11;
Shinya Kitaoka 120a6e
  a12 = a.a12;
Shinya Kitaoka 120a6e
  a13 = a.a13;
Shinya Kitaoka 120a6e
  a21 = a.a21;
Shinya Kitaoka 120a6e
  a22 = a.a22;
Shinya Kitaoka 120a6e
  a23 = a.a23;
Shinya Kitaoka 120a6e
  return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
TAffine TAffine::operator*(const TAffine &b) const {
Shinya Kitaoka 120a6e
  return TAffine(a11 * b.a11 + a12 * b.a21, a11 * b.a12 + a12 * b.a22,
Shinya Kitaoka 120a6e
                 a11 * b.a13 + a12 * b.a23 + a13,
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
                 a21 * b.a11 + a22 * b.a21, a21 * b.a12 + a22 * b.a22,
Shinya Kitaoka 120a6e
                 a21 * b.a13 + a22 * b.a23 + a23);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
TAffine TAffine::operator*=(const TAffine &b) { return *this = *this * b; }
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
TAffine TAffine::inv() const {
Shinya Kitaoka 120a6e
  if (a12 == 0.0 && a21 == 0.0) {
manongjohn 54e85d
    double inv_a11 =
manongjohn 54e85d
        (a11 == 0.0 ? std::numeric_limits<double>::max() / (1 << 16)</double>
manongjohn 54e85d
                    : 1.0 / a11);
manongjohn 54e85d
    double inv_a22 =
manongjohn 54e85d
        (a22 == 0.0 ? std::numeric_limits<double>::max() / (1 << 16)</double>
manongjohn 54e85d
                    : 1.0 / a22);
Shinya Kitaoka 120a6e
    return TAffine(inv_a11, 0, -a13 * inv_a11, 0, inv_a22, -a23 * inv_a22);
Shinya Kitaoka 120a6e
  } else if (a11 == 0.0 && a22 == 0.0) {
Shinya Kitaoka 120a6e
    assert(a12 != 0.0);
Shinya Kitaoka 120a6e
    assert(a21 != 0.0);
manongjohn 54e85d
    double inv_a21 =
manongjohn 54e85d
        (a21 == 0.0 ? std::numeric_limits<double>::max() / (1 << 16)</double>
manongjohn 54e85d
                    : 1.0 / a21);
manongjohn 54e85d
    double inv_a12 =
manongjohn 54e85d
        (a12 == 0.0 ? std::numeric_limits<double>::max() / (1 << 16)</double>
manongjohn 54e85d
                    : 1.0 / a12);
Shinya Kitaoka 120a6e
    return TAffine(0, inv_a21, -a23 * inv_a21, inv_a12, 0, -a13 * inv_a12);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    double d = 1. / det();
Shinya Kitaoka 120a6e
    return TAffine(a22 * d, -a12 * d, (a12 * a23 - a22 * a13) * d, -a21 * d,
Shinya Kitaoka 120a6e
                   a11 * d, (a21 * a13 - a11 * a23) * d);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
double TAffine::det() const { return a11 * a22 - a12 * a21; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Confronti tra affini
Shinya Kitaoka 120a6e
bool TAffine::operator==(const TAffine &a) const {
Shinya Kitaoka 120a6e
  return a11 == a.a11 && a12 == a.a12 && a13 == a.a13 && a21 == a.a21 &&
Shinya Kitaoka 120a6e
         a22 == a.a22 && a23 == a.a23;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
bool TAffine::operator!=(const TAffine &a) const {
Shinya Kitaoka 120a6e
  return a11 != a.a11 || a12 != a.a12 || a13 != a.a13 || a21 != a.a21 ||
Shinya Kitaoka 120a6e
         a22 != a.a22 || a23 != a.a23;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
bool TAffine::isIdentity(double err) const {
Shinya Kitaoka 120a6e
  return ((a11 - 1.0) * (a11 - 1.0) + (a22 - 1.0) * (a22 - 1.0) + a12 * a12 +
9a49d4
          a13 * a13 + a21 * a21 + a23 * a23) <+ err;
9a49d4
}
9a49d4
//--------------------------------------------------------------------------------------------------
9a49d4
bool TAffine::isZero(double err) const {
9a49d4
  return ( a11*a11 + a12*a12 + a13*a13 +
9a49d4
           a21*a21 + a22*a22 + a23*a23 ) <= err;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
bool TAffine::isTranslation(double err) const {
Shinya Kitaoka 120a6e
  return ((a11 - 1.0) * (a11 - 1.0) + (a22 - 1.0) * (a22 - 1.0) + a12 * a12 +
9a49d4
          a21 * a21) <= err;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
bool TAffine::isIsotropic(double err) const {
Shinya Kitaoka 120a6e
  return areAlmostEqual(a11, a22, err) && areAlmostEqual(a12, -a21, err);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// applicazione
Shinya Kitaoka 120a6e
TPointD TAffine::operator*(const TPointD &p) const {
Shinya Kitaoka 120a6e
  return TPointD(p.x * a11 + p.y * a12 + a13, p.x * a21 + p.y * a22 + a23);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
f9b4ad
TPointD TAffine::transformDirection(const TPointD &p) const {
f9b4ad
  return TPointD(p.x * a11 + p.y * a12, p.x * a21 + p.y * a22);
f9b4ad
}
f9b4ad
f9b4ad
//--------------------------------------------------------------------------------------------------
f9b4ad
Shinya Kitaoka 120a6e
TRectD TAffine::operator*(const TRectD &rect) const {
Shinya Kitaoka 120a6e
  if (rect != TConsts::infiniteRectD) {
Shinya Kitaoka 120a6e
    TPointD p1 = *this * rect.getP00(), p2 = *this * rect.getP01(),
Shinya Kitaoka 120a6e
            p3 = *this * rect.getP10(), p4 = *this * rect.getP11();
Shinya Kitaoka 120a6e
    return TRectD(
Shinya Kitaoka 120a6e
        std::min({p1.x, p2.x, p3.x, p4.x}), std::min({p1.y, p2.y, p3.y, p4.y}),
Shinya Kitaoka 120a6e
        std::max({p1.x, p2.x, p3.x, p4.x}), std::max({p1.y, p2.y, p3.y, p4.y}));
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    return TConsts::infiniteRectD;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TAffine TAffine::place(double u, double v, double x, double y) const {
Shinya Kitaoka 120a6e
  return TAffine(a11, a12, x - (a11 * u + a12 * v), a21, a22,
Shinya Kitaoka 120a6e
                 y - (a21 * u + a22 * v));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TAffine TAffine::place(const TPointD &pIn, const TPointD &pOut) const {
Shinya Kitaoka 120a6e
  return TAffine(a11, a12, pOut.x - (a11 * pIn.x + a12 * pIn.y), a21, a22,
Shinya Kitaoka 120a6e
                 pOut.y - (a21 * pIn.x + a22 * pIn.y));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
9a49d4
//--------------------------------------------------------------------------------------------------
9a49d4
9a49d4
TAffine TAffine::rotation(double angle) {
9a49d4
  double s = sin(angle);
9a49d4
  double c = cos(angle);
9a49d4
  return TAffine(c, -s, 0, s, c, 0);
9a49d4
}
9a49d4
Toshihiro Shimizu 890ddd
//==================================================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRotation::TRotation(double degrees) {
Shinya Kitaoka 120a6e
  double rad, sn, cs;
Shinya Kitaoka 120a6e
  int idegrees = (int)degrees;
Shinya Kitaoka 120a6e
  if ((double)idegrees == degrees && idegrees % 90 == 0) {
Shinya Kitaoka 120a6e
    switch ((idegrees / 90) & 3) {
Shinya Kitaoka 120a6e
    case 0:
Shinya Kitaoka 120a6e
      sn = 0;
Shinya Kitaoka 120a6e
      cs = 1;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    case 1:
Shinya Kitaoka 120a6e
      sn = 1;
Shinya Kitaoka 120a6e
      cs = 0;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    case 2:
Shinya Kitaoka 120a6e
      sn = 0;
Shinya Kitaoka 120a6e
      cs = -1;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    case 3:
Shinya Kitaoka 120a6e
      sn = -1;
Shinya Kitaoka 120a6e
      cs = 0;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    default:
Shinya Kitaoka 120a6e
      sn = 0;
Shinya Kitaoka 120a6e
      cs = 0;
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    rad                         = degrees * M_PI_180;
Shinya Kitaoka 120a6e
    sn                          = sin(rad);
Shinya Kitaoka 120a6e
    cs                          = cos(rad);
Shinya Kitaoka 120a6e
    if (sn == 1 || sn == -1) cs = 0;
Shinya Kitaoka 120a6e
    if (cs == 1 || cs == -1) sn = 0;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  a11 = cs;
Shinya Kitaoka 120a6e
  a12 = -sn;
Shinya Kitaoka 120a6e
  a21 = -a12;
Shinya Kitaoka 120a6e
  a22 = a11;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
TRotation::TRotation(const TPointD ¢er, double degrees) {
Shinya Kitaoka 120a6e
  TAffine a = TTranslation(center) * TRotation(degrees) * TTranslation(-center);
Shinya Kitaoka 120a6e
  a11       = a.a11;
Shinya Kitaoka 120a6e
  a12       = a.a12;
Shinya Kitaoka 120a6e
  a13       = a.a13;
Shinya Kitaoka 120a6e
  a21       = a.a21;
Shinya Kitaoka 120a6e
  a22       = a.a22;
Shinya Kitaoka 120a6e
  a23       = a.a23;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==================================================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TScale::TScale(const TPointD ¢er, double sx, double sy) {
Shinya Kitaoka 120a6e
  TAffine a = TTranslation(center) * TScale(sx, sy) * TTranslation(-center);
Shinya Kitaoka 120a6e
  a11       = a.a11;
Shinya Kitaoka 120a6e
  a12       = a.a12;
Shinya Kitaoka 120a6e
  a13       = a.a13;
Shinya Kitaoka 120a6e
  a21       = a.a21;
Shinya Kitaoka 120a6e
  a22       = a.a22;
Shinya Kitaoka 120a6e
  a23       = a.a23;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------------
Shinya Kitaoka 120a6e
TScale::TScale(const TPointD ¢er, double s) {
Shinya Kitaoka 120a6e
  TAffine a = TTranslation(center) * TScale(s) * TTranslation(-center);
Shinya Kitaoka 120a6e
  a11       = a.a11;
Shinya Kitaoka 120a6e
  a12       = a.a12;
Shinya Kitaoka 120a6e
  a13       = a.a13;
Shinya Kitaoka 120a6e
  a21       = a.a21;
Shinya Kitaoka 120a6e
  a22       = a.a22;
Shinya Kitaoka 120a6e
  a23       = a.a23;
Toshihiro Shimizu 890ddd
}
f9b4ad
f9b4ad
//==================================================================================================
f9b4ad
f9b4ad
TPoint4D TAffine4::operator*(const TPoint4D &b) const {
f9b4ad
  return TPoint4D(
f9b4ad
    b.x*a11 + b.y*a21 + b.z*a31 + b.w*a41,
f9b4ad
    b.x*a12 + b.y*a22 + b.z*a32 + b.w*a42,
f9b4ad
    b.x*a13 + b.y*a23 + b.z*a33 + b.w*a43,
f9b4ad
    b.x*a14 + b.y*a24 + b.z*a34 + b.w*a44 );
f9b4ad
}
f9b4ad
f9b4ad
TAffine4 TAffine4::operator*(const TAffine4 &b) const {
f9b4ad
  return TAffine4(
f9b4ad
    *this * b.rowX(),
f9b4ad
    *this * b.rowY(),
f9b4ad
    *this * b.rowZ(),
f9b4ad
    *this * b.rowW() );
f9b4ad
}
f9b4ad
f9b4ad
TAffine4 TAffine4::operator*=(const TAffine4 &b)
f9b4ad
  { return *this = *this * b; }
f9b4ad
f9b4ad
TAffine4 TAffine4::inv() const {
f9b4ad
  TAffine4 r;
f9b4ad
  r.a11 = a22*(a33*a44 - a34*a43) + a23*(a34*a42 - a32*a44) + a24*(a32*a43 - a33*a42);
f9b4ad
  r.a12 = a21*(a34*a43 - a33*a44) + a23*(a31*a44 - a34*a41) + a24*(a33*a41 - a31*a43);
f9b4ad
  r.a13 = a21*(a32*a44 - a34*a42) + a22*(a34*a41 - a31*a44) + a24*(a31*a42 - a32*a41);
f9b4ad
  r.a14 = a21*(a33*a42 - a32*a43) + a22*(a31*a43 - a33*a41) + a23*(a32*a41 - a31*a42);
f9b4ad
f9b4ad
  double det = a11*r.a11 + a12*r.a21 + a13*r.a31 + a14*r.a41;
f9b4ad
  if (fabs(det) > TConsts::epsilon) det = 1.0/det;
f9b4ad
  r.a11 *= det;
f9b4ad
  r.a12 *= det;
f9b4ad
  r.a13 *= det;
f9b4ad
  r.a14 *= det;
f9b4ad
f9b4ad
  r.a21 = det*( a12*(a34*a43 - a33*a44) + a13*(a32*a44 - a34*a42) + a14*(a33*a42 - a32*a43) );
f9b4ad
  r.a22 = det*( a11*(a33*a44 - a34*a43) + a13*(a34*a41 - a31*a44) + a14*(a31*a43 - a33*a41) );
f9b4ad
  r.a23 = det*( a11*(a34*a42 - a32*a44) + a12*(a31*a44 - a34*a41) + a14*(a32*a41 - a31*a42) );
f9b4ad
  r.a24 = det*( a11*(a32*a43 - a33*a42) + a12*(a33*a41 - a31*a43) + a13*(a31*a42 - a32*a41) );
f9b4ad
  r.a31 = det*( a12*(a23*a44 - a24*a43) + a13*(a24*a42 - a22*a44) + a14*(a22*a43 - a23*a42) );
f9b4ad
  r.a32 = det*( a11*(a24*a43 - a23*a44) + a13*(a21*a44 - a24*a41) + a14*(a23*a41 - a21*a43) );
f9b4ad
  r.a33 = det*( a11*(a22*a44 - a24*a42) + a12*(a24*a41 - a21*a44) + a14*(a21*a42 - a22*a41) );
f9b4ad
  r.a34 = det*( a11*(a23*a42 - a22*a43) + a12*(a21*a43 - a23*a41) + a13*(a22*a41 - a21*a42) );
f9b4ad
  r.a41 = det*( a12*(a24*a33 - a23*a34) + a13*(a22*a34 - a24*a32) + a14*(a23*a32 - a22*a33) );
f9b4ad
  r.a42 = det*( a11*(a23*a34 - a24*a33) + a13*(a24*a31 - a21*a34) + a14*(a21*a33 - a23*a31) );
f9b4ad
  r.a43 = det*( a11*(a24*a32 - a22*a34) + a12*(a21*a34 - a24*a31) + a14*(a22*a31 - a21*a32) );
f9b4ad
  r.a44 = det*( a11*(a22*a33 - a23*a32) + a12*(a23*a31 - a21*a33) + a13*(a21*a32 - a22*a31) );
f9b4ad
f9b4ad
  return r;
f9b4ad
}
f9b4ad
f9b4ad
TAffine TAffine4::get2d(double z) const {
f9b4ad
  return TAffine(
f9b4ad
    a11, a21, z*a31 + a41,
f9b4ad
    a12, a22, z*a32 + a42 );
f9b4ad
}
f9b4ad
f9b4ad
TAffine4 TAffine4::translation(double x, double y, double z) {
f9b4ad
  TAffine4 r;
f9b4ad
  r.rowW().x = x;
f9b4ad
  r.rowW().y = y;
f9b4ad
  r.rowW().z = z;
f9b4ad
  return r;
f9b4ad
}
f9b4ad
f9b4ad
TAffine4 TAffine4::scale(double x, double y, double z) {
f9b4ad
  TAffine4 r;
f9b4ad
  r.a11 = x;
f9b4ad
  r.a22 = y;
f9b4ad
  r.a33 = z;
f9b4ad
  return r;
f9b4ad
}
f9b4ad
f9b4ad
TAffine4 TAffine4::rotation(double x, double y, double z, double angle) {
f9b4ad
  TAffine4 r;
16421e
  double k = x*x + y*y + z*z;
16421e
  if (k > TConsts::epsilon*TConsts::epsilon) {
16421e
	k = 1.0 / sqrt(k);
16421e
	double s = sin(angle);
f9b4ad
    double c = cos(angle);
f9b4ad
    double ic = 1.0 - c;
f9b4ad
    x *= k;
f9b4ad
    y *= k;
f9b4ad
    z *= k;
f9b4ad
f9b4ad
    r.a11 = ic*x*x + c;
f9b4ad
    r.a12 = ic*x*y + s*z;
f9b4ad
    r.a13 = ic*z*x - s*y;
f9b4ad
f9b4ad
    r.a21 = ic*x*y - s*z;
f9b4ad
    r.a22 = ic*y*y + c;
f9b4ad
    r.a23 = ic*y*z + s*x;
f9b4ad
f9b4ad
    r.a31 = ic*z*x + s*y;
f9b4ad
    r.a32 = ic*y*z - s*x;
f9b4ad
    r.a33 = ic*z*z + c;
f9b4ad
  }
f9b4ad
  return r;
f9b4ad
}
f9b4ad
f9b4ad
TAffine4 TAffine4::rotationX(double angle) {
f9b4ad
  TAffine4 r;
f9b4ad
  double s = sin(angle);
f9b4ad
  double c = cos(angle);
f9b4ad
  r.a22 =  c;
f9b4ad
  r.a23 =  s;
f9b4ad
  r.a32 = -s;
f9b4ad
  r.a33 =  c;
f9b4ad
  return r;
f9b4ad
}
f9b4ad
f9b4ad
TAffine4 TAffine4::rotationY(double angle) {
f9b4ad
  TAffine4 r;
f9b4ad
  double s = sin(angle);
f9b4ad
  double c = cos(angle);
f9b4ad
  r.a11 =  c;
f9b4ad
  r.a13 = -s;
f9b4ad
  r.a31 =  s;
f9b4ad
  r.a33 =  c;
f9b4ad
  return r;
f9b4ad
}
f9b4ad
f9b4ad
TAffine4 TAffine4::rotationZ(double angle) {
f9b4ad
  TAffine4 r;
f9b4ad
  double s = sin(angle);
f9b4ad
  double c = cos(angle);
f9b4ad
  r.a11 =  c;
f9b4ad
  r.a12 =  s;
f9b4ad
  r.a21 = -s;
f9b4ad
  r.a22 =  c;
f9b4ad
  return r;
f9b4ad
}
58525d
58525d
//==================================================================================================
58525d
58525d
int TAngleRangeSet::find(Type a) const {
58525d
  assert(!m_angles.empty());
58525d
  int i0 = 0, i1 = m_angles.size() - 1;
58525d
  if (a < m_angles[0]) return i1;
58525d
  if (m_angles[i1] <= a) return i1;
58525d
  while(true) {
58525d
    int i = (i1 + i0)/2;
58525d
    if (i == i0) break;
58525d
    if (m_angles[i] <= a) i0 = i; else i1 = i;
58525d
  }
58525d
  return i0;
58525d
}
58525d
58525d
void TAngleRangeSet::insert(Type a) {
812e8c
  if (m_angles.empty()) {
812e8c
    m_angles.push_back(a);
812e8c
  } else {
812e8c
    int i = find(a);
812e8c
    if (m_angles[i] == a)
812e8c
      m_angles.erase(m_angles.begin() + i);
812e8c
    else if (a < m_angles[0])
812e8c
      m_angles.insert(m_angles.begin(), a);
812e8c
    else
812e8c
      m_angles.insert(m_angles.begin() + i + 1, a);
812e8c
  }
58525d
}
58525d
812e8c
void TAngleRangeSet::doAdd(Type a0, Type a1) {
812e8c
  if (m_angles.empty()) {
812e8c
    if (!m_flip) set(a0, a1);
812e8c
    return;
812e8c
  }
812e8c
58525d
  int i0 = find(a0);
58525d
  int i1 = find(a1);
58525d
  if (i0 == i1) {
58525d
    bool visible = (i0%2 != 0) == m_flip;
58525d
    if (m_angles[i0] != a0 && m_angles[i0] - a0 <= a1 - a0) {
812e8c
      if (visible) fill(); else set(a0, a1);
58525d
    } else
58525d
    if (!visible) {
58525d
      if (a1 < a0) m_flip = true;
58525d
      insert(a0);
58525d
      insert(a1);
58525d
    }
812e8c
    return;
58525d
  }
58525d
58525d
  bool visible0 = (i0%2 != 0) == m_flip;
58525d
  bool visible1 = (i1%2 != 0) == m_flip;
58525d
58525d
  // remove range (i0, i1]
58525d
  i0 = (i0 + 1)%m_angles.size();
58525d
  if (i1 < i0) {
58525d
    m_angles.erase(m_angles.begin() + i0, m_angles.end());
58525d
    m_angles.erase(m_angles.begin(), m_angles.begin() + i1 + 1);
58525d
  } else {
58525d
    m_angles.erase(m_angles.begin() + i0, m_angles.begin() + i1 + 1);
58525d
  }
58525d
58525d
  // insert new angles if need
58525d
  if (!visible0) insert(a0);
58525d
  if (!visible1) insert(a1);
812e8c
  if (m_angles.empty() || a1 < a0)
812e8c
    m_flip = true;
58525d
}
58525d
58525d
bool TAngleRangeSet::contains(Type a) const {
58525d
  if (isEmpty()) return false;
58525d
  if (isFull()) return true;
58525d
  return (find(a)%2 != 0) == m_flip;
58525d
}
58525d
58525d
bool TAngleRangeSet::check() const {
58525d
  if (m_angles.size() % 2 != 0)
58525d
    return false;
58525d
  for(int i = 1; i < (int)m_angles.size(); ++i)
58525d
    if (m_angles[i-1] >= m_angles[i])
58525d
      return false;
58525d
  return true;
58525d
}
58525d
58525d
void TAngleRangeSet::set(Type a0, Type a1) {
58525d
  m_angles.clear();
58525d
  if (a0 < a1) {
58525d
    m_flip = false;
58525d
    m_angles.push_back(a0);
58525d
    m_angles.push_back(a1);
58525d
  } else
58525d
  if (a0 > a1) {
58525d
    m_flip = true;
58525d
    m_angles.push_back(a1);
58525d
    m_angles.push_back(a0);
58525d
  } else {
58525d
    m_flip = true;
58525d
  }
58525d
}
58525d
ac9bac
void TAngleRangeSet::set(const TAngleRangeSet &x, bool flip) {
58525d
  if (&x == this) return;
58525d
  m_flip = (x.isFlipped() != flip);
58525d
  m_angles = x.angles();
58525d
}
58525d
58525d
void TAngleRangeSet::invert(Type a0, Type a1) {
58525d
  if (a0 == a1) return;
58525d
  if (isEmpty()) { set(a0, a1); return; }
58525d
  if (isFull()) { set(a1, a0); return; }
58525d
  if (a1 < a0) m_flip = !m_flip;
58525d
  insert(a0);
58525d
  insert(a1);
58525d
}
58525d
58525d
void TAngleRangeSet::invert(const TAngleRangeSet &x) {
58525d
  if (x.isEmpty()) { return; }
58525d
  if (x.isFull()) { invert(); return; }
58525d
  if (isEmpty()) { set(x); return; }
58525d
  if (isFull()) { set(x, true); return; }
58525d
  m_flip = m_flip != x.isFlipped();
58525d
  for(List::const_iterator i = x.angles().begin(); i != x.angles().end(); ++i)
58525d
    insert(*i);
58525d
}
58525d
58525d
void TAngleRangeSet::add(Type a0, Type a1) {
58525d
  if (!isFull() && a0 != a1)
58525d
    { if (isEmpty()) set(a0, a1); else doAdd(a0, a1); }
58525d
}
58525d
58525d
void TAngleRangeSet::add(const TAngleRangeSet &x) {
58525d
  if (&x == this || isFull() || x.isEmpty()) return;
58525d
  if (isEmpty()) { set(x); return; }
58525d
  if (x.isFull()) { fill(); return; }
812e8c
  for (Iterator i(x); i && !isFull(); ++i)
812e8c
    doAdd(i.a0(), i.a1());
58525d
}
58525d
58525d
void TAngleRangeSet::subtract(Type a0, Type a1) {
58525d
  if (!isEmpty() && a0 != a1) {
58525d
    if (isFull()) set(a1, a0); else
58525d
      { invert(); doAdd(a0, a1); invert(); }
58525d
  }
58525d
}
58525d
58525d
void TAngleRangeSet::subtract(const TAngleRangeSet &x) {
58525d
  if (isEmpty() || x.isEmpty()) return;
58525d
  if (&x == this || x.isFull()) { clear(); return; }
58525d
  if (isFull()) { set(x); invert(); return; }
58525d
58525d
  // a - b = !(!a + b)
58525d
  invert();
812e8c
  for (Iterator i(x); i && !isFull(); ++i)
812e8c
    doAdd(i.a0(), i.a1());
58525d
  invert();
58525d
}
58525d
58525d
void TAngleRangeSet::intersect(Type a0, Type a1) {
58525d
  if (!isEmpty()) {
58525d
    if (a0 == a1) clear(); else
58525d
      if (isFull()) set(a0, a1); else
58525d
        { invert(); doAdd(a1, a0); invert(); }
58525d
  }
58525d
}
58525d
58525d
void TAngleRangeSet::intersect(const TAngleRangeSet &x) {
58525d
  if (&x == this || isEmpty() || x.isFull()) return;
58525d
  if (x.isEmpty()) { clear(); return; }
58525d
  if (isFull()) { set(x); return; }
58525d
ac9bac
  // a & b = !(!a + !b)
58525d
  invert();
812e8c
  for (Iterator i(x, true); i && !isFull(); ++i)
812e8c
    doAdd(i.a0(), i.a1());
58525d
  invert();
58525d
}