BLCoordinateTransform.hh

Go to the documentation of this file.
00001 //      BLCoordinateTransform.hh
00002 /*
00003 This source file is part of G4beamline, http://g4beamline.muonsinc.com
00004 Copyright (C) 2003,2004,2005,2006 by Tom Roberts, all rights reserved.
00005 
00006 This program is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU General Public License
00008 as published by the Free Software Foundation; either version 2
00009 of the License, or (at your option) any later version.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 http://www.gnu.org/copyleft/gpl.html
00017 */
00018 
00019 #ifndef BLCOORDINATETRANSFORM_HH
00020 #define BLCOORDINATETRANSFORM_HH
00021 
00022 #include <stdio.h>
00023 
00024 #include "G4ThreeVector.hh"
00025 #include "G4RotationMatrix.hh"
00026 
00027 #define DUMPROTATION(rot,str)                                           \
00028 { G4ThreeVector x(1.0,0.0,0.0), z(0.0,0.0,1.0);                         \
00029   G4ThreeVector rx = rot * x;                                           \
00030   G4ThreeVector rz = rot * z;                                           \
00031   printf("%s: %.3f,%.3f,%.3f / %.3f,%.3f,%.3f / %.3f,%.3f,%.3f\n",      \
00032     str,rot.xx(),rot.xy(),rot.xz(),rot.yx(),rot.yy(),rot.yz(),          \
00033     rot.zx(),rot.zy(),rot.zz());                                        \
00034   printf("        rot*x=%.3f,%.3f,%.3f   rot*z = %.3f,%.3f,%.3f\n",     \
00035     rx[0],rx[1],rx[2],rz[0],rz[1],rz[2]);                               \
00036 }
00037 
00038 /**     class BLCoordinateTransform defines a linear coordinate transform.
00039  *
00040  *      An object is first defined in its local coordinates (i.e. with the
00041  *      beam centerline along +Z). The object is rotated in place, and is then 
00042  *      translated to position. That's how the constructors work; the
00043  *      actual transformation goes the other way. And normally the transform
00044  *      of each group is applied to the transforms of its elements, so each
00045  *      placed element's transform goes global->local in one fell swoop.
00046  *
00047  *      This class is completely inline.
00048  **/
00049 class BLCoordinateTransform {
00050         G4RotationMatrix rot_p2l;       /// rotation parent->local
00051         G4RotationMatrix rot_l2p;       /// rotation local->parent
00052         G4ThreeVector position;         /// parent position of local (0,0,0)
00053         G4bool rotated;         /// for efficiency in un-rotated xforms
00054         void checkRotation() {
00055                 // two test vectors is enough
00056                 G4ThreeVector x(1.0,0.0,0.0), y(0.0,1.0,0.0);
00057                 x = rot_p2l * x;
00058                 y = rot_p2l * y;
00059                 if(fabs(y[0]) > 1e-8 || fabs(y[1]-1.0) > 1e-8 || 
00060                    fabs(y[2]) > 1e-8 || fabs(x[0]-1.0) > 1e-8 ||
00061                    fabs(x[1]) > 1e-8 || fabs(x[2]) > 1e-8)
00062                         rotated = true;
00063                 else
00064                         rotated = false;
00065         }
00066 public:
00067         /// Default constructor. Identity transformation.
00068         BLCoordinateTransform() : rot_p2l(), rot_l2p(), position(),
00069                                   rotated(false) { }
00070 
00071         /// Constructor for a simple unrotated position.
00072         /// pos is the parent location of the object.
00073         BLCoordinateTransform(const G4ThreeVector& pos) : rot_p2l(), 
00074                                 rot_l2p(), position(pos), rotated(false) { }
00075 
00076         /// Constructor for a rotation and position
00077         BLCoordinateTransform(const G4RotationMatrix &rot, 
00078                                 const G4ThreeVector &pos) :
00079                                 rot_p2l(rot), rot_l2p(rot),
00080                                 position(pos), rotated(false) 
00081                 { rot_p2l.invert(); checkRotation(); }
00082 
00083         /// Constructor for a rotation and position
00084         BLCoordinateTransform(const G4RotationMatrix *rot, 
00085                                 const G4ThreeVector &pos) :
00086                                 rot_p2l(), rot_l2p(),
00087                                 position(pos), rotated(false) 
00088                 { if(rot) rot_p2l = rot_l2p = *rot; rot_p2l.invert(); 
00089                   checkRotation(); }
00090 
00091         /// getLocal() - get local coordinates from global coordinates.
00092         /// This assumes that the BLCoordinateTransform transform for each
00093         /// enclosing group has been applied (in descending order).
00094         /// (otherwise "global" is really just "parent")
00095         /// Both arguments can be the same 4-vector (Point); the time coord
00096         /// is unchanged.
00097         void getLocal(G4double local[4], const G4double global[4]) const {
00098                 G4ThreeVector l, g;     //@@ can probably optimize this....
00099                 g[0] = global[0];
00100                 g[1] = global[1];
00101                 g[2] = global[2];
00102                 getLocal(l,g);
00103                 local[0] = l[0];
00104                 local[1] = l[1];
00105                 local[2] = l[2];
00106                 local[3] = global[3];
00107         }
00108 
00109         /// getLocal() - get local coordinates from global coordinates.
00110         /// This assumes that the BLCoordinateTransform transform for each
00111         /// enclosing group has been applied (in descending order).
00112         /// (otherwise "global" is really just "parent")
00113         /// The two arguments should NOT be the same.
00114         void getLocal(G4ThreeVector& local, const G4ThreeVector& global) const
00115         {
00116                 if(rotated)
00117                         local = rot_p2l * (global - position);
00118                 else
00119                         local = global - position;
00120         }
00121 
00122         /// getGlobal() - get Global coordinates from local coordinates.
00123         /// This assumes that the BLCoordinateTransform transform for each
00124         /// enclosing group has been applied (in descending order).
00125         /// (otherwise "global" is really just "parent")
00126         /// Both arguments can be the same 4-vector (Point); the time coord
00127         /// is unchanged.
00128         void getGlobal(const G4double local[4], G4double global[4]) const {
00129                 G4ThreeVector l, g;     //@@ can probably optimize this....
00130                 l[0] = local[0];
00131                 l[1] = local[1];
00132                 l[2] = local[2];
00133                 getGlobal(l,g);
00134                 global[0] = g[0];
00135                 global[1] = g[1];
00136                 global[2] = g[2];
00137                 global[3] = local[3];
00138         }
00139 
00140         /// getGlobal() - get global coordinates from local coordinates.
00141         /// This assumes that the BLCoordinateTransform transform for each
00142         /// enclosing group has been applied (in descending order).
00143         /// (otherwise "global" is really just "parent")
00144         /// The two arguments should NOT be the same.
00145         void getGlobal(const G4ThreeVector& local, G4ThreeVector& global) const
00146         {
00147                 if(rotated)
00148                         global = rot_l2p * local + position;
00149                 else
00150                         global = local + position;
00151         }
00152 
00153         /// apply() will apply a BLCoordinateTransform to this one.
00154         /// This function is used to apply the transform for a parent to
00155         /// objects placed into the parent group -- the objects' rotations
00156         /// and positions are specified wrt the parent in the parent's local
00157         /// coordinates. This routine should be called during construction,
00158         /// not during tracking (it inverts a matrix).
00159         void apply(const BLCoordinateTransform& parentTransform) {
00160                 if(parentTransform.rotated) {
00161                         position = parentTransform.rot_l2p * position +
00162                                                 parentTransform.position;
00163                         if(rotated)
00164                                 rot_p2l = rot_p2l * parentTransform.rot_p2l;
00165                         else
00166                                 rot_p2l = parentTransform.rot_p2l;
00167                         rot_l2p = rot_p2l;
00168                         rot_l2p.invert();
00169                 } else {
00170                         position += parentTransform.position;
00171                 }
00172                 checkRotation();
00173         }
00174 
00175         /// getPosition() returns the position of the transform.
00176         G4ThreeVector& getPosition() { return position; }
00177 
00178         /// getRotation() returns the Rotation of the transform.
00179         G4RotationMatrix& getRotation() { return rot_p2l; }
00180 
00181         /// getRotationInverse() returns the inverse Rotation of the transform
00182         /// (this is the active rotation of the object).
00183         /// OK to use during tracking (the inverse is computed just once).
00184         G4RotationMatrix& getRotationInverse() { return rot_l2p; }
00185 
00186         /// isRotated() returns true iff this transformation includes rotation.
00187         G4bool isRotated() const { return rotated; }
00188 };
00189 
00190 #endif // BLCOORDINATETRANSFORM_HH
g4beamline