Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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//
27// $Id$
28//
29//
30// --------------------------------------------------------------------
31// GEANT 4 class source file
32//
33//
34// G4Polyhedra.cc
35//
36// Implementation of a CSG polyhedra, as an inherited class of G4VCSGfaceted.
37//
38// To be done:
39// * Cracks: there are probably small cracks in the seams between the
40// phi face (G4PolyPhiFace) and sides (G4PolyhedraSide) that are not
41// entirely leakproof. Also, I am not sure all vertices are leak proof.
42// * Many optimizations are possible, but not implemented.
43// * Visualization needs to be updated outside of this routine.
44//
45// Utility classes:
46// * G4EnclosingCylinder: I decided a quick check of geometry would be a
47// good idea (for CPU speed). If the quick check fails, the regular
48// full-blown G4VCSGfaceted version is invoked.
49// * G4ReduciblePolygon: Really meant as a check of input parameters,
50// this utility class also "converts" the GEANT3-like PGON/PCON
51// arguments into the newer ones.
52// Both these classes are implemented outside this file because they are
53// shared with G4Polycone.
54//
55// --------------------------------------------------------------------
56
57#include "G4Polyhedra.hh"
58
59#include "G4PolyhedraSide.hh"
60#include "G4PolyPhiFace.hh"
61
62#include "Randomize.hh"
63
64#include "G4Polyhedron.hh"
66#include "G4ReduciblePolygon.hh"
68
69#include <sstream>
70
71using namespace CLHEP;
72
73//
74// Constructor (GEANT3 style parameters)
75//
76// GEANT3 PGON radii are specified in the distance to the norm of each face.
77//
79 G4double phiStart,
80 G4double thePhiTotal,
81 G4int theNumSide,
82 G4int numZPlanes,
83 const G4double zPlane[],
84 const G4double rInner[],
85 const G4double rOuter[] )
86 : G4VCSGfaceted( name ), genericPgon(false)
87{
88 if (theNumSide <= 0)
89 {
90 std::ostringstream message;
91 message << "Solid must have at least one side - " << GetName() << G4endl
92 << " No sides specified !";
93 G4Exception("G4Polyhedra::G4Polyhedra()", "GeomSolids0002",
94 FatalErrorInArgument, message);
95 }
96
97 //
98 // Calculate conversion factor from G3 radius to G4 radius
99 //
100 G4double phiTotal = thePhiTotal;
101 if ( (phiTotal <=0) || (phiTotal >= twopi*(1-DBL_EPSILON)) )
102 { phiTotal = twopi; }
103 G4double convertRad = std::cos(0.5*phiTotal/theNumSide);
104
105 //
106 // Some historical stuff
107 //
109
110 original_parameters->numSide = theNumSide;
113 original_parameters->Num_z_planes = numZPlanes;
114 original_parameters->Z_values = new G4double[numZPlanes];
115 original_parameters->Rmin = new G4double[numZPlanes];
116 original_parameters->Rmax = new G4double[numZPlanes];
117
118 G4int i;
119 for (i=0; i<numZPlanes; i++)
120 {
121 if (( i < numZPlanes-1) && ( zPlane[i] == zPlane[i+1] ))
122 {
123 if( (rInner[i] > rOuter[i+1])
124 ||(rInner[i+1] > rOuter[i]) )
125 {
126 DumpInfo();
127 std::ostringstream message;
128 message << "Cannot create a Polyhedra with no contiguous segments."
129 << G4endl
130 << " Segments are not contiguous !" << G4endl
131 << " rMin[" << i << "] = " << rInner[i]
132 << " -- rMax[" << i+1 << "] = " << rOuter[i+1] << G4endl
133 << " rMin[" << i+1 << "] = " << rInner[i+1]
134 << " -- rMax[" << i << "] = " << rOuter[i];
135 G4Exception("G4Polyhedra::G4Polyhedra()", "GeomSolids0002",
136 FatalErrorInArgument, message);
137 }
138 }
139 original_parameters->Z_values[i] = zPlane[i];
140 original_parameters->Rmin[i] = rInner[i]/convertRad;
141 original_parameters->Rmax[i] = rOuter[i]/convertRad;
142 }
143
144
145 //
146 // Build RZ polygon using special PCON/PGON GEANT3 constructor
147 //
149 new G4ReduciblePolygon( rInner, rOuter, zPlane, numZPlanes );
150 rz->ScaleA( 1/convertRad );
151
152 //
153 // Do the real work
154 //
155 Create( phiStart, phiTotal, theNumSide, rz );
156
157 delete rz;
158}
159
160
161//
162// Constructor (generic parameters)
163//
165 G4double phiStart,
166 G4double phiTotal,
167 G4int theNumSide,
168 G4int numRZ,
169 const G4double r[],
170 const G4double z[] )
171 : G4VCSGfaceted( name ), genericPgon(true)
172{
173 G4ReduciblePolygon *rz = new G4ReduciblePolygon( r, z, numRZ );
174
175 Create( phiStart, phiTotal, theNumSide, rz );
176
177 // Set original_parameters struct for consistency
178 //
180
181 delete rz;
182}
183
184
185//
186// Create
187//
188// Generic create routine, called by each constructor
189// after conversion of arguments
190//
192 G4double phiTotal,
193 G4int theNumSide,
195{
196 //
197 // Perform checks of rz values
198 //
199 if (rz->Amin() < 0.0)
200 {
201 std::ostringstream message;
202 message << "Illegal input parameters - " << GetName() << G4endl
203 << " All R values must be >= 0 !";
204 G4Exception("G4Polyhedra::Create()", "GeomSolids0002",
205 FatalErrorInArgument, message);
206 }
207
208 G4double rzArea = rz->Area();
209 if (rzArea < -kCarTolerance)
210 rz->ReverseOrder();
211
212 else if (rzArea < -kCarTolerance)
213 {
214 std::ostringstream message;
215 message << "Illegal input parameters - " << GetName() << G4endl
216 << " R/Z cross section is zero or near zero: " << rzArea;
217 G4Exception("G4Polyhedra::Create()", "GeomSolids0002",
218 FatalErrorInArgument, message);
219 }
220
223 {
224 std::ostringstream message;
225 message << "Illegal input parameters - " << GetName() << G4endl
226 << " Too few unique R/Z values !";
227 G4Exception("G4Polyhedra::Create()", "GeomSolids0002",
228 FatalErrorInArgument, message);
229 }
230
231 if (rz->CrossesItself( 1/kInfinity ))
232 {
233 std::ostringstream message;
234 message << "Illegal input parameters - " << GetName() << G4endl
235 << " R/Z segments cross !";
236 G4Exception("G4Polyhedra::Create()", "GeomSolids0002",
237 FatalErrorInArgument, message);
238 }
239
240 numCorner = rz->NumVertices();
241
242
243 startPhi = phiStart;
244 while( startPhi < 0 ) startPhi += twopi;
245 //
246 // Phi opening? Account for some possible roundoff, and interpret
247 // nonsense value as representing no phi opening
248 //
249 if ( (phiTotal <= 0) || (phiTotal > twopi*(1-DBL_EPSILON)) )
250 {
251 phiIsOpen = false;
252 endPhi = phiStart+twopi;
253 }
254 else
255 {
256 phiIsOpen = true;
257
258 //
259 // Convert phi into our convention
260 //
261 endPhi = phiStart+phiTotal;
262 while( endPhi < startPhi ) 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
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
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
362//
363// Fake default constructor - sets only member data and allocates memory
364// for usage restricted to object persistency.
365//
367 : G4VCSGfaceted(a), numSide(0), startPhi(0.), endPhi(0.),
368 phiIsOpen(false), genericPgon(false), numCorner(0), corners(0),
369 original_parameters(0), enclosingCylinder(0)
370{
371}
372
373
374//
375// Destructor
376//
378{
379 delete [] corners;
381
382 delete enclosingCylinder;
383}
384
385
386//
387// Copy constructor
388//
390 : G4VCSGfaceted( source )
391{
392 CopyStuff( source );
393}
394
395
396//
397// Assignment operator
398//
400{
401 if (this == &source) return *this;
402
403 G4VCSGfaceted::operator=( source );
404
405 delete [] corners;
407
408 delete enclosingCylinder;
409
410 CopyStuff( source );
411
412 return *this;
413}
414
415
416//
417// CopyStuff
418//
420{
421 //
422 // Simple stuff
423 //
424 numSide = source.numSide;
425 startPhi = source.startPhi;
426 endPhi = source.endPhi;
427 phiIsOpen = source.phiIsOpen;
428 numCorner = source.numCorner;
429 genericPgon= source.genericPgon;
430
431 //
432 // The corner array
433 //
435
437 *sourceCorn = source.corners;
438 do
439 {
440 *corn = *sourceCorn;
441 } while( ++sourceCorn, ++corn < corners+numCorner );
442
443 //
444 // Original parameters
445 //
446 if (source.original_parameters)
447 {
450 }
451
452 //
453 // Enclosing cylinder
454 //
456}
457
458
459//
460// Reset
461//
462// Recalculates and reshapes the solid, given pre-assigned scaled
463// original_parameters.
464//
466{
467 if (genericPgon)
468 {
469 std::ostringstream message;
470 message << "Solid " << GetName() << " built using generic construct."
471 << G4endl << "Not applicable to the generic construct !";
472 G4Exception("G4Polyhedra::Reset()", "GeomSolids1001",
473 JustWarning, message, "Parameters NOT resetted.");
474 return 1;
475 }
476
477 //
478 // Clear old setup
479 //
481 delete [] corners;
482 delete enclosingCylinder;
483
484 //
485 // Rebuild polyhedra
486 //
495 delete rz;
496
497 return 0;
498}
499
500
501//
502// Inside
503//
504// This is an override of G4VCSGfaceted::Inside, created in order
505// to speed things up by first checking with G4EnclosingCylinder.
506//
508{
509 //
510 // Quick test
511 //
513
514 //
515 // Long answer
516 //
517 return G4VCSGfaceted::Inside(p);
518}
519
520
521//
522// DistanceToIn
523//
524// This is an override of G4VCSGfaceted::Inside, created in order
525// to speed things up by first checking with G4EnclosingCylinder.
526//
528 const G4ThreeVector &v ) const
529{
530 //
531 // Quick test
532 //
534 return kInfinity;
535
536 //
537 // Long answer
538 //
539 return G4VCSGfaceted::DistanceToIn( p, v );
540}
541
542
543//
544// DistanceToIn
545//
547{
549}
550
551
552//
553// ComputeDimensions
554//
556 const G4int n,
557 const G4VPhysicalVolume* pRep )
558{
559 p->ComputeDimensions(*this,n,pRep);
560}
561
562
563//
564// GetEntityType
565//
567{
568 return G4String("G4Polyhedra");
569}
570
571
572//
573// Make a clone of the object
574//
576{
577 return new G4Polyhedra(*this);
578}
579
580
581//
582// Stream object contents to an output stream
583//
584std::ostream& G4Polyhedra::StreamInfo( std::ostream& os ) const
585{
586 G4int oldprc = os.precision(16);
587 os << "-----------------------------------------------------------\n"
588 << " *** Dump for solid - " << GetName() << " ***\n"
589 << " ===================================================\n"
590 << " Solid type: G4Polyhedra\n"
591 << " Parameters: \n"
592 << " starting phi angle : " << startPhi/degree << " degrees \n"
593 << " ending phi angle : " << endPhi/degree << " degrees \n";
594 G4int i=0;
595 if (!genericPgon)
596 {
598 os << " number of Z planes: " << numPlanes << "\n"
599 << " Z values: \n";
600 for (i=0; i<numPlanes; i++)
601 {
602 os << " Z plane " << i << ": "
603 << original_parameters->Z_values[i] << "\n";
604 }
605 os << " Tangent distances to inner surface (Rmin): \n";
606 for (i=0; i<numPlanes; i++)
607 {
608 os << " Z plane " << i << ": "
609 << original_parameters->Rmin[i] << "\n";
610 }
611 os << " Tangent distances to outer surface (Rmax): \n";
612 for (i=0; i<numPlanes; i++)
613 {
614 os << " Z plane " << i << ": "
615 << original_parameters->Rmax[i] << "\n";
616 }
617 }
618 os << " number of RZ points: " << numCorner << "\n"
619 << " RZ values (corners): \n";
620 for (i=0; i<numCorner; i++)
621 {
622 os << " "
623 << corners[i].r << ", " << corners[i].z << "\n";
624 }
625 os << "-----------------------------------------------------------\n";
626 os.precision(oldprc);
627
628 return os;
629}
630
631
632//
633// GetPointOnPlane
634//
635// Auxiliary method for get point on surface
636//
638 G4ThreeVector p2, G4ThreeVector p3) const
639{
640 G4double lambda1, lambda2, chose,aOne,aTwo;
641 G4ThreeVector t, u, v, w, Area, normal;
642 aOne = 1.;
643 aTwo = 1.;
644
645 t = p1 - p0;
646 u = p2 - p1;
647 v = p3 - p2;
648 w = p0 - p3;
649
650 chose = RandFlat::shoot(0.,aOne+aTwo);
651 if( (chose>=0.) && (chose < aOne) )
652 {
653 lambda1 = RandFlat::shoot(0.,1.);
654 lambda2 = RandFlat::shoot(0.,lambda1);
655 return (p2+lambda1*v+lambda2*w);
656 }
657
658 lambda1 = RandFlat::shoot(0.,1.);
659 lambda2 = RandFlat::shoot(0.,lambda1);
660 return (p0+lambda1*t+lambda2*u);
661}
662
663
664//
665// GetPointOnTriangle
666//
667// Auxiliary method for get point on surface
668//
670 G4ThreeVector p2,
671 G4ThreeVector p3) const
672{
673 G4double lambda1,lambda2;
674 G4ThreeVector v=p3-p1, w=p1-p2;
675
676 lambda1 = RandFlat::shoot(0.,1.);
677 lambda2 = RandFlat::shoot(0.,lambda1);
678
679 return (p2 + lambda1*w + lambda2*v);
680}
681
682
683//
684// GetPointOnSurface
685//
687{
688 if( !genericPgon ) // Polyhedra by faces
689 {
690 G4int j, numPlanes = original_parameters->Num_z_planes, Flag=0;
691 G4double chose, totArea=0., Achose1, Achose2,
692 rad1, rad2, sinphi1, sinphi2, cosphi1, cosphi2;
693 G4double a, b, l2, rang, totalPhi, ksi,
694 area, aTop=0., aBottom=0., zVal=0.;
695
696 G4ThreeVector p0, p1, p2, p3;
697 std::vector<G4double> aVector1;
698 std::vector<G4double> aVector2;
699 std::vector<G4double> aVector3;
700
701 totalPhi= (phiIsOpen) ? (endPhi-startPhi) : twopi;
702 ksi = totalPhi/numSide;
703 G4double cosksi = std::cos(ksi/2.);
704
705 // Below we generate the areas relevant to our solid
706 //
707 for(j=0; j<numPlanes-1; j++)
708 {
709 a = original_parameters->Rmax[j+1];
712 -original_parameters->Z_values[j+1]) + sqr(b-a);
713 area = std::sqrt(l2-sqr((a-b)*cosksi))*(a+b)*cosksi;
714 aVector1.push_back(area);
715 }
716
717 for(j=0; j<numPlanes-1; j++)
718 {
719 a = original_parameters->Rmin[j+1];//*cosksi;
720 b = original_parameters->Rmin[j];//*cosksi;
722 -original_parameters->Z_values[j+1]) + sqr(b-a);
723 area = std::sqrt(l2-sqr((a-b)*cosksi))*(a+b)*cosksi;
724 aVector2.push_back(area);
725 }
726
727 for(j=0; j<numPlanes-1; j++)
728 {
729 if(phiIsOpen == true)
730 {
731 aVector3.push_back(0.5*(original_parameters->Rmax[j]
735 *std::fabs(original_parameters->Z_values[j+1]
737 }
738 else { aVector3.push_back(0.); }
739 }
740
741 for(j=0; j<numPlanes-1; j++)
742 {
743 totArea += numSide*(aVector1[j]+aVector2[j])+2.*aVector3[j];
744 }
745
746 // Must include top and bottom areas
747 //
748 if(original_parameters->Rmax[numPlanes-1] != 0.)
749 {
750 a = original_parameters->Rmax[numPlanes-1];
751 b = original_parameters->Rmin[numPlanes-1];
752 l2 = sqr(a-b);
753 aTop = std::sqrt(l2-sqr((a-b)*cosksi))*(a+b)*cosksi;
754 }
755
756 if(original_parameters->Rmax[0] != 0.)
757 {
760 l2 = sqr(a-b);
761 aBottom = std::sqrt(l2-sqr((a-b)*cosksi))*(a+b)*cosksi;
762 }
763
764 Achose1 = 0.;
765 Achose2 = numSide*(aVector1[0]+aVector2[0])+2.*aVector3[0];
766
767 chose = RandFlat::shoot(0.,totArea+aTop+aBottom);
768 if( (chose >= 0.) && (chose < aTop + aBottom) )
769 {
770 chose = RandFlat::shoot(startPhi,startPhi+totalPhi);
771 rang = std::floor((chose-startPhi)/ksi-0.01);
772 if(rang<0) { rang=0; }
773 rang = std::fabs(rang);
774 sinphi1 = std::sin(startPhi+rang*ksi);
775 sinphi2 = std::sin(startPhi+(rang+1)*ksi);
776 cosphi1 = std::cos(startPhi+rang*ksi);
777 cosphi2 = std::cos(startPhi+(rang+1)*ksi);
778 chose = RandFlat::shoot(0., aTop + aBottom);
779 if(chose>=0. && chose<aTop)
780 {
781 rad1 = original_parameters->Rmin[numPlanes-1];
782 rad2 = original_parameters->Rmax[numPlanes-1];
783 zVal = original_parameters->Z_values[numPlanes-1];
784 }
785 else
786 {
787 rad1 = original_parameters->Rmin[0];
788 rad2 = original_parameters->Rmax[0];
789 zVal = original_parameters->Z_values[0];
790 }
791 p0 = G4ThreeVector(rad1*cosphi1,rad1*sinphi1,zVal);
792 p1 = G4ThreeVector(rad2*cosphi1,rad2*sinphi1,zVal);
793 p2 = G4ThreeVector(rad2*cosphi2,rad2*sinphi2,zVal);
794 p3 = G4ThreeVector(rad1*cosphi2,rad1*sinphi2,zVal);
795 return GetPointOnPlane(p0,p1,p2,p3);
796 }
797 else
798 {
799 for (j=0; j<numPlanes-1; j++)
800 {
801 if( ((chose >= Achose1) && (chose < Achose2)) || (j == numPlanes-2) )
802 {
803 Flag = j; break;
804 }
805 Achose1 += numSide*(aVector1[j]+aVector2[j])+2.*aVector3[j];
806 Achose2 = Achose1 + numSide*(aVector1[j+1]+aVector2[j+1])
807 + 2.*aVector3[j+1];
808 }
809 }
810
811 // At this point we have chosen a subsection
812 // between to adjacent plane cuts...
813
814 j = Flag;
815
816 totArea = numSide*(aVector1[j]+aVector2[j])+2.*aVector3[j];
817 chose = RandFlat::shoot(0.,totArea);
818
819 if( (chose>=0.) && (chose<numSide*aVector1[j]) )
820 {
821 chose = RandFlat::shoot(startPhi,startPhi+totalPhi);
822 rang = std::floor((chose-startPhi)/ksi-0.01);
823 if(rang<0) { rang=0; }
824 rang = std::fabs(rang);
825 rad1 = original_parameters->Rmax[j];
826 rad2 = original_parameters->Rmax[j+1];
827 sinphi1 = std::sin(startPhi+rang*ksi);
828 sinphi2 = std::sin(startPhi+(rang+1)*ksi);
829 cosphi1 = std::cos(startPhi+rang*ksi);
830 cosphi2 = std::cos(startPhi+(rang+1)*ksi);
831 zVal = original_parameters->Z_values[j];
832
833 p0 = G4ThreeVector(rad1*cosphi1,rad1*sinphi1,zVal);
834 p1 = G4ThreeVector(rad1*cosphi2,rad1*sinphi2,zVal);
835
836 zVal = original_parameters->Z_values[j+1];
837
838 p2 = G4ThreeVector(rad2*cosphi2,rad2*sinphi2,zVal);
839 p3 = G4ThreeVector(rad2*cosphi1,rad2*sinphi1,zVal);
840 return GetPointOnPlane(p0,p1,p2,p3);
841 }
842 else if ( (chose >= numSide*aVector1[j])
843 && (chose <= numSide*(aVector1[j]+aVector2[j])) )
844 {
845 chose = RandFlat::shoot(startPhi,startPhi+totalPhi);
846 rang = std::floor((chose-startPhi)/ksi-0.01);
847 if(rang<0) { rang=0; }
848 rang = std::fabs(rang);
849 rad1 = original_parameters->Rmin[j];
850 rad2 = original_parameters->Rmin[j+1];
851 sinphi1 = std::sin(startPhi+rang*ksi);
852 sinphi2 = std::sin(startPhi+(rang+1)*ksi);
853 cosphi1 = std::cos(startPhi+rang*ksi);
854 cosphi2 = std::cos(startPhi+(rang+1)*ksi);
855 zVal = original_parameters->Z_values[j];
856
857 p0 = G4ThreeVector(rad1*cosphi1,rad1*sinphi1,zVal);
858 p1 = G4ThreeVector(rad1*cosphi2,rad1*sinphi2,zVal);
859
860 zVal = original_parameters->Z_values[j+1];
861
862 p2 = G4ThreeVector(rad2*cosphi2,rad2*sinphi2,zVal);
863 p3 = G4ThreeVector(rad2*cosphi1,rad2*sinphi1,zVal);
864 return GetPointOnPlane(p0,p1,p2,p3);
865 }
866
867 chose = RandFlat::shoot(0.,2.2);
868 if( (chose>=0.) && (chose < 1.) )
869 {
870 rang = startPhi;
871 }
872 else
873 {
874 rang = endPhi;
875 }
876
877 cosphi1 = std::cos(rang); rad1 = original_parameters->Rmin[j];
878 sinphi1 = std::sin(rang); rad2 = original_parameters->Rmax[j];
879
880 p0 = G4ThreeVector(rad1*cosphi1,rad1*sinphi1,
882 p1 = G4ThreeVector(rad2*cosphi1,rad2*sinphi1,
884
885 rad1 = original_parameters->Rmax[j+1];
886 rad2 = original_parameters->Rmin[j+1];
887
888 p2 = G4ThreeVector(rad1*cosphi1,rad1*sinphi1,
890 p3 = G4ThreeVector(rad2*cosphi1,rad2*sinphi1,
892 return GetPointOnPlane(p0,p1,p2,p3);
893 }
894 else // Generic polyhedra
895 {
896 return GetPointOnSurfaceGeneric();
897 }
898}
899
900//
901// CreatePolyhedron
902//
904{
905 if (!genericPgon)
906 {
914 }
915 else
916 {
917 // The following code prepares for:
918 // HepPolyhedron::createPolyhedron(int Nnodes, int Nfaces,
919 // const double xyz[][3],
920 // const int faces_vec[][4])
921 // Here is an extract from the header file HepPolyhedron.h:
922 /**
923 * Creates user defined polyhedron.
924 * This function allows to the user to define arbitrary polyhedron.
925 * The faces of the polyhedron should be either triangles or planar
926 * quadrilateral. Nodes of a face are defined by indexes pointing to
927 * the elements in the xyz array. Numeration of the elements in the
928 * array starts from 1 (like in fortran). The indexes can be positive
929 * or negative. Negative sign means that the corresponding edge is
930 * invisible. The normal of the face should be directed to exterior
931 * of the polyhedron.
932 *
933 * @param Nnodes number of nodes
934 * @param Nfaces number of faces
935 * @param xyz nodes
936 * @param faces_vec faces (quadrilaterals or triangles)
937 * @return status of the operation - is non-zero in case of problem
938 */
939 G4int nNodes;
940 G4int nFaces;
941 typedef G4double double3[3];
942 double3* xyz;
943 typedef G4int int4[4];
944 int4* faces_vec;
945 if (phiIsOpen)
946 {
947 // Triangulate open ends. Simple ear-chopping algorithm...
948 // I'm not sure how robust this algorithm is (J.Allison).
949 //
950 std::vector<G4bool> chopped(numCorner, false);
951 std::vector<G4int*> triQuads;
952 G4int remaining = numCorner;
953 G4int iStarter = 0;
954 while (remaining >= 3)
955 {
956 // Find unchopped corners...
957 //
958 G4int A = -1, B = -1, C = -1;
959 G4int iStepper = iStarter;
960 do
961 {
962 if (A < 0) { A = iStepper; }
963 else if (B < 0) { B = iStepper; }
964 else if (C < 0) { C = iStepper; }
965 do
966 {
967 if (++iStepper >= numCorner) iStepper = 0;
968 }
969 while (chopped[iStepper]);
970 }
971 while (C < 0 && iStepper != iStarter);
972
973 // Check triangle at B is pointing outward (an "ear").
974 // Sign of z cross product determines...
975
976 G4double BAr = corners[A].r - corners[B].r;
977 G4double BAz = corners[A].z - corners[B].z;
978 G4double BCr = corners[C].r - corners[B].r;
979 G4double BCz = corners[C].z - corners[B].z;
980 if (BAr * BCz - BAz * BCr < kCarTolerance)
981 {
982 G4int* tq = new G4int[3];
983 tq[0] = A + 1;
984 tq[1] = B + 1;
985 tq[2] = C + 1;
986 triQuads.push_back(tq);
987 chopped[B] = true;
988 --remaining;
989 }
990 else
991 {
992 do
993 {
994 if (++iStarter >= numCorner) { iStarter = 0; }
995 }
996 while (chopped[iStarter]);
997 }
998 }
999
1000 // Transfer to faces...
1001
1002 nNodes = (numSide + 1) * numCorner;
1003 nFaces = numSide * numCorner + 2 * triQuads.size();
1004 faces_vec = new int4[nFaces];
1005 G4int iface = 0;
1006 G4int addition = numCorner * numSide;
1007 G4int d = numCorner - 1;
1008 for (G4int iEnd = 0; iEnd < 2; ++iEnd)
1009 {
1010 for (size_t i = 0; i < triQuads.size(); ++i)
1011 {
1012 // Negative for soft/auxiliary/normally invisible edges...
1013 //
1014 G4int a, b, c;
1015 if (iEnd == 0)
1016 {
1017 a = triQuads[i][0];
1018 b = triQuads[i][1];
1019 c = triQuads[i][2];
1020 }
1021 else
1022 {
1023 a = triQuads[i][0] + addition;
1024 b = triQuads[i][2] + addition;
1025 c = triQuads[i][1] + addition;
1026 }
1027 G4int ab = std::abs(b - a);
1028 G4int bc = std::abs(c - b);
1029 G4int ca = std::abs(a - c);
1030 faces_vec[iface][0] = (ab == 1 || ab == d)? a: -a;
1031 faces_vec[iface][1] = (bc == 1 || bc == d)? b: -b;
1032 faces_vec[iface][2] = (ca == 1 || ca == d)? c: -c;
1033 faces_vec[iface][3] = 0;
1034 ++iface;
1035 }
1036 }
1037
1038 // Continue with sides...
1039
1040 xyz = new double3[nNodes];
1041 const G4double dPhi = (endPhi - startPhi) / numSide;
1042 G4double phi = startPhi;
1043 G4int ixyz = 0;
1044 for (G4int iSide = 0; iSide < numSide; ++iSide)
1045 {
1046 for (G4int iCorner = 0; iCorner < numCorner; ++iCorner)
1047 {
1048 xyz[ixyz][0] = corners[iCorner].r * std::cos(phi);
1049 xyz[ixyz][1] = corners[iCorner].r * std::sin(phi);
1050 xyz[ixyz][2] = corners[iCorner].z;
1051 if (iCorner < numCorner - 1)
1052 {
1053 faces_vec[iface][0] = ixyz + 1;
1054 faces_vec[iface][1] = ixyz + numCorner + 1;
1055 faces_vec[iface][2] = ixyz + numCorner + 2;
1056 faces_vec[iface][3] = ixyz + 2;
1057 }
1058 else
1059 {
1060 faces_vec[iface][0] = ixyz + 1;
1061 faces_vec[iface][1] = ixyz + numCorner + 1;
1062 faces_vec[iface][2] = ixyz + 2;
1063 faces_vec[iface][3] = ixyz - numCorner + 2;
1064 }
1065 ++iface;
1066 ++ixyz;
1067 }
1068 phi += dPhi;
1069 }
1070
1071 // Last corners...
1072
1073 for (G4int iCorner = 0; iCorner < numCorner; ++iCorner)
1074 {
1075 xyz[ixyz][0] = corners[iCorner].r * std::cos(phi);
1076 xyz[ixyz][1] = corners[iCorner].r * std::sin(phi);
1077 xyz[ixyz][2] = corners[iCorner].z;
1078 ++ixyz;
1079 }
1080 }
1081 else // !phiIsOpen - i.e., a complete 360 degrees.
1082 {
1083 nNodes = numSide * numCorner;
1084 nFaces = numSide * numCorner;;
1085 xyz = new double3[nNodes];
1086 faces_vec = new int4[nFaces];
1087 // const G4double dPhi = (endPhi - startPhi) / numSide;
1088 const G4double dPhi = twopi / numSide; // !phiIsOpen endPhi-startPhi = 360 degrees.
1089 G4double phi = startPhi;
1090 G4int ixyz = 0, iface = 0;
1091 for (G4int iSide = 0; iSide < numSide; ++iSide)
1092 {
1093 for (G4int iCorner = 0; iCorner < numCorner; ++iCorner)
1094 {
1095 xyz[ixyz][0] = corners[iCorner].r * std::cos(phi);
1096 xyz[ixyz][1] = corners[iCorner].r * std::sin(phi);
1097 xyz[ixyz][2] = corners[iCorner].z;
1098 if (iSide < numSide - 1)
1099 {
1100 if (iCorner < numCorner - 1)
1101 {
1102 faces_vec[iface][0] = ixyz + 1;
1103 faces_vec[iface][1] = ixyz + numCorner + 1;
1104 faces_vec[iface][2] = ixyz + numCorner + 2;
1105 faces_vec[iface][3] = ixyz + 2;
1106 }
1107 else
1108 {
1109 faces_vec[iface][0] = ixyz + 1;
1110 faces_vec[iface][1] = ixyz + numCorner + 1;
1111 faces_vec[iface][2] = ixyz + 2;
1112 faces_vec[iface][3] = ixyz - numCorner + 2;
1113 }
1114 }
1115 else // Last side joins ends...
1116 {
1117 if (iCorner < numCorner - 1)
1118 {
1119 faces_vec[iface][0] = ixyz + 1;
1120 faces_vec[iface][1] = ixyz + numCorner - nFaces + 1;
1121 faces_vec[iface][2] = ixyz + numCorner - nFaces + 2;
1122 faces_vec[iface][3] = ixyz + 2;
1123 }
1124 else
1125 {
1126 faces_vec[iface][0] = ixyz + 1;
1127 faces_vec[iface][1] = ixyz - nFaces + numCorner + 1;
1128 faces_vec[iface][2] = ixyz - nFaces + 2;
1129 faces_vec[iface][3] = ixyz - numCorner + 2;
1130 }
1131 }
1132 ++ixyz;
1133 ++iface;
1134 }
1135 phi += dPhi;
1136 }
1137 }
1138 G4Polyhedron* polyhedron = new G4Polyhedron;
1139 G4int problem = polyhedron->createPolyhedron(nNodes, nFaces, xyz, faces_vec);
1140 delete [] faces_vec;
1141 delete [] xyz;
1142 if (problem)
1143 {
1144 std::ostringstream message;
1145 message << "Problem creating G4Polyhedron for: " << GetName();
1146 G4Exception("G4Polyhedra::CreatePolyhedron()", "GeomSolids1002",
1147 JustWarning, message);
1148 delete polyhedron;
1149 return 0;
1150 }
1151 else
1152 {
1153 return polyhedron;
1154 }
1155 }
1156}
1157
1158//
1159// CreateNURBS
1160//
1162{
1163 return 0;
1164}
1165
1166
1167//
1168// G4PolyhedraHistorical stuff
1169//
1171 : Start_angle(0.), Opening_angle(0.), numSide(0), Num_z_planes(0),
1172 Z_values(0), Rmin(0), Rmax(0)
1173{
1174}
1175
1177{
1178 delete [] Z_values;
1179 delete [] Rmin;
1180 delete [] Rmax;
1181}
1182
1185{
1186 Start_angle = source.Start_angle;
1188 numSide = source.numSide;
1189 Num_z_planes = source.Num_z_planes;
1190
1192 Rmin = new G4double[Num_z_planes];
1193 Rmax = new G4double[Num_z_planes];
1194
1195 for( G4int i = 0; i < Num_z_planes; i++)
1196 {
1197 Z_values[i] = source.Z_values[i];
1198 Rmin[i] = source.Rmin[i];
1199 Rmax[i] = source.Rmax[i];
1200 }
1201}
1202
1205{
1206 if ( &right == this ) return *this;
1207
1208 if (&right)
1209 {
1210 Start_angle = right.Start_angle;
1212 numSide = right.numSide;
1213 Num_z_planes = right.Num_z_planes;
1214
1215 delete [] Z_values;
1216 delete [] Rmin;
1217 delete [] Rmax;
1219 Rmin = new G4double[Num_z_planes];
1220 Rmax = new G4double[Num_z_planes];
1221
1222 for( G4int i = 0; i < Num_z_planes; i++)
1223 {
1224 Z_values[i] = right.Z_values[i];
1225 Rmin[i] = right.Rmin[i];
1226 Rmax[i] = right.Rmax[i];
1227 }
1228 }
1229 return *this;
1230}
@ JustWarning
@ FatalErrorInArgument
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
static double shoot()
Definition: RandFlat.cc:59
G4bool ShouldMiss(const G4ThreeVector &p, const G4ThreeVector &v) const
G4bool MustBeOutside(const G4ThreeVector &p) const
G4PolyhedraHistorical & operator=(const G4PolyhedraHistorical &right)
G4ThreeVector GetPointOnSurface() const
Definition: G4Polyhedra.cc:686
std::ostream & StreamInfo(std::ostream &os) const
Definition: G4Polyhedra.cc:584
G4PolyhedraHistorical * original_parameters
Definition: G4Polyhedra.hh:195
const G4Polyhedra & operator=(const G4Polyhedra &source)
Definition: G4Polyhedra.cc:399
G4PolyhedraSideRZ * corners
Definition: G4Polyhedra.hh:194
G4Polyhedra(const G4String &name, G4double phiStart, G4double phiTotal, G4int numSide, G4int numZPlanes, const G4double zPlane[], const G4double rInner[], const G4double rOuter[])
Definition: G4Polyhedra.cc:78
G4bool genericPgon
Definition: G4Polyhedra.hh:192
void CopyStuff(const G4Polyhedra &source)
Definition: G4Polyhedra.cc:419
G4VSolid * Clone() const
Definition: G4Polyhedra.cc:575
void Create(G4double phiStart, G4double phiTotal, G4int numSide, G4ReduciblePolygon *rz)
Definition: G4Polyhedra.cc:191
G4GeometryType GetEntityType() const
Definition: G4Polyhedra.cc:566
G4double endPhi
Definition: G4Polyhedra.hh:190
G4ThreeVector GetPointOnPlane(G4ThreeVector p0, G4ThreeVector p1, G4ThreeVector p2, G4ThreeVector p3) const
Definition: G4Polyhedra.cc:637
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
Definition: G4Polyhedra.cc:555
G4bool phiIsOpen
Definition: G4Polyhedra.hh:191
G4double startPhi
Definition: G4Polyhedra.hh:189
G4int numCorner
Definition: G4Polyhedra.hh:193
virtual ~G4Polyhedra()
Definition: G4Polyhedra.cc:377
G4NURBS * CreateNURBS() const
G4bool Reset()
Definition: G4Polyhedra.cc:465
void SetOriginalParameters()
G4EnclosingCylinder * enclosingCylinder
Definition: G4Polyhedra.hh:197
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
Definition: G4Polyhedra.cc:527
EInside Inside(const G4ThreeVector &p) const
Definition: G4Polyhedra.cc:507
G4Polyhedron * CreatePolyhedron() const
Definition: G4Polyhedra.cc:903
G4ThreeVector GetPointOnTriangle(G4ThreeVector p0, G4ThreeVector p1, G4ThreeVector p2) const
Definition: G4Polyhedra.cc:669
G4double Amin() const
G4bool RemoveDuplicateVertices(G4double tolerance)
G4int NumVertices() const
G4bool RemoveRedundantVertices(G4double tolerance)
G4bool CrossesItself(G4double tolerance)
void ScaleA(G4double scale)
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
virtual EInside Inside(const G4ThreeVector &p) const
G4VCSGface ** faces
const G4VCSGfaceted & operator=(const G4VCSGfaceted &source)
G4ThreeVector GetPointOnSurfaceGeneric() const
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4String GetName() const
void DumpInfo() const
G4double kCarTolerance
Definition: G4VSolid.hh:307
G4int createPolyhedron(G4int Nnodes, G4int Nfaces, const G4double xyz[][3], const G4int faces[][4])
EInside
Definition: geomdefs.hh:58
@ kOutside
Definition: geomdefs.hh:58
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
Definition: DoubConv.h:17
T sqr(const T &x)
Definition: templates.hh:145
#define DBL_EPSILON
Definition: templates.hh:87