// ====================================================================== // // Copyright (c) 1999 The CGAL Consortium // // This software and related documentation is part of an INTERNAL release // of the Computational Geometry Algorithms Library (CGAL). It is not // intended for general use. // // ---------------------------------------------------------------------- // release : // release_date : 2000, October 15 // // source : webS3/S3.lw // file : include/CGAL/SimpleCartesian/Aff_transformationS3.h // package : S3 (1.7) // maintainer : Stefan Schirra // revision : 1.7 // revision_date : 15 Oct 2000 // author(s) : Stefan Schirra // based on code by // Andreas Fabri and // Herve Brönnimann // // coordinator : MPI, Saarbrücken // ====================================================================== #ifndef CGAL_AFF_TRANSFORMATIONS3_H #define CGAL_AFF_TRANSFORMATIONS3_H #include #include #include #include #ifdef CGAL_CFG_INCOMPLETE_TYPE_BUG_1 #define CGAL_NO_PLANE_TRANSFORM_IN_AT #endif // CGAL_CFG_INCOMPLETE_TYPE_BUG_1 CGAL_BEGIN_NAMESPACE template class Aff_transformationS3; template class Aff_transformation_repS3; template class Translation_repS3; template class Scaling_repS3; template Aff_transformationS3 _general_transformation_composition ( Aff_transformation_repS3& l, Aff_transformation_repS3& r ); template Aff_transformationS3 operator*(const Aff_transformationS3& a, const Aff_transformationS3& b); template std::ostream& operator<< (std::ostream& os, Translation_repS3& t); template std::ostream& operator<< (std::ostream& os, Scaling_repS3& t); template std::ostream& operator<< (std::ostream& os, const Aff_transformationS3& t); template < class FT > class Aff_transformation_rep_baseS3 : public Rep { public: virtual ~Aff_transformation_rep_baseS3(){} virtual PointS3 transform(const PointS3& p) const = 0; virtual VectorS3 transform(const VectorS3& v) const = 0; virtual DirectionS3 transform(const DirectionS3& d) const = 0; virtual Aff_transformationS3 inverse() const = 0; virtual Aff_transformationS3 transpose() const = 0; virtual bool is_even() const = 0; virtual FT cartesian(int i, int j) const = 0; virtual std::ostream& print(std::ostream& os) const = 0; virtual Aff_transformationS3 general_form() const = 0; }; template < class FT > class Aff_transformation_repS3 : public Aff_transformation_rep_baseS3 { friend class Aff_transformationS3; friend Aff_transformationS3 _general_transformation_composition CGAL_NULL_TMPL_ARGS( Aff_transformation_repS3& l, Aff_transformation_repS3& r ); friend Aff_transformationS3 operator* CGAL_NULL_TMPL_ARGS (const Aff_transformationS3& a, const Aff_transformationS3& b); public: Aff_transformation_repS3() {} Aff_transformation_repS3( const FT& m11, const FT& m12, const FT& m13, const FT& m21, const FT& m22, const FT& m23, const FT& m31, const FT& m32, const FT& m33) : t11(m11), t12(m12), t13(m13), t14(0), t21(m21), t22(m22), t23(m23), t24(0), t31(m31), t32(m32), t33(m33), t34(0) {} Aff_transformation_repS3( const FT& m11, const FT& m12, const FT& m13,const FT& m14, const FT& m21, const FT& m22, const FT& m23, const FT& m24, const FT& m31, const FT& m32, const FT& m33, const FT& m34) : t11(m11), t12(m12), t13(m13), t14(m14), t21(m21), t22(m22), t23(m23), t24(m24), t31(m31), t32(m32), t33(m33), t34(m34) {} ~Aff_transformation_repS3() {} PointS3 transform(const PointS3& p) const { return PointS3(t11 * p.x() + t12 * p.y() + t13 * p.z() + t14, t21 * p.x() + t22 * p.y() + t23 * p.z() + t24, t31 * p.x() + t32 * p.y() + t33 * p.z() + t34); } // note that a vector is not translated VectorS3 transform(const VectorS3& v) const { return VectorS3(t11 * v.x() + t12 * v.y() + t13 * v.z(), t21 * v.x() + t22 * v.y() + t23 * v.z(), t31 * v.x() + t32 * v.y() + t33 * v.z()); } // note that a direction is not translated DirectionS3 transform(const DirectionS3& dir) const { VectorS3 v = dir.vector(); return DirectionS3(t11 * v.x() + t12 * v.y() + t13 * v.z(), t21 * v.x() + t22 * v.y() + t23 * v.z(), t31 * v.x() + t32 * v.y() + t33 * v.z()); } Aff_transformationS3 inverse() const { return Aff_transformationS3( det2x2_by_formula( t22, t23, t32, t33), // i 11 - det2x2_by_formula( t12, t13, t32, t33), // i 12 det2x2_by_formula( t12, t13, t22, t23), // i 13 - det3x3_by_formula( t12, t13, t14, t22, t23, t24, // i 14 t32, t33, t34 ), - det2x2_by_formula( t21, t23, t31, t33), // i 21 det2x2_by_formula( t11, t13, t31, t33), // i 22 - det2x2_by_formula( t11, t13, t21, t23), // i 23 det3x3_by_formula( t11, t13, t14, t21, t23, t24, // i 24 t31, t33, t34 ), det2x2_by_formula( t21, t22, t31, t32), // i 31 - det2x2_by_formula( t11, t12, t31, t32), // i 32 det2x2_by_formula( t11, t12, t21, t22), // i 33 - det3x3_by_formula( t11, t12, t14, t21, t22, t24, // i 34 t31, t32, t34 ), det3x3_by_formula( t11, t12, t13, t21, t22, t23, // i 44 t31, t32, t33 ) ) ; } virtual Aff_transformationS3 general_form() const { return Aff_transformationS3(t11, t12, t13, t14, t21, t22, t23, t24, t31, t32, t33, t34); } virtual Aff_transformationS3 transpose() const { FT ft0(0); return Aff_transformationS3( t11, t21, t31, ft0, t12, t22, t32, ft0, t13, t23, t33, ft0); } virtual bool is_even() const { return sign_of_determinant3x3(t11, t12, t13, t21, t22, t23, t31, t32, t33) == POSITIVE; } virtual FT cartesian(int i, int j) const { switch (i) { case 0: switch (j) { case 0: return t11; case 1: return t12; case 2: return t13; case 3: return t14; } case 1: switch (j) { case 0: return t21; case 1: return t22; case 2: return t23; case 3: return t24; } case 2: switch (j) { case 0: return t31; case 1: return t32; case 2: return t33; case 3: return t34; } case 3: switch (j) { case 0: return FT(0); case 1: return FT(0); case 2: return FT(0); case 3: return FT(1); } } return FT(0); } std::ostream& print(std::ostream& os) const { os <<" "<< t11 <<' '<< t12 <<' '<< t13 <<' '<< t14 <<"\n"; os <<" "<< t21 <<' '<< t22 <<' '<< t23 <<' '<< t24 <<"\n"; os <<" "<< t31 <<' '<< t32 <<' '<< t33 <<' '<< t34 <<")\n"; return os; } private: FT t11, t12, t13, t14; FT t21, t22, t23, t24; FT t31, t32, t33, t34; }; template < class FT > class Translation_repS3 : public Aff_transformation_rep_baseS3 { friend std::ostream& operator<< CGAL_NULL_TMPL_ARGS( std::ostream& os, Translation_repS3& t); friend Aff_transformationS3 operator* CGAL_NULL_TMPL_ARGS (const Aff_transformationS3& a, const Aff_transformationS3& b); public: Translation_repS3() {} Translation_repS3(const VectorS3& tv) : translationvector(tv) {} ~Translation_repS3() {} PointS3 transform(const PointS3& p) const { return p + translationvector; } VectorS3 transform(const VectorS3& v) const { return v; } DirectionS3 transform(const DirectionS3& d) const { return d; } Aff_transformationS3 inverse() const { return Aff_transformationS3(TRANSLATION, - translationvector); } Aff_transformationS3 transpose() const { FT ft0(0), ft1(1); return Aff_transformationS3(ft1, ft0, ft0, ft0, ft0, ft1, ft0, ft0, ft0, ft0, ft1, ft0); } Aff_transformationS3 general_form() const { FT ft0(0), ft1(1); return Aff_transformationS3(ft1, ft0, ft0, translationvector.x(), ft0, ft1, ft0, translationvector.y(), ft0, ft0, ft1, translationvector.z()); } virtual bool is_even() const { return true; } virtual FT cartesian(int i, int j) const { if (j==i) return FT(1); if (j==3) return translationvector[i]; return FT(0); } std::ostream& print(std::ostream& os) const { FT ft0(0), ft1(1); os << " "<< ft1 <<' '<< ft0 <<' '<< ft0 <<' ' << translationvector.x() << "\n"; os << " "<< ft0 <<' '<< ft1 <<' '<< ft0 <<' ' << translationvector.y() << "\n"; os << " "<< ft0 <<' '<< ft0 <<' '<< ft1 <<' ' << translationvector.z() << ")\n"; return os; } private: VectorS3 translationvector; }; template < class FT > class Scaling_repS3: public Aff_transformation_rep_baseS3 { friend std::ostream& operator<< CGAL_NULL_TMPL_ARGS( std::ostream& os, Scaling_repS3& t); friend Aff_transformationS3 operator* CGAL_NULL_TMPL_ARGS (const Aff_transformationS3& a, const Aff_transformationS3& b); public: Scaling_repS3() {} Scaling_repS3(const FT& s) : scalefactor(s) {} ~Scaling_repS3() {} PointS3 transform(const PointS3& p) const { return PointS3(scalefactor * p.x(), scalefactor * p.y(), scalefactor * p.z()); } VectorS3 transform(const VectorS3& v) const { return VectorS3(scalefactor * v.x(), scalefactor * v.y(), scalefactor * v.z()); } DirectionS3 transform(const DirectionS3& d) const { return d; } Aff_transformationS3 inverse() const { return Aff_transformationS3(SCALING, FT(1)/scalefactor); } Aff_transformationS3 general_form() const { FT ft0(0); return Aff_transformationS3(scalefactor, ft0, ft0, ft0, scalefactor, ft0, ft0, ft0, scalefactor); } Aff_transformationS3 transpose() const { return general_form(); } virtual bool is_even() const { return true; } virtual FT cartesian(int i, int j) const { if (i!=j) return FT(0); if (i==3) return FT(1); return scalefactor; } virtual std::ostream& print(std::ostream& os) const { FT ft0(0); os << " "<< scalefactor <<' '<< ft0 <<' '<< ft0 << ' ' << ft0 << "\n"; os << " "<< ft0 <<' '<< scalefactor <<' '<< ft0 << ' ' << ft0 << "\n"; os << " "<< ft0 <<' '<< ft0 <<' '<< scalefactor <<' ' << ft0 << ")\n"; return os; } private: FT scalefactor; }; template < class FT > class Aff_transformationS3 : public Handle { friend std::ostream& operator<< CGAL_NULL_TMPL_ARGS(std::ostream& os, const Aff_transformationS3& t); friend Aff_transformationS3 _general_transformation_composition CGAL_NULL_TMPL_ARGS( Aff_transformation_repS3& l, Aff_transformation_repS3& r ); friend Aff_transformationS3 operator* CGAL_NULL_TMPL_ARGS (const Aff_transformationS3& a, const Aff_transformationS3& b); public: // default constructor: Aff_transformationS3(); // Identity Aff_transformationS3(const Identity_transformation& ); // Translation: Aff_transformationS3(const Translation, const VectorS3& v); // Scaling: Aff_transformationS3(const Scaling, const FT& s, const FT& w = FT(1)); // General form: Aff_transformationS3(const FT& m11, const FT& m12, const FT& m13, const FT& m21, const FT& m22, const FT& m23, const FT& m31, const FT& m32, const FT& m33, const FT& w= FT(1)); Aff_transformationS3(const FT& m11, const FT& m12, const FT& m13, const FT& m14, const FT& m21, const FT& m22, const FT& m23, const FT& m24, const FT& m31, const FT& m32, const FT& m33, const FT& m34, const FT& w = FT(1)); ~Aff_transformationS3(); PointS3 transform(const PointS3& p) const; PointS3 operator()(const PointS3& p) const; VectorS3 transform(const VectorS3& v) const; VectorS3 operator()(const VectorS3& v) const; DirectionS3 transform(const DirectionS3& d) const; DirectionS3 operator()(const DirectionS3& d) const; #ifndef CGAL_NO_PLANE_TRANSFORM_IN_AT PlaneS3 transform(const PlaneS3& p) const; PlaneS3 operator()(const PlaneS3& p) const; #endif // CGAL_NO_PLANE_TRANSFORM_IN_AT Aff_transformationS3 inverse() const; Aff_transformationS3 transpose() const; Aff_transformationS3 general_form() const; bool is_even() const; bool is_odd() const; FT cartesian(int i, int j) const { return ptr()->cartesian(i,j); } FT homogeneous(int i, int j) const { return cartesian(i,j); } FT m(int i, int j) const { return cartesian(i,j); } FT hm(int i, int j) const { return cartesian(i,j); } private: Aff_transformation_rep_baseS3* ptr() const { return (Aff_transformation_rep_baseS3*)PTR; } }; template < class FT > Aff_transformationS3::Aff_transformationS3() { FT ft1(1), ft0(0); PTR = new Aff_transformation_repS3(ft1, ft0, ft0, ft0, ft1, ft0, ft0, ft0, ft1); } template < class FT > Aff_transformationS3::Aff_transformationS3(const Identity_transformation& ) { FT ft1(1), ft0(0); PTR = new Aff_transformation_repS3(ft1, ft0, ft0, ft0, ft1, ft0, ft0, ft0, ft1); } template < class FT > Aff_transformationS3::Aff_transformationS3(const Translation, const VectorS3& v) { PTR = new Translation_repS3(v); } template < class FT > Aff_transformationS3::Aff_transformationS3(const Scaling, const FT& s, const FT& w) { if (w != FT(1)) PTR = new Scaling_repS3(s/w); else PTR = new Scaling_repS3(s); } template < class FT > Aff_transformationS3::Aff_transformationS3(const FT& m11, const FT& m12, const FT& m13, const FT& m14, const FT& m21, const FT& m22, const FT& m23, const FT& m24, const FT& m31, const FT& m32, const FT& m33, const FT& m34, const FT& w) { if (w != FT(1)) PTR = new Aff_transformation_repS3(m11/w, m12/w, m13/w, m14/w, m21/w, m22/w, m23/w, m24/w, m31/w, m32/w, m33/w, m34/w); else PTR = new Aff_transformation_repS3(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34); } template < class FT > Aff_transformationS3::Aff_transformationS3( const FT& m11, const FT& m12, const FT& m13, const FT& m21, const FT& m22, const FT& m23, const FT& m31, const FT& m32, const FT& m33, const FT& w) { if (w != FT(1)) PTR = new Aff_transformation_repS3(m11/w, m12/w, m13/w, m21/w, m22/w, m23/w, m31/w, m32/w, m33/w); else PTR = new Aff_transformation_repS3(m11, m12, m13, m21, m22, m23, m31, m32, m33); } template < class FT > Aff_transformationS3::~Aff_transformationS3() {} template < class FT > PointS3 Aff_transformationS3::transform(const PointS3& p) const { return ptr()->transform(p); } template < class FT > inline PointS3 Aff_transformationS3::operator()(const PointS3& p) const { return transform(p); } template < class FT > inline VectorS3 Aff_transformationS3::transform(const VectorS3& v) const { return ptr()->transform(v); } template < class FT > inline VectorS3 Aff_transformationS3::operator()(const VectorS3& v) const { return transform(v); } template < class FT > inline DirectionS3 Aff_transformationS3::transform(const DirectionS3& d) const { return ptr()->transform(d); } template < class FT > inline DirectionS3 Aff_transformationS3::operator()(const DirectionS3& d) const { return transform(d); } #ifndef CGAL_NO_PLANE_TRANSFORM_IN_AT template < class FT > inline PlaneS3 Aff_transformationS3::transform(const PlaneS3& p) const { return p.transform(*this); } template < class FT > inline PlaneS3 Aff_transformationS3::operator()(const PlaneS3& p) const { return transform(p); } #endif // CGAL_NO_PLANE_TRANSFORM_IN_AT template < class FT > Aff_transformationS3 Aff_transformationS3::inverse() const { return ptr()->inverse(); } template < class FT > Aff_transformationS3 Aff_transformationS3::general_form() const { return ptr()->general_form(); } template < class FT > Aff_transformationS3 Aff_transformationS3::transpose() const { return ptr()->transpose(); } template < class FT > bool Aff_transformationS3::is_even() const { return ptr()->is_even(); } template < class FT > bool Aff_transformationS3::is_odd() const { return ! (ptr()->is_even()); } template < class FT > Aff_transformationS3 _general_transformation_composition(Aff_transformation_repS3& l, Aff_transformation_repS3& r ) { return Aff_transformationS3( l.t11*r.t11 + l.t12*r.t21 + l.t13*r.t31, l.t11*r.t12 + l.t12*r.t22 + l.t13*r.t32, l.t11*r.t13 + l.t12*r.t23 + l.t13*r.t33, l.t11*r.t14 + l.t12*r.t24 + l.t13*r.t34 + l.t14, l.t21*r.t11 + l.t22*r.t21 + l.t23*r.t31, l.t21*r.t12 + l.t22*r.t22 + l.t23*r.t32, l.t21*r.t13 + l.t22*r.t23 + l.t23*r.t33, l.t21*r.t14 + l.t22*r.t24 + l.t23*r.t34 + l.t24, l.t31*r.t11 + l.t32*r.t21 + l.t33*r.t31, l.t31*r.t12 + l.t32*r.t22 + l.t33*r.t32, l.t31*r.t13 + l.t32*r.t23 + l.t33*r.t33, l.t31*r.t14 + l.t32*r.t24 + l.t33*r.t34 + l.t34); } // this is really quick and dirty. As in the 2D case the composition of // translations or scalings should be a translation or a scaling template < class FT > Aff_transformationS3 operator*(const Aff_transformationS3& a, const Aff_transformationS3& b) { return _general_transformation_composition( *(Aff_transformation_repS3*)(a.general_form().ptr()), *(Aff_transformation_repS3*)(b.general_form().ptr())); } #ifndef CGAL_NO_OSTREAM_INSERT_AFF_TRANSFORMATIONS3 template < class FT > std::ostream& operator<<(std::ostream& os, const Aff_transformationS3& t) { t.print(os); return os; } #endif // CGAL_NO_OSTREAM_INSERT_AFF_TRANSFORMATIONS3 #ifndef CGAL_NO_ISTREAM_EXTRACT_AFF_TRANSFORMATIONS3 #endif // CGAL_NO_ISTREAM_EXTRACT_AFF_TRANSFORMATIONS3 CGAL_END_NAMESPACE #endif // CGAL_AFF_TRANSFORMATIONS3_H