69 fLowerEndcap(nullptr), fUpperEndcap(nullptr), fLatterTwisted(nullptr),
70 fFormerTwisted(nullptr), fInnerHype(nullptr), fOuterHype(nullptr)
74 G4Exception(
"G4TwistedTubs::G4TwistedTubs()",
"GeomSolids0002",
78 G4double sinhalftwist = std::sin(0.5 * twistedangle);
80 G4double endinnerradX = endinnerrad * sinhalftwist;
81 G4double innerrad = std::sqrt( endinnerrad * endinnerrad
82 - endinnerradX * endinnerradX );
84 G4double endouterradX = endouterrad * sinhalftwist;
85 G4double outerrad = std::sqrt( endouterrad * endouterrad
86 - endouterradX * endouterradX );
89 SetFields(twistedangle, innerrad, outerrad, -halfzlen, halfzlen);
101 fLowerEndcap(nullptr), fUpperEndcap(nullptr), fLatterTwisted(nullptr),
102 fFormerTwisted(nullptr), fInnerHype(nullptr), fOuterHype(nullptr)
107 std::ostringstream message;
108 message <<
"Invalid number of segments." <<
G4endl
109 <<
" nseg = " << nseg;
110 G4Exception(
"G4TwistedTubs::G4TwistedTubs()",
"GeomSolids0002",
115 G4Exception(
"G4TwistedTubs::G4TwistedTubs()",
"GeomSolids0002",
119 G4double sinhalftwist = std::sin(0.5 * twistedangle);
121 G4double endinnerradX = endinnerrad * sinhalftwist;
122 G4double innerrad = std::sqrt( endinnerrad * endinnerrad
123 - endinnerradX * endinnerradX );
125 G4double endouterradX = endouterrad * sinhalftwist;
126 G4double outerrad = std::sqrt( endouterrad * endouterrad
127 - endouterradX * endouterradX );
130 fDPhi = totphi / nseg;
131 SetFields(twistedangle, innerrad, outerrad, -halfzlen, halfzlen);
143 fLowerEndcap(nullptr), fUpperEndcap(nullptr), fLatterTwisted(nullptr),
144 fFormerTwisted(nullptr), fInnerHype(nullptr), fOuterHype(nullptr)
148 G4Exception(
"G4TwistedTubs::G4TwistedTubs()",
"GeomSolids0002",
152 SetFields(twistedangle, innerrad, outerrad, negativeEndz, positiveEndz);
165 fLowerEndcap(nullptr), fUpperEndcap(nullptr), fLatterTwisted(nullptr),
166 fFormerTwisted(nullptr), fInnerHype(nullptr), fOuterHype(nullptr)
170 std::ostringstream message;
171 message <<
"Invalid number of segments." <<
G4endl
172 <<
" nseg = " << nseg;
173 G4Exception(
"G4TwistedTubs::G4TwistedTubs()",
"GeomSolids0002",
178 G4Exception(
"G4TwistedTubs::G4TwistedTubs()",
"GeomSolids0002",
182 fDPhi = totphi / nseg;
183 SetFields(twistedangle, innerrad, outerrad, negativeEndz, positiveEndz);
192 fLowerEndcap(nullptr), fUpperEndcap(nullptr),
193 fLatterTwisted(nullptr), fFormerTwisted(nullptr),
194 fInnerHype(nullptr), fOuterHype(nullptr)
205 delete fLatterTwisted;
206 delete fFormerTwisted;
209 delete fpPolyhedron; fpPolyhedron =
nullptr;
216 :
G4VSolid(rhs), fPhiTwist(rhs.fPhiTwist),
217 fInnerRadius(rhs.fInnerRadius), fOuterRadius(rhs.fOuterRadius),
218 fDPhi(rhs.fDPhi), fZHalfLength(rhs.fZHalfLength),
219 fInnerStereo(rhs.fInnerStereo), fOuterStereo(rhs.fOuterStereo),
220 fTanInnerStereo(rhs.fTanInnerStereo), fTanOuterStereo(rhs.fTanOuterStereo),
221 fKappa(rhs.fKappa), fInnerRadius2(rhs.fInnerRadius2),
222 fOuterRadius2(rhs.fOuterRadius2), fTanInnerStereo2(rhs.fTanInnerStereo2),
223 fTanOuterStereo2(rhs.fTanOuterStereo2),
224 fLowerEndcap(nullptr), fUpperEndcap(nullptr), fLatterTwisted(nullptr), fFormerTwisted(nullptr),
225 fInnerHype(nullptr), fOuterHype(nullptr),
226 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea)
228 for (
auto i=0; i<2; ++i)
230 fEndZ[i] = rhs.fEndZ[i];
231 fEndInnerRadius[i] = rhs.fEndInnerRadius[i];
232 fEndOuterRadius[i] = rhs.fEndOuterRadius[i];
233 fEndPhi[i] = rhs.fEndPhi[i];
234 fEndZ2[i] = rhs.fEndZ2[i];
247 if (
this == &rhs) {
return *
this; }
255 fPhiTwist= rhs.fPhiTwist;
256 fInnerRadius= rhs.fInnerRadius; fOuterRadius= rhs.fOuterRadius;
257 fDPhi= rhs.fDPhi; fZHalfLength= rhs.fZHalfLength;
258 fInnerStereo= rhs.fInnerStereo; fOuterStereo= rhs.fOuterStereo;
259 fTanInnerStereo= rhs.fTanInnerStereo; fTanOuterStereo= rhs.fTanOuterStereo;
260 fKappa= rhs.fKappa; fInnerRadius2= rhs.fInnerRadius2;
261 fOuterRadius2= rhs.fOuterRadius2; fTanInnerStereo2= rhs.fTanInnerStereo2;
262 fTanOuterStereo2= rhs.fTanOuterStereo2;
263 fLowerEndcap= fUpperEndcap= fLatterTwisted= fFormerTwisted=
nullptr;
264 fInnerHype= fOuterHype=
nullptr;
265 fCubicVolume= rhs.fCubicVolume; fSurfaceArea= rhs.fSurfaceArea;
267 for (
auto i=0; i<2; ++i)
269 fEndZ[i] = rhs.fEndZ[i];
270 fEndInnerRadius[i] = rhs.fEndInnerRadius[i];
271 fEndOuterRadius[i] = rhs.fEndOuterRadius[i];
272 fEndPhi[i] = rhs.fEndPhi[i];
273 fEndZ2[i] = rhs.fEndZ2[i];
277 fRebuildPolyhedron =
false;
278 delete fpPolyhedron; fpPolyhedron =
nullptr;
292 "G4TwistedTubs does not support Parameterisation.");
314 if (dphi <= 0 || totalphi >= CLHEP::twopi)
316 pMin.
set(-rmax,-rmax, zmin);
317 pMax.
set( rmax, rmax, zmax);
323 pMin.
set(vmin.
x(), vmin.
y(), zmin);
324 pMax.
set(vmax.
x(), vmax.
y(), zmax);
329 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
331 std::ostringstream message;
332 message <<
"Bad bounding box (min >= max) for solid: "
334 <<
"\npMin = " << pMin
335 <<
"\npMax = " << pMax;
336 G4Exception(
"G4TwistedTubs::BoundingLimits()",
"GeomMgt0001",
379 if ((outerhypearea ==
kOutside) || (distanceToOut < -halftol))
389 if (distanceToOut <= halftol)
418 surfaces[0] = fLatterTwisted;
419 surfaces[1] = fFormerTwisted;
420 surfaces[2] = fInnerHype;
421 surfaces[3] = fOuterHype;
422 surfaces[4] = fLowerEndcap;
423 surfaces[5] = fUpperEndcap;
428 for (
auto i=0; i<6; ++i)
431 if (tmpdistance < distance)
433 distance = tmpdistance;
439 return surfaces[besti]->
GetNormal(bestxx,
true);
488 surfaces[0] = fLowerEndcap;
489 surfaces[1] = fUpperEndcap;
490 surfaces[2] = fLatterTwisted;
491 surfaces[3] = fFormerTwisted;
492 surfaces[4] = fInnerHype;
493 surfaces[5] = fOuterHype;
497 for (
const auto & surface : surfaces)
499 G4double tmpdistance = surface->DistanceToIn(p, v, xx);
500 if (tmpdistance < distance)
502 distance = tmpdistance;
539 surfaces[0] = fLowerEndcap;
540 surfaces[1] = fUpperEndcap;
541 surfaces[2] = fLatterTwisted;
542 surfaces[3] = fFormerTwisted;
543 surfaces[4] = fInnerHype;
544 surfaces[5] = fOuterHype;
548 for (
const auto & surface : surfaces)
550 G4double tmpdistance = surface->DistanceTo(p, xx);
551 if (tmpdistance < distance)
553 distance = tmpdistance;
561 G4Exception(
"G4TwistedTubs::DistanceToIn(p)",
"GeomSolids0003",
621 surfaces[0] = fLatterTwisted;
622 surfaces[1] = fFormerTwisted;
623 surfaces[2] = fInnerHype;
624 surfaces[3] = fOuterHype;
625 surfaces[4] = fLowerEndcap;
626 surfaces[5] = fUpperEndcap;
631 for (
auto i=0; i<6; ++i)
634 if (tmpdistance < distance)
636 distance = tmpdistance;
646 *norm = (surfaces[besti]->
GetNormal(p,
true));
686 surfaces[0] = fLatterTwisted;
687 surfaces[1] = fFormerTwisted;
688 surfaces[2] = fInnerHype;
689 surfaces[3] = fOuterHype;
690 surfaces[4] = fLowerEndcap;
691 surfaces[5] = fUpperEndcap;
695 for (
const auto & surface : surfaces)
697 G4double tmpdistance = surface->DistanceTo(p, xx);
698 if (tmpdistance < distance)
700 distance = tmpdistance;
708 G4Exception(
"G4TwistedTubs::DistanceToOut(p)",
"GeomSolids0003",
724 G4long oldprc = os.precision(16);
725 os <<
"-----------------------------------------------------------\n"
726 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
727 <<
" ===================================================\n"
728 <<
" Solid type: G4TwistedTubs\n"
730 <<
" -ve end Z : " << fEndZ[0]/mm <<
" mm \n"
731 <<
" +ve end Z : " << fEndZ[1]/mm <<
" mm \n"
732 <<
" inner end radius(-ve z): " << fEndInnerRadius[0]/mm <<
" mm \n"
733 <<
" inner end radius(+ve z): " << fEndInnerRadius[1]/mm <<
" mm \n"
734 <<
" outer end radius(-ve z): " << fEndOuterRadius[0]/mm <<
" mm \n"
735 <<
" outer end radius(+ve z): " << fEndOuterRadius[1]/mm <<
" mm \n"
736 <<
" inner radius (z=0) : " << fInnerRadius/mm <<
" mm \n"
737 <<
" outer radius (z=0) : " << fOuterRadius/mm <<
" mm \n"
738 <<
" twisted angle : " << fPhiTwist/degree <<
" degrees \n"
739 <<
" inner stereo angle : " << fInnerStereo/degree <<
" degrees \n"
740 <<
" outer stereo angle : " << fOuterStereo/degree <<
" degrees \n"
741 <<
" phi-width of a piece : " << fDPhi/degree <<
" degrees \n"
742 <<
"-----------------------------------------------------------\n";
743 os.precision(oldprc);
766 return { pmin.
x(),pmax.
x(),
778 G4double absPhiTwist = std::abs(fPhiTwist);
779 G4double dA = std::max(fDPhi,absPhiTwist);
785 const G4int nnodes = 4*(k-1)*(n-2) + 2*k*k ;
786 const G4int nfaces = 4*(k-1)*(n-1) + 2*(k-1)*(k-1) ;
790 typedef G4int G4int4[4];
791 auto xyz =
new G4double3[nnodes];
792 auto faces =
new G4int4[nfaces] ;
793 fLowerEndcap->GetFacets(k,k,xyz,faces,0) ;
794 fUpperEndcap->GetFacets(k,k,xyz,faces,1) ;
795 fInnerHype->GetFacets(k,n,xyz,faces,2) ;
796 fFormerTwisted->GetFacets(k,n,xyz,faces,3) ;
797 fOuterHype->GetFacets(k,n,xyz,faces,4) ;
798 fLatterTwisted->GetFacets(k,n,xyz,faces,5) ;
800 ph->createPolyhedron(nnodes,nfaces,xyz,faces);
813 if (fpPolyhedron ==
nullptr ||
814 fRebuildPolyhedron ||
815 fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
816 fpPolyhedron->GetNumberOfRotationSteps())
821 fRebuildPolyhedron =
false;
830void G4TwistedTubs::CreateSurfaces()
838 fEndInnerRadius, fEndOuterRadius,
839 fDPhi, fEndPhi, fEndZ, -1) ;
842 fEndInnerRadius, fEndOuterRadius,
843 fDPhi, fEndPhi, fEndZ, 1) ;
846 rotHalfDPhi.
rotateZ(0.5*fDPhi);
849 fEndInnerRadius, fEndOuterRadius,
850 fDPhi, fEndPhi, fEndZ,
851 fInnerRadius, fOuterRadius, fKappa,
854 fEndInnerRadius, fEndOuterRadius,
855 fDPhi, fEndPhi, fEndZ,
856 fInnerRadius, fOuterRadius, fKappa,
860 fEndInnerRadius, fEndOuterRadius,
861 fDPhi, fEndPhi, fEndZ,
862 fInnerRadius, fOuterRadius,fKappa,
863 fTanInnerStereo, fTanOuterStereo, -1) ;
865 fEndInnerRadius, fEndOuterRadius,
866 fDPhi, fEndPhi, fEndZ,
867 fInnerRadius, fOuterRadius,fKappa,
868 fTanInnerStereo, fTanOuterStereo, 1) ;
874 fOuterHype, fFormerTwisted);
876 fOuterHype, fFormerTwisted);
878 fOuterHype, fUpperEndcap);
880 fOuterHype, fUpperEndcap);
882 fFormerTwisted, fUpperEndcap);
884 fFormerTwisted, fUpperEndcap);
893 return {
"G4TwistedTubs"};
910 if (z == 0) {
return 0.; }
921 area = 0.5*a*(h*std::sqrt(1. + kh*kh) + std::asinh(kh)/k);
932 if (
GetDPhi() >= CLHEP::twopi || r <= 0 || z == 0) {
return 0.; }
943 G4double sqroot = std::sqrt(pp + qq + 1);
945 0.5*p*(
pp + 3.)*std::atanh(q/sqroot) +
946 0.5*q*(qq + 3.)*std::atanh(p/sqroot) +
947 std::atan(sqroot/(pq)) - CLHEP::halfpi)*h*a/(3.*pq);
957 if (fCubicVolume == 0)
971 fCubicVolume = (2.*(Z1 - Z0)*(Aout + Ain)*(Aout - Ain)
972 + Z1*(R1out + R1in)*(R1out - R1in)
973 - Z0*(R0out + R0in)*(R0out - R0in))*DPhi/6.;
984 if (fSurfaceArea == 0)
997 G4double base0 = 0.5*dphi*(Rout0*Rout0 - Rinn0*Rinn0);
998 G4double inner0 = GetLateralArea(Ainn, Rinn0, z0);
999 G4double outer0 = GetLateralArea(Aout, Rout0, z0);
1001 GetPhiCutArea(Aout, Rout0, z0) - GetPhiCutArea(Ainn, Rinn0, z0);
1007 if (std::abs(z0) != std::abs(z1))
1009 base1 = 0.5*dphi*(Rout1*Rout1 - Rinn1*Rinn1);
1010 inner1 = GetLateralArea(Ainn, Rinn1, z1);
1011 outer1 = GetLateralArea(Aout, Rout1, z1);
1013 GetPhiCutArea(Aout, Rout1, z1) - GetPhiCutArea(Ainn, Rinn1, z1);
1015 fSurfaceArea = base0 + base1 +
1017 (inner0 + inner1 + outer0 + outer1 + 2.*(cut0 + cut1)) :
1018 std::abs(inner0 - inner1 + outer0 - outer1 + 2.*(cut0 - cut1)));
1021 return fSurfaceArea;
1035 G4double a1 = fOuterHype->GetSurfaceArea() ;
1036 G4double a2 = fInnerHype->GetSurfaceArea() ;
1037 G4double a3 = fLatterTwisted->GetSurfaceArea() ;
1038 G4double a4 = fFormerTwisted->GetSurfaceArea() ;
1039 G4double a5 = fLowerEndcap->GetSurfaceArea() ;
1040 G4double a6 = fUpperEndcap->GetSurfaceArea() ;
1047 phimin = fOuterHype->GetBoundaryMin(z) ;
1048 phimax = fOuterHype->GetBoundaryMax(z) ;
1051 return fOuterHype->SurfacePoint(phi,z,
true) ;
1053 if ( (chose >= a1) && (chose < a1 + a2 ) )
1056 phimin = fInnerHype->GetBoundaryMin(z) ;
1057 phimax = fInnerHype->GetBoundaryMax(z) ;
1060 return fInnerHype->SurfacePoint(phi,z,
true) ;
1062 if ( (chose >= a1 + a2 ) && (chose < a1 + a2 + a3 ) )
1065 xmin = fLatterTwisted->GetBoundaryMin(z) ;
1066 xmax = fLatterTwisted->GetBoundaryMax(z) ;
1069 return fLatterTwisted->SurfacePoint(x,z,
true) ;
1071 if ( (chose >= a1 + a2 + a3 ) && (chose < a1 + a2 + a3 + a4 ) )
1074 xmin = fFormerTwisted->GetBoundaryMin(z) ;
1075 xmax = fFormerTwisted->GetBoundaryMax(z) ;
1078 return fFormerTwisted->SurfacePoint(x,z,
true) ;
1080 if( (chose >= a1 + a2 + a3 + a4 )&&(chose < a1 + a2 + a3 + a4 + a5 ) )
1086 phimin = fLowerEndcap->GetBoundaryMin(r) ;
1087 phimax = fLowerEndcap->GetBoundaryMax(r) ;
1090 return fLowerEndcap->SurfacePoint(phi,r,
true) ;
1097 phimin = fUpperEndcap->GetBoundaryMin(r) ;
1098 phimax = fUpperEndcap->GetBoundaryMax(r) ;
1101 return fUpperEndcap->SurfacePoint(phi,r,
true) ;
G4TemplateAutoLock< G4Mutex > G4AutoLock
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4double G4QuickRand(uint32_t seed=0)
CLHEP::HepRotation G4RotationMatrix
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
void set(double x, double y, double z)
HepRotation & rotateZ(double delta)
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
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4TwistTubsFlatSide describes a flat boundary surface for a cylinder.
G4TwistTubsHypeSide describes hyperbolic boundary surface for a cylinder.
G4TwistTubsFlatSide describes a twisted boundary surface for a cylinder.
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcnorm=false, G4bool *validnorm=nullptr, G4ThreeVector *n=nullptr) const override
G4double GetOuterRadius() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const override
G4double GetZHalfLength() const
G4double GetPhiTwist() const
G4Polyhedron * CreatePolyhedron() const override
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4TwistedTubs & operator=(const G4TwistedTubs &rhs)
G4double GetEndInnerRadius() const
G4double GetEndOuterRadius() const
G4VSolid * Clone() const override
G4Polyhedron * GetPolyhedron() const override
~G4TwistedTubs() override
G4GeometryType GetEntityType() const override
G4double GetEndPhi(G4int i) const
G4TwistedTubs(const G4String &pname, G4double twistedangle, G4double endinnerrad, G4double endouterrad, G4double halfzlen, G4double dphi)
std::ostream & StreamInfo(std::ostream &os) const override
G4double GetSurfaceArea() override
G4double GetCubicVolume() override
void ComputeDimensions(G4VPVParameterisation *, const G4int, const G4VPhysicalVolume *) override
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4VisExtent GetExtent() const override
G4ThreeVector GetPointOnSurface() const override
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
G4double GetEndZ(G4int i) const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
G4double GetInnerRadius() const
EInside Inside(const G4ThreeVector &p) const override
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
void SetNeighbours(G4VTwistSurface *ax0min, G4VTwistSurface *ax1min, G4VTwistSurface *ax0max, G4VTwistSurface *ax1max)
G4bool IsValidNorm() const
virtual G4double DistanceTo(const G4ThreeVector &gp, G4ThreeVector &gxx)
virtual G4double DistanceToOut(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector &gxxbest)
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
static G4int GetNumberOfRotationSteps()