Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4Polyhedra.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 of G4Polyhedra, a CSG polyhedra,
27// as an inherited class of G4VCSGfaceted.
28//
29// Utility classes:
30// * G4EnclosingCylinder: decided a quick check of geometry would be a
31// good idea (for CPU speed). If the quick check fails, the regular
32// full-blown G4VCSGfaceted version is invoked.
33// * G4ReduciblePolygon: Really meant as a check of input parameters,
34// this utility class also "converts" the GEANT3-like PGON/PCON
35// arguments into the newer ones.
36// Both these classes are implemented outside this file because they are
37// shared with G4Polycone.
38//
39// Author: David C. Williams ([email protected])
40// --------------------------------------------------------------------
41
42#include "G4Polyhedra.hh"
43
44#if !defined(G4GEOM_USE_UPOLYHEDRA)
45
46#include "G4PolyhedraSide.hh"
47#include "G4PolyPhiFace.hh"
48
49#include "G4GeomTools.hh"
50#include "G4VoxelLimits.hh"
51#include "G4AffineTransform.hh"
52#include "G4BoundingEnvelope.hh"
53
54#include "G4QuickRand.hh"
55
57#include "G4ReduciblePolygon.hh"
59
60namespace
61{
62 G4Mutex surface_elementsMutex = G4MUTEX_INITIALIZER;
63}
64
65using namespace CLHEP;
66
67// Constructor (GEANT3 style parameters)
68//
69// GEANT3 PGON radii are specified in the distance to the norm of each face.
70//
72 G4double phiStart,
73 G4double thePhiTotal,
74 G4int theNumSide,
75 G4int numZPlanes,
76 const G4double zPlane[],
77 const G4double rInner[],
78 const G4double rOuter[] )
79 : G4VCSGfaceted( name )
80{
81 if (theNumSide <= 0)
82 {
83 std::ostringstream message;
84 message << "Solid must have at least one side - " << GetName() << G4endl
85 << " No sides specified !";
86 G4Exception("G4Polyhedra::G4Polyhedra()", "GeomSolids0002",
87 FatalErrorInArgument, message);
88 }
89
90 //
91 // Calculate conversion factor from G3 radius to G4 radius
92 //
93 G4double phiTotal = thePhiTotal;
94 if ( (phiTotal <=0) || (phiTotal >= twopi*(1-DBL_EPSILON)) )
95 { phiTotal = twopi; }
96 G4double convertRad = std::cos(0.5*phiTotal/theNumSide);
97
98 //
99 // Some historical stuff
100 //
102
103 original_parameters->numSide = theNumSide;
106 original_parameters->Num_z_planes = numZPlanes;
107 original_parameters->Z_values = new G4double[numZPlanes];
108 original_parameters->Rmin = new G4double[numZPlanes];
109 original_parameters->Rmax = new G4double[numZPlanes];
110
111 for (G4int i=0; i<numZPlanes; ++i)
112 {
113 if (( i < numZPlanes-1) && ( zPlane[i] == zPlane[i+1] ))
114 {
115 if( (rInner[i] > rOuter[i+1])
116 ||(rInner[i+1] > rOuter[i]) )
117 {
118 DumpInfo();
119 std::ostringstream message;
120 message << "Cannot create a Polyhedra with no contiguous segments."
121 << G4endl
122 << " Segments are not contiguous !" << G4endl
123 << " rMin[" << i << "] = " << rInner[i]
124 << " -- rMax[" << i+1 << "] = " << rOuter[i+1] << G4endl
125 << " rMin[" << i+1 << "] = " << rInner[i+1]
126 << " -- rMax[" << i << "] = " << rOuter[i];
127 G4Exception("G4Polyhedra::G4Polyhedra()", "GeomSolids0002",
128 FatalErrorInArgument, message);
129 }
130 }
131 original_parameters->Z_values[i] = zPlane[i];
132 original_parameters->Rmin[i] = rInner[i]/convertRad;
133 original_parameters->Rmax[i] = rOuter[i]/convertRad;
134 }
135
136
137 //
138 // Build RZ polygon using special PCON/PGON GEANT3 constructor
139 //
141 new G4ReduciblePolygon( rInner, rOuter, zPlane, numZPlanes );
142 rz->ScaleA( 1/convertRad );
143
144 //
145 // Do the real work
146 //
147 Create( phiStart, phiTotal, theNumSide, rz );
148
149 delete rz;
150}
151
152// Constructor (generic parameters)
153//
155 G4double phiStart,
156 G4double phiTotal,
157 G4int theNumSide,
158 G4int numRZ,
159 const G4double r[],
160 const G4double z[] )
161 : G4VCSGfaceted( name ), genericPgon(true)
162{
163 if (theNumSide <= 0)
164 {
165 std::ostringstream message;
166 message << "Solid must have at least one side - " << GetName() << G4endl
167 << " No sides specified !";
168 G4Exception("G4Polyhedra::G4Polyhedra()", "GeomSolids0002",
169 FatalErrorInArgument, message);
170 }
171
172 G4ReduciblePolygon* rz = new G4ReduciblePolygon( r, z, numRZ );
173
174 Create( phiStart, phiTotal, theNumSide, rz );
175
176 // Set original_parameters struct for consistency
177 //
179
180 delete rz;
181}
182
183// Create
184//
185// Generic create routine, called by each constructor
186// after conversion of arguments
187//
189 G4double phiTotal,
190 G4int theNumSide,
192{
193 //
194 // Perform checks of rz values
195 //
196 if (rz->Amin() < 0.0)
197 {
198 std::ostringstream message;
199 message << "Illegal input parameters - " << GetName() << G4endl
200 << " All R values must be >= 0 !";
201 G4Exception("G4Polyhedra::Create()", "GeomSolids0002",
202 FatalErrorInArgument, message);
203 }
204
205 G4double rzArea = rz->Area();
206 if (rzArea < -kCarTolerance)
207 {
208 rz->ReverseOrder();
209 }
210 else if (rzArea < kCarTolerance)
211 {
212 std::ostringstream message;
213 message << "Illegal input parameters - " << GetName() << G4endl
214 << " R/Z cross section is zero or near zero: " << rzArea;
215 G4Exception("G4Polyhedra::Create()", "GeomSolids0002",
216 FatalErrorInArgument, message);
217 }
218
221 {
222 std::ostringstream message;
223 message << "Illegal input parameters - " << GetName() << G4endl
224 << " Too few unique R/Z values !";
225 G4Exception("G4Polyhedra::Create()", "GeomSolids0002",
226 FatalErrorInArgument, message);
227 }
228
229 if (rz->CrossesItself( 1/kInfinity ))
230 {
231 std::ostringstream message;
232 message << "Illegal input parameters - " << GetName() << G4endl
233 << " R/Z segments cross !";
234 G4Exception("G4Polyhedra::Create()", "GeomSolids0002",
235 FatalErrorInArgument, message);
236 }
237
238 numCorner = rz->NumVertices();
239
240
241 startPhi = phiStart;
242 while( startPhi < 0 ) // Loop checking, 13.08.2015, G.Cosmo
243 startPhi += twopi;
244 //
245 // Phi opening? Account for some possible roundoff, and interpret
246 // nonsense value as representing no phi opening
247 //
248 if ( (phiTotal <= 0) || (phiTotal > twopi*(1-DBL_EPSILON)) )
249 {
250 phiIsOpen = false;
251 endPhi = phiStart+twopi;
252 }
253 else
254 {
255 phiIsOpen = true;
256
257 //
258 // Convert phi into our convention
259 //
260 endPhi = phiStart+phiTotal;
261 while( endPhi < startPhi ) // Loop checking, 13.08.2015, G.Cosmo
262 endPhi += twopi;
263 }
264
265 //
266 // Save number sides
267 //
268 numSide = theNumSide;
269
270 //
271 // Allocate corner array.
272 //
274
275 //
276 // Copy corners
277 //
279
281 iterRZ.Begin();
282 do // Loop checking, 13.08.2015, G.Cosmo
283 {
284 next->r = iterRZ.GetA();
285 next->z = iterRZ.GetB();
286 } while( ++next, iterRZ.Next() );
287
288 //
289 // Allocate face pointer array
290 //
292 faces = new G4VCSGface*[numFace];
293
294 //
295 // Construct side faces
296 //
297 // To do so properly, we need to keep track of four successive RZ
298 // corners.
299 //
300 // But! Don't construct a face if both points are at zero radius!
301 //
302 G4PolyhedraSideRZ* corner = corners,
303 * prev = corners + numCorner-1,
304 * nextNext;
305 G4VCSGface** face = faces;
306 do // Loop checking, 13.08.2015, G.Cosmo
307 {
308 next = corner+1;
309 if (next >= corners+numCorner) next = corners;
310 nextNext = next+1;
311 if (nextNext >= corners+numCorner) nextNext = corners;
312
313 if (corner->r < 1/kInfinity && next->r < 1/kInfinity) continue;
314/*
315 // We must decide here if we can dare declare one of our faces
316 // as having a "valid" normal (i.e. allBehind = true). This
317 // is never possible if the face faces "inward" in r *unless*
318 // we have only one side
319 //
320 G4bool allBehind;
321 if ((corner->z > next->z) && (numSide > 1))
322 {
323 allBehind = false;
324 }
325 else
326 {
327 //
328 // Otherwise, it is only true if the line passing
329 // through the two points of the segment do not
330 // split the r/z cross section
331 //
332 allBehind = !rz->BisectedBy( corner->r, corner->z,
333 next->r, next->z, kCarTolerance );
334 }
335*/
336 *face++ = new G4PolyhedraSide( prev, corner, next, nextNext,
338 } while( prev=corner, corner=next, corner > corners );
339
340 if (phiIsOpen)
341 {
342 //
343 // Construct phi open edges
344 //
345 *face++ = new G4PolyPhiFace( rz, startPhi, phiTotal/numSide, endPhi );
346 *face++ = new G4PolyPhiFace( rz, endPhi, phiTotal/numSide, startPhi );
347 }
348
349 //
350 // We might have dropped a face or two: recalculate numFace
351 //
352 numFace = face-faces;
353
354 //
355 // Make enclosingCylinder
356 //
358 new G4EnclosingCylinder( rz, phiIsOpen, phiStart, phiTotal );
359}
360
361// Fake default constructor - sets only member data and allocates memory
362// for usage restricted to object persistency.
363//
365 : G4VCSGfaceted(a), startPhi(0.), endPhi(0.)
366{
367}
368
369// Destructor
370//
372{
373 delete [] corners;
374 delete original_parameters;
375 delete enclosingCylinder;
376 delete fElements;
377 delete fpPolyhedron;
378 corners = nullptr;
379 original_parameters = nullptr;
380 enclosingCylinder = nullptr;
381 fElements = nullptr;
382 fpPolyhedron = nullptr;
383}
384
385// Copy constructor
386//
388 : G4VCSGfaceted( source )
389{
390 CopyStuff( source );
391}
392
393// Assignment operator
394//
396{
397 if (this == &source) return *this;
398
399 G4VCSGfaceted::operator=( source );
400
401 delete [] corners;
402 delete original_parameters;
403 delete enclosingCylinder;
404
405 CopyStuff( source );
406
407 return *this;
408}
409
410// CopyStuff
411//
413{
414 //
415 // Simple stuff
416 //
417 numSide = source.numSide;
418 startPhi = source.startPhi;
419 endPhi = source.endPhi;
420 phiIsOpen = source.phiIsOpen;
421 numCorner = source.numCorner;
422 genericPgon= source.genericPgon;
423
424 //
425 // The corner array
426 //
428
430 * sourceCorn = source.corners;
431 do // Loop checking, 13.08.2015, G.Cosmo
432 {
433 *corn = *sourceCorn;
434 } while( ++sourceCorn, ++corn < corners+numCorner );
435
436 //
437 // Original parameters
438 //
439 if (source.original_parameters)
440 {
443 }
444
445 //
446 // Enclosing cylinder
447 //
449
450 //
451 // Surface elements
452 //
453 delete fElements;
454 fElements = nullptr;
455
456 //
457 // Polyhedron
458 //
459 fRebuildPolyhedron = false;
460 delete fpPolyhedron;
461 fpPolyhedron = nullptr;
462}
463
464// Reset
465//
466// Recalculates and reshapes the solid, given pre-assigned scaled
467// original_parameters.
468//
470{
471 if (genericPgon)
472 {
473 std::ostringstream message;
474 message << "Solid " << GetName() << " built using generic construct."
475 << G4endl << "Not applicable to the generic construct !";
476 G4Exception("G4Polyhedra::Reset()", "GeomSolids1001",
477 JustWarning, message, "Parameters NOT resetted.");
478 return true;
479 }
480
481 //
482 // Clear old setup
483 //
485 delete [] corners;
486 delete enclosingCylinder;
487 delete fElements;
488 corners = nullptr;
489 fElements = nullptr;
490 enclosingCylinder = nullptr;
491
492 //
493 // Rebuild polyhedra
494 //
503 delete rz;
504
505 return false;
506}
507
508// Inside
509//
510// This is an override of G4VCSGfaceted::Inside, created in order
511// to speed things up by first checking with G4EnclosingCylinder.
512//
514{
515 //
516 // Quick test
517 //
519
520 //
521 // Long answer
522 //
523 return G4VCSGfaceted::Inside(p);
524}
525
526// DistanceToIn
527//
528// This is an override of G4VCSGfaceted::Inside, created in order
529// to speed things up by first checking with G4EnclosingCylinder.
530//
532 const G4ThreeVector& v ) const
533{
534 //
535 // Quick test
536 //
538 return kInfinity;
539
540 //
541 // Long answer
542 //
543 return G4VCSGfaceted::DistanceToIn( p, v );
544}
545
546// DistanceToIn
547//
549{
551}
552
553// Get bounding box
554//
556 G4ThreeVector& pMax) const
557{
558 G4double rmin = kInfinity, rmax = -kInfinity;
559 G4double zmin = kInfinity, zmax = -kInfinity;
560 for (G4int i=0; i<GetNumRZCorner(); ++i)
561 {
562 G4PolyhedraSideRZ corner = GetCorner(i);
563 if (corner.r < rmin) rmin = corner.r;
564 if (corner.r > rmax) rmax = corner.r;
565 if (corner.z < zmin) zmin = corner.z;
566 if (corner.z > zmax) zmax = corner.z;
567 }
568
569 G4double sphi = GetStartPhi();
570 G4double ephi = GetEndPhi();
571 G4double dphi = IsOpen() ? ephi-sphi : twopi;
572 G4int ksteps = GetNumSide();
573 G4double astep = dphi/ksteps;
574 G4double sinStep = std::sin(astep);
575 G4double cosStep = std::cos(astep);
576
577 G4double sinCur = GetSinStartPhi();
578 G4double cosCur = GetCosStartPhi();
579 if (!IsOpen()) rmin = 0.;
580 G4double xmin = rmin*cosCur, xmax = xmin;
581 G4double ymin = rmin*sinCur, ymax = ymin;
582 for (G4int k=0; k<ksteps+1; ++k)
583 {
584 G4double x = rmax*cosCur;
585 if (x < xmin) xmin = x;
586 if (x > xmax) xmax = x;
587 G4double y = rmax*sinCur;
588 if (y < ymin) ymin = y;
589 if (y > ymax) ymax = y;
590 if (rmin > 0)
591 {
592 G4double xx = rmin*cosCur;
593 if (xx < xmin) xmin = xx;
594 if (xx > xmax) xmax = xx;
595 G4double yy = rmin*sinCur;
596 if (yy < ymin) ymin = yy;
597 if (yy > ymax) ymax = yy;
598 }
599 G4double sinTmp = sinCur;
600 sinCur = sinCur*cosStep + cosCur*sinStep;
601 cosCur = cosCur*cosStep - sinTmp*sinStep;
602 }
603 pMin.set(xmin,ymin,zmin);
604 pMax.set(xmax,ymax,zmax);
605
606 // Check correctness of the bounding box
607 //
608 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
609 {
610 std::ostringstream message;
611 message << "Bad bounding box (min >= max) for solid: "
612 << GetName() << " !"
613 << "\npMin = " << pMin
614 << "\npMax = " << pMax;
615 G4Exception("G4Polyhedra::BoundingLimits()", "GeomMgt0001",
616 JustWarning, message);
617 DumpInfo();
618 }
619}
620
621// Calculate extent under transform and specified limit
622//
624 const G4VoxelLimits& pVoxelLimit,
625 const G4AffineTransform& pTransform,
626 G4double& pMin, G4double& pMax) const
627{
628 G4ThreeVector bmin, bmax;
629 G4bool exist;
630
631 // Check bounding box (bbox)
632 //
633 BoundingLimits(bmin,bmax);
634 G4BoundingEnvelope bbox(bmin,bmax);
635#ifdef G4BBOX_EXTENT
636 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
637#endif
638 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
639 {
640 return exist = (pMin < pMax) ? true : false;
641 }
642
643 // To find the extent, RZ contour of the polycone is subdivided
644 // in triangles. The extent is calculated as cumulative extent of
645 // all sub-polycones formed by rotation of triangles around Z
646 //
647 G4TwoVectorList contourRZ;
648 G4TwoVectorList triangles;
649 std::vector<G4int> iout;
650 G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
651 G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
652
653 // get RZ contour, ensure anticlockwise order of corners
654 for (G4int i=0; i<GetNumRZCorner(); ++i)
655 {
656 G4PolyhedraSideRZ corner = GetCorner(i);
657 contourRZ.push_back(G4TwoVector(corner.r,corner.z));
658 }
660 G4double area = G4GeomTools::PolygonArea(contourRZ);
661 if (area < 0.) std::reverse(contourRZ.begin(),contourRZ.end());
662
663 // triangulate RZ countour
664 if (!G4GeomTools::TriangulatePolygon(contourRZ,triangles))
665 {
666 std::ostringstream message;
667 message << "Triangulation of RZ contour has failed for solid: "
668 << GetName() << " !"
669 << "\nExtent has been calculated using boundary box";
670 G4Exception("G4Polyhedra::CalculateExtent()",
671 "GeomMgt1002",JustWarning,message);
672 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
673 }
674
675 // set trigonometric values
676 G4double sphi = GetStartPhi();
677 G4double ephi = GetEndPhi();
678 G4double dphi = IsOpen() ? ephi-sphi : twopi;
679 G4int ksteps = GetNumSide();
680 G4double astep = dphi/ksteps;
681 G4double sinStep = std::sin(astep);
682 G4double cosStep = std::cos(astep);
683 G4double sinStart = GetSinStartPhi();
684 G4double cosStart = GetCosStartPhi();
685
686 // allocate vector lists
687 std::vector<const G4ThreeVectorList *> polygons;
688 polygons.resize(ksteps+1);
689 for (G4int k=0; k<ksteps+1; ++k)
690 {
691 polygons[k] = new G4ThreeVectorList(3);
692 }
693
694 // main loop along triangles
695 pMin = kInfinity;
696 pMax = -kInfinity;
697 G4int ntria = triangles.size()/3;
698 for (G4int i=0; i<ntria; ++i)
699 {
700 G4double sinCur = sinStart;
701 G4double cosCur = cosStart;
702 G4int i3 = i*3;
703 for (G4int k=0; k<ksteps+1; ++k) // rotate triangle
704 {
705 G4ThreeVectorList* ptr = const_cast<G4ThreeVectorList*>(polygons[k]);
706 G4ThreeVectorList::iterator iter = ptr->begin();
707 iter->set(triangles[i3+0].x()*cosCur,
708 triangles[i3+0].x()*sinCur,
709 triangles[i3+0].y());
710 iter++;
711 iter->set(triangles[i3+1].x()*cosCur,
712 triangles[i3+1].x()*sinCur,
713 triangles[i3+1].y());
714 iter++;
715 iter->set(triangles[i3+2].x()*cosCur,
716 triangles[i3+2].x()*sinCur,
717 triangles[i3+2].y());
718
719 G4double sinTmp = sinCur;
720 sinCur = sinCur*cosStep + cosCur*sinStep;
721 cosCur = cosCur*cosStep - sinTmp*sinStep;
722 }
723
724 // set sub-envelope and adjust extent
725 G4double emin,emax;
726 G4BoundingEnvelope benv(polygons);
727 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
728 if (emin < pMin) pMin = emin;
729 if (emax > pMax) pMax = emax;
730 if (eminlim > pMin && emaxlim < pMax) break; // max possible extent
731 }
732 // free memory
733 for (G4int k=0; k<ksteps+1; ++k) { delete polygons[k]; polygons[k]=0;}
734 return (pMin < pMax);
735}
736
737// ComputeDimensions
738//
740 const G4int n,
741 const G4VPhysicalVolume* pRep )
742{
743 p->ComputeDimensions(*this,n,pRep);
744}
745
746// GetEntityType
747//
749{
750 return G4String("G4Polyhedra");
751}
752
753// Make a clone of the object
754//
756{
757 return new G4Polyhedra(*this);
758}
759
760// Stream object contents to an output stream
761//
762std::ostream& G4Polyhedra::StreamInfo( std::ostream& os ) const
763{
764 G4int oldprc = os.precision(16);
765 os << "-----------------------------------------------------------\n"
766 << " *** Dump for solid - " << GetName() << " ***\n"
767 << " ===================================================\n"
768 << " Solid type: G4Polyhedra\n"
769 << " Parameters: \n"
770 << " starting phi angle : " << startPhi/degree << " degrees \n"
771 << " ending phi angle : " << endPhi/degree << " degrees \n"
772 << " number of sides : " << numSide << " \n";
773 G4int i=0;
774 if (!genericPgon)
775 {
777 os << " number of Z planes: " << numPlanes << "\n"
778 << " Z values: \n";
779 for (i=0; i<numPlanes; ++i)
780 {
781 os << " Z plane " << i << ": "
782 << original_parameters->Z_values[i] << "\n";
783 }
784 os << " Tangent distances to inner surface (Rmin): \n";
785 for (i=0; i<numPlanes; ++i)
786 {
787 os << " Z plane " << i << ": "
788 << original_parameters->Rmin[i] << "\n";
789 }
790 os << " Tangent distances to outer surface (Rmax): \n";
791 for (i=0; i<numPlanes; ++i)
792 {
793 os << " Z plane " << i << ": "
794 << original_parameters->Rmax[i] << "\n";
795 }
796 }
797 os << " number of RZ points: " << numCorner << "\n"
798 << " RZ values (corners): \n";
799 for (i=0; i<numCorner; ++i)
800 {
801 os << " "
802 << corners[i].r << ", " << corners[i].z << "\n";
803 }
804 os << "-----------------------------------------------------------\n";
805 os.precision(oldprc);
806
807 return os;
808}
809
810//////////////////////////////////////////////////////////////////////////
811//
812// Return volume
813
815{
816 if (fCubicVolume == 0.)
817 {
818 G4double total = 0.;
819 G4int nrz = GetNumRZCorner();
820 G4PolyhedraSideRZ a = GetCorner(nrz - 1);
821 for (G4int i=0; i<nrz; ++i)
822 {
824 total += (b.r*b.r + b.r*a.r + a.r*a.r)*(b.z - a.z);
825 a = b;
826 }
827 fCubicVolume = std::abs(total)*
828 std::sin((GetEndPhi() - GetStartPhi())/GetNumSide())*GetNumSide()/6.;
829 }
830 return fCubicVolume;
831}
832
833//////////////////////////////////////////////////////////////////////////
834//
835// Return surface area
836
838{
839 if (fSurfaceArea == 0.)
840 {
841 G4double total = 0.;
842 G4int nrz = GetNumRZCorner();
843 if (IsOpen())
844 {
845 G4PolyhedraSideRZ a = GetCorner(nrz - 1);
846 for (G4int i=0; i<nrz; ++i)
847 {
849 total += a.r*b.z - a.z*b.r;
850 a = b;
851 }
852 total = std::abs(total);
853 }
855 G4double cosa = std::cos(alp);
856 G4double sina = std::sin(alp);
857 G4PolyhedraSideRZ a = GetCorner(nrz - 1);
858 for (G4int i=0; i<nrz; ++i)
859 {
861 G4ThreeVector p1(a.r, 0, a.z);
862 G4ThreeVector p2(a.r*cosa, a.r*sina, a.z);
863 G4ThreeVector p3(b.r*cosa, b.r*sina, b.z);
864 G4ThreeVector p4(b.r, 0, b.z);
865 total += GetNumSide()*(G4GeomTools::QuadAreaNormal(p1, p2, p3, p4)).mag();
866 a = b;
867 }
868 fSurfaceArea = total;
869 }
870 return fSurfaceArea;
871}
872
873//////////////////////////////////////////////////////////////////////////
874//
875// Set vector of surface elements, auxiliary method for sampling
876// random points on surface
877
879{
880 fElements = new std::vector<G4Polyhedra::surface_element>;
881 G4double total = 0.;
882 G4int nrz = GetNumRZCorner();
883
884 // set lateral surface elements
885 G4double dphi = (GetEndPhi() - GetStartPhi())/GetNumSide();
886 G4double cosa = std::cos(dphi);
887 G4double sina = std::sin(dphi);
888 G4int ia = nrz - 1;
889 for (G4int ib=0; ib<nrz; ++ib)
890 {
894 selem.i0 = ia;
895 selem.i1 = ib;
896 ia = ib;
897 if (a.r == 0. && b.r == 0.) continue;
898 G4ThreeVector p1(a.r, 0, a.z);
899 G4ThreeVector p2(a.r*cosa, a.r*sina, a.z);
900 G4ThreeVector p3(b.r*cosa, b.r*sina, b.z);
901 G4ThreeVector p4(b.r, 0, b.z);
902 if (a.r > 0.)
903 {
904 selem.i2 = -1;
905 total += GetNumSide()*(G4GeomTools::TriangleAreaNormal(p1, p2, p3)).mag();
906 selem.area = total;
907 fElements->push_back(selem);
908 }
909 if (b.r > 0.)
910 {
911 selem.i2 = -2;
912 total += GetNumSide()*(G4GeomTools::TriangleAreaNormal(p1, p3, p4)).mag();
913 selem.area = total;
914 fElements->push_back(selem);
915 }
916 }
917
918 // set elements for phi cuts
919 if (IsOpen())
920 {
921 G4TwoVectorList contourRZ;
922 std::vector<G4int> triangles;
923 for (G4int i=0; i<nrz; ++i)
924 {
925 G4PolyhedraSideRZ corner = GetCorner(i);
926 contourRZ.push_back(G4TwoVector(corner.r, corner.z));
927 }
928 G4GeomTools::TriangulatePolygon(contourRZ, triangles);
929 G4int ntria = triangles.size();
930 for (G4int i=0; i<ntria; i+=3)
931 {
933 selem.i0 = triangles[i];
934 selem.i1 = triangles[i+1];
935 selem.i2 = triangles[i+2];
936 G4PolyhedraSideRZ a = GetCorner(selem.i0);
937 G4PolyhedraSideRZ b = GetCorner(selem.i1);
938 G4PolyhedraSideRZ c = GetCorner(selem.i2);
939 G4double stria =
940 std::abs(G4GeomTools::TriangleArea(a.r, a.z, b.r, b.z, c.r, c.z));
941 total += stria;
942 selem.area = total;
943 fElements->push_back(selem); // start phi
944 total += stria;
945 selem.area = total;
946 selem.i0 += nrz;
947 fElements->push_back(selem); // end phi
948 }
949 }
950}
951
952//////////////////////////////////////////////////////////////////////////
953//
954// Generate random point on surface
955
957{
958 // Set surface elements
959 if (!fElements)
960 {
961 G4AutoLock l(&surface_elementsMutex);
963 l.unlock();
964 }
965
966 // Select surface element
968 selem = fElements->back();
969 G4double select = selem.area*G4QuickRand();
970 auto it = std::lower_bound(fElements->begin(), fElements->end(), select,
971 [](const G4Polyhedra::surface_element& x, G4double val)
972 -> G4bool { return x.area < val; });
973
974 // Generate random point
975 G4double x = 0, y = 0, z = 0;
976 G4double u = G4QuickRand();
977 G4double v = G4QuickRand();
978 if (u + v > 1.) { u = 1. - u; v = 1. - v; }
979 G4int i0 = (*it).i0;
980 G4int i1 = (*it).i1;
981 G4int i2 = (*it).i2;
982 if (i2 < 0) // lateral surface
983 {
984 // sample point
985 G4int nside = GetNumSide();
986 G4double dphi = (GetEndPhi() - GetStartPhi())/nside;
987 G4double cosa = std::cos(dphi);
988 G4double sina = std::sin(dphi);
991 G4ThreeVector p0(a.r, 0, a.z);
992 G4ThreeVector p1(b.r, 0, b.z);
993 G4ThreeVector p2(b.r*cosa, b.r*sina, b.z);
994 if (i2 == -1) p1.set(a.r*cosa, a.r*sina, a.z);
995 p0 += (p1 - p0)*u + (p2 - p0)*v;
996 // find selected side and rotate point
997 G4double scurr = (*it).area;
998 G4double sprev = (it == fElements->begin()) ? 0. : (*(--it)).area;
999 G4int iside = nside*(select - sprev)/(scurr - sprev);
1000 if (iside == 0 && GetStartPhi() == 0.)
1001 {
1002 x = p0.x();
1003 y = p0.y();
1004 z = p0.z();
1005 }
1006 else
1007 {
1008 if (iside == nside) --iside; // iside must be less then nside
1009 G4double phi = iside*dphi + GetStartPhi();
1010 G4double cosphi = std::cos(phi);
1011 G4double sinphi = std::sin(phi);
1012 x = p0.x()*cosphi - p0.y()*sinphi;
1013 y = p0.x()*sinphi + p0.y()*cosphi;
1014 z = p0.z();
1015 }
1016 }
1017 else // phi cut
1018 {
1019 G4int nrz = GetNumRZCorner();
1020 G4double phi = (i0 < nrz) ? GetStartPhi() : GetEndPhi();
1021 if (i0 >= nrz) { i0 -= nrz; }
1025 G4double r = (p1.r - p0.r)*u + (p2.r - p0.r)*v + p0.r;
1026 x = r*std::cos(phi);
1027 y = r*std::sin(phi);
1028 z = (p1.z - p0.z)*u + (p2.z - p0.z)*v + p0.z;
1029 }
1030 return G4ThreeVector(x, y, z);
1031}
1032
1033//////////////////////////////////////////////////////////////////////////
1034//
1035// CreatePolyhedron
1036
1038{
1039 if (!genericPgon)
1040 {
1048 }
1049 else
1050 {
1051 // The following code prepares for:
1052 // HepPolyhedron::createPolyhedron(int Nnodes, int Nfaces,
1053 // const double xyz[][3],
1054 // const int faces_vec[][4])
1055 // Here is an extract from the header file HepPolyhedron.h:
1056 /**
1057 * Creates user defined polyhedron.
1058 * This function allows to the user to define arbitrary polyhedron.
1059 * The faces of the polyhedron should be either triangles or planar
1060 * quadrilateral. Nodes of a face are defined by indexes pointing to
1061 * the elements in the xyz array. Numeration of the elements in the
1062 * array starts from 1 (like in fortran). The indexes can be positive
1063 * or negative. Negative sign means that the corresponding edge is
1064 * invisible. The normal of the face should be directed to exterior
1065 * of the polyhedron.
1066 *
1067 * @param Nnodes number of nodes
1068 * @param Nfaces number of faces
1069 * @param xyz nodes
1070 * @param faces_vec faces (quadrilaterals or triangles)
1071 * @return status of the operation - is non-zero in case of problem
1072 */
1073 G4int nNodes;
1074 G4int nFaces;
1075 typedef G4double double3[3];
1076 double3* xyz;
1077 typedef G4int int4[4];
1078 int4* faces_vec;
1079 if (phiIsOpen)
1080 {
1081 // Triangulate open ends. Simple ear-chopping algorithm...
1082 // I'm not sure how robust this algorithm is (J.Allison).
1083 //
1084 std::vector<G4bool> chopped(numCorner, false);
1085 std::vector<G4int*> triQuads;
1086 G4int remaining = numCorner;
1087 G4int iStarter = 0;
1088 while (remaining >= 3) // Loop checking, 13.08.2015, G.Cosmo
1089 {
1090 // Find unchopped corners...
1091 //
1092 G4int A = -1, B = -1, C = -1;
1093 G4int iStepper = iStarter;
1094 do // Loop checking, 13.08.2015, G.Cosmo
1095 {
1096 if (A < 0) { A = iStepper; }
1097 else if (B < 0) { B = iStepper; }
1098 else if (C < 0) { C = iStepper; }
1099 do // Loop checking, 13.08.2015, G.Cosmo
1100 {
1101 if (++iStepper >= numCorner) iStepper = 0;
1102 }
1103 while (chopped[iStepper]);
1104 }
1105 while (C < 0 && iStepper != iStarter);
1106
1107 // Check triangle at B is pointing outward (an "ear").
1108 // Sign of z cross product determines...
1109
1110 G4double BAr = corners[A].r - corners[B].r;
1111 G4double BAz = corners[A].z - corners[B].z;
1112 G4double BCr = corners[C].r - corners[B].r;
1113 G4double BCz = corners[C].z - corners[B].z;
1114 if (BAr * BCz - BAz * BCr < kCarTolerance)
1115 {
1116 G4int* tq = new G4int[3];
1117 tq[0] = A + 1;
1118 tq[1] = B + 1;
1119 tq[2] = C + 1;
1120 triQuads.push_back(tq);
1121 chopped[B] = true;
1122 --remaining;
1123 }
1124 else
1125 {
1126 do // Loop checking, 13.08.2015, G.Cosmo
1127 {
1128 if (++iStarter >= numCorner) { iStarter = 0; }
1129 }
1130 while (chopped[iStarter]);
1131 }
1132 }
1133
1134 // Transfer to faces...
1135
1136 nNodes = (numSide + 1) * numCorner;
1137 nFaces = numSide * numCorner + 2 * triQuads.size();
1138 faces_vec = new int4[nFaces];
1139 G4int iface = 0;
1140 G4int addition = numCorner * numSide;
1141 G4int d = numCorner - 1;
1142 for (G4int iEnd = 0; iEnd < 2; ++iEnd)
1143 {
1144 for (size_t i = 0; i < triQuads.size(); ++i)
1145 {
1146 // Negative for soft/auxiliary/normally invisible edges...
1147 //
1148 G4int a, b, c;
1149 if (iEnd == 0)
1150 {
1151 a = triQuads[i][0];
1152 b = triQuads[i][1];
1153 c = triQuads[i][2];
1154 }
1155 else
1156 {
1157 a = triQuads[i][0] + addition;
1158 b = triQuads[i][2] + addition;
1159 c = triQuads[i][1] + addition;
1160 }
1161 G4int ab = std::abs(b - a);
1162 G4int bc = std::abs(c - b);
1163 G4int ca = std::abs(a - c);
1164 faces_vec[iface][0] = (ab == 1 || ab == d)? a: -a;
1165 faces_vec[iface][1] = (bc == 1 || bc == d)? b: -b;
1166 faces_vec[iface][2] = (ca == 1 || ca == d)? c: -c;
1167 faces_vec[iface][3] = 0;
1168 ++iface;
1169 }
1170 }
1171
1172 // Continue with sides...
1173
1174 xyz = new double3[nNodes];
1175 const G4double dPhi = (endPhi - startPhi) / numSide;
1176 G4double phi = startPhi;
1177 G4int ixyz = 0;
1178 for (G4int iSide = 0; iSide < numSide; ++iSide)
1179 {
1180 for (G4int iCorner = 0; iCorner < numCorner; ++iCorner)
1181 {
1182 xyz[ixyz][0] = corners[iCorner].r * std::cos(phi);
1183 xyz[ixyz][1] = corners[iCorner].r * std::sin(phi);
1184 xyz[ixyz][2] = corners[iCorner].z;
1185 if (iCorner < numCorner - 1)
1186 {
1187 faces_vec[iface][0] = ixyz + 1;
1188 faces_vec[iface][1] = ixyz + numCorner + 1;
1189 faces_vec[iface][2] = ixyz + numCorner + 2;
1190 faces_vec[iface][3] = ixyz + 2;
1191 }
1192 else
1193 {
1194 faces_vec[iface][0] = ixyz + 1;
1195 faces_vec[iface][1] = ixyz + numCorner + 1;
1196 faces_vec[iface][2] = ixyz + 2;
1197 faces_vec[iface][3] = ixyz - numCorner + 2;
1198 }
1199 ++iface;
1200 ++ixyz;
1201 }
1202 phi += dPhi;
1203 }
1204
1205 // Last corners...
1206
1207 for (G4int iCorner = 0; iCorner < numCorner; ++iCorner)
1208 {
1209 xyz[ixyz][0] = corners[iCorner].r * std::cos(phi);
1210 xyz[ixyz][1] = corners[iCorner].r * std::sin(phi);
1211 xyz[ixyz][2] = corners[iCorner].z;
1212 ++ixyz;
1213 }
1214 }
1215 else // !phiIsOpen - i.e., a complete 360 degrees.
1216 {
1217 nNodes = numSide * numCorner;
1218 nFaces = numSide * numCorner;;
1219 xyz = new double3[nNodes];
1220 faces_vec = new int4[nFaces];
1221 // const G4double dPhi = (endPhi - startPhi) / numSide;
1222 const G4double dPhi = twopi / numSide;
1223 // !phiIsOpen endPhi-startPhi = 360 degrees.
1224 G4double phi = startPhi;
1225 G4int ixyz = 0, iface = 0;
1226 for (G4int iSide = 0; iSide < numSide; ++iSide)
1227 {
1228 for (G4int iCorner = 0; iCorner < numCorner; ++iCorner)
1229 {
1230 xyz[ixyz][0] = corners[iCorner].r * std::cos(phi);
1231 xyz[ixyz][1] = corners[iCorner].r * std::sin(phi);
1232 xyz[ixyz][2] = corners[iCorner].z;
1233 if (iSide < numSide - 1)
1234 {
1235 if (iCorner < numCorner - 1)
1236 {
1237 faces_vec[iface][0] = ixyz + 1;
1238 faces_vec[iface][1] = ixyz + numCorner + 1;
1239 faces_vec[iface][2] = ixyz + numCorner + 2;
1240 faces_vec[iface][3] = ixyz + 2;
1241 }
1242 else
1243 {
1244 faces_vec[iface][0] = ixyz + 1;
1245 faces_vec[iface][1] = ixyz + numCorner + 1;
1246 faces_vec[iface][2] = ixyz + 2;
1247 faces_vec[iface][3] = ixyz - numCorner + 2;
1248 }
1249 }
1250 else // Last side joins ends...
1251 {
1252 if (iCorner < numCorner - 1)
1253 {
1254 faces_vec[iface][0] = ixyz + 1;
1255 faces_vec[iface][1] = ixyz + numCorner - nFaces + 1;
1256 faces_vec[iface][2] = ixyz + numCorner - nFaces + 2;
1257 faces_vec[iface][3] = ixyz + 2;
1258 }
1259 else
1260 {
1261 faces_vec[iface][0] = ixyz + 1;
1262 faces_vec[iface][1] = ixyz - nFaces + numCorner + 1;
1263 faces_vec[iface][2] = ixyz - nFaces + 2;
1264 faces_vec[iface][3] = ixyz - numCorner + 2;
1265 }
1266 }
1267 ++ixyz;
1268 ++iface;
1269 }
1270 phi += dPhi;
1271 }
1272 }
1273 G4Polyhedron* polyhedron = new G4Polyhedron;
1274 G4int problem = polyhedron->createPolyhedron(nNodes,nFaces,xyz,faces_vec);
1275 delete [] faces_vec;
1276 delete [] xyz;
1277 if (problem)
1278 {
1279 std::ostringstream message;
1280 message << "Problem creating G4Polyhedron for: " << GetName();
1281 G4Exception("G4Polyhedra::CreatePolyhedron()", "GeomSolids1002",
1282 JustWarning, message);
1283 delete polyhedron;
1284 return nullptr;
1285 }
1286 else
1287 {
1288 return polyhedron;
1289 }
1290 }
1291}
1292
1293// SetOriginalParameters
1294//
1296{
1297 G4int numPlanes = numCorner;
1298 G4bool isConvertible = true;
1299 G4double Zmax=rz->Bmax();
1300 rz->StartWithZMin();
1301
1302 // Prepare vectors for storage
1303 //
1304 std::vector<G4double> Z;
1305 std::vector<G4double> Rmin;
1306 std::vector<G4double> Rmax;
1307
1308 G4int countPlanes=1;
1309 G4int icurr=0;
1310 G4int icurl=0;
1311
1312 // first plane Z=Z[0]
1313 //
1314 Z.push_back(corners[0].z);
1315 G4double Zprev=Z[0];
1316 if (Zprev == corners[1].z)
1317 {
1318 Rmin.push_back(corners[0].r);
1319 Rmax.push_back (corners[1].r);icurr=1;
1320 }
1321 else if (Zprev == corners[numPlanes-1].z)
1322 {
1323 Rmin.push_back(corners[numPlanes-1].r);
1324 Rmax.push_back (corners[0].r);
1325 icurl=numPlanes-1;
1326 }
1327 else
1328 {
1329 Rmin.push_back(corners[0].r);
1330 Rmax.push_back (corners[0].r);
1331 }
1332
1333 // next planes until last
1334 //
1335 G4int inextr=0, inextl=0;
1336 for (G4int i=0; i < numPlanes-2; ++i)
1337 {
1338 inextr=1+icurr;
1339 inextl=(icurl <= 0)? numPlanes-1 : icurl-1;
1340
1341 if((corners[inextr].z >= Zmax) & (corners[inextl].z >= Zmax)) { break; }
1342
1343 G4double Zleft = corners[inextl].z;
1344 G4double Zright = corners[inextr].z;
1345 if(Zright>Zleft)
1346 {
1347 Z.push_back(Zleft);
1348 countPlanes++;
1349 G4double difZr=corners[inextr].z - corners[icurr].z;
1350 G4double difZl=corners[inextl].z - corners[icurl].z;
1351
1352 if(std::fabs(difZl) < kCarTolerance)
1353 {
1354 if(std::fabs(difZr) < kCarTolerance)
1355 {
1356 Rmin.push_back(corners[inextl].r);
1357 Rmax.push_back(corners[icurr].r);
1358 }
1359 else
1360 {
1361 Rmin.push_back(corners[inextl].r);
1362 Rmax.push_back(corners[icurr].r + (Zleft-corners[icurr].z)/difZr
1363 *(corners[inextr].r - corners[icurr].r));
1364 }
1365 }
1366 else if (difZl >= kCarTolerance)
1367 {
1368 if(std::fabs(difZr) < kCarTolerance)
1369 {
1370 Rmin.push_back(corners[icurl].r);
1371 Rmax.push_back(corners[icurr].r);
1372 }
1373 else
1374 {
1375 Rmin.push_back(corners[icurl].r);
1376 Rmax.push_back(corners[icurr].r + (Zleft-corners[icurr].z)/difZr
1377 *(corners[inextr].r - corners[icurr].r));
1378 }
1379 }
1380 else
1381 {
1382 isConvertible=false; break;
1383 }
1384 icurl=(icurl == 0)? numPlanes-1 : icurl-1;
1385 }
1386 else if(std::fabs(Zright-Zleft)<kCarTolerance) // Zright=Zleft
1387 {
1388 Z.push_back(Zleft);
1389 ++countPlanes;
1390 ++icurr;
1391
1392 icurl=(icurl == 0)? numPlanes-1 : icurl-1;
1393
1394 Rmin.push_back(corners[inextl].r);
1395 Rmax.push_back (corners[inextr].r);
1396 }
1397 else // Zright<Zleft
1398 {
1399 Z.push_back(Zright);
1400 ++countPlanes;
1401
1402 G4double difZr=corners[inextr].z - corners[icurr].z;
1403 G4double difZl=corners[inextl].z - corners[icurl].z;
1404 if(std::fabs(difZr) < kCarTolerance)
1405 {
1406 if(std::fabs(difZl) < kCarTolerance)
1407 {
1408 Rmax.push_back(corners[inextr].r);
1409 Rmin.push_back(corners[icurr].r);
1410 }
1411 else
1412 {
1413 Rmin.push_back(corners[icurl].r + (Zright-corners[icurl].z)/difZl
1414 * (corners[inextl].r - corners[icurl].r));
1415 Rmax.push_back(corners[inextr].r);
1416 }
1417 ++icurr;
1418 } // plate
1419 else if (difZr >= kCarTolerance)
1420 {
1421 if(std::fabs(difZl) < kCarTolerance)
1422 {
1423 Rmax.push_back(corners[inextr].r);
1424 Rmin.push_back (corners[icurr].r);
1425 }
1426 else
1427 {
1428 Rmax.push_back(corners[inextr].r);
1429 Rmin.push_back (corners[icurl].r+(Zright-corners[icurl].z)/difZl
1430 * (corners[inextl].r - corners[icurl].r));
1431 }
1432 ++icurr;
1433 }
1434 else
1435 {
1436 isConvertible=false; break;
1437 }
1438 }
1439 } // end for loop
1440
1441 // last plane Z=Zmax
1442 //
1443 Z.push_back(Zmax);
1444 ++countPlanes;
1445 inextr=1+icurr;
1446 inextl=(icurl <= 0)? numPlanes-1 : icurl-1;
1447
1448 Rmax.push_back(corners[inextr].r);
1449 Rmin.push_back(corners[inextl].r);
1450
1451 // Set original parameters Rmin,Rmax,Z
1452 //
1453 if(isConvertible)
1454 {
1457 original_parameters->Z_values = new G4double[countPlanes];
1458 original_parameters->Rmin = new G4double[countPlanes];
1459 original_parameters->Rmax = new G4double[countPlanes];
1460
1461 for(G4int j=0; j < countPlanes; ++j)
1462 {
1463 original_parameters->Z_values[j] = Z[j];
1464 original_parameters->Rmax[j] = Rmax[j];
1465 original_parameters->Rmin[j] = Rmin[j];
1466 }
1469 original_parameters->Num_z_planes = countPlanes;
1470
1471 }
1472 else // Set parameters(r,z) with Rmin==0 as convention
1473 {
1474#ifdef G4SPECSDEBUG
1475 std::ostringstream message;
1476 message << "Polyhedra " << GetName() << G4endl
1477 << "cannot be converted to Polyhedra with (Rmin,Rmaz,Z) parameters!";
1478 G4Exception("G4Polyhedra::SetOriginalParameters()",
1479 "GeomSolids0002", JustWarning, message);
1480#endif
1483 original_parameters->Z_values = new G4double[numPlanes];
1484 original_parameters->Rmin = new G4double[numPlanes];
1485 original_parameters->Rmax = new G4double[numPlanes];
1486
1487 for(G4int j=0; j < numPlanes; ++j)
1488 {
1491 original_parameters->Rmin[j] = 0.0;
1492 }
1495 original_parameters->Num_z_planes = numPlanes;
1496 }
1497}
1498
1499#endif
std::vector< G4ThreeVector > G4ThreeVectorList
double B(double temperature)
double C(double temp)
double A(double temperature)
@ JustWarning
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
std::vector< G4TwoVector > G4TwoVectorList
Definition: G4GeomTools.hh:42
G4double G4QuickRand()
Definition: G4QuickRand.hh:34
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:85
std::mutex G4Mutex
Definition: G4Threading.hh:81
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
Definition: G4TwoVector.hh:36
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
double z() const
double x() const
double y() const
void set(double x, double y, double z)
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4bool ShouldMiss(const G4ThreeVector &p, const G4ThreeVector &v) const
G4bool MustBeOutside(const G4ThreeVector &p) const
static G4ThreeVector QuadAreaNormal(const G4ThreeVector &A, const G4ThreeVector &B, const G4ThreeVector &C, const G4ThreeVector &D)
Definition: G4GeomTools.cc:609
static G4bool TriangulatePolygon(const G4TwoVectorList &polygon, G4TwoVectorList &result)
Definition: G4GeomTools.cc:193
static void RemoveRedundantVertices(G4TwoVectorList &polygon, std::vector< G4int > &iout, G4double tolerance=0.0)
Definition: G4GeomTools.cc:305
static G4double TriangleArea(G4double Ax, G4double Ay, G4double Bx, G4double By, G4double Cx, G4double Cy)
Definition: G4GeomTools.cc:41
static G4double PolygonArea(const G4TwoVectorList &polygon)
Definition: G4GeomTools.cc:76
static G4ThreeVector TriangleAreaNormal(const G4ThreeVector &A, const G4ThreeVector &B, const G4ThreeVector &C)
Definition: G4GeomTools.cc:598
G4ThreeVector GetPointOnSurface() const
Definition: G4Polyhedra.cc:956
G4Polyhedra & operator=(const G4Polyhedra &source)
Definition: G4Polyhedra.cc:395
std::ostream & StreamInfo(std::ostream &os) const
Definition: G4Polyhedra.cc:762
G4PolyhedraHistorical * original_parameters
Definition: G4Polyhedra.hh:189
G4double GetCubicVolume()
Definition: G4Polyhedra.cc:814
G4PolyhedraSideRZ * corners
Definition: G4Polyhedra.hh:188
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
Definition: G4Polyhedra.cc:623
G4Polyhedra(const G4String &name, G4double phiStart, G4double phiTotal, G4int numSide, G4int numZPlanes, const G4double zPlane[], const G4double rInner[], const G4double rOuter[])
Definition: G4Polyhedra.cc:71
G4int GetNumRZCorner() const
G4bool genericPgon
Definition: G4Polyhedra.hh:186
void CopyStuff(const G4Polyhedra &source)
Definition: G4Polyhedra.cc:412
G4double GetSinStartPhi() const
G4VSolid * Clone() const
Definition: G4Polyhedra.cc:755
void Create(G4double phiStart, G4double phiTotal, G4int numSide, G4ReduciblePolygon *rz)
Definition: G4Polyhedra.cc:188
G4bool IsOpen() const
G4GeometryType GetEntityType() const
Definition: G4Polyhedra.cc:748
G4double endPhi
Definition: G4Polyhedra.hh:184
G4double GetSurfaceArea()
Definition: G4Polyhedra.cc:837
G4double GetEndPhi() const
std::vector< surface_element > * fElements
Definition: G4Polyhedra.hh:194
void SetOriginalParameters(G4PolyhedraHistorical *pars)
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
Definition: G4Polyhedra.cc:739
G4bool phiIsOpen
Definition: G4Polyhedra.hh:185
G4double startPhi
Definition: G4Polyhedra.hh:183
G4int GetNumSide() const
G4int numCorner
Definition: G4Polyhedra.hh:187
virtual ~G4Polyhedra()
Definition: G4Polyhedra.cc:371
G4PolyhedraSideRZ GetCorner(const G4int index) const
G4bool Reset()
Definition: G4Polyhedra.cc:469
G4double GetStartPhi() const
G4EnclosingCylinder * enclosingCylinder
Definition: G4Polyhedra.hh:191
G4double GetCosStartPhi() const
void SetSurfaceElements() const
Definition: G4Polyhedra.cc:878
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
Definition: G4Polyhedra.cc:531
EInside Inside(const G4ThreeVector &p) const
Definition: G4Polyhedra.cc:513
G4Polyhedron * CreatePolyhedron() const
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
Definition: G4Polyhedra.cc:555
G4double Amin() const
G4bool RemoveDuplicateVertices(G4double tolerance)
G4int NumVertices() const
G4bool RemoveRedundantVertices(G4double tolerance)
G4bool CrossesItself(G4double tolerance)
G4double Bmax() const
void ScaleA(G4double scale)
G4VCSGfaceted & operator=(const G4VCSGfaceted &source)
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4double fCubicVolume
virtual EInside Inside(const G4ThreeVector &p) const
G4VCSGface ** faces
G4Polyhedron * fpPolyhedron
G4bool fRebuildPolyhedron
G4double fSurfaceArea
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4String GetName() const
void DumpInfo() const
G4double kCarTolerance
Definition: G4VSolid.hh:302
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const
G4int createPolyhedron(G4int Nnodes, G4int Nfaces, const G4double xyz[][3], const G4int faces[][4])
EAxis
Definition: geomdefs.hh:54
EInside
Definition: geomdefs.hh:67
@ kOutside
Definition: geomdefs.hh:68
Definition: DoubConv.h:17
#define DBL_EPSILON
Definition: templates.hh:66