75 fLowerEndcap(nullptr), fUpperEndcap(nullptr), fSide0(nullptr),
76 fSide90(nullptr), fSide180(nullptr), fSide270(nullptr)
96 fDxDown = ( fDx1 > fDx2 ? fDx1 : fDx2 ) ;
97 fDxUp = ( fDx3 > fDx4 ? fDx3 : fDx4 ) ;
98 fDx = ( fDxUp > fDxDown ? fDxUp : fDxDown ) ;
99 fDy = ( fDy1 > fDy2 ? fDy1 : fDy2 ) ;
103 if ( fDx1 != fDx2 && fDx3 != fDx4 )
105 pDytmp = fDy1 * ( fDx3 - fDx4 ) / ( fDx1 - fDx2 ) ;
108 std::ostringstream message;
109 message <<
"Not planar surface in untwisted Trapezoid: "
111 <<
"fDy2 is " << fDy2 <<
" but should be "
113 G4Exception(
"G4VTwistedFaceted::G4VTwistedFaceted()",
"GeomSolids0002",
119 if ( fDx1 == fDx2 && fDx3 == fDx4 )
126 if ( ( fDx1 == fDx2 && fDx3 != fDx4 ) || ( fDx1 != fDx2 && fDx3 == fDx4 ) )
128 std::ostringstream message;
129 message <<
"Not planar surface in untwisted Trapezoid: "
131 <<
"One endcap is rectangular, the other is a trapezoid." <<
G4endl
132 <<
"For planarity reasons they have to be rectangles or trapezoids "
134 G4Exception(
"G4VTwistedFaceted::G4VTwistedFaceted()",
"GeomSolids0002",
140 fPhiTwist = PhiTwist ;
145 fTAlph = std::tan(fAlph) ;
152 fdeltaX = 2 * fDz * std::tan(fTheta) * std::cos(fPhi) ;
156 fdeltaY = 2 * fDz * std::tan(fTheta) * std::sin(fPhi) ;
165 || ( std::fabs(fPhiTwist) <= 2*kAngTolerance )
166 || ( std::fabs(fPhiTwist) >= pi/2 )
167 || ( std::fabs(fAlph) >= pi/2 )
168 || fTheta >= pi/2 || fTheta < 0
171 std::ostringstream message;
172 message <<
"Invalid dimensions. Too small, or twist angle too big: "
174 <<
"fDx 1-4 = " << fDx1/cm <<
", " << fDx2/cm <<
", "
175 << fDx3/cm <<
", " << fDx4/cm <<
" cm" <<
G4endl
176 <<
"fDy 1-2 = " << fDy1/cm <<
", " << fDy2/cm <<
", "
178 <<
"fDz = " << fDz/cm <<
" cm" <<
G4endl
179 <<
" twistangle " << fPhiTwist/deg <<
" deg" <<
G4endl
180 <<
" phi,theta = " << fPhi/deg <<
", " << fTheta/deg <<
" deg";
193 fLowerEndcap(nullptr), fUpperEndcap(nullptr),
194 fSide0(nullptr), fSide90(nullptr), fSide180(nullptr), fSide270(nullptr)
204 delete fLowerEndcap ;
205 delete fUpperEndcap ;
221 fTheta(rhs.fTheta), fPhi(rhs.fPhi),
222 fDy1(rhs.fDy1), fDx1(rhs.fDx1), fDx2(rhs.fDx2), fDy2(rhs.fDy2),
223 fDx3(rhs.fDx3), fDx4(rhs.fDx4), fDz(rhs.fDz), fDx(rhs.fDx), fDy(rhs.fDy),
224 fAlph(rhs.fAlph), fTAlph(rhs.fTAlph), fdeltaX(rhs.fdeltaX),
225 fdeltaY(rhs.fdeltaY), fPhiTwist(rhs.fPhiTwist), fLowerEndcap(nullptr),
226 fUpperEndcap(nullptr), fSide0(nullptr), fSide90(nullptr), fSide180(nullptr), fSide270(nullptr)
239 if (
this == &rhs) {
return *
this; }
247 fTheta = rhs.fTheta; fPhi = rhs.fPhi;
248 fDy1= rhs.fDy1; fDx1= rhs.fDx1; fDx2= rhs.fDx2; fDy2= rhs.fDy2;
249 fDx3= rhs.fDx3; fDx4= rhs.fDx4; fDz= rhs.fDz; fDx= rhs.fDx; fDy= rhs.fDy;
250 fAlph= rhs.fAlph; fTAlph= rhs.fTAlph; fdeltaX= rhs.fdeltaX;
251 fdeltaY= rhs.fdeltaY; fPhiTwist= rhs.fPhiTwist; fLowerEndcap=
nullptr;
252 fUpperEndcap=
nullptr; fSide0=
nullptr; fSide90=
nullptr; fSide180=
nullptr; fSide270=
nullptr;
270 G4Exception(
"G4VTwistedFaceted::ComputeDimensions()",
272 "G4VTwistedFaceted does not support Parameterisation.");
284 G4double tanTheta = std::tan(fTheta);
288 G4double x1 = std::abs(xmid1 + fDx1);
289 G4double x2 = std::abs(xmid1 - fDx1);
290 G4double x3 = std::abs(xmid1 + fDx2);
291 G4double x4 = std::abs(xmid1 - fDx2);
292 G4double xmax1 = std::max(std::max(std::max(x1, x2), x3), x4);
293 G4double rmax1 = std::sqrt(xmax1*xmax1 + fDy1*fDy1);
296 G4double x5 = std::abs(xmid2 + fDx3);
297 G4double x6 = std::abs(xmid2 - fDx3);
298 G4double x7 = std::abs(xmid2 + fDx4);
299 G4double x8 = std::abs(xmid2 - fDx4);
300 G4double xmax2 = std::max(std::max(std::max(x5, x6), x7), x8);
301 G4double rmax2 = std::sqrt(xmax2*xmax2 + fDy2*fDy2);
305 G4double xmin = std::min(-x0 - rmax1, x0 - rmax2);
306 G4double ymin = std::min(-y0 - rmax1, y0 - rmax2);
307 G4double xmax = std::max(-x0 + rmax1, x0 + rmax2);
308 G4double ymax = std::max(-y0 + rmax1, y0 + rmax2);
309 pMin.
set(xmin, ymin,-fDz);
310 pMax.
set(xmax, ymax, fDz);
343 G4double phi = p.
z()/(2*fDz) * fPhiTwist ;
347 G4double px = p.
x() + fdeltaX * ( -phi/fPhiTwist) ;
348 G4double py = p.
y() + fdeltaY * ( -phi/fPhiTwist) ;
351 G4double posx = px * cphi - py * sphi ;
352 G4double posy = px * sphi + py * cphi ;
375 G4cout <<
"phi,theta = " << fPhi <<
" , " << fTheta <<
G4endl ;
446 surfaces[0] = fSide0 ;
447 surfaces[1] = fSide90 ;
448 surfaces[2] = fSide180 ;
449 surfaces[3] = fSide270 ;
450 surfaces[4] = fLowerEndcap;
451 surfaces[5] = fUpperEndcap;
460 if (tmpdistance < distance)
462 distance = tmpdistance;
468 return surfaces[besti]->
GetNormal(bestxx,
true);
516 surfaces[0] = fSide0;
517 surfaces[1] = fSide90 ;
518 surfaces[2] = fSide180 ;
519 surfaces[3] = fSide270 ;
520 surfaces[4] = fLowerEndcap;
521 surfaces[5] = fUpperEndcap;
525 for (
const auto & surface : surfaces)
530 G4double tmpdistance = surface->DistanceToIn(p, v, xx);
532 G4cout <<
"Solid DistanceToIn : distance = " << tmpdistance <<
G4endl ;
535 if (tmpdistance < distance)
537 distance = tmpdistance;
588 surfaces[0] = fSide0;
589 surfaces[1] = fSide90 ;
590 surfaces[2] = fSide180 ;
591 surfaces[3] = fSide270 ;
592 surfaces[4] = fLowerEndcap;
593 surfaces[5] = fUpperEndcap;
597 for (
const auto & surface : surfaces)
599 G4double tmpdistance = surface->DistanceTo(p, xx);
600 if (tmpdistance < distance)
602 distance = tmpdistance;
611 G4Exception(
"G4VTwistedFaceted::DistanceToIn(p)",
"GeomSolids0003",
671 surfaces[0] = fSide0;
672 surfaces[1] = fSide90 ;
673 surfaces[2] = fSide180 ;
674 surfaces[3] = fSide270 ;
675 surfaces[4] = fLowerEndcap;
676 surfaces[5] = fUpperEndcap;
681 for (
auto i=0; i<6 ; ++i)
684 if (tmpdistance < distance)
686 distance = tmpdistance;
696 *norm = (surfaces[besti]->
GetNormal(p,
true));
733 G4cout.precision(oldprc) ;
734 G4Exception(
"G4VTwistedFaceted::DistanceToOut(p)",
"GeomSolids1002",
755 surfaces[0] = fSide0;
756 surfaces[1] = fSide90 ;
757 surfaces[2] = fSide180 ;
758 surfaces[3] = fSide270 ;
759 surfaces[4] = fLowerEndcap;
760 surfaces[5] = fUpperEndcap;
764 for (
const auto & surface : surfaces)
766 G4double tmpdistance = surface->DistanceTo(p, xx);
767 if (tmpdistance < distance)
769 distance = tmpdistance;
779 G4Exception(
"G4VTwistedFaceted::DistanceToOut(p)",
"GeomSolids0003",
797 G4long oldprc = os.precision(16);
798 os <<
"-----------------------------------------------------------\n"
799 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
800 <<
" ===================================================\n"
801 <<
" Solid type: G4VTwistedFaceted\n"
803 <<
" polar angle theta = " << fTheta/degree <<
" deg" <<
G4endl
804 <<
" azimuthal angle phi = " << fPhi/degree <<
" deg" <<
G4endl
805 <<
" tilt angle alpha = " << fAlph/degree <<
" deg" <<
G4endl
806 <<
" TWIST angle = " << fPhiTwist/degree <<
" deg" <<
G4endl
807 <<
" Half length along y (lower endcap) = " << fDy1/cm <<
" cm"
809 <<
" Half length along x (lower endcap, bottom) = " << fDx1/cm <<
" cm"
811 <<
" Half length along x (lower endcap, top) = " << fDx2/cm <<
" cm"
813 <<
" Half length along y (upper endcap) = " << fDy2/cm <<
" cm"
815 <<
" Half length along x (upper endcap, bottom) = " << fDx3/cm <<
" cm"
817 <<
" Half length along x (upper endcap, top) = " << fDx4/cm <<
" cm"
819 <<
"-----------------------------------------------------------\n";
820 os.precision(oldprc);
840 G4double maxRad = std::sqrt( fDx*fDx + fDy*fDy);
842 return { -maxRad, maxRad ,
851void G4VTwistedFaceted::CreateSurfaces()
856 if ( fDx1 == fDx2 && fDx3 == fDx4 )
859 fDy1, fDx1, fDx1, fDy2, fDx3, fDx3, fAlph, 0.*deg);
860 fSide180 =
new G4TwistBoxSide(
"180deg", fPhiTwist, fDz, fTheta, fPhi+pi,
861 fDy1, fDx1, fDx1, fDy2, fDx3, fDx3, fAlph, 180.*deg);
865 fSide0 =
new G4TwistTrapAlphaSide(
"0deg" ,fPhiTwist, fDz, fTheta,
866 fPhi, fDy1, fDx1, fDx2, fDy2, fDx3, fDx4, fAlph, 0.*deg);
867 fSide180 =
new G4TwistTrapAlphaSide(
"180deg", fPhiTwist, fDz, fTheta,
868 fPhi+pi, fDy1, fDx2, fDx1, fDy2, fDx4, fDx3, fAlph, 180.*deg);
873 fSide90 =
new G4TwistTrapParallelSide(
"90deg", fPhiTwist, fDz, fTheta,
874 fPhi, fDy1, fDx1, fDx2, fDy2, fDx3, fDx4, fAlph, 0.*deg);
875 fSide270 =
new G4TwistTrapParallelSide(
"270deg", fPhiTwist, fDz, fTheta,
876 fPhi+pi, fDy1, fDx2, fDx1, fDy2, fDx4, fDx3, fAlph, 180.*deg);
880 fUpperEndcap =
new G4TwistTrapFlatSide(
"UpperCap",fPhiTwist, fDx3, fDx4, fDy2,
881 fDz, fAlph, fPhi, fTheta, 1 );
882 fLowerEndcap =
new G4TwistTrapFlatSide(
"LowerCap",fPhiTwist, fDx1, fDx2, fDy1,
883 fDz, fAlph, fPhi, fTheta, -1 );
887 fSide0->SetNeighbours( fSide270 , fLowerEndcap , fSide90 , fUpperEndcap );
888 fSide90->SetNeighbours( fSide0 , fLowerEndcap , fSide180 , fUpperEndcap );
889 fSide180->SetNeighbours(fSide90 , fLowerEndcap , fSide270 , fUpperEndcap );
890 fSide270->SetNeighbours(fSide180 , fLowerEndcap , fSide0 , fUpperEndcap );
891 fUpperEndcap->SetNeighbours( fSide180, fSide270 , fSide0 , fSide90 );
892 fLowerEndcap->SetNeighbours( fSide180, fSide270 , fSide0 , fSide90 );
900G4VTwistedFaceted::GetLateralFaceArea(
const G4TwoVector& p1,
905 constexpr G4int NSTEP = 100;
910 G4double hTanTheta = h*std::tan(fTheta);
923 G4double lmax = std::max(std::max(std::abs(x21),std::abs(y21)),
924 std::max(std::abs(x43),std::abs(y43)));
927 std::abs(x21*y43 - y21*x43) < eps)
929 G4double x0 = hTanTheta*std::cos(fPhi);
930 G4double y0 = hTanTheta*std::sin(fPhi);
933 return (
A.cross(
B)).mag()*0.5;
938 for (
G4int i = 0; i < NSTEP; ++i)
947 G4double ang = fPhi + fPhiTwist*(0.5 - t);
948 G4double A = fPhiTwist*(II + JJ) + x21*y43 - x43*y21;
949 G4double B = fPhiTwist*(I*(x1 + x31*t) + J*(y1 + y31*t)) +
950 hTanTheta*(I*std::sin(ang) - J*std::cos(ang)) +
961 G4double R1 = std::sqrt(aa + bb + cc);
963 G4double log1 = std::log(std::abs(sqrtAA*R1 + 2.*aa + bb));
964 G4double log0 = std::log(std::abs(sqrtAA*R0 + bb));
966 area += 0.5*R1 + 0.25*bb*invAA*(R1 - R0) + IIJJ*invSqrtAA*(log1 - log0);
979 fCubicVolume = ((fDx1 + fDx2 + fDx3 + fDx4)*(fDy1 + fDy2) +
980 (fDx4 + fDx3 - fDx2 - fDx1)*(fDy2 - fDy1)/3)*fDz;
1003 fSurfaceArea = 2.*(fDy1*(fDx1 + fDx2) + fDy2*(fDx3 + fDx4)) +
1004 GetLateralFaceArea(vv[0], vv[1], vv[4], vv[5]) +
1005 GetLateralFaceArea(vv[1], vv[3], vv[5], vv[7]) +
1006 GetLateralFaceArea(vv[3], vv[2], vv[7], vv[6]) +
1007 GetLateralFaceArea(vv[2], vv[0], vv[6], vv[4]);
1018 return {
"G4VTwistedFaceted"};
1029 fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
1058 G4double a1 = fSide0->GetSurfaceArea();
1059 G4double a2 = fSide90->GetSurfaceArea();
1060 G4double a3 = fSide180->GetSurfaceArea() ;
1061 G4double a4 = fSide270->GetSurfaceArea() ;
1062 G4double a5 = fLowerEndcap->GetSurfaceArea() ;
1063 G4double a6 = fUpperEndcap->GetSurfaceArea() ;
1078 umin = fSide0->GetBoundaryMin(phi) ;
1079 umax = fSide0->GetBoundaryMax(phi) ;
1081 return fSide0->SurfacePoint(phi, u,
true) ;
1083 if( (chose >= a1) && (chose < a1 + a2 ) )
1085 umin = fSide90->GetBoundaryMin(phi) ;
1086 umax = fSide90->GetBoundaryMax(phi) ;
1088 return fSide90->SurfacePoint(phi, u,
true);
1090 if( (chose >= a1 + a2 ) && (chose < a1 + a2 + a3 ) )
1092 umin = fSide180->GetBoundaryMin(phi) ;
1093 umax = fSide180->GetBoundaryMax(phi) ;
1095 return fSide180->SurfacePoint(phi, u,
true);
1097 if( (chose >= a1 + a2 + a3 ) && (chose < a1 + a2 + a3 + a4 ) )
1099 umin = fSide270->GetBoundaryMin(phi) ;
1100 umax = fSide270->GetBoundaryMax(phi) ;
1102 return fSide270->SurfacePoint(phi, u,
true);
1104 if( (chose >= a1 + a2 + a3 + a4 ) && (chose < a1 + a2 + a3 + a4 + a5 ) )
1107 umin = fLowerEndcap->GetBoundaryMin(y) ;
1108 umax = fLowerEndcap->GetBoundaryMax(y) ;
1110 return fLowerEndcap->SurfacePoint(u,y,
true);
1113 umin = fUpperEndcap->GetBoundaryMin(y) ;
1114 umax = fUpperEndcap->GetBoundaryMax(y) ;
1116 return fUpperEndcap->SurfacePoint(u,y,
true);
1128 std::abs(fPhiTwist) / twopi) + 2;
1131 const G4int nnodes = 4*(k-1)*(n-2) + 2*k*k ;
1132 const G4int nfaces = 4*(k-1)*(n-1) + 2*(k-1)*(k-1) ;
1136 typedef G4int G4int4[4];
1137 auto xyz =
new G4double3[nnodes];
1138 auto faces =
new G4int4[nfaces] ;
1140 fLowerEndcap->GetFacets(k,k,xyz,faces,0) ;
1141 fUpperEndcap->GetFacets(k,k,xyz,faces,1) ;
1142 fSide270->GetFacets(k,n,xyz,faces,2) ;
1143 fSide0->GetFacets(k,n,xyz,faces,3) ;
1144 fSide90->GetFacets(k,n,xyz,faces,4) ;
1145 fSide180->GetFacets(k,n,xyz,faces,5) ;
1147 ph->createPolyhedron(nnodes,nfaces,xyz,faces);
G4TemplateAutoLock< G4Mutex > G4AutoLock
G4double B(G4double temperature)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4double G4QuickRand(uint32_t seed=0)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
G4GLOB_DLL std::ostream G4cout
void set(double x, double y, double z)
G4BoundingEnvelope is a helper class to facilitate calculation of the extent of a solid within the li...
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
static G4GeometryTolerance * GetInstance()
G4double GetAngularTolerance() const
G4TwistBoxSide describes a twisted boundary surface for a trapezoid.
virtual void AddSolid(const G4Box &)=0
G4VPVParameterisation ia an abstract base class for Parameterisation, able to compute the transformat...
G4VPhysicalVolume is an abstract base class for the representation of a positioned volume....
G4VSolid(const G4String &name)
G4VSolid & operator=(const G4VSolid &rhs)
G4VTwistSurface is a base class for boundary surface of a G4VSolid.
virtual G4ThreeVector GetNormal(const G4ThreeVector &p, G4bool isGlobal)=0
G4bool IsValidNorm() const
virtual G4double DistanceTo(const G4ThreeVector &gp, G4ThreeVector &gxx)
virtual G4double DistanceToOut(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector &gxxbest)
G4Polyhedron * GetPolyhedron() const override
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
G4ThreeVector GetPointOnSurface() const override
G4VTwistedFaceted & operator=(const G4VTwistedFaceted &rhs)
G4Polyhedron * fpPolyhedron
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4double GetCubicVolume() override
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4bool fRebuildPolyhedron
EInside Inside(const G4ThreeVector &p) const override
void ComputeDimensions(G4VPVParameterisation *, const G4int, const G4VPhysicalVolume *) override
G4Polyhedron * CreatePolyhedron() const override
std::ostream & StreamInfo(std::ostream &os) const override
G4GeometryType GetEntityType() const override
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcnorm=false, G4bool *validnorm=nullptr, G4ThreeVector *n=nullptr) const override
~G4VTwistedFaceted() override
G4VTwistedFaceted(const G4String &pname, G4double PhiTwist, G4double pDz, G4double pTheta, G4double pPhi, G4double pDy1, G4double pDx1, G4double pDx2, G4double pDy2, G4double pDx3, G4double pDx4, G4double pAlph)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const override
G4VisExtent GetExtent() const override
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
G4double GetValueB(G4double phi) const
G4double Xcoef(G4double u, G4double phi, G4double ftg) const
G4double GetSurfaceArea() override
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
static G4int GetNumberOfRotationSteps()