VGM Version 5.3
Loading...
Searching...
No Matches
transform.cxx
Go to the documentation of this file.
1// $Id$
2
3// -----------------------------------------------------------------------
4// The RootGM package of the Virtual Geometry Model
5// Copyright (C) 2007, Ivana Hrivnacova
6// All rights reserved.
7//
8// For the licensing terms see vgm/LICENSE.
9// Contact: ivana@ipno.in2p3.fr
10// -----------------------------------------------------------------------
11
12//
13// RootGM utilities
14// --------------
15// Utility functions
16//
17// Author: Ivana Hrivnacova; IPN Orsay
18
20
21#include "RootGM/common/Units.h"
23
24#include "TGeoBBox.h"
25#include "TGeoPatternFinder.h"
26#include "TMath.h"
27
28#include <float.h>
29#include <iostream>
30#include <math.h>
31
32//
33// Root -> VGM
34//
35
36//_____________________________________________________________________________
37VGM::Transform RootGM::Transform(const TGeoMatrix& matrix)
38{
39 //
40 // Translation
41 //
42 const Double_t* translation = matrix.GetTranslation();
43
44 VGM::Transform transform(VGM::kSize);
45 transform[0] = translation[VGM::kDx] * Units::Length();
46 transform[1] = translation[VGM::kDy] * Units::Length();
47 transform[2] = translation[VGM::kDz] * Units::Length();
48
49 // Rotation
50 //
51 const Double_t* rm = matrix.GetRotationMatrix();
52
53 double xx, xz, // 3x3 Rotation Matrix (xy not used)
54 yx, yy, yz, zx, zy, zz;
55
56 xx = rm[0];
57 xz = rm[2];
58 yx = rm[3];
59 yy = rm[4];
60 yz = rm[5];
61 zx = rm[6];
62 zy = rm[7];
63 zz = rm[8];
64
65 // Decompose reflectionZ from rotation matrix
66
67 if (HasReflection(matrix)) {
68 xz = -xz;
69 yz = -yz;
70 zz = -zz;
71 }
72
73 // Get axis angles
74 // (Using E.Tchernaiev formula)
75
76 double angleX;
77 double angleY;
78 double angleZ;
79 double cosb = sqrt(xx * xx + yx * yx);
80 if (cosb > 16 * FLT_EPSILON) {
81 angleX = atan2(zy, zz);
82 angleY = atan2(-zx, cosb);
83 angleZ = atan2(yx, xx);
84 }
85 else {
86 angleX = atan2(-yz, yy);
87 angleY = atan2(-zx, cosb);
88 angleZ = 0.;
89 }
90
91 transform[VGM::kAngleX] = angleX * TMath::RadToDeg() * Units::Angle();
92 transform[VGM::kAngleY] = angleY * TMath::RadToDeg() * Units::Angle();
93 transform[VGM::kAngleZ] = angleZ * TMath::RadToDeg() * Units::Angle();
94
95 // Reflection
96 //
97 transform[VGM::kReflZ] = 0.;
98 if (matrix.IsReflection()) transform[VGM::kReflZ] = 1.;
99
100 return transform;
101}
102
103//_____________________________________________________________________________
105{
106 const Double_t* dscale = scale.GetScale();
107
108 VGM::Transform transform(VGM::kSize);
109 transform[VGM::kDx] = dscale[0];
110 transform[VGM::kDy] = dscale[1];
111 transform[VGM::kDz] = dscale[2];
112
113 return transform;
114}
115
116//_____________________________________________________________________________
117bool RootGM::HasReflection(const TGeoMatrix& matrix)
118{
119 //
120 /*
121 // Decompose general matrix
122 const Double_t* rm = matrix.GetRotation()
123
124 // Matrix
125 // rm[0] * sm[0], rm[1] * sm[1], rm[2] * sm[2], tm[0]
126 // rm[3] * sm[0], rm[4] * sm[1], rm[5] * sm[2], tm[1]
127 // rm[6] * sm[0], rm[7] * sm[1], rm[8] * sm[2], tm[2]
128
129 double xx, xy, xz, dx, // 4x3 Transformation Matrix
130 yx, yy, yz, dy,
131 zx, zy, zz, dz;
132
133 xx = rm[0]; xy = rm[1]; xz = rm[2];
134 yx = rm[3]; yy = rm[4]; yz = rm[5];
135 zx = rm[6]; zy = rm[7]; zz = rm[8];
136 dx = tm[0]; dy = tm[1]; dz = tm[2];
137 sx = sm[0]; sy = sm[1]; sz = sm[2];
138
139 // If reflection, apply it to scaleZ
140 if (xx*(yy*zz-yz*zy) - xy*(yx*zz-yz*zx) + xz*(yx*zy-yy*zx) < 0)
141 return true;
142 else
143 return false
144 */
145
146 return matrix.IsReflection();
147}
148
149//
150// VGM -> Root
151//
152
153//_____________________________________________________________________________
154TGeoMatrix* RootGM::CreateTransform(const VGM::Transform& transform)
155{
156
157 if (transform.size() != VGM::kSize) {
158 std::cerr << "RootGM::CreateTransform: " << std::endl;
159 std::cerr << "Wrong transform vector size. " << std::endl;
160 exit(1);
161 }
162
163 TGeoRotation* rootRotation = new TGeoRotation();
164 rootRotation->RotateX(transform[VGM::kAngleX] / Units::Angle());
165 rootRotation->RotateY(transform[VGM::kAngleY] / Units::Angle());
166 rootRotation->RotateZ(transform[VGM::kAngleZ] / Units::Angle());
167
168 if (HasReflection(transform)) {
169 // copy matrix in a new one
170 const Double_t* matrix = rootRotation->GetRotationMatrix();
171 Double_t matrix2[9];
172 for (Int_t i = 0; i < 9; i++) matrix2[i] = matrix[i];
173
174 // apply reflectionZ to rotation matrix
175 matrix2[2] = -matrix2[2]; // xz
176 matrix2[5] = -matrix2[5]; // yz
177 matrix2[8] = -matrix2[8]; // zz
178
179 // reset matrix
180 rootRotation->SetMatrix(matrix2);
181 }
182
183 return new TGeoCombiTrans(transform[VGM::kDx] / Units::Length(),
184 transform[VGM::kDy] / Units::Length(),
185 transform[VGM::kDz] / Units::Length(), rootRotation);
186}
187
188//_____________________________________________________________________________
189TGeoScale* RootGM::CreateScale(const VGM::Transform& transform)
190{
191 return new TGeoScale(
192 transform[VGM::kDx], transform[VGM::kDy], transform[VGM::kDz]);
193}
194
195//_____________________________________________________________________________
197{
198 return BaseVGM::Round(transform[VGM::kReflZ]) == 1.;
199}
200
201//
202// Root special
203//
204
205//_____________________________________________________________________________
206TGeoHMatrix RootGM::Displacement(TGeoShape* shape)
207{
208 TGeoBBox* box = dynamic_cast<TGeoBBox*>(shape);
209 if (!box) return TGeoHMatrix();
210
211 const Double_t* origin = box->GetOrigin();
212 if (!origin) return TGeoHMatrix();
213
214 return TGeoHMatrix(TGeoTranslation(origin[0], origin[1], origin[2]));
215 ;
216}
217
218//_____________________________________________________________________________
219
220// The following code was taken from the paper:
221// http://jgt.akpeters.com/papers/MollerHughes99/
222// Changed float to double.
223// See below the authors.
224
225#include <math.h>
226
227#define EPSILON 0.000001
228
229#define CROSS(dest, v1, v2) \
230 { \
231 dest[0] = v1[1] * v2[2] - v1[2] * v2[1]; \
232 dest[1] = v1[2] * v2[0] - v1[0] * v2[2]; \
233 dest[2] = v1[0] * v2[1] - v1[1] * v2[0]; \
234 }
235
236#define DOT(v1, v2) (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2])
237
238#define SUB(dest, v1, v2) \
239 { \
240 dest[0] = v1[0] - v2[0]; \
241 dest[1] = v1[1] - v2[1]; \
242 dest[2] = v1[2] - v2[2]; \
243 }
244
245/*
246 * A function for creating a rotation matrix that rotates a vector called
247 * "from" into another vector called "to".
248 * Input : from[3], to[3] which both must be *normalized* non-zero vectors
249 * Output: mtx[3][3] -- a 3x3 matrix in colum-major form
250 * Authors: Tomas Möller, John Hughes
251 * "Efficiently Building a Matrix to Rotate One Vector to Another"
252 * Journal of Graphics Tools, 4(4):1-4, 1999
253 */
254void RootGM::fromToRotation(double from[3], double to[3], double mtx[3][3])
255{
256 double v[3];
257 double e, h, f;
258
259 CROSS(v, from, to);
260 e = DOT(from, to);
261 f = (e < 0) ? -e : e;
262 if (f > 1.0 - EPSILON) /* "from" and "to"-vector almost parallel */
263 {
264 double utmp[3], vtmp[3]; /* temporary storage vectors */
265 double x[3]; /* vector most nearly orthogonal to "from" */
266 double c1, c2, c3; /* coefficients for later use */
267 int i, j;
268
269 x[0] = (from[0] > 0.0) ? from[0] : -from[0];
270 x[1] = (from[1] > 0.0) ? from[1] : -from[1];
271 x[2] = (from[2] > 0.0) ? from[2] : -from[2];
272
273 if (x[0] < x[1]) {
274 if (x[0] < x[2]) {
275 x[0] = 1.0;
276 x[1] = x[2] = 0.0;
277 }
278 else {
279 x[2] = 1.0;
280 x[0] = x[1] = 0.0;
281 }
282 }
283 else {
284 if (x[1] < x[2]) {
285 x[1] = 1.0;
286 x[0] = x[2] = 0.0;
287 }
288 else {
289 x[2] = 1.0;
290 x[0] = x[1] = 0.0;
291 }
292 }
293
294 utmp[0] = x[0] - from[0];
295 utmp[1] = x[1] - from[1];
296 utmp[2] = x[2] - from[2];
297 vtmp[0] = x[0] - to[0];
298 vtmp[1] = x[1] - to[1];
299 vtmp[2] = x[2] - to[2];
300
301 c1 = 2.0 / DOT(utmp, utmp);
302 c2 = 2.0 / DOT(vtmp, vtmp);
303 c3 = c1 * c2 * DOT(utmp, vtmp);
304
305 for (i = 0; i < 3; i++) {
306 for (j = 0; j < 3; j++) {
307 mtx[i][j] = -c1 * utmp[i] * utmp[j] - c2 * vtmp[i] * vtmp[j] +
308 c3 * vtmp[i] * utmp[j];
309 }
310 mtx[i][i] += 1.0;
311 }
312 }
313 else /* the most common case, unless "from"="to", or "from"=-"to" */
314 {
315#if 0
316 /* unoptimized version - a good compiler will optimize this. */
317 /* h = (1.0 - e)/DOT(v, v); old code */
318 h = 1.0/(1.0 + e); /* optimization by Gottfried Chen */
319 mtx[0][0] = e + h * v[0] * v[0];
320 mtx[0][1] = h * v[0] * v[1] - v[2];
321 mtx[0][2] = h * v[0] * v[2] + v[1];
322
323 mtx[1][0] = h * v[0] * v[1] + v[2];
324 mtx[1][1] = e + h * v[1] * v[1];
325 mtx[1][2] = h * v[1] * v[2] - v[0];
326
327 mtx[2][0] = h * v[0] * v[2] - v[1];
328 mtx[2][1] = h * v[1] * v[2] + v[0];
329 mtx[2][2] = e + h * v[2] * v[2];
330#else
331 /* ...otherwise use this hand optimized version (9 mults less) */
332 double hvx, hvz, hvxy, hvxz, hvyz;
333 /* h = (1.0 - e)/DOT(v, v); old code */
334 h = 1.0 / (1.0 + e); /* optimization by Gottfried Chen */
335 hvx = h * v[0];
336 hvz = h * v[2];
337 hvxy = hvx * v[1];
338 hvxz = hvx * v[2];
339 hvyz = hvz * v[1];
340 mtx[0][0] = e + hvx * v[0];
341 mtx[0][1] = hvxy - v[2];
342 mtx[0][2] = hvxz + v[1];
343
344 mtx[1][0] = hvxy + v[2];
345 mtx[1][1] = e + h * v[1] * v[1];
346 mtx[1][2] = hvyz - v[0];
347
348 mtx[2][0] = hvxz - v[1];
349 mtx[2][1] = hvyz + v[0];
350 mtx[2][2] = e + hvz * v[2];
351#endif
352 }
353}
#define EPSILON
#define CROSS(dest, v1, v2)
#define DOT(v1, v2)
double Round(double x)
Round number.
Definition utilities.cxx:34
void fromToRotation(double from[3], double to[3], double mtx[3][3])
TGeoScale * CreateScale(const VGM::Transform &transform)
TGeoMatrix * CreateTransform(const VGM::Transform &transform)
TGeoHMatrix Displacement(TGeoShape *shape)
VGM::Transform Transform(const TGeoMatrix &matrix)
Definition transform.cxx:37
bool HasReflection(const TGeoMatrix &matrix)
VGM::Transform TransformScale(const TGeoScale &scale)
std::vector< double > Transform
Definition Transform.h:40
@ kAngleZ
Definition Transform.h:49
@ kDx
Definition Transform.h:44
@ kSize
Definition Transform.h:51
@ kReflZ
Definition Transform.h:50
@ kAngleY
Definition Transform.h:48
@ kDz
Definition Transform.h:46
@ kAngleX
Definition Transform.h:47
@ kDy
Definition Transform.h:45