Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4UPara.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// Implementation for G4UPara wrapper class
27//
28// 13.09.13 G.Cosmo, CERN
29// --------------------------------------------------------------------
30
31#include "G4Para.hh"
32#include "G4UPara.hh"
33
34#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
35
36#include "G4AffineTransform.hh"
38#include "G4BoundingEnvelope.hh"
39
40using namespace CLHEP;
41
42//////////////////////////////////////////////////////////////////////////
43//
44// Constructor - set & check half widths
45
46G4UPara::G4UPara(const G4String& pName,
47 G4double pDx, G4double pDy, G4double pDz,
48 G4double pAlpha, G4double pTheta, G4double pPhi)
49 : Base_t(pName, pDx, pDy, pDz, pAlpha, pTheta, pPhi)
50{
51 fTalpha = std::tan(pAlpha);
52 fTthetaCphi = std::tan(pTheta)*std::cos(pPhi);
53 fTthetaSphi = std::tan(pTheta)*std::sin(pPhi);
54 CheckParameters();
55 MakePlanes();
56}
57
58//////////////////////////////////////////////////////////////////////////
59//
60// Constructor - design of trapezoid based on 8 vertices
61
62G4UPara::G4UPara( const G4String& pName,
63 const G4ThreeVector pt[8] )
64 : Base_t(pName)
65{
66 // Find dimensions and trigonometric values
67 //
68 G4double fDx = (pt[3].x() - pt[2].x())*0.5;
69 G4double fDy = (pt[2].y() - pt[1].y())*0.5;
70 G4double fDz = pt[7].z();
71 SetDimensions(fDx, fDy, fDz);
72 CheckParameters(); // check dimensions
73
74 fTalpha = (pt[2].x() + pt[3].x() - pt[1].x() - pt[0].x())*0.25/fDy;
75 fTthetaCphi = (pt[4].x() + fDy*fTalpha + fDx)/fDz;
76 fTthetaSphi = (pt[4].y() + fDy)/fDz;
77 SetAlpha(std::atan(fTalpha));
78 SetTheta(std::atan(std::sqrt(fTthetaSphi*fTthetaSphi
79 + fTthetaCphi*fTthetaCphi)));
80 SetPhi (std::atan2(fTthetaSphi, fTthetaCphi));
81 MakePlanes();
82
83 // Recompute vertices
84 //
85 G4ThreeVector v[8];
86 G4double DyTalpha = fDy*fTalpha;
87 G4double DzTthetaSphi = fDz*fTthetaSphi;
88 G4double DzTthetaCphi = fDz*fTthetaCphi;
89 v[0].set(-DzTthetaCphi-DyTalpha-fDx, -DzTthetaSphi-fDy, -fDz);
90 v[1].set(-DzTthetaCphi-DyTalpha+fDx, -DzTthetaSphi-fDy, -fDz);
91 v[2].set(-DzTthetaCphi+DyTalpha-fDx, -DzTthetaSphi+fDy, -fDz);
92 v[3].set(-DzTthetaCphi+DyTalpha+fDx, -DzTthetaSphi+fDy, -fDz);
93 v[4].set( DzTthetaCphi-DyTalpha-fDx, DzTthetaSphi-fDy, fDz);
94 v[5].set( DzTthetaCphi-DyTalpha+fDx, DzTthetaSphi-fDy, fDz);
95 v[6].set( DzTthetaCphi+DyTalpha-fDx, DzTthetaSphi+fDy, fDz);
96 v[7].set( DzTthetaCphi+DyTalpha+fDx, DzTthetaSphi+fDy, fDz);
97
98 // Compare with original vertices
99 //
100 for (G4int i=0; i<8; ++i)
101 {
102 G4double delx = std::abs(pt[i].x() - v[i].x());
103 G4double dely = std::abs(pt[i].y() - v[i].y());
104 G4double delz = std::abs(pt[i].z() - v[i].z());
105 G4double discrepancy = std::max(std::max(delx,dely),delz);
106 if (discrepancy > 0.1*kCarTolerance)
107 {
108 std::ostringstream message;
109 G4long oldprc = message.precision(16);
110 message << "Invalid vertice coordinates for Solid: " << GetName()
111 << "\nVertix #" << i << ", discrepancy = " << discrepancy
112 << "\n original : " << pt[i]
113 << "\n recomputed : " << v[i];
114 G4cout.precision(oldprc);
115 G4Exception("G4UPara::G4UPara()", "GeomSolids0002",
116 FatalException, message);
117
118 }
119 }
120}
121
122//////////////////////////////////////////////////////////////////////////
123//
124// Copy constructor
125
126G4UPara::G4UPara(const G4UPara& rhs)
127 : Base_t(rhs), fTalpha(rhs.fTalpha),
128 fTthetaCphi(rhs.fTthetaCphi),fTthetaSphi(rhs.fTthetaSphi)
129{
130 for (G4int i=0; i<4; ++i) { fPlanes[i] = rhs.fPlanes[i]; }
131}
132
133//////////////////////////////////////////////////////////////////////////
134//
135// Assignment operator
136
137G4UPara& G4UPara::operator = (const G4UPara& rhs)
138{
139 // Check assignment to self
140 //
141 if (this == &rhs) { return *this; }
142
143 // Copy base class data
144 //
145 Base_t::operator=(rhs);
146
147 // Copy data
148 //
149 fTalpha = rhs.fTalpha;
150 fTthetaCphi = rhs.fTthetaCphi;
151 fTthetaSphi = rhs.fTthetaSphi;
152 for (G4int i=0; i<4; ++i) { fPlanes[i] = rhs.fPlanes[i]; }
153
154 return *this;
155}
156
157//////////////////////////////////////////////////////////////////////////
158//
159// Accessors & modifiers
160
161G4double G4UPara::GetZHalfLength() const
162{
163 return GetZ();
164}
165G4double G4UPara::GetYHalfLength() const
166{
167 return GetY();
168}
169G4double G4UPara::GetXHalfLength() const
170{
171 return GetX();
172}
173G4ThreeVector G4UPara::GetSymAxis() const
174{
175 return G4ThreeVector(fTthetaCphi,fTthetaSphi,1.).unit();
176}
177G4double G4UPara::GetTanAlpha() const
178{
179 return fTalpha;
180}
181
182G4double G4UPara::GetPhi() const
183{
184 return std::atan2(fTthetaSphi,fTthetaCphi);
185}
186
187G4double G4UPara::GetTheta() const
188{
189 return std::atan(std::sqrt(fTthetaCphi*fTthetaCphi
190 +fTthetaSphi*fTthetaSphi));
191}
192
193G4double G4UPara::GetAlpha() const
194{
195 return std::atan(fTalpha);
196}
197
198void G4UPara::SetXHalfLength(G4double val)
199{
200 SetDimensions(val, GetY(), GetZ());
201 fRebuildPolyhedron = true;
202
203 CheckParameters();
204 MakePlanes();
205}
206void G4UPara::SetYHalfLength(G4double val)
207{
208 SetDimensions(GetX(), val, GetZ());
209 fRebuildPolyhedron = true;
210
211 CheckParameters();
212 MakePlanes();
213}
214void G4UPara::SetZHalfLength(G4double val)
215{
216 SetDimensions(GetX(), GetY(), val);
217 fRebuildPolyhedron = true;
218
219 CheckParameters();
220 MakePlanes();
221}
222void G4UPara::SetAlpha(G4double alpha)
223{
224 Base_t::SetAlpha(alpha);
225 fTalpha = std::tan(alpha);
226 fRebuildPolyhedron = true;
227
228 MakePlanes();
229}
230void G4UPara::SetTanAlpha(G4double val)
231{
232 fTalpha = val;
233 fRebuildPolyhedron = true;
234
235 MakePlanes();
236}
237void G4UPara::SetThetaAndPhi(double pTheta, double pPhi)
238{
239 Base_t::SetThetaAndPhi(pTheta, pPhi);
240 G4double tanTheta = std::tan(pTheta);
241 fTthetaCphi = tanTheta*std::cos(pPhi);
242 fTthetaSphi = tanTheta*std::sin(pPhi);
243 fRebuildPolyhedron = true;
244
245 MakePlanes();
246}
247
248//////////////////////////////////////////////////////////////////////////
249//
250// Set all parameters, as for constructor - set and check half-widths
251
252void G4UPara::SetAllParameters(G4double pDx, G4double pDy, G4double pDz,
253 G4double pAlpha, G4double pTheta, G4double pPhi)
254{
255 // Reset data of the base class
256 fRebuildPolyhedron = true;
257
258 // Set parameters
259 SetDimensions(pDx, pDy, pDz);
260 Base_t::SetAlpha(pAlpha);
261 Base_t::SetThetaAndPhi(pTheta, pPhi);
262 fTalpha = std::tan(pAlpha);
263 fTthetaCphi = std::tan(pTheta)*std::cos(pPhi);
264 fTthetaSphi = std::tan(pTheta)*std::sin(pPhi);
265
266 CheckParameters();
267 MakePlanes();
268}
269
270//////////////////////////////////////////////////////////////////////////
271//
272// Check dimensions
273
274void G4UPara::CheckParameters()
275{
276 if (GetX() < 2*kCarTolerance ||
277 GetY() < 2*kCarTolerance ||
278 GetZ() < 2*kCarTolerance)
279 {
280 std::ostringstream message;
281 message << "Invalid (too small or negative) dimensions for Solid: "
282 << GetName()
283 << "\n X - " << GetX()
284 << "\n Y - " << GetY()
285 << "\n Z - " << GetZ();
286 G4Exception("G4UPara::CheckParameters()", "GeomSolids0002",
287 FatalException, message);
288 }
289}
290
291//////////////////////////////////////////////////////////////////////////
292//
293// Set side planes
294
295void G4UPara::MakePlanes()
296{
297 G4ThreeVector vx(1, 0, 0);
298 G4ThreeVector vy(fTalpha, 1, 0);
299 G4ThreeVector vz(fTthetaCphi, fTthetaSphi, 1);
300
301 // Set -Y & +Y planes
302 //
303 G4ThreeVector ynorm = (vx.cross(vz)).unit();
304
305 fPlanes[0].a = 0.;
306 fPlanes[0].b = ynorm.y();
307 fPlanes[0].c = ynorm.z();
308 fPlanes[0].d = fPlanes[0].b*GetY(); // point (0,fDy,0) is on plane
309
310 fPlanes[1].a = 0.;
311 fPlanes[1].b = -fPlanes[0].b;
312 fPlanes[1].c = -fPlanes[0].c;
313 fPlanes[1].d = fPlanes[0].d;
314
315 // Set -X & +X planes
316 //
317 G4ThreeVector xnorm = (vz.cross(vy)).unit();
318
319 fPlanes[2].a = xnorm.x();
320 fPlanes[2].b = xnorm.y();
321 fPlanes[2].c = xnorm.z();
322 fPlanes[2].d = fPlanes[2].a*GetZ(); // point (fDx,0,0) is on plane
323
324 fPlanes[3].a = -fPlanes[2].a;
325 fPlanes[3].b = -fPlanes[2].b;
326 fPlanes[3].c = -fPlanes[2].c;
327 fPlanes[3].d = fPlanes[2].d;
328}
329
330//////////////////////////////////////////////////////////////////////////
331//
332// Dispatch to parameterisation for replication mechanism dimension
333// computation & modification
334
335void G4UPara::ComputeDimensions( G4VPVParameterisation* p,
336 const G4int n,
337 const G4VPhysicalVolume* pRep )
338{
339 p->ComputeDimensions(*(G4Para*)this,n,pRep);
340}
341
342//////////////////////////////////////////////////////////////////////////
343//
344// Get bounding box
345
346void G4UPara::BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const
347{
348 G4double dz = GetZHalfLength();
349 G4double dx = GetXHalfLength();
350 G4double dy = GetYHalfLength();
351
352 G4double x0 = dz*fTthetaCphi;
353 G4double x1 = dy*GetTanAlpha();
354 G4double xmin =
355 std::min(
356 std::min(
357 std::min(-x0-x1-dx,-x0+x1-dx),x0-x1-dx),x0+x1-dx);
358 G4double xmax =
359 std::max(
360 std::max(
361 std::max(-x0-x1+dx,-x0+x1+dx),x0-x1+dx),x0+x1+dx);
362
363 G4double y0 = dz*fTthetaSphi;
364 G4double ymin = std::min(-y0-dy,y0-dy);
365 G4double ymax = std::max(-y0+dy,y0+dy);
366
367 pMin.set(xmin,ymin,-dz);
368 pMax.set(xmax,ymax, dz);
369
370 // Check correctness of the bounding box
371 //
372 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
373 {
374 std::ostringstream message;
375 message << "Bad bounding box (min >= max) for solid: "
376 << GetName() << " !"
377 << "\npMin = " << pMin
378 << "\npMax = " << pMax;
379 G4Exception("G4UPara::BoundingLimits()", "GeomMgt0001",
380 JustWarning, message);
381 StreamInfo(G4cout);
382 }
383}
384
385//////////////////////////////////////////////////////////////////////////
386//
387// Calculate extent under transform and specified limit
388
389G4bool G4UPara::CalculateExtent( const EAxis pAxis,
390 const G4VoxelLimits& pVoxelLimit,
391 const G4AffineTransform& pTransform,
392 G4double& pMin, G4double& pMax ) const
393{
394 G4ThreeVector bmin, bmax;
395 G4bool exist;
396
397 // Check bounding box (bbox)
398 //
399 BoundingLimits(bmin,bmax);
400 G4BoundingEnvelope bbox(bmin,bmax);
401#ifdef G4BBOX_EXTENT
402 if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
403#endif
404 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
405 {
406 return exist = pMin < pMax;
407 }
408
409 // Set bounding envelope (benv) and calculate extent
410 //
411 G4double dz = GetZHalfLength();
412 G4double dx = GetXHalfLength();
413 G4double dy = GetYHalfLength();
414
415 G4double x0 = dz*fTthetaCphi;
416 G4double x1 = dy*GetTanAlpha();
417 G4double y0 = dz*fTthetaSphi;
418
419 G4ThreeVectorList baseA(4), baseB(4);
420 baseA[0].set(-x0-x1-dx,-y0-dy,-dz);
421 baseA[1].set(-x0-x1+dx,-y0-dy,-dz);
422 baseA[2].set(-x0+x1+dx,-y0+dy,-dz);
423 baseA[3].set(-x0+x1-dx,-y0+dy,-dz);
424
425 baseB[0].set(+x0-x1-dx, y0-dy, dz);
426 baseB[1].set(+x0-x1+dx, y0-dy, dz);
427 baseB[2].set(+x0+x1+dx, y0+dy, dz);
428 baseB[3].set(+x0+x1-dx, y0+dy, dz);
429
430 std::vector<const G4ThreeVectorList *> polygons(2);
431 polygons[0] = &baseA;
432 polygons[1] = &baseB;
433
434 G4BoundingEnvelope benv(bmin,bmax,polygons);
435 exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
436 return exist;
437}
438
439//////////////////////////////////////////////////////////////////////////
440//
441// Make a clone of the object
442//
443G4VSolid* G4UPara::Clone() const
444{
445 return new G4UPara(*this);
446}
447
448//////////////////////////////////////////////////////////////////////////
449//
450// Methods for visualisation
451
452G4Polyhedron* G4UPara::CreatePolyhedron () const
453{
454 return new G4PolyhedronPara(GetX(), GetY(), GetZ(),
455 GetAlpha(), GetTheta(), GetPhi());
456}
457
458#endif // G4GEOM_USE_USOLIDS
const G4double kCarTolerance
std::vector< G4ThreeVector > G4ThreeVectorList
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
long G4long
Definition G4Types.hh:87
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4GLOB_DLL std::ostream G4cout
double z() const
Hep3Vector unit() const
double x() const
double y() const
void set(double x, double y, double z)
G4AffineTransform is a class for geometric affine transformations. It supports efficient arbitrary ro...
G4BoundingEnvelope is a helper class to facilitate calculation of the extent of a solid within the li...
G4Para represents a parallelepiped, essentially a box with half lengths dx,dy,dz 'skewed' so that the...
Definition G4Para.hh:86
G4VPVParameterisation ia an abstract base class for Parameterisation, able to compute the transformat...
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4VPhysicalVolume is an abstract base class for the representation of a positioned volume....
G4VSolid is an abstract base class for solids, physical shapes that can be tracked through....
Definition G4VSolid.hh:80
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
EAxis
Definition geomdefs.hh:54