/** \file Header for Coordinate System class This file provides the classes which make up the coordinate system class. The classes intended for the end-user are - CoordinateSystem - BaseCoordinateSystem They are typedef's to the factorised, policy-based implementation. Coordinate systems are implemented using a three-layer hierarchy: -# CoordinateTransformer implementes the common functionality -# VBasePolicy (not existent interface) deals with the reference system, implemented in DerivedCSPolicy and BaseCSPolicy -# TransformerConstructor (template) implementes the constructors. \author Lukas Nellen \version $Id$ \date 20 May 2003 */ #ifndef _utl_CoordinateSystem_h_ #define _utl_CoordinateSystem_h_ #include #include #include #include #ifdef OFFLINE_GEOMETRY_IS_COUNTED #include #endif #include #include namespace utl { inline void CoordinateSystemValid(const CoordinateSystemPtr& theCoordinateSystem) { if (!theCoordinateSystem) throw CoordinateSystemException("NULL coordinate system pointer;"); } /** \class CoordinateTransformer CoordinateSystem.h utl/CoordinateSystem.h \ingroup geometry \brief Bottom part of Coordinate system class Both CoordinateSystem's and other geometry objects contain (a reference to) a coordinates system, relative to which the coordinates representing the objects are defined. To guarantee that a CoordinateSystem object exists as long as some other objects refers to it, and to make sure that it is deleted when no longer needed, all references should be held through a CoordinateSystemPtr smart pointer. This implies that, under normal cirumstances, all CoordinateSystem's should be allocated on the heap. Creating CoordinateSystem objects on the stack is dangerous - one has to make sure that no geometry object refers to such a CoordinateSystem at the moment when it goes out of scope and is destroyed. This class provides the common user interface for coordinate systems. Classes layered on top of this class implement the creation of coordinate systems and the policy for dealing with the base system relative to which the coordinate system is defined. */ class CoordinateTransformer : public ::boost::enable_shared_from_this { protected: typedef boost::weak_ptr WeakCoordinateSystemPtr; public: /** \brief Type to use to hold objects of this type. This is the type returned by the TransformerConstructor factory methods. \note This is required by the policy interface of TransformerConstructor. */ typedef CoordinateSystemPtr type; // Getters /** \brief Get the reference system for this coordinate system Takes care to keep the ultimate root coordinate system unique. */ const CoordinateSystemPtr GetReferenceSystem() const { return fReferenceSystem ? fReferenceSystem : GetRootCoordinateSystem(); } /// Get the transformation matrix relative to reference system const TransformationMatrix& GetTransformation() const { return fTransformation; } /// Get the transformation to other coordinate system (with caching) const TransformationMatrix& GetTransformationTo(const CoordinateSystemPtr& target) const; /// Get the inverse transformation to other coordinate system (w/ caching) const TransformationMatrix& GetInverseTransformationTo(const CoordinateSystemPtr& target) const; /// Get reference system for the creation of new coordinate systems virtual const CoordinateSystemPtr GetReferenceForNewCS() const = 0; /// Calculate the correct transformation for the new CS virtual const TransformationMatrix GetTransformationForNewCS(const TransformationMatrix& theTransformation) const = 0; static CoordinateSystemPtr GetRootCoordinateSystem(); protected: // Default constructor - used only to construct the root CS CoordinateTransformer(); CoordinateTransformer(const TransformationMatrix& theTransformation, const CoordinateSystemPtr& theReferenceCS); virtual ~CoordinateTransformer(); /// Get a \c CoordinateSystemPointer for \c this CoordinateSystemPtr GetThis() const; private: // Copy constructor private and not implemented CoordinateTransformer(const CoordinateTransformer& theSystem); // Assignement private and not implemented CoordinateTransformer& operator=(const CoordinateTransformer& theSystem); const CoordinateSystemPtr FindCommonBase(const CoordinateSystemPtr& other) const; const TransformationMatrix CollectTransformationFrom(const CoordinateSystemPtr& target) const; /** \brief Transformation of the components of a vector or point This is the transformation of the components of the vector represented in the reference system into this coordinate system. */ TransformationMatrix fTransformation; /// The base system - 0 for default base. CoordinateSystemPtr fReferenceSystem; // for the transformation cache mutable WeakCoordinateSystemPtr fLastTarget; mutable TransformationMatrix* fLastTransformation; mutable TransformationMatrix* fLastInverseTransformation; /// The root coordinate system - the unique, ultimate reference system static CoordinateSystemPtr RootCoordinateSystem; }; /** \class DerivedCSPolicy CoordinateSystem.h utl/CoordinateSystem.h \brief Policy for derived coordinate systems A derived coordinate system supplies its own reference system as the reference system to use when contructing a new coordinate systems relative to it. \note Derived coordinate systems can never be reference systems. \author Lukas Nellen \date 19 Oct 2003 \ingroup geometry */ class DerivedCSPolicy : public CoordinateTransformer #ifdef OFFLINE_GEOMETRY_IS_COUNTED , private CountedObject #endif { protected: DerivedCSPolicy() : CoordinateTransformer() { } DerivedCSPolicy(const TransformationMatrix& theTransformation, const CoordinateSystemPtr& theReferenceCS) : CoordinateTransformer(theTransformation, theReferenceCS) { } /// Get reference system for the creation of new coordinate systems virtual const CoordinateSystemPtr GetReferenceForNewCS() const; virtual const TransformationMatrix GetTransformationForNewCS(const TransformationMatrix& theTransformation) const; /// Generic factory for post-processing static type FromTransformation(const TransformationMatrix& theTrafo, const CoordinateSystemPtr& theCS); }; /** \class BaseCSPolicy CoordinateSystem.h utl/CoordinateSystem.h \brief Policy for base coordinate systems A base coordinate system supplies itself as the reference system when contructing a new coordinate systems relative to it. \note All reference coordinate systems have to be base cooridinate systems (by construction). \author Lukas Nellen \date 19 Oct 2003 \ingroup geometry */ class BaseCSPolicy : public CoordinateTransformer #ifdef OFFLINE_GEOMETRY_IS_COUNTED , private CountedObject #endif { friend class CoordinateTransformer; protected: BaseCSPolicy() : CoordinateTransformer() { } BaseCSPolicy(const TransformationMatrix& theTransformation, const CoordinateSystemPtr& theReferenceCS) : CoordinateTransformer(theTransformation, theReferenceCS) { } /// Get reference system for the creation of new coordinate systems virtual const CoordinateSystemPtr GetReferenceForNewCS() const; virtual const TransformationMatrix GetTransformationForNewCS(const TransformationMatrix& theTransformation) const; /// Generic factory for post-processing static type FromTransformation(const TransformationMatrix& theTrafo, const CoordinateSystemPtr& theCS); }; /*! \brief The normal coordinate system type \ingroup geometry */ typedef TransformerConstructor CoordinateSystem; /// For base coordinate systems typedef TransformerConstructor BaseCoordinateSystem; } // utl #endif // _utl_CoordinateSystem_h_ // Configure (x)emacs for this file ... // Local Variables: // mode:c++ // compile-command: "make -C .. -k" // End: