ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4UPara.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4UPara.cc
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/PH
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"
37 #include "G4VPVParameterisation.hh"
38 #include "G4BoundingEnvelope.hh"
39 
40 using namespace CLHEP;
41 
43 //
44 // Constructor - set & check half widths
45 
46 G4UPara::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 
59 //
60 // Constructor - design of trapezoid based on 8 vertices
61 
62 G4UPara::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  G4int 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 
123 //
124 // Fake default constructor - sets only member data and allocates memory
125 // for usage restricted to object persistency
126 
127 G4UPara::G4UPara( __void__& a )
128  : Base_t(a)
129 {
130  SetAllParameters(1., 1., 1., 0., 0., 0.);
131  fRebuildPolyhedron = false;
132 }
133 
135 //
136 // Destructor
137 
138 G4UPara::~G4UPara()
139 {
140 }
141 
143 //
144 // Copy constructor
145 
146 G4UPara::G4UPara(const G4UPara& rhs)
147  : Base_t(rhs), fTalpha(rhs.fTalpha),
148  fTthetaCphi(rhs.fTthetaCphi),fTthetaSphi(rhs.fTthetaSphi)
149 {
150  for (G4int i=0; i<4; ++i) { fPlanes[i] = rhs.fPlanes[i]; }
151 }
152 
154 //
155 // Assignment operator
156 
157 G4UPara& G4UPara::operator = (const G4UPara& rhs)
158 {
159  // Check assignment to self
160  //
161  if (this == &rhs) { return *this; }
162 
163  // Copy base class data
164  //
165  Base_t::operator=(rhs);
166 
167  // Copy data
168  //
169  fTalpha = rhs.fTalpha;
170  fTthetaCphi = rhs.fTthetaCphi;
171  fTthetaSphi = rhs.fTthetaSphi;
172  for (G4int i=0; i<4; ++i) { fPlanes[i] = rhs.fPlanes[i]; }
173 
174  return *this;
175 }
176 
178 //
179 // Accessors & modifiers
180 
181 G4double G4UPara::GetZHalfLength() const
182 {
183  return GetZ();
184 }
185 G4double G4UPara::GetYHalfLength() const
186 {
187  return GetY();
188 }
189 G4double G4UPara::GetXHalfLength() const
190 {
191  return GetZ();
192 }
193 G4ThreeVector G4UPara::GetSymAxis() const
194 {
195  return G4ThreeVector(fTthetaCphi,fTthetaSphi,1.).unit();
196 }
197 G4double G4UPara::GetTanAlpha() const
198 {
199  return fTalpha;
200 }
201 
202 void G4UPara::SetXHalfLength(G4double val)
203 {
204  SetDimensions(val, GetY(), GetZ());
205  fRebuildPolyhedron = true;
206 
207  CheckParameters();
208  MakePlanes();
209 }
210 void G4UPara::SetYHalfLength(G4double val)
211 {
212  SetDimensions(GetX(), val, GetZ());
213  fRebuildPolyhedron = true;
214 
215  CheckParameters();
216  MakePlanes();
217 }
218 void G4UPara::SetZHalfLength(G4double val)
219 {
220  SetDimensions(GetX(), GetY(), val);
221  fRebuildPolyhedron = true;
222 
223  CheckParameters();
224  MakePlanes();
225 }
226 void G4UPara::SetAlpha(G4double alpha)
227 {
228  Base_t::SetAlpha(alpha);
229  fTalpha = std::tan(alpha);
230  fRebuildPolyhedron = true;
231 
232  MakePlanes();
233 }
234 void G4UPara::SetTanAlpha(G4double val)
235 {
236  fTalpha = val;
237  fRebuildPolyhedron = true;
238 
239  MakePlanes();
240 }
241 void G4UPara::SetThetaAndPhi(double pTheta, double pPhi)
242 {
243  Base_t::SetThetaAndPhi(pTheta, pPhi);
244  G4double tanTheta = std::tan(pTheta);
245  fTthetaCphi = tanTheta*std::cos(pPhi);
246  fTthetaSphi = tanTheta*std::sin(pPhi);
247  fRebuildPolyhedron = true;
248 
249  MakePlanes();
250 }
251 
253 //
254 // Set all parameters, as for constructor - set and check half-widths
255 
256 void G4UPara::SetAllParameters(G4double pDx, G4double pDy, G4double pDz,
257  G4double pAlpha, G4double pTheta, G4double pPhi)
258 {
259  // Reset data of the base class
260  fRebuildPolyhedron = true;
261 
262  // Set parameters
263  SetDimensions(pDx, pDy, pDz);
264  Base_t::SetAlpha(pAlpha);
265  Base_t::SetThetaAndPhi(pTheta, pPhi);
266  fTalpha = std::tan(pAlpha);
267  fTthetaCphi = std::tan(pTheta)*std::cos(pPhi);
268  fTthetaSphi = std::tan(pTheta)*std::sin(pPhi);
269 
270  CheckParameters();
271  MakePlanes();
272 }
273 
275 //
276 // Check dimensions
277 
278 void G4UPara::CheckParameters()
279 {
280  if (GetX() < 2*kCarTolerance ||
281  GetY() < 2*kCarTolerance ||
282  GetZ() < 2*kCarTolerance)
283  {
284  std::ostringstream message;
285  message << "Invalid (too small or negative) dimensions for Solid: "
286  << GetName()
287  << "\n X - " << GetX()
288  << "\n Y - " << GetY()
289  << "\n Z - " << GetZ();
290  G4Exception("G4UPara::CheckParameters()", "GeomSolids0002",
291  FatalException, message);
292  }
293 }
294 
296 //
297 // Set side planes
298 
299 void G4UPara::MakePlanes()
300 {
301  G4ThreeVector vx(1, 0, 0);
302  G4ThreeVector vy(fTalpha, 1, 0);
303  G4ThreeVector vz(fTthetaCphi, fTthetaSphi, 1);
304 
305  // Set -Y & +Y planes
306  //
307  G4ThreeVector ynorm = (vx.cross(vz)).unit();
308 
309  fPlanes[0].a = 0.;
310  fPlanes[0].b = ynorm.y();
311  fPlanes[0].c = ynorm.z();
312  fPlanes[0].d = fPlanes[0].b*GetY(); // point (0,fDy,0) is on plane
313 
314  fPlanes[1].a = 0.;
315  fPlanes[1].b = -fPlanes[0].b;
316  fPlanes[1].c = -fPlanes[0].c;
317  fPlanes[1].d = fPlanes[0].d;
318 
319  // Set -X & +X planes
320  //
321  G4ThreeVector xnorm = (vz.cross(vy)).unit();
322 
323  fPlanes[2].a = xnorm.x();
324  fPlanes[2].b = xnorm.y();
325  fPlanes[2].c = xnorm.z();
326  fPlanes[2].d = fPlanes[2].a*GetZ(); // point (fDx,0,0) is on plane
327 
328  fPlanes[3].a = -fPlanes[2].a;
329  fPlanes[3].b = -fPlanes[2].b;
330  fPlanes[3].c = -fPlanes[2].c;
331  fPlanes[3].d = fPlanes[2].d;
332 }
333 
335 //
336 // Dispatch to parameterisation for replication mechanism dimension
337 // computation & modification
338 
339 void G4UPara::ComputeDimensions( G4VPVParameterisation* p,
340  const G4int n,
341  const G4VPhysicalVolume* pRep )
342 {
343  p->ComputeDimensions(*(G4Para*)this,n,pRep);
344 }
345 
347 //
348 // Get bounding box
349 
350 void G4UPara::BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const
351 {
352  G4double dz = GetZHalfLength();
353  G4double dx = GetXHalfLength();
354  G4double dy = GetYHalfLength();
355 
356  G4double x0 = dz*fTthetaCphi;
357  G4double x1 = dy*GetTanAlpha();
358  G4double xmin =
359  std::min(
360  std::min(
361  std::min(-x0-x1-dx,-x0+x1-dx),x0-x1-dx),x0+x1-dx);
362  G4double xmax =
363  std::max(
364  std::max(
365  std::max(-x0-x1+dx,-x0+x1+dx),x0-x1+dx),x0+x1+dx);
366 
367  G4double y0 = dz*fTthetaSphi;
368  G4double ymin = std::min(-y0-dy,y0-dy);
369  G4double ymax = std::max(-y0+dy,y0+dy);
370 
371  pMin.set(xmin,ymin,-dz);
372  pMax.set(xmax,ymax, dz);
373 
374  // Check correctness of the bounding box
375  //
376  if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
377  {
378  std::ostringstream message;
379  message << "Bad bounding box (min >= max) for solid: "
380  << GetName() << " !"
381  << "\npMin = " << pMin
382  << "\npMax = " << pMax;
383  G4Exception("G4UPara::BoundingLimits()", "GeomMgt0001",
384  JustWarning, message);
385  StreamInfo(G4cout);
386  }
387 }
388 
390 //
391 // Calculate extent under transform and specified limit
392 
393 G4bool G4UPara::CalculateExtent( const EAxis pAxis,
394  const G4VoxelLimits& pVoxelLimit,
395  const G4AffineTransform& pTransform,
396  G4double& pMin, G4double& pMax ) const
397 {
398  G4ThreeVector bmin, bmax;
399  G4bool exist;
400 
401  // Check bounding box (bbox)
402  //
403  BoundingLimits(bmin,bmax);
404  G4BoundingEnvelope bbox(bmin,bmax);
405 #ifdef G4BBOX_EXTENT
406  if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
407 #endif
408  if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
409  {
410  return exist = (pMin < pMax) ? true : false;
411  }
412 
413  // Set bounding envelope (benv) and calculate extent
414  //
415  G4double dz = GetZHalfLength();
416  G4double dx = GetXHalfLength();
417  G4double dy = GetYHalfLength();
418 
419  G4double x0 = dz*fTthetaCphi;
420  G4double x1 = dy*GetTanAlpha();
421  G4double y0 = dz*fTthetaSphi;
422 
423  G4ThreeVectorList baseA(4), baseB(4);
424  baseA[0].set(-x0-x1-dx,-y0-dy,-dz);
425  baseA[1].set(-x0-x1+dx,-y0-dy,-dz);
426  baseA[2].set(-x0+x1+dx,-y0+dy,-dz);
427  baseA[3].set(-x0+x1-dx,-y0+dy,-dz);
428 
429  baseB[0].set(+x0-x1-dx, y0-dy, dz);
430  baseB[1].set(+x0-x1+dx, y0-dy, dz);
431  baseB[2].set(+x0+x1+dx, y0+dy, dz);
432  baseB[3].set(+x0+x1-dx, y0+dy, dz);
433 
434  std::vector<const G4ThreeVectorList *> polygons(2);
435  polygons[0] = &baseA;
436  polygons[1] = &baseB;
437 
438  G4BoundingEnvelope benv(bmin,bmax,polygons);
439  exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
440  return exist;
441 }
442 
444 //
445 // Make a clone of the object
446 //
447 G4VSolid* G4UPara::Clone() const
448 {
449  return new G4UPara(*this);
450 }
451 
453 //
454 // Methods for visualisation
455 
456 G4Polyhedron* G4UPara::CreatePolyhedron () const
457 {
458  return new G4PolyhedronPara(GetX(), GetY(), GetZ(),
459  GetAlpha(), GetTheta(), GetPhi());
460 }
461 
462 #endif // G4GEOM_USE_USOLIDS