Geant4  v4-10.4-release
 모두 클래스 네임스페이스들 파일들 함수 변수 타입정의 열거형 타입 열거형 멤버 Friends 매크로 그룹들 페이지들
G4Trd.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 //
27 // $Id: G4Trd.cc 107895 2017-12-11 07:33:57Z gcosmo $
28 //
29 //
30 // Implementation for G4Trd class
31 //
32 // History:
33 //
34 // 25.05.17 E.Tcherniaev: complete revision, speed-up
35 // 23.09.16 E.Tcherniaev: use G4BoundingEnvelope for CalculateExtent(),
36 // removed CreateRotatedVertices()
37 // 28.04.05 V.Grichine: new SurfaceNormal according to J. Apostolakis proposal
38 // 26.04.05, V.Grichine, new SurfaceNoramal is default
39 // 07.12.04, V.Grichine, SurfaceNoramal with edges/vertices.
40 // 07.05.00, V.Grichine, in d = DistanceToIn(p,v), if d<0.5*kCarTolerance, d=0
41 // ~1996, V.Grichine, 1st implementation based on old code of P.Kent
42 //
44 
45 #include "G4Trd.hh"
46 
47 #if !defined(G4GEOM_USE_UTRD)
48 
49 #include "G4GeomTools.hh"
50 
51 #include "G4VoxelLimits.hh"
52 #include "G4AffineTransform.hh"
53 #include "G4BoundingEnvelope.hh"
54 #include "Randomize.hh"
55 
56 #include "G4VPVParameterisation.hh"
57 
58 #include "G4VGraphicsScene.hh"
59 
60 using namespace CLHEP;
61 
63 //
64 // Constructor - set & check half widths
65 
66 G4Trd::G4Trd(const G4String& pName,
67  G4double pdx1, G4double pdx2,
68  G4double pdy1, G4double pdy2,
69  G4double pdz)
70  : G4CSGSolid(pName), halfCarTolerance(0.5*kCarTolerance),
71  fDx1(pdx1), fDx2(pdx2), fDy1(pdy1), fDy2(pdy2), fDz(pdz)
72 {
74  MakePlanes();
75 }
76 
78 //
79 // Fake default constructor - sets only member data and allocates memory
80 // for usage restricted to object persistency
81 //
82 G4Trd::G4Trd( __void__& a )
83  : G4CSGSolid(a), halfCarTolerance(0.5*kCarTolerance),
84  fDx1(1.), fDx2(1.), fDy1(1.), fDy2(1.), fDz(1.)
85 {
86  MakePlanes();
87 }
88 
90 //
91 // Destructor
92 
94 {
95 }
96 
98 //
99 // Copy constructor
100 
101 G4Trd::G4Trd(const G4Trd& rhs)
102  : G4CSGSolid(rhs), halfCarTolerance(rhs.halfCarTolerance),
103  fDx1(rhs.fDx1), fDx2(rhs.fDx2),
104  fDy1(rhs.fDy1), fDy2(rhs.fDy2), fDz(rhs.fDz)
105 {
106  for (G4int i=0; i<4; ++i) { fPlanes[i] = rhs.fPlanes[i]; }
107 }
108 
110 //
111 // Assignment operator
112 
114 {
115  // Check assignment to self
116  //
117  if (this == &rhs) { return *this; }
118 
119  // Copy base class data
120  //
122 
123  // Copy data
124  //
126  fDx1 = rhs.fDx1; fDx2 = rhs.fDx2;
127  fDy1 = rhs.fDy1; fDy2 = rhs.fDy2;
128  fDz = rhs.fDz;
129  for (G4int i=0; i<4; ++i) { fPlanes[i] = rhs.fPlanes[i]; }
130 
131  return *this;
132 }
133 
135 //
136 // Set all parameters, as for constructor - set and check half-widths
137 
139  G4double pdy1, G4double pdy2, G4double pdz)
140 {
141  // Reset data of the base class
142  fCubicVolume = 0;
143  fSurfaceArea = 0;
144  fRebuildPolyhedron = true;
145 
146  // Set parameters
147  fDx1 = pdx1; fDx2 = pdx2;
148  fDy1 = pdy1; fDy2 = pdy2;
149  fDz = pdz;
150 
151  CheckParameters();
152  MakePlanes();
153 }
154 
156 //
157 // Check dimensions
158 
160 {
161  G4double dmin = 2*kCarTolerance;
162  if ((fDx1 < 0 || fDx2 < 0 || fDy1 < 0 || fDy2 < 0 || fDz < dmin) ||
163  (fDx1 < dmin && fDx2 < dmin) ||
164  (fDy1 < dmin && fDy2 < dmin))
165  {
166  std::ostringstream message;
167  message << "Invalid (too small or negative) dimensions for Solid: "
168  << GetName()
169  << "\n X - " << fDx1 << ", " << fDx2
170  << "\n Y - " << fDy1 << ", " << fDy2
171  << "\n Z - " << fDz;
172  G4Exception("G4Trd::CheckParameters()", "GeomSolids0002",
173  FatalException, message);
174  }
175 }
176 
178 //
179 // Set side planes
180 
182 {
183  G4double dx = fDx1 - fDx2;
184  G4double dy = fDy1 - fDy2;
185  G4double dz = 2*fDz;
186  G4double magx = std::sqrt(dx*dx + dz*dz);
187  G4double magy = std::sqrt(dy*dy + dz*dz);
188 
189  // Set -Y & +Y planes
190  //
191  fPlanes[0].a = 0.;
192  fPlanes[0].b = -dz/magy;
193  fPlanes[0].c = dy/magy;
194  fPlanes[0].d = fPlanes[0].b*fDy1 + fPlanes[0].c*fDz;
195 
196  fPlanes[1].a = fPlanes[0].a;
197  fPlanes[1].b = -fPlanes[0].b;
198  fPlanes[1].c = fPlanes[0].c;
199  fPlanes[1].d = fPlanes[0].d;
200 
201  // Set -X & +X planes
202  //
203  fPlanes[2].a = -dz/magx;
204  fPlanes[2].b = 0.;
205  fPlanes[2].c = dx/magx;
206  fPlanes[2].d = fPlanes[2].a*fDx1 + fPlanes[2].c*fDz;
207 
208  fPlanes[3].a = -fPlanes[2].a;
209  fPlanes[3].b = fPlanes[2].b;
210  fPlanes[3].c = fPlanes[2].c;
211  fPlanes[3].d = fPlanes[2].d;
212 }
213 
215 //
216 // Get volume
217 
219 {
220  if (fCubicVolume == 0)
221  {
222  fCubicVolume = 2*fDz*( (fDx1+fDx2)*(fDy1+fDy2) +
223  (fDx2-fDx1)*(fDy2-fDy1)/3 );
224  }
225  return fCubicVolume;
226 }
227 
229 //
230 // Get surface area
231 
233 {
234  if (fSurfaceArea == 0)
235  {
236  fSurfaceArea =
237  4*(fDx1*fDy1+fDx2*fDy2) +
238  2*(fDy1+fDy2)*std::hypot(fDx1-fDx2,2*fDz) +
239  2*(fDx1+fDx2)*std::hypot(fDy1-fDy2,2*fDz);
240  }
241  return fSurfaceArea;
242 }
243 
245 //
246 // Dispatch to parameterisation for replication mechanism dimension
247 // computation & modification
248 
250  const G4int n,
251  const G4VPhysicalVolume* pRep )
252 {
253  p->ComputeDimensions(*this,n,pRep);
254 }
255 
257 //
258 // Get bounding box
259 
261 {
262  G4double dx1 = GetXHalfLength1();
263  G4double dx2 = GetXHalfLength2();
264  G4double dy1 = GetYHalfLength1();
265  G4double dy2 = GetYHalfLength2();
266  G4double dz = GetZHalfLength();
267 
268  G4double xmax = std::max(dx1,dx2);
269  G4double ymax = std::max(dy1,dy2);
270  pMin.set(-xmax,-ymax,-dz);
271  pMax.set( xmax, ymax, dz);
272 
273  // Check correctness of the bounding box
274  //
275  if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
276  {
277  std::ostringstream message;
278  message << "Bad bounding box (min >= max) for solid: "
279  << GetName() << " !"
280  << "\npMin = " << pMin
281  << "\npMax = " << pMax;
282  G4Exception("G4Trd::BoundingLimits()", "GeomMgt0001", JustWarning, message);
283  DumpInfo();
284  }
285 }
286 
288 //
289 // Calculate extent under transform and specified limit
290 
292  const G4VoxelLimits& pVoxelLimit,
293  const G4AffineTransform& pTransform,
294  G4double& pMin, G4double& pMax ) const
295 {
296  G4ThreeVector bmin, bmax;
297  G4bool exist;
298 
299  // Check bounding box (bbox)
300  //
301  BoundingLimits(bmin,bmax);
302  G4BoundingEnvelope bbox(bmin,bmax);
303 #ifdef G4BBOX_EXTENT
304  if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
305 #endif
306  if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
307  {
308  return exist = (pMin < pMax) ? true : false;
309  }
310 
311  // Set bounding envelope (benv) and calculate extent
312  //
313  G4double dx1 = GetXHalfLength1();
314  G4double dx2 = GetXHalfLength2();
315  G4double dy1 = GetYHalfLength1();
316  G4double dy2 = GetYHalfLength2();
317  G4double dz = GetZHalfLength();
318 
319  G4ThreeVectorList baseA(4), baseB(4);
320  baseA[0].set(-dx1,-dy1,-dz);
321  baseA[1].set( dx1,-dy1,-dz);
322  baseA[2].set( dx1, dy1,-dz);
323  baseA[3].set(-dx1, dy1,-dz);
324  baseB[0].set(-dx2,-dy2, dz);
325  baseB[1].set( dx2,-dy2, dz);
326  baseB[2].set( dx2, dy2, dz);
327  baseB[3].set(-dx2, dy2, dz);
328 
329  std::vector<const G4ThreeVectorList *> polygons(2);
330  polygons[0] = &baseA;
331  polygons[1] = &baseB;
332 
333  G4BoundingEnvelope benv(bmin,bmax,polygons);
334  exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
335  return exist;
336 }
337 
339 //
340 // Return whether point inside/outside/on surface, using tolerance
341 
343 {
344  G4double dx = fPlanes[3].a*std::abs(p.x())+fPlanes[3].c*p.z()+fPlanes[3].d;
345  G4double dy = fPlanes[1].b*std::abs(p.y())+fPlanes[1].c*p.z()+fPlanes[1].d;
346  G4double dxy = std::max(dx,dy);
347 
348  G4double dz = std::abs(p.z())-fDz;
349  G4double dist = std::max(dz,dxy);
350 
351  if (dist > halfCarTolerance) return kOutside;
352  return (dist > -halfCarTolerance) ? kSurface : kInside;
353 }
354 
356 //
357 // Determine side where point is, and return corresponding normal
358 
360 {
361  G4int nsurf = 0; // number of surfaces where p is placed
362 
363  // Check Z faces
364  //
365  G4double nz = 0;
366  G4double dz = std::abs(p.z()) - fDz;
367  if (std::abs(dz) <= halfCarTolerance)
368  {
369  nz = (p.z() < 0) ? -1 : 1;
370  ++nsurf;
371  }
372 
373  // Check Y faces
374  //
375  G4double ny = 0;
376  G4double dy1 = fPlanes[0].b*p.y();
377  G4double dy2 = fPlanes[0].c*p.z() + fPlanes[0].d;
378  if (std::abs(dy2 + dy1) <= halfCarTolerance)
379  {
380  ny += fPlanes[0].b;
381  nz += fPlanes[0].c;
382  ++nsurf;
383  }
384  if (std::abs(dy2 - dy1) <= halfCarTolerance)
385  {
386  ny += fPlanes[1].b;
387  nz += fPlanes[1].c;
388  ++nsurf;
389  }
390 
391  // Check X faces
392  //
393  G4double nx = 0;
394  G4double dx1 = fPlanes[2].a*p.x();
395  G4double dx2 = fPlanes[2].c*p.z() + fPlanes[2].d;
396  if (std::abs(dx2 + dx1) <= halfCarTolerance)
397  {
398  nx += fPlanes[2].a;
399  nz += fPlanes[2].c;
400  ++nsurf;
401  }
402  if (std::abs(dx2 - dx1) <= halfCarTolerance)
403  {
404  nx += fPlanes[3].a;
405  nz += fPlanes[3].c;
406  ++nsurf;
407  }
408 
409  // Return normal
410  //
411  if (nsurf == 1) return G4ThreeVector(nx,ny,nz);
412  else if (nsurf != 0) return G4ThreeVector(nx,ny,nz).unit(); // edge or corner
413  else
414  {
415  // Point is not on the surface
416  //
417 #ifdef G4CSGDEBUG
418  std::ostringstream message;
419  G4int oldprc = message.precision(16);
420  message << "Point p is not on surface (!?) of solid: "
421  << GetName() << G4endl;
422  message << "Position:\n";
423  message << " p.x() = " << p.x()/mm << " mm\n";
424  message << " p.y() = " << p.y()/mm << " mm\n";
425  message << " p.z() = " << p.z()/mm << " mm";
426  G4cout.precision(oldprc) ;
427  G4Exception("G4Trd::SurfaceNormal(p)", "GeomSolids1002",
428  JustWarning, message );
429  DumpInfo();
430 #endif
431  return ApproxSurfaceNormal(p);
432  }
433 }
434 
436 //
437 // Algorithm for SurfaceNormal() following the original specification
438 // for points not on the surface
439 
441 {
442  G4double dist = -DBL_MAX;
443  G4int iside = 0;
444  for (G4int i=0; i<4; ++i)
445  {
446  G4double d = fPlanes[i].a*p.x() +
447  fPlanes[i].b*p.y() +
448  fPlanes[i].c*p.z() + fPlanes[i].d;
449  if (d > dist) { dist = d; iside = i; }
450  }
451 
452  G4double distz = std::abs(p.z()) - fDz;
453  if (dist > distz)
454  return G4ThreeVector(fPlanes[iside].a, fPlanes[iside].b, fPlanes[iside].c);
455  else
456  return G4ThreeVector(0, 0, (p.z() < 0) ? -1 : 1);
457 }
458 
460 //
461 // Calculate distance to shape from outside
462 // - return kInfinity if no intersection
463 
465  const G4ThreeVector& v ) const
466 {
467  // Z intersections
468  //
469  if ((std::abs(p.z()) - fDz) >= -halfCarTolerance && p.z()*v.z() >= 0)
470  return kInfinity;
471  G4double invz = (-v.z() == 0) ? DBL_MAX : -1./v.z();
472  G4double dz = (invz < 0) ? fDz : -fDz;
473  G4double tzmin = (p.z() + dz)*invz;
474  G4double tzmax = (p.z() - dz)*invz;
475 
476  // Y intersections
477  //
478  G4double tmin0 = tzmin, tmax0 = tzmax;
479  G4double ya = fPlanes[0].b*v.y(), yb = fPlanes[0].c*v.z();
480  G4double yc = fPlanes[0].b*p.y(), yd = fPlanes[0].c*p.z()+fPlanes[0].d;
481  G4double cos0 = yb + ya;
482  G4double dis0 = yd + yc;
483  if (dis0 >= -halfCarTolerance)
484  {
485  if (cos0 >= 0) return kInfinity;
486  G4double tmp = -dis0/cos0;
487  if (tmin0 < tmp) tmin0 = tmp;
488  }
489  else if (cos0 > 0)
490  {
491  G4double tmp = -dis0/cos0;
492  if (tmax0 > tmp) tmax0 = tmp;
493  }
494 
495  G4double tmin1 = tmin0, tmax1 = tmax0;
496  G4double cos1 = yb - ya;
497  G4double dis1 = yd - yc;
498  if (dis1 >= -halfCarTolerance)
499  {
500  if (cos1 >= 0) return kInfinity;
501  G4double tmp = -dis1/cos1;
502  if (tmin1 < tmp) tmin1 = tmp;
503  }
504  else if (cos1 > 0)
505  {
506  G4double tmp = -dis1/cos1;
507  if (tmax1 > tmp) tmax1 = tmp;
508  }
509 
510  // X intersections
511  //
512  G4double tmin2 = tmin1, tmax2 = tmax1;
513  G4double xa = fPlanes[2].a*v.x(), xb = fPlanes[2].c*v.z();
514  G4double xc = fPlanes[2].a*p.x(), xd = fPlanes[2].c*p.z()+fPlanes[2].d;
515  G4double cos2 = xb + xa;
516  G4double dis2 = xd + xc;
517  if (dis2 >= -halfCarTolerance)
518  {
519  if (cos2 >= 0) return kInfinity;
520  G4double tmp = -dis2/cos2;
521  if (tmin2 < tmp) tmin2 = tmp;
522  }
523  else if (cos2 > 0)
524  {
525  G4double tmp = -dis2/cos2;
526  if (tmax2 > tmp) tmax2 = tmp;
527  }
528 
529  G4double tmin3 = tmin2, tmax3 = tmax2;
530  G4double cos3 = xb - xa;
531  G4double dis3 = xd - xc;
532  if (dis3 >= -halfCarTolerance)
533  {
534  if (cos3 >= 0) return kInfinity;
535  G4double tmp = -dis3/cos3;
536  if (tmin3 < tmp) tmin3 = tmp;
537  }
538  else if (cos3 > 0)
539  {
540  G4double tmp = -dis3/cos3;
541  if (tmax3 > tmp) tmax3 = tmp;
542  }
543 
544  // Find distance
545  //
546  G4double tmin = tmin3, tmax = tmax3;
547  if (tmax <= tmin + halfCarTolerance) return kInfinity; // touch or no hit
548  return (tmin < halfCarTolerance ) ? 0. : tmin;
549 }
550 
552 //
553 // Calculate exact shortest distance to any boundary from outside
554 // This is the best fast estimation of the shortest distance to trap
555 // - returns 0 if point is inside
556 
558 {
559  G4double dx = fPlanes[3].a*std::abs(p.x())+fPlanes[3].c*p.z()+fPlanes[3].d;
560  G4double dy = fPlanes[1].b*std::abs(p.y())+fPlanes[1].c*p.z()+fPlanes[1].d;
561  G4double dxy = std::max(dx,dy);
562 
563  G4double dz = std::abs(p.z())-fDz;
564  G4double dist = std::max(dz,dxy);
565 
566  return (dist > 0) ? dist : 0.;
567 }
568 
570 //
571 // Calculate distance to surface of shape from inside and
572 // find normal at exit point, if required
573 // - when leaving the surface, return 0
574 
576  const G4bool calcNorm,
577  G4bool *validNorm, G4ThreeVector *n) const
578 {
579  // Z intersections
580  //
581  if ((std::abs(p.z()) - fDz) >= -halfCarTolerance && p.z()*v.z() > 0)
582  {
583  if (calcNorm)
584  {
585  *validNorm = true;
586  n->set(0, 0, (p.z() < 0) ? -1 : 1);
587  }
588  return 0;
589  }
590  G4double vz = v.z();
591  G4double tmax = (vz == 0) ? DBL_MAX : (std::copysign(fDz,vz) - p.z())/vz;
592  G4int iside = (vz < 0) ? -4 : -2; // little trick: (-4+3)=-1, (-2+3)=+1
593 
594  // Y intersections
595  //
596  G4int i = 0;
597  for ( ; i<2; ++i)
598  {
599  G4double cosa = fPlanes[i].b*v.y() + fPlanes[i].c*v.z();
600  if (cosa > 0)
601  {
602  G4double dist = fPlanes[i].b*p.y()+fPlanes[i].c*p.z()+fPlanes[i].d;
603  if (dist >= -halfCarTolerance)
604  {
605  if (calcNorm)
606  {
607  *validNorm = true;
608  n->set(0, fPlanes[i].b, fPlanes[i].c);
609  }
610  return 0;
611  }
612  G4double tmp = -dist/cosa;
613  if (tmax > tmp) { tmax = tmp; iside = i; }
614  }
615  }
616 
617  // X intersections
618  //
619  for ( ; i<4; ++i)
620  {
621  G4double cosa = fPlanes[i].a*v.x()+fPlanes[i].c*v.z();
622  if (cosa > 0)
623  {
624  G4double dist = fPlanes[i].a*p.x()+fPlanes[i].c*p.z()+fPlanes[i].d;
625  if (dist >= -halfCarTolerance)
626  {
627  if (calcNorm)
628  {
629  *validNorm = true;
630  n->set(fPlanes[i].a, fPlanes[i].b, fPlanes[i].c);
631  }
632  return 0;
633  }
634  G4double tmp = -dist/cosa;
635  if (tmax > tmp) { tmax = tmp; iside = i; }
636  }
637  }
638 
639  // Set normal, if required, and return distance
640  //
641  if (calcNorm)
642  {
643  *validNorm = true;
644  if (iside < 0)
645  n->set(0, 0, iside + 3); // (-4+3)=-1, (-2+3)=+1
646  else
647  n->set(fPlanes[iside].a, fPlanes[iside].b, fPlanes[iside].c);
648  }
649  return tmax;
650 }
651 
653 //
654 // Calculate exact shortest distance to any boundary from inside
655 // - returns 0 if point is outside
656 
658 {
659 #ifdef G4CSGDEBUG
660  if( Inside(p) == kOutside )
661  {
662  std::ostringstream message;
663  G4int oldprc = message.precision(16);
664  message << "Point p is outside (!?) of solid: " << GetName() << G4endl;
665  message << "Position:\n";
666  message << " p.x() = " << p.x()/mm << " mm\n";
667  message << " p.y() = " << p.y()/mm << " mm\n";
668  message << " p.z() = " << p.z()/mm << " mm";
669  G4cout.precision(oldprc) ;
670  G4Exception("G4Trd::DistanceToOut(p)", "GeomSolids1002",
671  JustWarning, message );
672  DumpInfo();
673  }
674 #endif
675  G4double dx = fPlanes[3].a*std::abs(p.x())+fPlanes[3].c*p.z()+fPlanes[3].d;
676  G4double dy = fPlanes[1].b*std::abs(p.y())+fPlanes[1].c*p.z()+fPlanes[1].d;
677  G4double dxy = std::max(dx,dy);
678 
679  G4double dz = std::abs(p.z())-fDz;
680  G4double dist = std::max(dz,dxy);
681 
682  return (dist < 0) ? -dist : 0.;
683 }
684 
686 //
687 // GetEntityType
688 
690 {
691  return G4String("G4Trd");
692 }
693 
695 //
696 // Make a clone of the object
697 //
699 {
700  return new G4Trd(*this);
701 }
702 
704 //
705 // Stream object contents to an output stream
706 
707 std::ostream& G4Trd::StreamInfo( std::ostream& os ) const
708 {
709  G4int oldprc = os.precision(16);
710  os << "-----------------------------------------------------------\n"
711  << " *** Dump for solid - " << GetName() << " ***\n"
712  << " ===================================================\n"
713  << " Solid type: G4Trd\n"
714  << " Parameters: \n"
715  << " half length X, surface -dZ: " << fDx1/mm << " mm \n"
716  << " half length X, surface +dZ: " << fDx2/mm << " mm \n"
717  << " half length Y, surface -dZ: " << fDy1/mm << " mm \n"
718  << " half length Y, surface +dZ: " << fDy2/mm << " mm \n"
719  << " half length Z : " << fDz/mm << " mm \n"
720  << "-----------------------------------------------------------\n";
721  os.precision(oldprc);
722 
723  return os;
724 }
725 
727 //
728 // Return a point randomly and uniformly selected on the solid surface
729 
731 {
732  // Set vertices
733  //
734  G4ThreeVector pt[8];
735  pt[0].set(-fDx1,-fDy1,-fDz);
736  pt[1].set( fDx1,-fDy1,-fDz);
737  pt[2].set(-fDx1, fDy1,-fDz);
738  pt[3].set( fDx1, fDy1,-fDz);
739  pt[4].set(-fDx2,-fDy2, fDz);
740  pt[5].set( fDx2,-fDy2, fDz);
741  pt[6].set(-fDx2, fDy2, fDz);
742  pt[7].set( fDx2, fDy2, fDz);
743 
744  // Set faces (-Z, -Y, +Y, -X, +X, +Z)
745  //
746  G4int iface [6][4] =
747  { {0,1,3,2}, {0,4,5,1}, {2,3,7,6}, {0,2,6,4}, {1,5,7,3}, {4,6,7,5} };
748 
749  // Set areas
750  //
751  G4double sxz = (fDy1 + fDy2)*std::hypot(fDx1 - fDx2, 2*fDz);
752  G4double syz = (fDx1 + fDx2)*std::hypot(fDy1 - fDy2, 2*fDz);
753  G4double sface[6] = { 4*fDx1*fDy1, syz, syz, sxz, sxz, 4*fDx2*fDy2 };
754  for (G4int i=1; i<6; ++i) { sface[i] += sface[i-1]; }
755 
756  // Select face
757  //
758  G4double select = sface[5]*G4UniformRand();
759  G4int k = 5;
760  if (select <= sface[4]) k = 4;
761  if (select <= sface[3]) k = 3;
762  if (select <= sface[2]) k = 2;
763  if (select <= sface[1]) k = 1;
764  if (select <= sface[0]) k = 0;
765 
766  // Select sub-triangle
767  //
768  G4int i0 = iface[k][0];
769  G4int i1 = iface[k][1];
770  G4int i2 = iface[k][2];
771  G4int i3 = iface[k][3];
772  G4double s1 = G4GeomTools::TriangleAreaNormal(pt[i0],pt[i1],pt[i3]).mag();
773  G4double s2 = G4GeomTools::TriangleAreaNormal(pt[i2],pt[i1],pt[i3]).mag();
774  if ((s1+s2)*G4UniformRand() > s1) i0 = i2;
775 
776  // Generate point
777  //
778  G4double u = G4UniformRand();
779  G4double v = G4UniformRand();
780  if (u + v > 1.) { u = 1. - u; v = 1. - v; }
781  return (1.-u-v)*pt[i0] + u*pt[i1] + v*pt[i3];
782 }
783 
785 //
786 // Methods for visualisation
787 
789 {
790  scene.AddSolid (*this);
791 }
792 
794 {
795  return new G4PolyhedronTrd2 (fDx1, fDx2, fDy1, fDy2, fDz);
796 }
797 
798 #endif
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4double fDy2
Definition: G4Trd.hh:179
G4double a
Definition: G4Trd.hh:180
void CheckParameters()
Definition: G4Trd.cc:159
void set(double x, double y, double z)
T max(const T t1, const T t2)
brief Return the largest of the two arguments
CLHEP::Hep3Vector G4ThreeVector
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
Definition: G4Trd.cc:260
std::vector< ExP01TrackerHit * > a
Definition: ExP01Classes.hh:33
virtual void AddSolid(const G4Box &)=0
static const G4double kInfinity
Definition: geomdefs.hh:42
G4double halfCarTolerance
Definition: G4Trd.hh:178
G4double GetCubicVolume()
Definition: G4Trd.cc:218
static constexpr double mm
Definition: G4SIunits.hh:115
G4CSGSolid & operator=(const G4CSGSolid &rhs)
Definition: G4CSGSolid.cc:92
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
#define G4endl
Definition: G4ios.hh:61
const char * p
Definition: xmltok.h:285
void message(RunManager *runmanager)
Definition: ts_scorers.cc:72
G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
Definition: G4Trd.cc:440
double z() const
const G4double kCarTolerance
G4double fDz
Definition: G4Trd.hh:179
Float_t tmp
G4double GetSurfaceArea()
Definition: G4Trd.cc:232
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const
Definition: G4Trd.cc:575
G4double fDy1
Definition: G4Trd.hh:179
G4Trd(const G4String &pName, G4double pdx1, G4double pdx2, G4double pdy1, G4double pdy2, G4double pdz)
Definition: G4Trd.cc:66
G4double GetYHalfLength2() const
G4VSolid * Clone() const
Definition: G4Trd.cc:698
G4double GetZHalfLength() const
G4double GetXHalfLength1() const
EInside Inside(const G4ThreeVector &p) const
Definition: G4Trd.cc:342
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
double G4double
Definition: G4Types.hh:76
bool G4bool
Definition: G4Types.hh:79
std::vector< G4ThreeVector > G4ThreeVectorList
std::ostream & StreamInfo(std::ostream &os) const
Definition: G4Trd.cc:707
G4double kCarTolerance
Definition: G4VSolid.hh:307
#define G4UniformRand()
Definition: Randomize.hh:53
TMarker * pt
Definition: egs.C:25
void MakePlanes()
Definition: G4Trd.cc:181
G4double GetYHalfLength1() const
~G4Trd()
Definition: G4Trd.cc:93
Hep3Vector unit() const
G4Polyhedron * CreatePolyhedron() const
Definition: G4Trd.cc:793
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.hh:65
double mag() const
G4double fDx1
Definition: G4Trd.hh:179
int G4int
Definition: G4Types.hh:78
EInside
Definition: geomdefs.hh:58
EAxis
Definition: geomdefs.hh:54
G4String GetName() const
void DumpInfo() const
Definition: G4Trd.hh:72
G4double GetXHalfLength2() const
G4GLOB_DLL std::ostream G4cout
double x() const
G4GeometryType GetEntityType() const
Definition: G4Trd.cc:689
struct G4Trd::@34 fPlanes[4]
Char_t n[5]
double y() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
Definition: G4Trd.cc:359
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
Definition: G4Trd.cc:249
void DescribeYourselfTo(G4VGraphicsScene &scene) const
Definition: G4Trd.cc:788
static G4ThreeVector TriangleAreaNormal(const G4ThreeVector &A, const G4ThreeVector &B, const G4ThreeVector &C)
Definition: G4GeomTools.cc:603
G4double fSurfaceArea
Definition: G4CSGSolid.hh:79
G4double fDx2
Definition: G4Trd.hh:179
#define DBL_MAX
Definition: templates.hh:83
G4double b
Definition: G4Trd.hh:180
G4double fCubicVolume
Definition: G4CSGSolid.hh:78
G4double c
Definition: G4Trd.hh:180
G4bool fRebuildPolyhedron
Definition: G4CSGSolid.hh:80
void SetAllParameters(G4double pdx1, G4double pdx2, G4double pdy1, G4double pdy2, G4double pdz)
Definition: G4Trd.cc:138
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
Definition: G4Trd.cc:464
G4Trd & operator=(const G4Trd &rhs)
Definition: G4Trd.cc:113
G4ThreeVector GetPointOnSurface() const
Definition: G4Trd.cc:730
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
Definition: G4Trd.cc:291
G4double d
Definition: G4Trd.hh:180