diff --git a/toonz/sources/common/tgeometry/tgeometry.cpp b/toonz/sources/common/tgeometry/tgeometry.cpp index 5844316..ec1f3ae 100644 --- a/toonz/sources/common/tgeometry/tgeometry.cpp +++ b/toonz/sources/common/tgeometry/tgeometry.cpp @@ -235,8 +235,8 @@ TScale::TScale(const TPointD ¢er, double s) { //================================================================================================== -TPoint3D TAffine3::operator*(const TPoint3D &b) const { - return TPoint3D( +T3DPointD TAffine3::operator*(const T3DPointD &b) const { + return T3DPointD( b.x*a11 + b.y*a21 + b.z*a31, b.x*a12 + b.y*a22 + b.z*a32, b.x*a13 + b.y*a23 + b.z*a33 ); @@ -306,8 +306,8 @@ TAffine3 TAffine3::rotation2d(double angle) { //================================================================================================== -TPoint4D TAffine4::operator*(const TPoint4D &b) const { - return TPoint4D( +T4DPointD TAffine4::operator*(const T4DPointD &b) const { + return T4DPointD( b.x*a11 + b.y*a21 + b.z*a31 + b.w*a41, b.x*a12 + b.y*a22 + b.z*a32 + b.w*a42, b.x*a13 + b.y*a23 + b.z*a33 + b.w*a43, @@ -363,9 +363,9 @@ TAffine TAffine4::get2d(double z) const { TAffine3 TAffine4::get2dPersp(double z) const { return TAffine3( - TPoint3D( a11 , a12 , a14 ), - TPoint3D( a21 , a22 , a24 ), - TPoint3D( a31*z+a41 , a32*z+a42 , a34*z+a44 ) ); + T3DPointD( a11 , a12 , a14 ), + T3DPointD( a21 , a22 , a24 ), + T3DPointD( a31*z+a41 , a32*z+a42 , a34*z+a44 ) ); } TAffine4 TAffine4::translation(double x, double y, double z) { diff --git a/toonz/sources/include/tgeometry.h b/toonz/sources/include/tgeometry.h index 67eb0f5..bc0185b 100644 --- a/toonz/sources/include/tgeometry.h +++ b/toonz/sources/include/tgeometry.h @@ -26,8 +26,8 @@ inline double logNormalDistribuition(double x, double x0, double w) //============================================================================= -template class TPoint3T; -template class TPoint4T; +template class T3DPointT; +template class T4DPointT; /* * This is an example of how to use the TPointT, the TRectT and the TAffine @@ -41,175 +41,104 @@ public: T x, y; inline TPointT() : x(0), y(0){}; - inline TPointT(T _x, T _y) : x(_x), y(_y){}; - inline TPointT(const TPointT &point) : x(point.x), y(point.y){}; - inline explicit TPointT(const TPoint3T &point); - inline explicit TPointT(const TPoint4T &point); - - inline TPointT &operator=(const TPointT &a) { - x = a.x; - y = a.y; - return *this; - }; - - inline TPointT &operator+=(const TPointT &a) { - x += a.x; - y += a.y; - return *this; - }; - inline TPointT &operator-=(const TPointT &a) { - x -= a.x; - y -= a.y; - return *this; - }; - inline TPointT operator+(const TPointT &a) const { - return TPointT(x + a.x, y + a.y); - }; - inline TPointT operator-(const TPointT &a) const { - return TPointT(x - a.x, y - a.y); - }; - inline TPointT operator-() const { return TPointT(-x, -y); }; -}; - -template -class TPoint3T { -public: - union { - struct { T x, y, z; }; - T a[3]; - }; - - inline TPoint3T(): - x(), y(), z() { }; - inline TPoint3T(T x, T y, T z): - x(x), y(y), z(z) { }; - inline explicit TPoint3T(const TPointT &p, T z = (T)0): - x(p.x), y(p.y), z(z) { }; - inline explicit TPoint3T(const TPoint4T &point); -}; - -template -class TPoint4T { -public: - union { - struct { T x, y, z, w; }; - T a[4]; - }; + inline TPointT(T x, T y) : x(x), y(y){}; + inline explicit TPointT(const T3DPointT &p); + inline explicit TPointT(const T4DPointT &p); + + inline TPointT& operator+=(const TPointT &a) + { return x += a.x, y += a.y, *this; }; + inline TPointT& operator-=(const TPointT &a) + { return x -= a.x, y -= a.y, *this; }; + inline TPointT operator+(const TPointT &a) const + { return TPointT(x + a.x, y + a.y); }; + inline TPointT operator-(const TPointT &a) const + { return TPointT(x - a.x, y - a.y); }; + inline TPointT operator-() const + { return TPointT(-x, -y); }; + + //! Scalar(dot) Product + inline T operator*(const TPointT &a) const + { return x*a.x + y*a.y; } + + inline TPointT operator*=(T a) + { return x *= a, y *= a, *this; } + inline TPointT operator*(T a) const + { return TPointT(x*a, y*a); } + friend inline TPointT operator*(T a, const TPointT &b) + { return TPointT(a*b.x, a*b.y); } + + inline TPointT operator/(T a) const + { return TPointT(x/a, y/a); } + inline TPointT operator/=(T a) + { return x /= a, y /= a, *this; } + + inline bool operator==(const TPointT &a) const + { return x == a.x && y == a.y; } + inline bool operator!=(const TPointT &a) const + { return !(*this == a); } + + friend inline std::ostream &operator<<(std::ostream &out, const TPointT &p) + { return out << "(" << p.x << ", " << p.y << ")"; } + + /*! Rotate a point 90 degrees (counterclockwise). + \param p a point. + \return the rotated point + \sa rotate270 */ + friend inline TPointT rotate90(const TPointT &p) // 90 counterclockwise + { return TPointT(-p.y, p.x); } + + /*! Rotate a point 270 degrees (clockwise). + \param p a point. + \return the rotated point + \sa rotate90 */ + friend inline TPointT rotate270(const TPointT &p) // 90 clockwise + { return TPointT(p.y, -p.x); } + + //! This helper function returns the square of the absolute value of the point + friend inline T norm2(const TPointT &a) + { return a*a; } + + //! This helper function returns the square of the distance between two points + friend inline T tdistance2(const TPointT &a, const TPointT &b) + { return norm2(a - b); } - inline TPoint4T(): - x(), y(), z(), w() { }; - inline TPoint4T(T x, T y, T z, T w): - x(x), y(y), z(z), w(w) { }; - inline explicit TPoint4T(const TPointT &p, T z = (T)0, T w = (T)1): - x(p.x), y(p.y), z(z), w(w) { }; - inline explicit TPoint4T(const TPoint3T &p, T w = (T)1): - x(p.x), y(p.y), z(p.z), w(w) { }; + //! the cross product + friend inline T cross(const TPointT &a, const TPointT &b) + { return a.x*b.y - a.y*b.x; } }; -template -inline TPointT::TPointT(const TPoint3T &point) : x(point.x), y(point.y){}; -template -inline TPointT::TPointT(const TPoint4T &point) : x(point.x), y(point.y){}; -template -inline TPoint3T::TPoint3T(const TPoint4T &point) : x(point.x), y(point.y), z(point.z){}; - - -/*! \relates TPointT -* Rotate a point 90 degrees (counterclockwise). -\param p a point. -\return the rotated point -\sa rotate270 -*/ -template -inline TPointT rotate90(const TPointT &p) // 90 counterclockwise -{ - return TPointT(-p.y, p.x); -} -/*! \relates TPointT -* Rotate a point 270 degrees (clockwise). -\param p a point. -\return the rotated point -\sa rotate90 -*/ -template -inline TPointT rotate270(const TPointT &p) // 90 clockwise -{ - return TPointT(p.y, -p.x); -} - -/*! -\relates TPointT -*/ -template // Scalar(dot) Product -inline T operator*(const TPointT &a, const TPointT &b) { - return a.x * b.x + a.y * b.y; -} - -//----------------------------------------------------------------------------- +template <> +inline bool TPointT::operator==(const TPointT &a) const + { return tdistance2(*this, a) <= TConsts::epsilon * TConsts::epsilon; } -template -inline std::ostream &operator<<(std::ostream &out, const TPointT &p) { - return out << "(" << p.x << ", " << p.y << ")"; -} //----------------------------------------------------------------------------- typedef TPointT TPoint, TPointI; typedef TPointT TPointD; -typedef TPoint3T TPoint3D; -typedef TPoint4T TPoint4D; #ifdef _WIN32 template class DVAPI TPointT; template class DVAPI TPointT; #endif -template -inline bool operator==(const TPointT &p0, const TPointT &p1) { - return p0.x == p1.x && p0.y == p1.y; -} -template -inline bool operator!=(const TPointT &p0, const TPointT &p1) { - return p0.x != p1.x || p0.y != p1.y; -} //----------------------------------------------------------------------------- -//!\relates TPointT -inline TPoint operator*(int a, const TPoint &p) { - return TPoint(a * p.x, a * p.y); -} - -//!\relates TPointT -inline TPoint operator*(const TPoint &p, int a) { - return TPoint(a * p.x, a * p.y); -} - -//!\relates TPointT -inline TPointD operator*(double a, const TPointD &p) { - return TPointD(a * p.x, a * p.y); -} - -//!\relates TPointT -inline TPointD operator*(const TPointD &p, double a) { - return TPointD(a * p.x, a * p.y); -} - -//----------------------------------------------------------------------------- /*! \relates TPointT -This helper function returns the square of the absolute value of the specified -point (a TPointI) +This helper function converts a TPoint (TPointT) into a TPointD */ -inline int norm2(const TPointI &p) { return p.x * p.x + p.y * p.y; } +inline TPointD convert(const TPoint &p) + { return TPointD(p.x, p.y); } -//----------------------------------------------------------------------------- /*! \relates TPointT -This helper function returns the square of the absolute value of the specified -point (a TPointD) +This helper function converts a TPointD (TPointT) into a TPoint */ -inline double norm2(const TPointD &p) { return p.x * p.x + p.y * p.y; } +inline TPoint convert(const TPointD &p) + { return TPoint(tround(p.x), tround(p.y)); } + /*! \relates TPointT @@ -223,8 +152,8 @@ This helper function returns the normalized version of the specified point */ inline TPointD normalize(const TPointD &p) { double n = norm(p); - assert(n != 0.0); - return (1.0 / n) * p; + assert(n); + return p*(1/n); } /*! @@ -239,56 +168,10 @@ inline TPointD normalizeOrZero(const TPointD &p) { /*! \relates TPointT -This helper function converts a TPoint (TPointT) into a TPointD -*/ -inline TPointD convert(const TPoint &p) { return TPointD(p.x, p.y); } - -/*! -\relates TPointT -This helper function converts a TPointD (TPointT) into a TPoint -*/ -inline TPoint convert(const TPointD &p) { - return TPoint(tround(p.x), tround(p.y)); -} - -/*! -\relates TPointT -This helper function returns the square of the distance between two points -*/ -inline double tdistance2(const TPointD &p1, const TPointD &p2) { - return norm2(p2 - p1); -} - -inline bool operator==(const TPointD &p0, const TPointD &p1) { - return tdistance2(p0, p1) <= TConsts::epsilon * TConsts::epsilon; -} -inline bool operator!=(const TPointD &p0, const TPointD &p1) { - return !(p0 == p1); -} - -/*! -\relates TPointT This helper function returns the distance between two points */ -inline double tdistance(const TPointD &p1, const TPointD &p2) { - return norm(p2 - p1); -} - -/*! -the cross product -\relates TPointT -*/ -inline double cross(const TPointD &a, const TPointD &b) { - return a.x * b.y - a.y * b.x; -} - -/*! -the cross product -\relates TPoint -*/ -inline int cross(const TPoint &a, const TPoint &b) { - return a.x * b.y - a.y * b.x; -} +inline double tdistance(const TPointD &p1, const TPointD &p2) + { return norm(p2 - p1); } /*! returns the angle of the point p in polar coordinates @@ -303,59 +186,73 @@ class DVAPI T3DPointT { public: T x, y, z; - T3DPointT() : x(0), y(0), z(0) {} - - T3DPointT(T _x, T _y, T _z) : x(_x), y(_y), z(_z) {} - T3DPointT(const TPointT &_p, T _z) : x(_p.x), y(_p.y), z(_z) {} - - T3DPointT(const T3DPointT &_p) : x(_p.x), y(_p.y), z(_p.z) {} - - inline T3DPointT &operator=(const T3DPointT &a) { - x = a.x; - y = a.y; - z = a.z; - return *this; - } - - inline T3DPointT &operator+=(const T3DPointT &a) { - x += a.x; - y += a.y; - z += a.z; - return *this; - } - - inline T3DPointT &operator-=(const T3DPointT &a) { - x -= a.x; - y -= a.y; - z -= a.z; - return *this; - } - - inline T3DPointT operator+(const T3DPointT &a) const { - return T3DPointT(x + a.x, y + a.y, z + a.z); - } - - inline T3DPointT operator-(const T3DPointT &a) const { - return T3DPointT(x - a.x, y - a.y, z - a.z); - } - - inline T3DPointT operator-() const { return T3DPointT(-x, -y, -z); } - - bool operator==(const T3DPointT &p) const { - return x == p.x && y == p.y && z == p.z; - } - - bool operator!=(const T3DPointT &p) const { - return x != p.x || y != p.y || z != p.z; + inline T3DPointT() : x(), y(), z() {} + inline T3DPointT(T x, T y, T z) : x(x), y(y), z(z) {} + inline T3DPointT(const TPointT &p, T z) : x(p.x), y(p.y), z(z) {} + inline explicit T3DPointT(const T4DPointT &p); + + inline TPointT& xy() { return *(TPointT*)this; } + inline TPointT& xy() const { return *(const TPointT*)this; } + + inline T3DPointT &operator+=(const T3DPointT &a) + { return x += a.x, y += a.y, z += a.z, *this; } + inline T3DPointT &operator-=(const T3DPointT &a) + { return x -= a.x, y -= a.y, z -= a.z, *this; } + inline T3DPointT operator+(const T3DPointT &a) const + { return T3DPointT(x + a.x, y + a.y, z + a.z); } + inline T3DPointT operator-(const T3DPointT &a) const + { return T3DPointT(x - a.x, y - a.y, z - a.z); } + inline T3DPointT operator-() const + { return T3DPointT(-x, -y, -z); } + + //! Scalar(dot) Product + inline T operator*(const T3DPointT &a) const + { return x*a.x + y*a.y + z*a.z; } + + inline T3DPointT operator*=(T a) + { return x *= a, y *= a, z *= a, *this; } + inline T3DPointT operator*(T a) const + { return T3DPointT(x*a, y*a, z*a); } + friend inline T3DPointT operator*(T a, const T3DPointT &b) + { return T3DPointT(a*b.x, a*b.y, a*b.z); } + + inline T3DPointT operator/(T a) const + { return T3DPointT(x/a, y/a, z/a); } + inline T3DPointT operator/=(T a) + { return x /= a, y /= a, z /= a, *this; } + + inline bool operator==(const T3DPointT &a) const + { return x == a.x && y == a.y && z == a.z; } + inline bool operator!=(const T3DPointT &a) const + { return !(*this == a); } + + friend inline std::ostream &operator<<(std::ostream &out, const T3DPointT &p) + { return out << "(" << p.x << ", " << p.y << ", " << p.z << ")"; } + + //! This helper function returns the square of the absolute value of the point + friend inline T norm2(const T3DPointT &a) + { return a*a; } + + //! This helper function returns the square of the distance between two points + friend inline T tdistance2(const T3DPointT &a, const T3DPointT &b) + { return norm2(a - b); } + + //! the cross product + friend inline T3DPointT cross(const T3DPointT &a, const T3DPointT &b) { + return T3DPointT( a.y*b.z - b.y*a.z, + a.z*b.x - b.z*a.x, + a.x*b.y - b.x*a.y); } }; -//============================================================================= +template <> +inline bool T3DPointT::operator==(const T3DPointT &a) const + { return tdistance2(*this, a) <= TConsts::epsilon * TConsts::epsilon; } template -inline std::ostream &operator<<(std::ostream &out, const T3DPointT &p) { - return out << "(" << p.x << ", " << p.y << ", " << p.z << ")"; -} +inline TPointT::TPointT(const T3DPointT &p) : x(p.x), y(p.y) {}; + +//============================================================================= typedef T3DPointT T3DPoint, T3DPointI; typedef T3DPointT T3DPointD; @@ -367,72 +264,86 @@ template class DVAPI T3DPointT; //----------------------------------------------------------------------------- -//!\relates T3DPointT -template -inline T3DPointT operator*(T a, const T3DPointT &p) { - return T3DPointT(a * p.x, a * p.y, a * p.z); -} +inline T3DPointD convert(const T3DPoint &p) + { return T3DPointD(p.x, p.y, p.z); } +inline T3DPoint convert(const T3DPointD &p) + { return T3DPoint(tround(p.x), tround(p.y), tround(p.z)); } -//!\relates TPointT -template -inline T3DPointT operator*(const T3DPointT &p, T a) { - return T3DPointT(a * p.x, a * p.y, a * p.z); +inline double norm(const T3DPointD &p) + { return std::sqrt(norm2(p)); } + +inline T3DPointD normalize(const T3DPointD &p) { + double n = norm(p); + assert(n); + return p*(1/n); } -//----------------------------------------------------------------------------- -/*! -\relates TPointT -This helper function returns the square of the absolute value of the specified -point (a TPointI) -*/ -template -inline T norm2(const T3DPointT &p) { - return p.x * p.x + p.y * p.y + p.z * p.z; +inline T3DPointD normalizeOrZero(const T3DPointD &p) { + double n = norm2(p); + return fabs(n) > TConsts::epsilon*TConsts::epsilon ? p*(1/sqrt(n)) : T3DPointD(); } -/*! -*/ +inline double tdistance(const T3DPointD &p1, const T3DPointD &p2) + { return norm(p2 - p1); } + +//============================================================================= + template -inline T norm(const T3DPointT &p) { - return std::sqrt(norm2(p)); -} +class DVAPI T4DPointT { +public: + T x, y, z, w; -/*! -*/ -inline T3DPointD normalize(const T3DPointD &p) { - double n = norm(p); - assert(n != 0.0); - return (1.0 / n) * p; -} + inline T4DPointT() : x(), y(), z(), w() {} + inline T4DPointT(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {} + inline T4DPointT(const TPointT &p, T z, T w) : x(p.x), y(p.y), z(z), w(w) {} + inline T4DPointT(const T3DPointT &p, T w) : x(p.x), y(p.y), z(p.z), w(w) {} -/*! -*/ -inline T3DPointD convert(const T3DPoint &p) { return T3DPointD(p.x, p.y, p.z); } + inline TPointT& xy() { return *(TPointT*)this; } + inline T3DPointT& xyz() { return *(T3DPointT*)this; } -/*! -*/ -inline T3DPoint convert(const T3DPointD &p) { - return T3DPoint(tround(p.x), tround(p.y), tround(p.z)); -} + inline TPointT& xy() const { return *(const TPointT*)this; } + inline T3DPointT& xyz() const { return *(const T3DPointT*)this; } + + inline bool operator==(const T4DPointT &p) const + { return x == p.x && y == p.y && z == p.z && w == p.w; } + inline bool operator!=(const T4DPointT &p) const + { return !(*this == p); } + + friend inline std::ostream &operator<<(std::ostream &out, const T4DPointT &p) + { return out << "(" << p.x << ", " << p.y << ", " << p.z << ", " << p.w << ")"; } +}; -//! -template -inline T tdistance(const T3DPointT &p1, const T3DPointT &p2) { - return norm(p2 - p1); +template <> +inline bool T4DPointT::operator==(const T4DPointT &a) const { + T4DPointT d(x - a.x, y - a.y, z - a.z, w - a.w); + return d.x*d.x + d.y*d.y + d.z*d.z + d.w*d.w + <= TConsts::epsilon * TConsts::epsilon; } -//! template -inline T tdistance2(const T3DPointT &p1, const T3DPointT &p2) { - return norm2(p2 - p1); -} - -//! +inline TPointT::TPointT(const T4DPointT &p) : x(p.x), y(p.y) {}; template -inline T3DPointT cross(const T3DPointT &a, const T3DPointT &b) { - return T3DPointT(a.y * b.z - b.y * a.z, a.z * b.x - b.z * a.x, - a.x * b.y - b.x * a.y); -} +inline T3DPointT::T3DPointT(const T4DPointT &p) : x(p.x), y(p.y), z(p.z) {}; + +//============================================================================= + +typedef T4DPointT T4DPoint, T4DPointI; +typedef T4DPointT T4DPointD; + +#ifdef _WIN32 +template class DVAPI T4DPointT; +template class DVAPI T4DPointT; +#endif + +//----------------------------------------------------------------------------- + +//!\relates T4DPointT + +inline T4DPointD convert(const T4DPoint &p) + { return T4DPointD(p.x, p.y, p.z, p.w); } +inline T4DPoint convert(const T4DPointD &p) + { return T4DPoint(tround(p.x), tround(p.y), tround(p.z), tround(p.w)); } + //============================================================================= /*! TThickPoint describe a thick point. @@ -1321,28 +1232,28 @@ public: a31(a.a13), a32(a.a23), a33(1.0) { } inline TAffine3( - const TPoint3D &rowX, - const TPoint3D &rowY, - const TPoint3D &rowZ + const T3DPointD &rowX, + const T3DPointD &rowY, + const T3DPointD &rowZ ): a11(rowX.x), a12(rowX.y), a13(rowX.z), a21(rowY.x), a22(rowY.y), a23(rowY.z), a31(rowZ.x), a32(rowZ.y), a33(rowZ.z) { } - inline TPoint3D& row(int index) - { return *(TPoint3D*)(m[index]); } - inline const TPoint3D& row(int index) const - { return *(const TPoint3D*)(m[index]); } + inline T3DPointD& row(int index) + { return *(T3DPointD*)(m[index]); } + inline const T3DPointD& row(int index) const + { return *(const T3DPointD*)(m[index]); } - inline TPoint3D& rowX() { return row(0); } - inline TPoint3D& rowY() { return row(1); } - inline TPoint3D& rowZ() { return row(2); } + inline T3DPointD& rowX() { return row(0); } + inline T3DPointD& rowY() { return row(1); } + inline T3DPointD& rowZ() { return row(2); } - inline const TPoint3D& rowX() const { return row(0); } - inline const TPoint3D& rowY() const { return row(1); } - inline const TPoint3D& rowZ() const { return row(2); } + inline const T3DPointD& rowX() const { return row(0); } + inline const T3DPointD& rowY() const { return row(1); } + inline const T3DPointD& rowZ() const { return row(2); } - TPoint3D operator*(const TPoint3D &b) const; + T3DPointD operator*(const T3DPointD &b) const; TAffine3 operator*(const TAffine3 &b) const; TAffine3 operator*=(const TAffine3 &b); @@ -1388,32 +1299,32 @@ public: a41(a.a13), a42(a.a23), a43(0.0), a44(1.0) { } inline TAffine4( - const TPoint4D &rowX, - const TPoint4D &rowY, - const TPoint4D &rowZ, - const TPoint4D &rowW + const T4DPointD &rowX, + const T4DPointD &rowY, + const T4DPointD &rowZ, + const T4DPointD &rowW ): a11(rowX.x), a12(rowX.y), a13(rowX.z), a14(rowX.w), a21(rowY.x), a22(rowY.y), a23(rowY.z), a24(rowY.w), a31(rowZ.x), a32(rowZ.y), a33(rowZ.z), a34(rowZ.w), a41(rowW.x), a42(rowW.y), a43(rowW.z), a44(rowW.w) { } - inline TPoint4D& row(int index) - { return *(TPoint4D*)(m[index]); } - inline const TPoint4D& row(int index) const - { return *(const TPoint4D*)(m[index]); } + inline T4DPointD& row(int index) + { return *(T4DPointD*)(m[index]); } + inline const T4DPointD& row(int index) const + { return *(const T4DPointD*)(m[index]); } - inline TPoint4D& rowX() { return row(0); } - inline TPoint4D& rowY() { return row(1); } - inline TPoint4D& rowZ() { return row(2); } - inline TPoint4D& rowW() { return row(3); } + inline T4DPointD& rowX() { return row(0); } + inline T4DPointD& rowY() { return row(1); } + inline T4DPointD& rowZ() { return row(2); } + inline T4DPointD& rowW() { return row(3); } - inline const TPoint4D& rowX() const { return row(0); } - inline const TPoint4D& rowY() const { return row(1); } - inline const TPoint4D& rowZ() const { return row(2); } - inline const TPoint4D& rowW() const { return row(3); } + inline const T4DPointD& rowX() const { return row(0); } + inline const T4DPointD& rowY() const { return row(1); } + inline const T4DPointD& rowZ() const { return row(2); } + inline const T4DPointD& rowW() const { return row(3); } - TPoint4D operator*(const TPoint4D &b) const; + T4DPointD operator*(const T4DPointD &b) const; TAffine4 operator*(const TAffine4 &b) const; TAffine4 operator*=(const TAffine4 &b);