74 fLowerEndcap(0), fUpperEndcap(0), fSide0(0),
75 fSide90(0), fSide180(0), fSide270(0)
95 fDxDown = ( fDx1 > fDx2 ? fDx1 : fDx2 ) ;
96 fDxUp = ( fDx3 > fDx4 ? fDx3 : fDx4 ) ;
97 fDx = ( fDxUp > fDxDown ? fDxUp : fDxDown ) ;
98 fDy = ( fDy1 > fDy2 ? fDy1 : fDy2 ) ;
102 if ( fDx1 != fDx2 && fDx3 != fDx4 )
104 pDytmp = fDy1 * ( fDx3 - fDx4 ) / ( fDx1 - fDx2 ) ;
107 std::ostringstream message;
108 message <<
"Not planar surface in untwisted Trapezoid: "
110 <<
"fDy2 is " << fDy2 <<
" but should be "
112 G4Exception(
"G4VTwistedFaceted::G4VTwistedFaceted()",
"GeomSolids0002",
118 if ( fDx1 == fDx2 && fDx3 == fDx4 )
125 if ( ( fDx1 == fDx2 && fDx3 != fDx4 ) || ( fDx1 != fDx2 && fDx3 == fDx4 ) )
127 std::ostringstream message;
128 message <<
"Not planar surface in untwisted Trapezoid: "
130 <<
"One endcap is rectangular, the other is a trapezoid." <<
G4endl
131 <<
"For planarity reasons they have to be rectangles or trapezoids "
133 G4Exception(
"G4VTwistedFaceted::G4VTwistedFaceted()",
"GeomSolids0002",
139 fPhiTwist = PhiTwist ;
144 fTAlph = std::tan(fAlph) ;
151 fdeltaX = 2 * fDz * std::tan(fTheta) * std::cos(fPhi) ;
155 fdeltaY = 2 * fDz * std::tan(fTheta) * std::sin(fPhi) ;
164 && ( std::fabs(fPhiTwist) > 2*kAngTolerance )
165 && ( std::fabs(fPhiTwist) < pi/2 )
166 && ( std::fabs(fAlph) < pi/2 )
167 && ( fTheta < pi/2 && fTheta >= 0 ) )
170 std::ostringstream message;
171 message <<
"Invalid dimensions. Too small, or twist angle too big: "
173 <<
"fDx 1-4 = " << fDx1/cm <<
", " << fDx2/cm <<
", "
174 << fDx3/cm <<
", " << fDx4/cm <<
" cm" <<
G4endl
175 <<
"fDy 1-2 = " << fDy1/cm <<
", " << fDy2/cm <<
", "
177 <<
"fDz = " << fDz/cm <<
" cm" <<
G4endl
178 <<
" twistangle " << fPhiTwist/deg <<
" deg" <<
G4endl
179 <<
" phi,theta = " << fPhi/deg <<
", " << fTheta/deg <<
" deg";
192 fTheta(0.), fPhi(0.), fDy1(0.),
193 fDx1(0.), fDx2(0.), fDy2(0.), fDx3(0.), fDx4(0.),
194 fDz(0.), fDx(0.), fDy(0.), fAlph(0.),
195 fTAlph(0.), fdeltaX(0.), fdeltaY(0.), fPhiTwist(0.),
196 fLowerEndcap(0), fUpperEndcap(0), fSide0(0), fSide90(0), fSide180(0),
207 if (fLowerEndcap) {
delete fLowerEndcap ; }
208 if (fUpperEndcap) {
delete fUpperEndcap ; }
210 if (fSide0) {
delete fSide0 ; }
211 if (fSide90) {
delete fSide90 ; }
212 if (fSide180) {
delete fSide180 ; }
213 if (fSide270) {
delete fSide270 ; }
223 fTheta(rhs.fTheta), fPhi(rhs.fPhi),
224 fDy1(rhs.fDy1), fDx1(rhs.fDx1), fDx2(rhs.fDx2), fDy2(rhs.fDy2),
225 fDx3(rhs.fDx3), fDx4(rhs.fDx4), fDz(rhs.fDz), fDx(rhs.fDx), fDy(rhs.fDy),
226 fAlph(rhs.fAlph), fTAlph(rhs.fTAlph), fdeltaX(rhs.fdeltaX),
227 fdeltaY(rhs.fdeltaY), fPhiTwist(rhs.fPhiTwist), fLowerEndcap(0),
228 fUpperEndcap(0), fSide0(0), fSide90(0), fSide180(0), fSide270(0),
229 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
230 fLastInside(rhs.fLastInside), fLastNormal(rhs.fLastNormal),
231 fLastDistanceToIn(rhs.fLastDistanceToIn),
232 fLastDistanceToOut(rhs.fLastDistanceToOut),
233 fLastDistanceToInWithV(rhs.fLastDistanceToInWithV),
234 fLastDistanceToOutWithV(rhs.fLastDistanceToOutWithV)
247 if (
this == &rhs) {
return *
this; }
255 fTheta = rhs.fTheta; fPhi = rhs.fPhi;
256 fDy1= rhs.fDy1; fDx1= rhs.fDx1; fDx2= rhs.fDx2; fDy2= rhs.fDy2;
257 fDx3= rhs.fDx3; fDx4= rhs.fDx4; fDz= rhs.fDz; fDx= rhs.fDx; fDy= rhs.fDy;
258 fAlph= rhs.fAlph; fTAlph= rhs.fTAlph; fdeltaX= rhs.fdeltaX;
259 fdeltaY= rhs.fdeltaY; fPhiTwist= rhs.fPhiTwist; fLowerEndcap= 0;
260 fUpperEndcap= 0; fSide0= 0; fSide90= 0; fSide180= 0; fSide270= 0;
264 fLastInside= rhs.fLastInside; fLastNormal= rhs.fLastNormal;
265 fLastDistanceToIn= rhs.fLastDistanceToIn;
266 fLastDistanceToOut= rhs.fLastDistanceToOut;
267 fLastDistanceToInWithV= rhs.fLastDistanceToInWithV;
268 fLastDistanceToOutWithV= rhs.fLastDistanceToOutWithV;
283 G4Exception(
"G4VTwistedFaceted::ComputeDimensions()",
285 "G4VTwistedFaceted does not support Parameterisation.");
295 G4double maxRad = std::sqrt(fDx*fDx + fDy*fDy);
296 pMin.
set(-maxRad,-maxRad,-fDz);
297 pMax.
set( maxRad, maxRad, fDz);
330 if (fLastInside.p == p)
332 return fLastInside.inside;
337 tmpin =
const_cast<EInside*
>(&(fLastInside.inside));
338 tmpp->
set(p.
x(), p.
y(), p.
z());
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 ;
418 return fLastInside.inside;
435 if (fLastNormal.p == p)
437 return fLastNormal.vec;
444 tmpp->
set(p.
x(), p.
y(), p.
z());
450 surfaces[0] = fSide0 ;
451 surfaces[1] = fSide90 ;
452 surfaces[2] = fSide180 ;
453 surfaces[3] = fSide270 ;
454 surfaces[4] = fLowerEndcap;
455 surfaces[5] = fUpperEndcap;
464 if (tmpdistance < distance)
466 distance = tmpdistance;
472 tmpsurface[0] = surfaces[besti];
473 *tmpnormal = tmpsurface[0]->
GetNormal(bestxx,
true);
475 return fLastNormal.vec;
499 if (fLastDistanceToInWithV.p == p && fLastDistanceToInWithV.vec == v)
501 return fLastDistanceToIn.value;
505 tmpp =
const_cast<G4ThreeVector*
>(&(fLastDistanceToInWithV.p));
506 tmpv =
const_cast<G4ThreeVector*
>(&(fLastDistanceToInWithV.vec));
507 tmpdist =
const_cast<G4double*
>(&(fLastDistanceToInWithV.value));
508 tmpp->
set(p.
x(), p.
y(), p.
z());
509 tmpv->
set(v.
x(), v.
y(), v.
z());
530 return fLastDistanceToInWithV.value;
544 surfaces[0] = fSide0;
545 surfaces[1] = fSide90 ;
546 surfaces[2] = fSide180 ;
547 surfaces[3] = fSide270 ;
548 surfaces[4] = fLowerEndcap;
549 surfaces[5] = fUpperEndcap;
553 for (
auto i=0; i < 6 ; ++i)
560 G4cout <<
"Solid DistanceToIn : distance = " << tmpdistance <<
G4endl ;
563 if (tmpdistance < distance)
565 distance = tmpdistance;
576 return fLastDistanceToInWithV.value;
596 if (fLastDistanceToIn.p == p)
598 return fLastDistanceToIn.value;
603 tmpdist =
const_cast<G4double*
>(&(fLastDistanceToIn.value));
604 tmpp->
set(p.
x(), p.
y(), p.
z());
622 return fLastDistanceToIn.value;
635 surfaces[0] = fSide0;
636 surfaces[1] = fSide90 ;
637 surfaces[2] = fSide180 ;
638 surfaces[3] = fSide270 ;
639 surfaces[4] = fLowerEndcap;
640 surfaces[5] = fUpperEndcap;
644 for (
auto i=0; i< 6; ++i)
647 if (tmpdistance < distance)
649 distance = tmpdistance;
654 return fLastDistanceToIn.value;
659 G4Exception(
"G4VTwistedFaceted::DistanceToIn(p)",
"GeomSolids0003",
691 if (fLastDistanceToOutWithV.p == p && fLastDistanceToOutWithV.vec == v )
693 return fLastDistanceToOutWithV.value;
697 tmpp =
const_cast<G4ThreeVector*
>(&(fLastDistanceToOutWithV.p));
698 tmpv =
const_cast<G4ThreeVector*
>(&(fLastDistanceToOutWithV.vec));
699 tmpdist =
const_cast<G4double*
>(&(fLastDistanceToOutWithV.value));
700 tmpp->
set(p.
x(), p.
y(), p.
z());
701 tmpv->
set(v.
x(), v.
y(), v.
z());
724 *norm = (blockedsurface->
GetNormal(p,
true));
729 return fLastDistanceToOutWithV.value;
741 surfaces[0] = fSide0;
742 surfaces[1] = fSide90 ;
743 surfaces[2] = fSide180 ;
744 surfaces[3] = fSide270 ;
745 surfaces[4] = fLowerEndcap;
746 surfaces[5] = fUpperEndcap;
751 for (
auto i=0; i<6 ; ++i)
754 if (tmpdistance < distance)
756 distance = tmpdistance;
766 *norm = (surfaces[besti]->
GetNormal(p,
true));
772 return fLastDistanceToOutWithV.value;
792 if (fLastDistanceToOut.p == p)
794 return fLastDistanceToOut.value;
799 tmpdist =
const_cast<G4double*
>(&(fLastDistanceToOut.value));
800 tmpp->
set(p.
x(), p.
y(), p.
z());
822 G4cout.precision(oldprc) ;
823 G4Exception(
"G4VTwistedFaceted::DistanceToOut(p)",
"GeomSolids1002",
831 retval = fLastDistanceToOut.value;
845 surfaces[0] = fSide0;
846 surfaces[1] = fSide90 ;
847 surfaces[2] = fSide180 ;
848 surfaces[3] = fSide270 ;
849 surfaces[4] = fLowerEndcap;
850 surfaces[5] = fUpperEndcap;
854 for (
auto i=0; i<6; ++i)
857 if (tmpdistance < distance)
859 distance = tmpdistance;
865 retval = fLastDistanceToOut.value;
871 G4Exception(
"G4VTwistedFaceted::DistanceToOut(p)",
"GeomSolids0003",
889 G4long oldprc = os.precision(16);
890 os <<
"-----------------------------------------------------------\n"
891 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
892 <<
" ===================================================\n"
893 <<
" Solid type: G4VTwistedFaceted\n"
895 <<
" polar angle theta = " << fTheta/degree <<
" deg" <<
G4endl
896 <<
" azimuthal angle phi = " << fPhi/degree <<
" deg" <<
G4endl
897 <<
" tilt angle alpha = " << fAlph/degree <<
" deg" <<
G4endl
898 <<
" TWIST angle = " << fPhiTwist/degree <<
" deg" <<
G4endl
899 <<
" Half length along y (lower endcap) = " << fDy1/cm <<
" cm"
901 <<
" Half length along x (lower endcap, bottom) = " << fDx1/cm <<
" cm"
903 <<
" Half length along x (lower endcap, top) = " << fDx2/cm <<
" cm"
905 <<
" Half length along y (upper endcap) = " << fDy2/cm <<
" cm"
907 <<
" Half length along x (upper endcap, bottom) = " << fDx3/cm <<
" cm"
909 <<
" Half length along x (upper endcap, top) = " << fDx4/cm <<
" cm"
911 <<
"-----------------------------------------------------------\n";
912 os.precision(oldprc);
932 G4double maxRad = std::sqrt( fDx*fDx + fDy*fDy);
943void G4VTwistedFaceted::CreateSurfaces()
948 if ( fDx1 == fDx2 && fDx3 == fDx4 )
951 fDy1, fDx1, fDx1, fDy2, fDx3, fDx3, fAlph, 0.*deg);
952 fSide180 =
new G4TwistBoxSide(
"180deg", fPhiTwist, fDz, fTheta, fPhi+pi,
953 fDy1, fDx1, fDx1, fDy2, fDx3, fDx3, fAlph, 180.*deg);
958 fPhi, fDy1, fDx1, fDx2, fDy2, fDx3, fDx4, fAlph, 0.*deg);
960 fPhi+pi, fDy1, fDx2, fDx1, fDy2, fDx4, fDx3, fAlph, 180.*deg);
966 fPhi, fDy1, fDx1, fDx2, fDy2, fDx3, fDx4, fAlph, 0.*deg);
968 fPhi+pi, fDy1, fDx2, fDx1, fDy2, fDx4, fDx3, fAlph, 180.*deg);
973 fDz, fAlph, fPhi, fTheta, 1 );
975 fDz, fAlph, fPhi, fTheta, -1 );
979 fSide0->
SetNeighbours( fSide270 , fLowerEndcap , fSide90 , fUpperEndcap );
980 fSide90->
SetNeighbours( fSide0 , fLowerEndcap , fSide180 , fUpperEndcap );
981 fSide180->
SetNeighbours(fSide90 , fLowerEndcap , fSide270 , fUpperEndcap );
982 fSide270->
SetNeighbours(fSide180 , fLowerEndcap , fSide0 , fUpperEndcap );
983 fUpperEndcap->
SetNeighbours( fSide180, fSide270 , fSide0 , fSide90 );
984 fLowerEndcap->
SetNeighbours( fSide180, fSide270 , fSide0 , fSide90 );
995 fCubicVolume = ((fDx1 + fDx2 + fDx3 + fDx4)*(fDy1 + fDy2) +
996 (fDx4 + fDx3 - fDx2 - fDx1)*(fDy2 - fDy1)/3)*fDz;
1005G4VTwistedFaceted::GetLateralFaceArea(
const G4TwoVector& p1,
1010 constexpr G4int NSTEP = 100;
1015 G4double hTanTheta = h*std::tan(fTheta);
1028 G4double lmax = std::max(std::max(std::abs(x21),std::abs(y21)),
1029 std::max(std::abs(x43),std::abs(y43)));
1032 std::abs(x21*y43 - y21*x43) < eps)
1034 G4double x0 = hTanTheta*std::cos(fPhi);
1035 G4double y0 = hTanTheta*std::sin(fPhi);
1038 return (
A.cross(B)).mag()*0.5;
1043 for (
G4int i = 0; i < NSTEP; ++i)
1052 G4double ang = fPhi + fPhiTwist*(0.5 - t);
1053 G4double A = fPhiTwist*(II + JJ) + x21*y43 - x43*y21;
1054 G4double B = fPhiTwist*(
I*(x1 + x31*t) + J*(y1 + y31*t)) +
1055 hTanTheta*(I*std::sin(ang) - J*std::cos(ang)) +
1066 G4double R1 = std::sqrt(aa + bb + cc);
1068 G4double log1 = std::log(std::abs(sqrtAA*R1 + 2.*aa + bb));
1069 G4double log0 = std::log(std::abs(sqrtAA*R0 + bb));
1071 area += 0.5*R1 + 0.25*bb*invAA*(R1 - R0) + IIJJ*invSqrtAA*(log1 - log0);
1092 fSurfaceArea = 2.*(fDy1*(fDx1 + fDx2) + fDy2*(fDx3 + fDx4)) +
1093 GetLateralFaceArea(vv[0], vv[1], vv[4], vv[5]) +
1094 GetLateralFaceArea(vv[1], vv[3], vv[5], vv[7]) +
1095 GetLateralFaceArea(vv[3], vv[2], vv[7], vv[6]) +
1096 GetLateralFaceArea(vv[2], vv[0], vv[6], vv[4]);
1106 return G4String(
"G4VTwistedFaceted");
1141 if ( z == fDz ) z -= 0.1*fDz ;
1142 if ( z == -fDz ) z += 0.1*fDz ;
1144 G4double phi = z/(2*fDz)*fPhiTwist ;
1146 return G4ThreeVector(fdeltaX * phi/fPhiTwist, fdeltaY * phi/fPhiTwist, z ) ;
1156 G4double phi = G4RandFlat::shoot(-fPhiTwist/2.,fPhiTwist/2.);
1181 G4double chose = G4RandFlat::shoot(0.,a1 + a2 + a3 + a4 + a5 + a6) ;
1187 u = G4RandFlat::shoot(umin,umax) ;
1192 else if( (chose >= a1) && (chose < a1 + a2 ) )
1197 u = G4RandFlat::shoot(umin,umax) ;
1201 else if( (chose >= a1 + a2 ) && (chose < a1 + a2 + a3 ) )
1205 u = G4RandFlat::shoot(umin,umax) ;
1209 else if( (chose >= a1 + a2 + a3 ) && (chose < a1 + a2 + a3 + a4 ) )
1213 u = G4RandFlat::shoot(umin,umax) ;
1216 else if( (chose >= a1 + a2 + a3 + a4 ) && (chose < a1 + a2 + a3 + a4 + a5 ) )
1218 y = G4RandFlat::shoot(-fDy1,fDy1) ;
1221 u = G4RandFlat::shoot(umin,umax) ;
1227 y = G4RandFlat::shoot(-fDy2,fDy2) ;
1230 u = G4RandFlat::shoot(umin,umax) ;
1246 std::abs(fPhiTwist) / twopi) + 2;
1249 const G4int nnodes = 4*(k-1)*(n-2) + 2*k*k ;
1250 const G4int nfaces = 4*(k-1)*(n-1) + 2*(k-1)*(k-1) ;
1254 typedef G4int G4int4[4];
1255 G4double3* xyz =
new G4double3[nnodes];
1256 G4int4* faces =
new G4int4[nfaces] ;
1258 fLowerEndcap->
GetFacets(k,k,xyz,faces,0) ;
1259 fUpperEndcap->
GetFacets(k,k,xyz,faces,1) ;
G4double B(G4double temperature)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
G4GLOB_DLL std::ostream G4cout
void set(double x, double y, double z)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
static G4GeometryTolerance * GetInstance()
G4double GetAngularTolerance() const
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
virtual void AddSolid(const G4Box &)=0
G4VSolid & operator=(const G4VSolid &rhs)
virtual void GetFacets(G4int m, G4int n, G4double xyz[][3], G4int faces[][4], G4int iside)=0
void SetNeighbours(G4VTwistSurface *ax0min, G4VTwistSurface *ax1min, G4VTwistSurface *ax0max, G4VTwistSurface *ax1max)
virtual G4double GetBoundaryMin(G4double)=0
G4bool IsValidNorm() const
virtual G4double DistanceTo(const G4ThreeVector &gp, G4ThreeVector &gxx)
virtual G4double DistanceToOut(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector &gxxbest)
virtual G4double DistanceToIn(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector &gxxbest)
virtual G4ThreeVector SurfacePoint(G4double, G4double, G4bool isGlobal=false)=0
virtual G4double GetBoundaryMax(G4double)=0
virtual G4ThreeVector GetNormal(const G4ThreeVector &xx, G4bool isGlobal)=0
virtual G4double GetSurfaceArea()=0
virtual G4double GetCubicVolume()
virtual void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4VTwistedFaceted & operator=(const G4VTwistedFaceted &rhs)
G4Polyhedron * fpPolyhedron
virtual G4Polyhedron * GetPolyhedron() const
G4ThreeVector GetPointOnSurface() const
virtual G4GeometryType GetEntityType() const
G4bool fRebuildPolyhedron
G4ThreeVector GetPointInSolid(G4double z) const
virtual G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcnorm=false, G4bool *validnorm=nullptr, G4ThreeVector *n=nullptr) const
virtual EInside Inside(const G4ThreeVector &p) const
virtual std::ostream & StreamInfo(std::ostream &os) const
virtual ~G4VTwistedFaceted()
virtual void ComputeDimensions(G4VPVParameterisation *, const G4int, const G4VPhysicalVolume *)
virtual G4VisExtent GetExtent() const
virtual G4Polyhedron * CreatePolyhedron() const
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)
virtual void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4double GetValueB(G4double phi) const
G4double Xcoef(G4double u, G4double phi, G4double ftg) const
virtual G4double GetSurfaceArea()
static G4int GetNumberOfRotationSteps()
G4int createPolyhedron(G4int Nnodes, G4int Nfaces, const G4double xyz[][3], const G4int faces[][4])