ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RotationC.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RotationC.cc
1 // -*- C++ -*-
2 // ---------------------------------------------------------------------------
3 //
4 // This file is a part of the CLHEP - a Class Library for High Energy Physics.
5 //
6 // This is the implementation of methods of the HepRotation class which
7 // were introduced when ZOOM PhysicsVectors was merged in, which involve
8 // correcting user-supplied data which is supposed to form a Rotation, or
9 // rectifying a rotation matrix which may have drifted due to roundoff.
10 //
11 
12 #ifdef GNUPRAGMA
13 #pragma implementation
14 #endif
15 
16 #include "CLHEP/Vector/Rotation.h"
17 
18 #include <cmath>
19 
20 namespace CLHEP {
21 
22 // --------- Helper methods (private) for setting from 3 columns:
23 
25  ( const Hep3Vector & u1, const Hep3Vector & u2, const Hep3Vector & u3,
26  double u1u2,
27  Hep3Vector & v1, Hep3Vector & v2, Hep3Vector & v3 ) const {
28 
29  if ( (1-std::fabs(u1u2)) <= Hep4RotationInterface::tolerance ) {
30  std::cerr << "HepRotation::setCols() - "
31  << "All three cols supplied for a Rotation are parallel --"
32  << "\n an arbitrary rotation will be returned" << std::endl;
33  setArbitrarily (u1, v1, v2, v3);
34  return true;
35  }
36 
37  v1 = u1;
38  v2 = Hep3Vector(u2 - u1u2 * u1).unit();
39  v3 = v1.cross(v2);
40  if ( v3.dot(u3) >= 0 ) {
41  return true;
42  } else {
43  return false; // looks more like a reflection in this case!
44  }
45 
46 } // HepRotation::setCols
47 
49  Hep3Vector & v1, Hep3Vector & v2, Hep3Vector & v3) const {
50 
51  // We have all three col's parallel. Warnings already been given;
52  // this just supplies a result which is a valid rotation.
53 
54  v1 = ccolX.unit();
55  v2 = v1.cross(Hep3Vector(0,0,1));
56  if (v2.mag2() != 0) {
57  v2 = v2.unit();
58  } else {
59  v2 = Hep3Vector(1,0,0);
60  }
61  v3 = v1.cross(v2);
62 
63  return;
64 
65 } // HepRotation::setArbitrarily
66 
67 
68 
69 // ---------- Constructors and Assignment:
70 
71 // 3 orthogonal columns or rows
72 
74  const Hep3Vector & ccolY,
75  const Hep3Vector & ccolZ ) {
76  Hep3Vector ucolX = ccolX.unit();
77  Hep3Vector ucolY = ccolY.unit();
78  Hep3Vector ucolZ = ccolZ.unit();
79 
80  double u1u2 = ucolX.dot(ucolY);
81  double f12 = std::fabs(u1u2);
83  std::cerr << "HepRotation::set() - "
84  << "col's X and Y supplied for Rotation are not close to orthogonal"
85  << std::endl;
86  }
87  double u1u3 = ucolX.dot(ucolZ);
88  double f13 = std::fabs(u1u3);
90  std::cerr << "HepRotation::set() - "
91  << "col's X and Z supplied for Rotation are not close to orthogonal"
92  << std::endl;
93  }
94  double u2u3 = ucolY.dot(ucolZ);
95  double f23 = std::fabs(u2u3);
97  std::cerr << "HepRotation::set() - "
98  << "col's Y and Z supplied for Rotation are not close to orthogonal"
99  << std::endl;
100  }
101 
102  Hep3Vector v1, v2, v3;
103  bool isRotation;
104  if ( (f12 <= f13) && (f12 <= f23) ) {
105  isRotation = setCols ( ucolX, ucolY, ucolZ, u1u2, v1, v2, v3 );
106  if ( !isRotation ) {
107  std::cerr << "HepRotation::set() - "
108  << "col's X Y and Z supplied form closer to a reflection than a Rotation "
109  << "\n col Z is set to col X cross col Y" << std::endl;
110  }
111  } else if ( f13 <= f23 ) {
112  isRotation = setCols ( ucolZ, ucolX, ucolY, u1u3, v3, v1, v2 );
113  if ( !isRotation ) {
114  std::cerr << "HepRotation::set() - "
115  << "col's X Y and Z supplied form closer to a reflection than a Rotation "
116  << "\n col Y is set to col Z cross col X" << std::endl;
117  }
118  } else {
119  isRotation = setCols ( ucolY, ucolZ, ucolX, u2u3, v2, v3, v1 );
120  if ( !isRotation ) {
121  std::cerr << "HepRotation::set() - "
122  << "col's X Y and Z supplied form closer to a reflection than a Rotation "
123  << "\n col X is set to col Y cross col Z" << std::endl;
124  }
125  }
126 
127  rxx = v1.x(); ryx = v1.y(); rzx = v1.z();
128  rxy = v2.x(); ryy = v2.y(); rzy = v2.z();
129  rxz = v3.x(); ryz = v3.y(); rzz = v3.z();
130 
131  return *this;
132 
133 } // HepRotation::set(colX, colY, colZ)
134 
136  const Hep3Vector & ccolY,
137  const Hep3Vector & ccolZ )
138 {
139  set (ccolX, ccolY, ccolZ);
140 }
141 
143  const Hep3Vector & rrowY,
144  const Hep3Vector & rrowZ ) {
145  set (rrowX, rrowY, rrowZ);
146  invert();
147  return *this;
148 }
149 
150 // ------- Rectify a near-rotation
151 
153  // Assuming the representation of this is close to a true Rotation,
154  // but may have drifted due to round-off error from many operations,
155  // this forms an "exact" orthonormal matrix for the rotation again.
156 
157  // The first step is to average with the transposed inverse. This
158  // will correct for small errors such as those occuring when decomposing
159  // a LorentzTransformation. Then we take the bull by the horns and
160  // formally extract the axis and delta (assuming the Rotation were true)
161  // and re-setting the rotation according to those.
162 
163  double det = rxx * ryy * rzz +
164  rxy * ryz * rzx +
165  rxz * ryx * rzy -
166  rxx * ryz * rzy -
167  rxy * ryx * rzz -
168  rxz * ryy * rzx ;
169  if (det <= 0) {
170  std::cerr << "HepRotation::rectify() - "
171  << "Attempt to rectify a Rotation with determinant <= 0" << std::endl;
172  return;
173  }
174  double di = 1.0 / det;
175 
176  // xx, xy, ... are components of inverse matrix:
177  double xx1 = (ryy * rzz - ryz * rzy) * di;
178  double xy1 = (rzy * rxz - rzz * rxy) * di;
179  double xz1 = (rxy * ryz - rxz * ryy) * di;
180  double yx1 = (ryz * rzx - ryx * rzz) * di;
181  double yy1 = (rzz * rxx - rzx * rxz) * di;
182  double yz1 = (rxz * ryx - rxx * ryz) * di;
183  double zx1 = (ryx * rzy - ryy * rzx) * di;
184  double zy1 = (rzx * rxy - rzy * rxx) * di;
185  double zz1 = (rxx * ryy - rxy * ryx) * di;
186 
187  // Now average with the TRANSPOSE of that:
188  rxx = .5*(rxx + xx1);
189  rxy = .5*(rxy + yx1);
190  rxz = .5*(rxz + zx1);
191  ryx = .5*(ryx + xy1);
192  ryy = .5*(ryy + yy1);
193  ryz = .5*(ryz + zy1);
194  rzx = .5*(rzx + xz1);
195  rzy = .5*(rzy + yz1);
196  rzz = .5*(rzz + zz1);
197 
198  // Now force feed this improved rotation
199  double del = delta();
200  Hep3Vector u = axis();
201  u = u.unit(); // Because if the rotation is inexact, then the
202  // axis() returned will not have length 1!
203  set(u, del);
204 
205 } // rectify()
206 
207 } // namespace CLHEP
208