CMS 3D CMS Logo

Transform3DPJ.cc
Go to the documentation of this file.
1 // @(#)root/mathcore:$Name: V02-02-29 $:$Id: Transform3DPJ.cc,v 1.2 2008/01/22 20:41:27 muzaffar Exp $
2 // Authors: W. Brown, M. Fischler, L. Moneta 2005
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2005 , LCG ROOT MathLib Team *
7  * *
8  * *
9  **********************************************************************/
10 
11 // implementation file for class Transform3D
12 //
13 // Created by: Lorenzo Moneta October 27 2005
14 //
15 //
16 
18 
19 #include <cmath>
20 #include <algorithm>
21 
22 
23 
24 
25 namespace ROOT {
26 
27 namespace Math {
28 
29 
32 
33 
34 // ========== Constructors and Assignment =====================
35 
36 
37 
38 // construct from two ref frames
39 Transform3DPJ::Transform3DPJ(const XYZPoint & fr0, const XYZPoint & fr1, const XYZPoint & fr2,
40  const XYZPoint & to0, const XYZPoint & to1, const XYZPoint & to2 )
41 {
42  // takes impl. from CLHEP ( E.Chernyaev). To be checked
43 
44  XYZVector x1,y1,z1, x2,y2,z2;
45  x1 = (fr1 - fr0).Unit();
46  y1 = (fr2 - fr0).Unit();
47  x2 = (to1 - to0).Unit();
48  y2 = (to2 - to0).Unit();
49 
50  // C H E C K A N G L E S
51 
52  double cos1, cos2;
53  cos1 = x1.Dot(y1);
54  cos2 = x2.Dot(y2);
55 
56  if (std::fabs(1.0-cos1) <= 0.000001 || std::fabs(1.0-cos2) <= 0.000001) {
57  std::cerr << "Transform3DPJ: Error : zero angle between axes" << std::endl;
58  SetIdentity();
59  } else {
60  if (std::fabs(cos1-cos2) > 0.000001) {
61  std::cerr << "Transform3DPJ: Warning: angles between axes are not equal"
62  << std::endl;
63  }
64 
65  // F I N D R O T A T I O N M A T R I X
66 
67  z1 = (x1.Cross(y1)).Unit();
68  y1 = z1.Cross(x1);
69 
70  z2 = (x2.Cross(y2)).Unit();
71  y2 = z2.Cross(x2);
72 
73  double x1x = x1.X(), x1y = x1.Y(), x1z = x1.Z();
74  double y1x = y1.X(), y1y = y1.Y(), y1z = y1.Z();
75  double z1x = z1.X(), z1y = z1.Y(), z1z = z1.Z();
76 
77  double detxx = (y1y*z1z - z1y*y1z);
78  double detxy = -(y1x*z1z - z1x*y1z);
79  double detxz = (y1x*z1y - z1x*y1y);
80  double detyx = -(x1y*z1z - z1y*x1z);
81  double detyy = (x1x*z1z - z1x*x1z);
82  double detyz = -(x1x*z1y - z1x*x1y);
83  double detzx = (x1y*y1z - y1y*x1z);
84  double detzy = -(x1x*y1z - y1x*x1z);
85  double detzz = (x1x*y1y - y1x*x1y);
86 
87  double x2x = x2.X(), x2y = x2.Y(), x2z = x2.Z();
88  double y2x = y2.X(), y2y = y2.Y(), y2z = y2.Z();
89  double z2x = z2.X(), z2y = z2.Y(), z2z = z2.Z();
90 
91  double txx = x2x*detxx + y2x*detyx + z2x*detzx;
92  double txy = x2x*detxy + y2x*detyy + z2x*detzy;
93  double txz = x2x*detxz + y2x*detyz + z2x*detzz;
94  double tyx = x2y*detxx + y2y*detyx + z2y*detzx;
95  double tyy = x2y*detxy + y2y*detyy + z2y*detzy;
96  double tyz = x2y*detxz + y2y*detyz + z2y*detzz;
97  double tzx = x2z*detxx + y2z*detyx + z2z*detzx;
98  double tzy = x2z*detxy + y2z*detyy + z2z*detzy;
99  double tzz = x2z*detxz + y2z*detyz + z2z*detzz;
100 
101  // S E T T R A N S F O R M A T I O N
102 
103  double dx1 = fr0.X(), dy1 = fr0.Y(), dz1 = fr0.Z();
104  double dx2 = to0.X(), dy2 = to0.Y(), dz2 = to0.Z();
105 
106  SetComponents(txx, txy, txz, dx2-txx*dx1-txy*dy1-txz*dz1,
107  tyx, tyy, tyz, dy2-tyx*dx1-tyy*dy1-tyz*dz1,
108  tzx, tzy, tzz, dz2-tzx*dx1-tzy*dy1-tzz*dz1);
109  }
110 }
111 
112 
113 // inversion (from CLHEP)
115 {
116  //
117  // Name: Transform3DPJ::inverse Date: 24.09.96
118  // Author: E.Chernyaev (IHEP/Protvino) Revised:
119  //
120  // Function: Find inverse affine transformation.
121 
122  double detxx = fM[kYY]*fM[kZZ] - fM[kYZ]*fM[kZY];
123  double detxy = fM[kYX]*fM[kZZ] - fM[kYZ]*fM[kZX];
124  double detxz = fM[kYX]*fM[kZY] - fM[kYY]*fM[kZX];
125  double det = fM[kXX]*detxx - fM[kXY]*detxy + fM[kXZ]*detxz;
126  if (det == 0) {
127  std::cerr << "Transform3DPJ::inverse error: zero determinant" << std::endl;
128  return;
129  }
130  det = 1./det; detxx *= det; detxy *= det; detxz *= det;
131  double detyx = (fM[kXY]*fM[kZZ] - fM[kXZ]*fM[kZY] )*det;
132  double detyy = (fM[kXX]*fM[kZZ] - fM[kXZ]*fM[kZX] )*det;
133  double detyz = (fM[kXX]*fM[kZY] - fM[kXY]*fM[kZX] )*det;
134  double detzx = (fM[kXY]*fM[kYZ] - fM[kXZ]*fM[kYY] )*det;
135  double detzy = (fM[kXX]*fM[kYZ] - fM[kXZ]*fM[kYX] )*det;
136  double detzz = (fM[kXX]*fM[kYY] - fM[kXY]*fM[kYX] )*det;
138  (detxx, -detyx, detzx, -detxx*fM[kDX]+detyx*fM[kDY]-detzx*fM[kDZ],
139  -detxy, detyy, -detzy, detxy*fM[kDX]-detyy*fM[kDY]+detzy*fM[kDZ],
140  detxz, -detyz, detzz, -detxz*fM[kDX]+detyz*fM[kDY]-detzz*fM[kDZ]);
141 }
142 
143 
144 // get rotations and translations
145 void Transform3DPJ::GetDecomposition ( Rotation3D &r, XYZVector &v) const
146 {
147  // decompose a trasfomation in a 3D rotation and in a 3D vector (cartesian coordinates)
148  r.SetComponents( fM[kXX], fM[kXY], fM[kXZ],
149  fM[kYX], fM[kYY], fM[kYZ],
150  fM[kZX], fM[kZY], fM[kZZ] );
151 
152  v.SetCoordinates( fM[kDX], fM[kDY], fM[kDZ] );
153 }
154 
155 // transformation on Position Vector (rotation + translations)
156 XYZPoint Transform3DPJ::operator() (const XYZPoint & p) const
157 {
158  // pass through rotation class (could be implemented directly to be faster)
159 
160  Rotation3D r;
161  XYZVector t;
162  GetDecomposition(r, t);
163  XYZPoint pnew = r(p);
164  pnew += t;
165  return pnew;
166 }
167 
168 // transformation on Displacement Vector (only rotation)
169 XYZVector Transform3DPJ::operator() (const XYZVector & v) const
170 {
171  // pass through rotation class ( could be implemented directly to be faster)
172 
173  Rotation3D r;
174  XYZVector t;
175  GetDecomposition(r, t);
176  // only rotation
177  return r(v);
178 }
179 
181 {
182  // combination of transformations
183 
184  SetComponents(fM[kXX]*t.fM[kXX]+fM[kXY]*t.fM[kYX]+fM[kXZ]*t.fM[kZX],
185  fM[kXX]*t.fM[kXY]+fM[kXY]*t.fM[kYY]+fM[kXZ]*t.fM[kZY],
186  fM[kXX]*t.fM[kXZ]+fM[kXY]*t.fM[kYZ]+fM[kXZ]*t.fM[kZZ],
187  fM[kXX]*t.fM[kDX]+fM[kXY]*t.fM[kDY]+fM[kXZ]*t.fM[kDZ]+fM[kDX],
188 
189  fM[kYX]*t.fM[kXX]+fM[kYY]*t.fM[kYX]+fM[kYZ]*t.fM[kZX],
190  fM[kYX]*t.fM[kXY]+fM[kYY]*t.fM[kYY]+fM[kYZ]*t.fM[kZY],
191  fM[kYX]*t.fM[kXZ]+fM[kYY]*t.fM[kYZ]+fM[kYZ]*t.fM[kZZ],
192  fM[kYX]*t.fM[kDX]+fM[kYY]*t.fM[kDY]+fM[kYZ]*t.fM[kDZ]+fM[kDY],
193 
194  fM[kZX]*t.fM[kXX]+fM[kZY]*t.fM[kYX]+fM[kZZ]*t.fM[kZX],
195  fM[kZX]*t.fM[kXY]+fM[kZY]*t.fM[kYY]+fM[kZZ]*t.fM[kZY],
196  fM[kZX]*t.fM[kXZ]+fM[kZY]*t.fM[kYZ]+fM[kZZ]*t.fM[kZZ],
197  fM[kZX]*t.fM[kDX]+fM[kZY]*t.fM[kDY]+fM[kZZ]*t.fM[kDZ]+fM[kDZ]);
198 
199  return *this;
200 }
201 
203 {
204  //set identity ( identity rotation and zero translation)
205  fM[kXX] = 1.0; fM[kXY] = 0.0; fM[kXZ] = 0.0; fM[kDX] = 0.0;
206  fM[kYX] = 0.0; fM[kYY] = 1.0; fM[kYZ] = 0.0; fM[kDY] = 0.0;
207  fM[kZX] = 0.0; fM[kZY] = 0.0; fM[kZZ] = 1.0; fM[kDZ] = 0.0;
208 }
209 
210 
211 void Transform3DPJ::AssignFrom (const Rotation3D & r, const XYZVector & v)
212 {
213  // assignment from rotation + translation
214 
215  double rotData[9];
216  r.GetComponents(rotData, rotData +9);
217  // first raw
218  for (int i = 0; i < 3; ++i)
219  fM[i] = rotData[i];
220  // second raw
221  for (int i = 0; i < 3; ++i)
222  fM[kYX+i] = rotData[3+i];
223  // third raw
224  for (int i = 0; i < 3; ++i)
225  fM[kZX+i] = rotData[6+i];
226 
227  // translation data
228  double vecData[3];
229  v.GetCoordinates(vecData, vecData+3);
230  fM[kDX] = vecData[0];
231  fM[kDY] = vecData[1];
232  fM[kDZ] = vecData[2];
233 }
234 
235 
236 void Transform3DPJ::AssignFrom(const Rotation3D & r)
237 {
238  // assign from only a rotation (null translation)
239  double rotData[9];
240  r.GetComponents(rotData, rotData +9);
241  for (int i = 0; i < 3; ++i) {
242  for (int j = 0; j < 3; ++j)
243  fM[4*i + j] = rotData[3*i+j];
244  // empty vector data
245  fM[4*i + 3] = 0;
246  }
247 }
248 
249 void Transform3DPJ::AssignFrom(const XYZVector & v)
250 {
251  // assign from a translation only (identity rotations)
252  fM[kXX] = 1.0; fM[kXY] = 0.0; fM[kXZ] = 0.0; fM[kDX] = v.X();
253  fM[kYX] = 0.0; fM[kYY] = 1.0; fM[kYZ] = 0.0; fM[kDY] = v.Y();
254  fM[kZX] = 0.0; fM[kZY] = 0.0; fM[kZZ] = 1.0; fM[kDZ] = v.Z();
255 }
256 
258 {
259  // transformations on a 3D plane
260  XYZVector n = plane.Normal();
261  // take a point on the plane. Use origin projection on the plane
262  // ( -ad, -bd, -cd) if (a**2 + b**2 + c**2 ) = 1
263  double d = plane.HesseDistance();
264  XYZPoint p( - d * n.X() , - d *n.Y(), -d *n.Z() );
265  return Plane3D ( operator() (n), operator() (p) );
266 }
267 
268 std::ostream & operator<< (std::ostream & os, const Transform3DPJ & t)
269 {
270  // TODO - this will need changing for machine-readable issues
271  // and even the human readable form needs formatiing improvements
272 
273  double m[12];
274  t.GetComponents(m, m+12);
275  os << "\n" << m[0] << " " << m[1] << " " << m[2] << " " << m[3] ;
276  os << "\n" << m[4] << " " << m[5] << " " << m[6] << " " << m[7] ;
277  os << "\n" << m[8] << " " << m[9] << " " << m[10]<< " " << m[11] << "\n";
278  return os;
279 }
280 
281 } // end namespace Math
282 } // end namespace ROOT
void AssignFrom(const Rotation3D &r, const Vector &v)
PositionVector3D< Cartesian3D< double >, DefaultCoordinateSystemTag > Point
Definition: Transform3DPJ.h:67
DisplacementVector3D< Cartesian3D< double >, DefaultCoordinateSystemTag > Vector
Definition: Transform3DPJ.h:66
Transform3DPJ & operator*=(const Transform3DPJ &t)
std::ostream & operator<<(std::ostream &os, const Transform3DPJ &t)
Point operator()(const Point &p) const
Transform3DPJ::Vector XYZVector
void SetComponents(IT begin, IT end)
void GetDecomposition(Rotation3D &r, Vector &v) const
Transform3DPJ::Point XYZPoint
void GetComponents(IT begin, IT end) const
ROOT::Math::Plane3D Plane3D