// @(#)root/mathcore:$Name:  $:$Id: Transform3D.h,v 1.10 2006/02/06 17:22:03 moneta Exp $
// Authors: W. Brown, M. Fischler, L. Moneta    2005  

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2005 , LCG ROOT MathLib Team                         *
 *                                                                    *
 *                                                                    *
 **********************************************************************/

// Header file for class Transform3D
// 
// Created by: Lorenzo Moneta  October 21 2005
// 
// 
#ifndef ROOT_Math_GenVector_Transform3D 
#define ROOT_Math_GenVector_Transform3D  1



#include "Math/GenVector/Cartesian3D.h"
#include "Math/GenVector/DisplacementVector3D.h"
#include "Math/GenVector/PositionVector3D.h"
#include "Math/GenVector/LorentzVector.h"
#include "Math/GenVector/Rotation3D.h"
#include "Math/GenVector/AxisAnglefwd.h"
#include "Math/GenVector/EulerAnglesfwd.h"
#include "Math/GenVector/Quaternionfwd.h"
#include "Math/GenVector/RotationXfwd.h"
#include "Math/GenVector/RotationYfwd.h"
#include "Math/GenVector/RotationZfwd.h"

#include <iostream>

//#include "Math/Vector3Dfwd.h"



namespace ROOT { 

  namespace Math { 

    class Plane3D; 

    typedef  DisplacementVector3D<Cartesian3D<double> > XYZVector; 
    typedef  PositionVector3D<Cartesian3D<double> > XYZPoint; 



  /** 
     Basic 3D Transformation class describing  a rotation and then a translation
     The internal data are a rotation data and a vector and cabe represented 
     like a 4x4 matrix

     @ingroup GenVector

  */ 

  class Transform3D { 
    

  public: 

    enum ETransform3DMatrixIndex {
      kXX = 0, kXY = 1, kXZ = 2, kDX = 3, 
      kYX = 4, kYY = 5, kYZ = 6, kDY = 7,
      kZX = 8, kZY = 9, kZZ =10, kDZ = 11
    };



    /** 
	Default constructor (identy rotation) + zero translation
    */ 
    Transform3D()
    {
      SetIdentity();
    }
    
    /**
       Construct given a pair of pointers or iterators defining the
       beginning and end of an array of 12 Scalars
    */
    template<class IT>
    Transform3D(IT begin, IT end) 
    { 
      SetComponents(begin,end); 
    }

    /**
       Construct from a rotation and then a translation described by a XYZVector 
    */
    Transform3D( const Rotation3D & r, const XYZVector & v) 
    {
      AssignFrom( r, v ); 
    }
    /**
       Construct from a translation and then a rotation (inverse assignment) 
    */
    Transform3D( const XYZVector & v, const Rotation3D & r) 
    {
      // is equivalent from having first the rotation and then the translation vector rotated
      AssignFrom( r, r(v) ); 
    }

    /**
       Construct from a 3D Rotation only with zero translation
    */
    explicit Transform3D( const Rotation3D & r) { 
      AssignFrom(r);
    } 
    // convenience methods for the other rotations (cannot use templates for conflict with LA)
    explicit Transform3D( const AxisAngle & r) { 
      AssignFrom(Rotation3D(r));
    } 
    explicit Transform3D( const EulerAngles & r) { 
      AssignFrom(Rotation3D(r));
    } 
    explicit Transform3D( const Quaternion & r) { 
      AssignFrom(Rotation3D(r));
    } 
    // TO DO: implement direct methods for axial rotations without going through Rotation3D
    explicit Transform3D( const RotationX & r) { 
      AssignFrom(Rotation3D(r));
    } 
    explicit Transform3D( const RotationY & r) { 
      AssignFrom(Rotation3D(r));
    } 
    explicit Transform3D( const RotationZ & r) { 
      AssignFrom(Rotation3D(r));
    } 

    /**
       Construct from a translation only, represented by any DisplacementVector3D 
       and with an identity rotation
    */
    template<class CoordSystem>
    explicit Transform3D( const DisplacementVector3D<CoordSystem> & v) { 
      AssignFrom(XYZVector(v));
    }
    /**
       Construct from a translation only, represented by a Cartesian 3D Vector,  
       and with an identity rotation
    */
    explicit Transform3D( const XYZVector & v) { 
      AssignFrom(v);
    }



    //#if !defined(__MAKECINT__) && !defined(G__DICTIONARY)  // this is ambigous with double * , double *   
    /**
       Construct from a rotation (any rotation object)  and then a translation 
       (represented by any DisplacementVector)
       The requirements on the rotation and vector objects are that they can be transformed in a 
       Rotation3D class and in a XYZVector
    */
    // to do : change to displacement vector3D
    template <class ARotation, class CoordSystem>
    Transform3D( const ARotation & r, const DisplacementVector3D<CoordSystem> & v) 
    {
      AssignFrom( Rotation3D(r), XYZVector (v) ); 
    }
    /**
       Construct from a translation (using any type of DisplacementVector ) 
       and then a rotation (any rotation object). 
       Requirement on the rotation and vector objects are that they can be transformed in a 
       Rotation3D class and in a XYZVector 
    */
    template <class ARotation, class CoordSystem>
    Transform3D(const DisplacementVector3D<CoordSystem> & v , const ARotation & r) 
    {
      // is equivalent from having first the rotation and then the translation vector rotated
      Rotation3D r3d(r);
      AssignFrom( r3d, r3d( XYZVector(v) ) ); 
    }

    //#endif

    /**
       Construct transformation from one coordinate system defined by three 
       points (origin + two axis) to 
       a new coordinate system defined by other three points (origin + axis) 
       @param fr0  point defining origin of original reference system 
       @param fr1  point defining first axis of original reference system 
       @param fr2  point defining second axis of original reference system 
       @param to0  point defining origin of transformed reference system 
       @param to1  point defining first axis transformed reference system 
       @param to2  point defining second axis transformed reference system 

     */
    Transform3D
    (const XYZPoint & fr0, const XYZPoint & fr1, const XYZPoint & fr2,  
     const XYZPoint & to0, const XYZPoint & to1, const XYZPoint & to2 );  


    // use compiler generated copy ctor, copy assignmet and dtor

    /**
       Construct from a linear algebra matrix of size at least 3x4,
       which must support operator()(i,j) to obtain elements (0,0) thru (2,3).
       The 3x3 sub-block is assumed to be the rotation part and the translations vector 
       are described by the 4-th column
    */
    template<class ForeignMatrix>
    explicit Transform3D(const ForeignMatrix & m) { 
      SetComponents(m); 
    }

    /**
       Raw constructor from 12 Scalar components
    */
    Transform3D(double  xx, double  xy, double  xz, double dx, 
		double  yx, double  yy, double  yz, double dy,
		double  zx, double  zy, double  zz, double dz)
    {
      SetComponents (xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz);
    }


    /**
       Construct from a linear algebra matrix of size at least 3x4,
       which must support operator()(i,j) to obtain elements (0,0) thru (2,3).
       The 3x3 sub-block is assumed to be the rotation part and the translations vector 
       are described by the 4-th column
    */
    template<class ForeignMatrix>
    Transform3D & operator= (const ForeignMatrix & m) { 
      SetComponents(m); 
      return *this; 
    }


    // ======== Components ==============


    /**
       Set the 12 matrix components given an iterator to the start of
       the desired data, and another to the end (12 past start).
    */
    template<class IT>
    void SetComponents(IT begin, IT end) {
      assert (end==begin+12);
      std::copy ( begin, end, fM );
    }

    /**
       Get the 12 matrix components into data specified by an iterator begin
       and another to the end of the desired data (12 past start).
    */
    template<class IT>
    void GetComponents(IT begin, IT end) const {
      assert (end==begin+12);
      std::copy ( fM, fM+12, begin );
    }

    /**
       Set components from a linear algebra matrix of size at least 3x4,
       which must support operator()(i,j) to obtain elements (0,0) thru (2,3).
       The 3x3 sub-block is assumed to be the rotation part and the translations vector 
       are described by the 4-th column
    */
    template<class ForeignMatrix>
    void
    SetComponents (const ForeignMatrix & m) {
      fM[kXX]=m(0,0);  fM[kXY]=m(0,1);  fM[kXZ]=m(0,2); fM[kDX]=m(0,3);
      fM[kYX]=m(1,0);  fM[kYY]=m(1,1);  fM[kYZ]=m(1,2); fM[kDY]=m(1,3);
      fM[kZX]=m(2,0);  fM[kZY]=m(2,1);  fM[kZZ]=m(2,2); fM[kDZ]=m(2,3);
    }

    /**
       Get components into a linear algebra matrix of size at least 3x4,
       which must support operator()(i,j) for write access to elements
       (0,0) thru (2,3).
    */
    template<class ForeignMatrix>
    void
    GetComponents (ForeignMatrix & m) const {
      m(0,0)=fM[kXX];  m(0,1)=fM[kXY];  m(0,2)=fM[kXZ];  m(0,3)=fM[kDX];
      m(1,0)=fM[kYX];  m(1,1)=fM[kYY];  m(1,2)=fM[kYZ];  m(0,3)=fM[kDY];
      m(2,0)=fM[kZX];  m(2,1)=fM[kZY];  m(2,2)=fM[kZZ];  m(0,3)=fM[kDZ];
    }


    /**
       Set the components from 12 scalars 
    */
    void
    SetComponents (double  xx, double  xy, double  xz, double dx,  
		   double  yx, double  yy, double  yz, double dy, 
		   double  zx, double  zy, double  zz, double dz) {
      fM[kXX]=xx;  fM[kXY]=xy;  fM[kXZ]=xz;  fM[kDX]=dx;
      fM[kYX]=yx;  fM[kYY]=yy;  fM[kYZ]=yz;  fM[kDY]=dy;
      fM[kZX]=zx;  fM[kZY]=zy;  fM[kZZ]=zz;  fM[kDZ]=dz;
    }

    /**
       Get the nine components into 12 scalars
    */
    void
    GetComponents (double &xx, double &xy, double &xz, double &dx,
		   double &yx, double &yy, double &yz, double &dy,
		   double &zx, double &zy, double &zz, double &dz) const {
      xx=fM[kXX];  xy=fM[kXY];  xz=fM[kXZ];  dx=fM[kDX];
      yx=fM[kYX];  yy=fM[kYY];  yz=fM[kYZ];  dy=fM[kDY];
      zx=fM[kZX];  zy=fM[kZY];  zz=fM[kZZ];  dz=fM[kDZ];
    }

    

    /**
       Get the rotation and translation vector representing the 3D transformation
    */    
    void GetDecomposition(Rotation3D &r, XYZVector &v) const;



    // operations on points and vectors 

    /**
       Transformation operation for Position Vector in Cartesian coordinate 
    */
    XYZPoint operator() (const XYZPoint & p) const;  


    /**
       Transformation operation for Displacement Vectors in Cartesian coordinate 
       For the Displacement Vectors only the rotation applies - no translations
    */
    XYZVector operator() (const XYZVector & v) const;


    /**
       Transformation operation for Position Vector in any coordinate system 
    */
    template<class CoordSystem > 
    PositionVector3D<CoordSystem> operator() (const PositionVector3D <CoordSystem> & p) const { 
      XYZPoint xyzNew = operator() ( XYZPoint(p) );
      return  PositionVector3D<CoordSystem> (xyzNew);
    }

    /**
       Transformation operation for Displacement Vector in any coordinate system 
    */
    template<class CoordSystem > 
    DisplacementVector3D<CoordSystem> operator() (const DisplacementVector3D <CoordSystem> & v) const { 
      XYZVector xyzNew = operator() ( XYZVector(v) );
      return  DisplacementVector3D<CoordSystem> (xyzNew);
    }

    /**
       Transformation operation for a Lorentz Vector in any  coordinate system 
    */
    template <class CoordSystem > 
    LorentzVector<CoordSystem> operator() (const LorentzVector<CoordSystem> & q) const { 
      XYZVector xyzNew = operator() ( XYZVector(q.Vect() ) );
      return  LorentzVector<CoordSystem> (xyzNew.X(), xyzNew.Y(), xyzNew.Z(), q.E() );
    }

    /**
       Transformation on a 3D plane
    */
    Plane3D operator() (const Plane3D & plane) const; 
          

    // skip transformation for arbitrary vectors - not really defined if point or displacement vectors

    // same but with operator * 
    /**
       Transformation operation for Vectors. Apply same rules as operator() 
       depending on type of vector. 
       Will work only for DisplacementVector3D, PositionVector3D and LorentzVector
    */
    template<class AVector > 
    AVector operator * (const AVector & v) const { 
      return operator() (v);
    }



    /**
       multiply (combine) with another transformation in place
     */
    Transform3D & operator *= (const Transform3D  & t);

    /**
       multiply (combine) two transformations
     */ 
    Transform3D operator * (const Transform3D  & t) const { 
      Transform3D tmp(*this);
      tmp*= t;
      return tmp;
    }

    /** 
	Invert the transformation in place
    */
    void Invert();

    /**
       Return the inverse of the transformation.
    */
    Transform3D Inverse() const { 
      Transform3D t(*this);
      t.Invert();
      return t;
    }


    /**
       Equality/inequality operators
    */
    bool operator == (const Transform3D & rhs) {
      if( fM[0] != rhs.fM[0] )  return false;
      if( fM[1] != rhs.fM[1] )  return false;
      if( fM[2] != rhs.fM[2] )  return false;
      if( fM[3] != rhs.fM[3] )  return false;
      if( fM[4] != rhs.fM[4] )  return false;
      if( fM[5] != rhs.fM[5] )  return false;
      if( fM[6] != rhs.fM[6] )  return false;
      if( fM[7] != rhs.fM[7] )  return false;
      if( fM[8] != rhs.fM[8] )  return false;
      if( fM[9] != rhs.fM[9] )  return false;
      if( fM[10]!= rhs.fM[10] ) return false;
      if( fM[11]!= rhs.fM[11] ) return false;
      return true;
    }

    bool operator != (const Transform3D & rhs) {
      return ! operator==(rhs);
    }


  protected: 

    /**
       make transformation from first a rotation then a translation
     */
    void  AssignFrom( const Rotation3D & r, const XYZVector & v);  

    /**
       make transformation from only rotations (zero translation)
     */
    void  AssignFrom( const Rotation3D & r);  

    /**
       make transformation from only translation (identity rotations)
     */
    void  AssignFrom( const XYZVector & v);  

    /**
       Set identity transformation (identity rotation , zero translation)
     */
    void SetIdentity() ; 

  private: 


    double fM[12];

  };


    // global functions 

  // TODO - I/O should be put in the manipulator form 

    std::ostream & operator<< (std::ostream & os, const Transform3D & t);
  
    // need a function Transform = Translation * Rotation ???

   




  } // end namespace Math

} // end namespace ROOT


#endif /* MATHCORE_BASIC3DTRANSFORMATION */


ROOT page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.