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