74 fLowerEndcap(nullptr), fUpperEndcap(nullptr), fSide0(nullptr),
75 fSide90(nullptr), fSide180(nullptr), fSide270(nullptr)
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 fLowerEndcap(nullptr), fUpperEndcap(nullptr),
193 fSide0(nullptr), fSide90(nullptr), fSide180(nullptr), fSide270(nullptr)
203 delete fLowerEndcap ;
204 delete fUpperEndcap ;
219 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
220 fTheta(rhs.fTheta), fPhi(rhs.fPhi),
221 fDy1(rhs.fDy1), fDx1(rhs.fDx1), fDx2(rhs.fDx2), fDy2(rhs.fDy2),
222 fDx3(rhs.fDx3), fDx4(rhs.fDx4), fDz(rhs.fDz), fDx(rhs.fDx), fDy(rhs.fDy),
223 fAlph(rhs.fAlph), fTAlph(rhs.fTAlph), fdeltaX(rhs.fdeltaX),
224 fdeltaY(rhs.fdeltaY), fPhiTwist(rhs.fPhiTwist), fLowerEndcap(nullptr),
225 fUpperEndcap(nullptr), fSide0(nullptr), fSide90(nullptr), fSide180(nullptr), fSide270(nullptr),
226 fLastInside(rhs.fLastInside), fLastNormal(rhs.fLastNormal),
227 fLastDistanceToIn(rhs.fLastDistanceToIn),
228 fLastDistanceToOut(rhs.fLastDistanceToOut),
229 fLastDistanceToInWithV(rhs.fLastDistanceToInWithV),
230 fLastDistanceToOutWithV(rhs.fLastDistanceToOutWithV)
243 if (
this == &rhs) {
return *
this; }
251 fTheta = rhs.fTheta; fPhi = rhs.fPhi;
252 fDy1= rhs.fDy1; fDx1= rhs.fDx1; fDx2= rhs.fDx2; fDy2= rhs.fDy2;
253 fDx3= rhs.fDx3; fDx4= rhs.fDx4; fDz= rhs.fDz; fDx= rhs.fDx; fDy= rhs.fDy;
254 fAlph= rhs.fAlph; fTAlph= rhs.fTAlph; fdeltaX= rhs.fdeltaX;
255 fdeltaY= rhs.fdeltaY; fPhiTwist= rhs.fPhiTwist; fLowerEndcap=
nullptr;
256 fUpperEndcap=
nullptr; fSide0=
nullptr; fSide90=
nullptr; fSide180=
nullptr; fSide270=
nullptr;
260 fLastInside= rhs.fLastInside; fLastNormal= rhs.fLastNormal;
261 fLastDistanceToIn= rhs.fLastDistanceToIn;
262 fLastDistanceToOut= rhs.fLastDistanceToOut;
263 fLastDistanceToInWithV= rhs.fLastDistanceToInWithV;
264 fLastDistanceToOutWithV= rhs.fLastDistanceToOutWithV;
279 G4Exception(
"G4VTwistedFaceted::ComputeDimensions()",
281 "G4VTwistedFaceted does not support Parameterisation.");
293 G4double tanTheta = std::tan(fTheta);
297 G4double x1 = std::abs(xmid1 + fDx1);
298 G4double x2 = std::abs(xmid1 - fDx1);
299 G4double x3 = std::abs(xmid1 + fDx2);
300 G4double x4 = std::abs(xmid1 - fDx2);
301 G4double xmax1 = std::max(std::max(std::max(x1, x2), x3), x4);
302 G4double rmax1 = std::sqrt(xmax1*xmax1 + fDy1*fDy1);
305 G4double x5 = std::abs(xmid2 + fDx3);
306 G4double x6 = std::abs(xmid2 - fDx3);
307 G4double x7 = std::abs(xmid2 + fDx4);
308 G4double x8 = std::abs(xmid2 - fDx4);
309 G4double xmax2 = std::max(std::max(std::max(x5, x6), x7), x8);
310 G4double rmax2 = std::sqrt(xmax2*xmax2 + fDy2*fDy2);
314 G4double xmin = std::min(-x0 - rmax1, x0 - rmax2);
315 G4double ymin = std::min(-y0 - rmax1, y0 - rmax2);
316 G4double xmax = std::max(-x0 + rmax1, x0 + rmax2);
317 G4double ymax = std::max(-y0 + rmax1, y0 + rmax2);
318 pMin.
set(xmin, ymin,-fDz);
319 pMax.
set(xmax, ymax, fDz);
352 if (fLastInside.p == p)
354 return fLastInside.inside;
359 tmpin =
const_cast<EInside*
>(&(fLastInside.inside));
360 tmpp->
set(p.
x(), p.
y(), p.
z());
365 G4double phi = p.
z()/(2*fDz) * fPhiTwist ;
369 G4double px = p.
x() + fdeltaX * ( -phi/fPhiTwist) ;
370 G4double py = p.
y() + fdeltaY * ( -phi/fPhiTwist) ;
373 G4double posx = px * cphi - py * sphi ;
374 G4double posy = px * sphi + py * cphi ;
397 G4cout <<
"phi,theta = " << fPhi <<
" , " << fTheta <<
G4endl ;
440 return fLastInside.inside;
457 if (fLastNormal.p == p)
459 return fLastNormal.vec;
463 auto tmpnormal =
const_cast<G4ThreeVector*
>(&(fLastNormal.vec));
465 tmpp->set(p.
x(), p.
y(), p.
z());
471 surfaces[0] = fSide0 ;
472 surfaces[1] = fSide90 ;
473 surfaces[2] = fSide180 ;
474 surfaces[3] = fSide270 ;
475 surfaces[4] = fLowerEndcap;
476 surfaces[5] = fUpperEndcap;
485 if (tmpdistance < distance)
487 distance = tmpdistance;
493 tmpsurface[0] = surfaces[besti];
494 *tmpnormal = tmpsurface[0]->
GetNormal(bestxx,
true);
496 return fLastNormal.vec;
520 if (fLastDistanceToInWithV.p == p && fLastDistanceToInWithV.vec == v)
522 return fLastDistanceToIn.value;
526 tmpp =
const_cast<G4ThreeVector*
>(&(fLastDistanceToInWithV.p));
527 tmpv =
const_cast<G4ThreeVector*
>(&(fLastDistanceToInWithV.vec));
528 tmpdist =
const_cast<G4double*
>(&(fLastDistanceToInWithV.value));
529 tmpp->
set(p.
x(), p.
y(), p.
z());
530 tmpv->
set(v.
x(), v.
y(), v.
z());
551 return fLastDistanceToInWithV.value;
565 surfaces[0] = fSide0;
566 surfaces[1] = fSide90 ;
567 surfaces[2] = fSide180 ;
568 surfaces[3] = fSide270 ;
569 surfaces[4] = fLowerEndcap;
570 surfaces[5] = fUpperEndcap;
574 for (
const auto & surface : surfaces)
579 G4double tmpdistance = surface->DistanceToIn(p, v, xx);
581 G4cout <<
"Solid DistanceToIn : distance = " << tmpdistance <<
G4endl ;
584 if (tmpdistance < distance)
586 distance = tmpdistance;
597 return fLastDistanceToInWithV.value;
617 if (fLastDistanceToIn.p == p)
619 return fLastDistanceToIn.value;
624 tmpdist =
const_cast<G4double*
>(&(fLastDistanceToIn.value));
625 tmpp->
set(p.
x(), p.
y(), p.
z());
643 return fLastDistanceToIn.value;
656 surfaces[0] = fSide0;
657 surfaces[1] = fSide90 ;
658 surfaces[2] = fSide180 ;
659 surfaces[3] = fSide270 ;
660 surfaces[4] = fLowerEndcap;
661 surfaces[5] = fUpperEndcap;
665 for (
const auto & surface : surfaces)
667 G4double tmpdistance = surface->DistanceTo(p, xx);
668 if (tmpdistance < distance)
670 distance = tmpdistance;
675 return fLastDistanceToIn.value;
680 G4Exception(
"G4VTwistedFaceted::DistanceToIn(p)",
"GeomSolids0003",
712 if (fLastDistanceToOutWithV.p == p && fLastDistanceToOutWithV.vec == v )
714 return fLastDistanceToOutWithV.value;
718 tmpp =
const_cast<G4ThreeVector*
>(&(fLastDistanceToOutWithV.p));
719 tmpv =
const_cast<G4ThreeVector*
>(&(fLastDistanceToOutWithV.vec));
720 tmpdist =
const_cast<G4double*
>(&(fLastDistanceToOutWithV.value));
721 tmpp->
set(p.
x(), p.
y(), p.
z());
722 tmpv->
set(v.
x(), v.
y(), v.
z());
745 *norm = (blockedsurface->
GetNormal(p,
true));
750 return fLastDistanceToOutWithV.value;
762 surfaces[0] = fSide0;
763 surfaces[1] = fSide90 ;
764 surfaces[2] = fSide180 ;
765 surfaces[3] = fSide270 ;
766 surfaces[4] = fLowerEndcap;
767 surfaces[5] = fUpperEndcap;
772 for (
auto i=0; i<6 ; ++i)
775 if (tmpdistance < distance)
777 distance = tmpdistance;
787 *norm = (surfaces[besti]->
GetNormal(p,
true));
793 return fLastDistanceToOutWithV.value;
813 if (fLastDistanceToOut.p == p)
815 return fLastDistanceToOut.value;
820 tmpdist =
const_cast<G4double*
>(&(fLastDistanceToOut.value));
821 tmpp->
set(p.
x(), p.
y(), p.
z());
843 G4cout.precision(oldprc) ;
844 G4Exception(
"G4VTwistedFaceted::DistanceToOut(p)",
"GeomSolids1002",
852 retval = fLastDistanceToOut.value;
866 surfaces[0] = fSide0;
867 surfaces[1] = fSide90 ;
868 surfaces[2] = fSide180 ;
869 surfaces[3] = fSide270 ;
870 surfaces[4] = fLowerEndcap;
871 surfaces[5] = fUpperEndcap;
875 for (
const auto & surface : surfaces)
877 G4double tmpdistance = surface->DistanceTo(p, xx);
878 if (tmpdistance < distance)
880 distance = tmpdistance;
886 retval = fLastDistanceToOut.value;
892 G4Exception(
"G4VTwistedFaceted::DistanceToOut(p)",
"GeomSolids0003",
910 G4long oldprc = os.precision(16);
911 os <<
"-----------------------------------------------------------\n"
912 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
913 <<
" ===================================================\n"
914 <<
" Solid type: G4VTwistedFaceted\n"
916 <<
" polar angle theta = " << fTheta/degree <<
" deg" <<
G4endl
917 <<
" azimuthal angle phi = " << fPhi/degree <<
" deg" <<
G4endl
918 <<
" tilt angle alpha = " << fAlph/degree <<
" deg" <<
G4endl
919 <<
" TWIST angle = " << fPhiTwist/degree <<
" deg" <<
G4endl
920 <<
" Half length along y (lower endcap) = " << fDy1/cm <<
" cm"
922 <<
" Half length along x (lower endcap, bottom) = " << fDx1/cm <<
" cm"
924 <<
" Half length along x (lower endcap, top) = " << fDx2/cm <<
" cm"
926 <<
" Half length along y (upper endcap) = " << fDy2/cm <<
" cm"
928 <<
" Half length along x (upper endcap, bottom) = " << fDx3/cm <<
" cm"
930 <<
" Half length along x (upper endcap, top) = " << fDx4/cm <<
" cm"
932 <<
"-----------------------------------------------------------\n";
933 os.precision(oldprc);
953 G4double maxRad = std::sqrt( fDx*fDx + fDy*fDy);
955 return { -maxRad, maxRad ,
964void G4VTwistedFaceted::CreateSurfaces()
969 if ( fDx1 == fDx2 && fDx3 == fDx4 )
972 fDy1, fDx1, fDx1, fDy2, fDx3, fDx3, fAlph, 0.*deg);
973 fSide180 =
new G4TwistBoxSide(
"180deg", fPhiTwist, fDz, fTheta, fPhi+pi,
974 fDy1, fDx1, fDx1, fDy2, fDx3, fDx3, fAlph, 180.*deg);
979 fPhi, fDy1, fDx1, fDx2, fDy2, fDx3, fDx4, fAlph, 0.*deg);
981 fPhi+pi, fDy1, fDx2, fDx1, fDy2, fDx4, fDx3, fAlph, 180.*deg);
987 fPhi, fDy1, fDx1, fDx2, fDy2, fDx3, fDx4, fAlph, 0.*deg);
989 fPhi+pi, fDy1, fDx2, fDx1, fDy2, fDx4, fDx3, fAlph, 180.*deg);
994 fDz, fAlph, fPhi, fTheta, 1 );
996 fDz, fAlph, fPhi, fTheta, -1 );
1000 fSide0->
SetNeighbours( fSide270 , fLowerEndcap , fSide90 , fUpperEndcap );
1001 fSide90->
SetNeighbours( fSide0 , fLowerEndcap , fSide180 , fUpperEndcap );
1002 fSide180->
SetNeighbours(fSide90 , fLowerEndcap , fSide270 , fUpperEndcap );
1003 fSide270->
SetNeighbours(fSide180 , fLowerEndcap , fSide0 , fUpperEndcap );
1004 fUpperEndcap->
SetNeighbours( fSide180, fSide270 , fSide0 , fSide90 );
1005 fLowerEndcap->
SetNeighbours( fSide180, fSide270 , fSide0 , fSide90 );
1016 fCubicVolume = ((fDx1 + fDx2 + fDx3 + fDx4)*(fDy1 + fDy2) +
1017 (fDx4 + fDx3 - fDx2 - fDx1)*(fDy2 - fDy1)/3)*fDz;
1026G4VTwistedFaceted::GetLateralFaceArea(
const G4TwoVector& p1,
1031 constexpr G4int NSTEP = 100;
1036 G4double hTanTheta = h*std::tan(fTheta);
1049 G4double lmax = std::max(std::max(std::abs(x21),std::abs(y21)),
1050 std::max(std::abs(x43),std::abs(y43)));
1053 std::abs(x21*y43 - y21*x43) < eps)
1055 G4double x0 = hTanTheta*std::cos(fPhi);
1056 G4double y0 = hTanTheta*std::sin(fPhi);
1059 return (
A.cross(B)).mag()*0.5;
1064 for (
G4int i = 0; i < NSTEP; ++i)
1073 G4double ang = fPhi + fPhiTwist*(0.5 - t);
1074 G4double A = fPhiTwist*(II + JJ) + x21*y43 - x43*y21;
1075 G4double B = fPhiTwist*(I*(x1 + x31*t) + J*(y1 + y31*t)) +
1076 hTanTheta*(I*std::sin(ang) - J*std::cos(ang)) +
1087 G4double R1 = std::sqrt(aa + bb + cc);
1089 G4double log1 = std::log(std::abs(sqrtAA*R1 + 2.*aa + bb));
1090 G4double log0 = std::log(std::abs(sqrtAA*R0 + bb));
1092 area += 0.5*R1 + 0.25*bb*invAA*(R1 - R0) + IIJJ*invSqrtAA*(log1 - log0);
1113 fSurfaceArea = 2.*(fDy1*(fDx1 + fDx2) + fDy2*(fDx3 + fDx4)) +
1114 GetLateralFaceArea(vv[0], vv[1], vv[4], vv[5]) +
1115 GetLateralFaceArea(vv[1], vv[3], vv[5], vv[7]) +
1116 GetLateralFaceArea(vv[3], vv[2], vv[7], vv[6]) +
1117 GetLateralFaceArea(vv[2], vv[0], vv[6], vv[4]);
1127 return {
"G4VTwistedFaceted"};
1162 if ( z == fDz ) z -= 0.1*fDz ;
1163 if ( z == -fDz ) z += 0.1*fDz ;
1165 G4double phi = z/(2*fDz)*fPhiTwist ;
1167 return { fdeltaX * phi/fPhiTwist, fdeltaY * phi/fPhiTwist, z };
1177 G4double phi = G4RandFlat::shoot(-fPhiTwist/2.,fPhiTwist/2.);
1202 G4double chose = G4RandFlat::shoot(0.,a1 + a2 + a3 + a4 + a5 + a6) ;
1208 u = G4RandFlat::shoot(umin,umax) ;
1213 else if( (chose >= a1) && (chose < a1 + a2 ) )
1218 u = G4RandFlat::shoot(umin,umax) ;
1222 else if( (chose >= a1 + a2 ) && (chose < a1 + a2 + a3 ) )
1226 u = G4RandFlat::shoot(umin,umax) ;
1230 else if( (chose >= a1 + a2 + a3 ) && (chose < a1 + a2 + a3 + a4 ) )
1234 u = G4RandFlat::shoot(umin,umax) ;
1237 else if( (chose >= a1 + a2 + a3 + a4 ) && (chose < a1 + a2 + a3 + a4 + a5 ) )
1239 y = G4RandFlat::shoot(-fDy1,fDy1) ;
1242 u = G4RandFlat::shoot(umin,umax) ;
1248 y = G4RandFlat::shoot(-fDy2,fDy2) ;
1251 u = G4RandFlat::shoot(umin,umax) ;
1267 std::abs(fPhiTwist) / twopi) + 2;
1270 const G4int nnodes = 4*(k-1)*(n-2) + 2*k*k ;
1271 const G4int nfaces = 4*(k-1)*(n-1) + 2*(k-1)*(k-1) ;
1275 typedef G4int G4int4[4];
1276 auto xyz =
new G4double3[nnodes];
1277 auto faces =
new G4int4[nfaces] ;
1279 fLowerEndcap->
GetFacets(k,k,xyz,faces,0) ;
1280 fUpperEndcap->
GetFacets(k,k,xyz,faces,1) ;
1286 ph->createPolyhedron(nnodes,nfaces,xyz,faces);
G4double B(G4double temperature)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define G4MUTEX_INITIALIZER
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 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
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
G4ThreeVector GetPointInSolid(G4double z) const
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
virtual ~G4VTwistedFaceted()
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(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
static G4int GetNumberOfRotationSteps()