69 fLowerEndcap(0), fUpperEndcap(0), fLatterTwisted(0),
70 fFormerTwisted(0), fInnerHype(0), fOuterHype(0)
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(0), fUpperEndcap(0), fLatterTwisted(0),
102 fFormerTwisted(0), fInnerHype(0), fOuterHype(0)
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(0), fUpperEndcap(0), fLatterTwisted(0),
144 fFormerTwisted(0), fInnerHype(0), fOuterHype(0)
148 G4Exception(
"G4TwistedTubs::G4TwistedTubs()",
"GeomSolids0002",
152 SetFields(twistedangle, innerrad, outerrad, negativeEndz, positiveEndz);
165 fLowerEndcap(0), fUpperEndcap(0), fLatterTwisted(0),
166 fFormerTwisted(0), fInnerHype(0), fOuterHype(0)
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);
191 :
G4VSolid(a), fPhiTwist(0.), fInnerRadius(0.), fOuterRadius(0.), fDPhi(0.),
192 fZHalfLength(0.), fInnerStereo(0.), fOuterStereo(0.), fTanInnerStereo(0.),
193 fTanOuterStereo(0.), fKappa(0.), fInnerRadius2(0.), fOuterRadius2(0.),
194 fTanInnerStereo2(0.), fTanOuterStereo2(0.), fLowerEndcap(0), fUpperEndcap(0),
195 fLatterTwisted(0), fFormerTwisted(0), fInnerHype(0), fOuterHype(0)
204 if (fLowerEndcap) {
delete fLowerEndcap; }
205 if (fUpperEndcap) {
delete fUpperEndcap; }
206 if (fLatterTwisted) {
delete fLatterTwisted; }
207 if (fFormerTwisted) {
delete fFormerTwisted; }
208 if (fInnerHype) {
delete fInnerHype; }
209 if (fOuterHype) {
delete fOuterHype; }
210 if (fpPolyhedron) {
delete fpPolyhedron; fpPolyhedron =
nullptr; }
217 :
G4VSolid(rhs), fPhiTwist(rhs.fPhiTwist),
218 fInnerRadius(rhs.fInnerRadius), fOuterRadius(rhs.fOuterRadius),
219 fDPhi(rhs.fDPhi), fZHalfLength(rhs.fZHalfLength),
220 fInnerStereo(rhs.fInnerStereo), fOuterStereo(rhs.fOuterStereo),
221 fTanInnerStereo(rhs.fTanInnerStereo), fTanOuterStereo(rhs.fTanOuterStereo),
222 fKappa(rhs.fKappa), fInnerRadius2(rhs.fInnerRadius2),
223 fOuterRadius2(rhs.fOuterRadius2), fTanInnerStereo2(rhs.fTanInnerStereo2),
224 fTanOuterStereo2(rhs.fTanOuterStereo2),
225 fLowerEndcap(0), fUpperEndcap(0), fLatterTwisted(0), fFormerTwisted(0),
226 fInnerHype(0), fOuterHype(0),
227 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
228 fLastInside(rhs.fLastInside), fLastNormal(rhs.fLastNormal),
229 fLastDistanceToIn(rhs.fLastDistanceToIn),
230 fLastDistanceToOut(rhs.fLastDistanceToOut),
231 fLastDistanceToInWithV(rhs.fLastDistanceToInWithV),
232 fLastDistanceToOutWithV(rhs.fLastDistanceToOutWithV)
234 for (
auto i=0; i<2; ++i)
236 fEndZ[i] = rhs.fEndZ[i];
237 fEndInnerRadius[i] = rhs.fEndInnerRadius[i];
238 fEndOuterRadius[i] = rhs.fEndOuterRadius[i];
239 fEndPhi[i] = rhs.fEndPhi[i];
240 fEndZ2[i] = rhs.fEndZ2[i];
253 if (
this == &rhs) {
return *
this; }
261 fPhiTwist= rhs.fPhiTwist;
262 fInnerRadius= rhs.fInnerRadius; fOuterRadius= rhs.fOuterRadius;
263 fDPhi= rhs.fDPhi; fZHalfLength= rhs.fZHalfLength;
264 fInnerStereo= rhs.fInnerStereo; fOuterStereo= rhs.fOuterStereo;
265 fTanInnerStereo= rhs.fTanInnerStereo; fTanOuterStereo= rhs.fTanOuterStereo;
266 fKappa= rhs.fKappa; fInnerRadius2= rhs.fInnerRadius2;
267 fOuterRadius2= rhs.fOuterRadius2; fTanInnerStereo2= rhs.fTanInnerStereo2;
268 fTanOuterStereo2= rhs.fTanOuterStereo2;
269 fLowerEndcap= fUpperEndcap= fLatterTwisted= fFormerTwisted= 0;
270 fInnerHype= fOuterHype= 0;
271 fCubicVolume= rhs.fCubicVolume; fSurfaceArea= rhs.fSurfaceArea;
272 fLastInside= rhs.fLastInside; fLastNormal= rhs.fLastNormal;
273 fLastDistanceToIn= rhs.fLastDistanceToIn;
274 fLastDistanceToOut= rhs.fLastDistanceToOut;
275 fLastDistanceToInWithV= rhs.fLastDistanceToInWithV;
276 fLastDistanceToOutWithV= rhs.fLastDistanceToOutWithV;
278 for (
auto i=0; i<2; ++i)
280 fEndZ[i] = rhs.fEndZ[i];
281 fEndInnerRadius[i] = rhs.fEndInnerRadius[i];
282 fEndOuterRadius[i] = rhs.fEndOuterRadius[i];
283 fEndPhi[i] = rhs.fEndPhi[i];
284 fEndZ2[i] = rhs.fEndZ2[i];
288 fRebuildPolyhedron =
false;
289 delete fpPolyhedron; fpPolyhedron =
nullptr;
303 "G4TwistedTubs does not support Parameterisation.");
325 if (dphi <= 0 || totalphi >= CLHEP::twopi)
327 pMin.
set(-rmax,-rmax, zmin);
328 pMax.
set( rmax, rmax, zmax);
334 pMin.
set(vmin.
x(), vmin.
y(), zmin);
335 pMax.
set(vmax.
x(), vmax.
y(), zmax);
340 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
342 std::ostringstream message;
343 message <<
"Bad bounding box (min >= max) for solid: "
345 <<
"\npMin = " << pMin
346 <<
"\npMax = " << pMax;
347 G4Exception(
"G4TwistedTubs::BoundingLimits()",
"GeomMgt0001",
387 if (fLastInside.p == p)
389 return fLastInside.inside;
394 tmpinside =
const_cast<EInside*
>(&(fLastInside.inside));
395 tmpp->
set(p.
x(), p.
y(), p.
z());
402 if ((outerhypearea ==
kOutside) || (distanceToOut < -halftol))
412 if (distanceToOut <= halftol)
422 return fLastInside.inside;
437 if (fLastNormal.p == p)
439 return fLastNormal.vec;
447 tmpp->
set(p.
x(), p.
y(), p.
z());
452 surfaces[0] = fLatterTwisted;
453 surfaces[1] = fFormerTwisted;
454 surfaces[2] = fInnerHype;
455 surfaces[3] = fOuterHype;
456 surfaces[4] = fLowerEndcap;
457 surfaces[5] = fUpperEndcap;
462 for (
auto i=0; i<6; ++i)
465 if (tmpdistance < distance)
467 distance = tmpdistance;
473 tmpsurface[0] = surfaces[besti];
474 *tmpnormal = tmpsurface[0]->
GetNormal(bestxx,
true);
476 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());
532 return fLastDistanceToInWithV.value;
546 surfaces[0] = fLowerEndcap;
547 surfaces[1] = fUpperEndcap;
548 surfaces[2] = fLatterTwisted;
549 surfaces[3] = fFormerTwisted;
550 surfaces[4] = fInnerHype;
551 surfaces[5] = fOuterHype;
555 for (
auto i=0; i<6; ++i)
558 if (tmpdistance < distance)
560 distance = tmpdistance;
566 return fLastDistanceToInWithV.value;
584 if (fLastDistanceToIn.p == p)
586 return fLastDistanceToIn.value;
591 tmpdist =
const_cast<G4double*
>(&(fLastDistanceToIn.value));
592 tmpp->
set(p.
x(), p.
y(), p.
z());
608 return fLastDistanceToIn.value;
617 surfaces[0] = fLowerEndcap;
618 surfaces[1] = fUpperEndcap;
619 surfaces[2] = fLatterTwisted;
620 surfaces[3] = fFormerTwisted;
621 surfaces[4] = fInnerHype;
622 surfaces[5] = fOuterHype;
626 for (
auto i=0; i<6; ++i)
629 if (tmpdistance < distance)
631 distance = tmpdistance;
636 return fLastDistanceToIn.value;
640 G4Exception(
"G4TwistedTubs::DistanceToIn(p)",
"GeomSolids0003",
670 if ((fLastDistanceToOutWithV.p == p) && (fLastDistanceToOutWithV.vec == v) )
672 return fLastDistanceToOutWithV.value;
676 tmpp =
const_cast<G4ThreeVector*
>(&(fLastDistanceToOutWithV.p));
677 tmpv =
const_cast<G4ThreeVector*
>(&(fLastDistanceToOutWithV.vec));
678 tmpdist =
const_cast<G4double*
>(&(fLastDistanceToOutWithV.value));
679 tmpp->
set(p.
x(), p.
y(), p.
z());
680 tmpv->
set(v.
x(), v.
y(), v.
z());
705 *norm = (blockedsurface->
GetNormal(p,
true));
709 return fLastDistanceToOutWithV.value;
723 surfaces[0] = fLatterTwisted;
724 surfaces[1] = fFormerTwisted;
725 surfaces[2] = fInnerHype;
726 surfaces[3] = fOuterHype;
727 surfaces[4] = fLowerEndcap;
728 surfaces[5] = fUpperEndcap;
733 for (
auto i=0; i<6; ++i)
736 if (tmpdistance < distance)
738 distance = tmpdistance;
748 *norm = (surfaces[besti]->
GetNormal(p,
true));
755 return fLastDistanceToOutWithV.value;
774 if (fLastDistanceToOut.p == p)
776 return fLastDistanceToOut.value;
781 tmpdist =
const_cast<G4double*
>(&(fLastDistanceToOut.value));
782 tmpp->
set(p.
x(), p.
y(), p.
z());
799 return fLastDistanceToOut.value;
808 surfaces[0] = fLatterTwisted;
809 surfaces[1] = fFormerTwisted;
810 surfaces[2] = fInnerHype;
811 surfaces[3] = fOuterHype;
812 surfaces[4] = fLowerEndcap;
813 surfaces[5] = fUpperEndcap;
817 for (
auto i=0; i<6; ++i)
820 if (tmpdistance < distance)
822 distance = tmpdistance;
828 return fLastDistanceToOut.value;
832 G4Exception(
"G4TwistedTubs::DistanceToOut(p)",
"GeomSolids0003",
848 G4long oldprc = os.precision(16);
849 os <<
"-----------------------------------------------------------\n"
850 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
851 <<
" ===================================================\n"
852 <<
" Solid type: G4TwistedTubs\n"
854 <<
" -ve end Z : " << fEndZ[0]/mm <<
" mm \n"
855 <<
" +ve end Z : " << fEndZ[1]/mm <<
" mm \n"
856 <<
" inner end radius(-ve z): " << fEndInnerRadius[0]/mm <<
" mm \n"
857 <<
" inner end radius(+ve z): " << fEndInnerRadius[1]/mm <<
" mm \n"
858 <<
" outer end radius(-ve z): " << fEndOuterRadius[0]/mm <<
" mm \n"
859 <<
" outer end radius(+ve z): " << fEndOuterRadius[1]/mm <<
" mm \n"
860 <<
" inner radius (z=0) : " << fInnerRadius/mm <<
" mm \n"
861 <<
" outer radius (z=0) : " << fOuterRadius/mm <<
" mm \n"
862 <<
" twisted angle : " << fPhiTwist/degree <<
" degrees \n"
863 <<
" inner stereo angle : " << fInnerStereo/degree <<
" degrees \n"
864 <<
" outer stereo angle : " << fOuterStereo/degree <<
" degrees \n"
865 <<
" phi-width of a piece : " << fDPhi/degree <<
" degrees \n"
866 <<
"-----------------------------------------------------------\n";
867 os.precision(oldprc);
902 G4double absPhiTwist = std::abs(fPhiTwist);
903 G4double dA = std::max(fDPhi,absPhiTwist);
909 const G4int nnodes = 4*(k-1)*(n-2) + 2*k*k ;
910 const G4int nfaces = 4*(k-1)*(n-1) + 2*(k-1)*(k-1) ;
914 typedef G4int G4int4[4];
915 G4double3* xyz =
new G4double3[nnodes];
916 G4int4* faces =
new G4int4[nfaces] ;
917 fLowerEndcap->
GetFacets(k,k,xyz,faces,0) ;
918 fUpperEndcap->
GetFacets(k,k,xyz,faces,1) ;
920 fFormerTwisted->
GetFacets(k,n,xyz,faces,3) ;
922 fLatterTwisted->
GetFacets(k,n,xyz,faces,5) ;
937 if (fpPolyhedron ==
nullptr ||
938 fRebuildPolyhedron ||
945 fRebuildPolyhedron =
false;
954void G4TwistedTubs::CreateSurfaces()
962 fEndInnerRadius, fEndOuterRadius,
963 fDPhi, fEndPhi, fEndZ, -1) ;
966 fEndInnerRadius, fEndOuterRadius,
967 fDPhi, fEndPhi, fEndZ, 1) ;
970 rotHalfDPhi.
rotateZ(0.5*fDPhi);
973 fEndInnerRadius, fEndOuterRadius,
974 fDPhi, fEndPhi, fEndZ,
975 fInnerRadius, fOuterRadius, fKappa,
978 fEndInnerRadius, fEndOuterRadius,
979 fDPhi, fEndPhi, fEndZ,
980 fInnerRadius, fOuterRadius, fKappa,
984 fEndInnerRadius, fEndOuterRadius,
985 fDPhi, fEndPhi, fEndZ,
986 fInnerRadius, fOuterRadius,fKappa,
987 fTanInnerStereo, fTanOuterStereo, -1) ;
989 fEndInnerRadius, fEndOuterRadius,
990 fDPhi, fEndPhi, fEndZ,
991 fInnerRadius, fOuterRadius,fKappa,
992 fTanInnerStereo, fTanOuterStereo, 1) ;
998 fOuterHype, fFormerTwisted);
1000 fOuterHype, fFormerTwisted);
1002 fOuterHype, fUpperEndcap);
1004 fOuterHype, fUpperEndcap);
1006 fFormerTwisted, fUpperEndcap);
1008 fFormerTwisted, fUpperEndcap);
1033 if (fCubicVolume == 0.)
1046 fCubicVolume = (2.*(Z1 - Z0)*(Aout + Ain)*(Aout - Ain)
1047 + Z1*(R1out + R1in)*(R1out - R1in)
1048 - Z0*(R0out + R0in)*(R0out - R0in))*DPhi/6.;
1050 return fCubicVolume;
1059 if (z == 0)
return 0.;
1068 G4double k = std::sqrt(aa + cc)/cc;
1070 area = 0.5*a*(h*std::sqrt(1. + kh*kh) + std::asinh(kh)/k);
1081 if (
GetDPhi() >= CLHEP::twopi || r <= 0 || z == 0)
return 0.;
1092 G4double sqroot = std::sqrt(pp + qq + 1);
1094 0.5*p*(
pp + 3.)*std::atanh(q/sqroot) +
1095 0.5*q*(qq + 3.)*std::atanh(p/sqroot) +
1096 std::atan(sqroot/(pq)) - CLHEP::halfpi)*h*a/(3.*pq);
1106 if (fSurfaceArea == 0.)
1118 G4double base0 = 0.5*dphi*(Rout0*Rout0 - Rinn0*Rinn0);
1119 G4double inner0 = GetLateralArea(Ainn, Rinn0, z0);
1120 G4double outer0 = GetLateralArea(Aout, Rout0, z0);
1122 GetPhiCutArea(Aout, Rout0, z0) - GetPhiCutArea(Ainn, Rinn0, z0);
1128 if (std::abs(z0) != std::abs(z1))
1130 base1 = 0.5*dphi*(Rout1*Rout1 - Rinn1*Rinn1);
1131 inner1 = GetLateralArea(Ainn, Rinn1, z1);
1132 outer1 = GetLateralArea(Aout, Rout1, z1);
1134 GetPhiCutArea(Aout, Rout1, z1) - GetPhiCutArea(Ainn, Rinn1, z1);
1136 fSurfaceArea = base0 + base1 +
1138 (inner0 + inner1 + outer0 + outer1 + 2.*(cut0 + cut1)) :
1139 std::abs(inner0 - inner1 + outer0 - outer1 + 2.*(cut0 - cut1)));
1141 return fSurfaceArea;
1150 G4double z = G4RandFlat::shoot(fEndZ[0],fEndZ[1]);
1162 G4double chose = G4RandFlat::shoot(0.,a1 + a2 + a3 + a4 + a5 + a6) ;
1169 phi = G4RandFlat::shoot(phimin,phimax) ;
1174 else if ( (chose >= a1) && (chose < a1 + a2 ) )
1179 phi = G4RandFlat::shoot(phimin,phimax) ;
1184 else if ( (chose >= a1 + a2 ) && (chose < a1 + a2 + a3 ) )
1189 x = G4RandFlat::shoot(xmin,xmax) ;
1194 else if ( (chose >= a1 + a2 + a3 ) && (chose < a1 + a2 + a3 + a4 ) )
1199 x = G4RandFlat::shoot(xmin,xmax) ;
1203 else if( (chose >= a1 + a2 + a3 + a4 )&&(chose < a1 + a2 + a3 + a4 + a5 ) )
1207 r = std::sqrt(G4RandFlat::shoot()*(
sqr(rmax)-
sqr(rmin))+
sqr(rmin));
1211 phi = G4RandFlat::shoot(phimin,phimax) ;
1219 r = rmin + (rmax-rmin)*std::sqrt(G4RandFlat::shoot());
1223 phi = G4RandFlat::shoot(phimin,phimax) ;
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define G4MUTEX_INITIALIZER
void set(double x, double y, double z)
HepRotation & rotateZ(double delta)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
G4double GetOuterRadius() const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
G4ThreeVector GetPointOnSurface() const
G4double GetZHalfLength() const
G4double GetPhiTwist() const
G4double GetSurfaceArea()
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4Polyhedron * CreatePolyhedron() const
void ComputeDimensions(G4VPVParameterisation *, const G4int, const G4VPhysicalVolume *)
G4TwistedTubs & operator=(const G4TwistedTubs &rhs)
G4double GetEndInnerRadius() const
G4double GetEndOuterRadius() const
G4double GetCubicVolume()
G4Polyhedron * GetPolyhedron() const
G4GeometryType GetEntityType() const
G4double GetEndPhi(G4int i) const
G4TwistedTubs(const G4String &pname, G4double twistedangle, G4double endinnerrad, G4double endouterrad, G4double halfzlen, G4double dphi)
EInside Inside(const G4ThreeVector &p) const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcnorm=false, G4bool *validnorm=nullptr, G4ThreeVector *n=nullptr) const
G4VisExtent GetExtent() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4double GetEndZ(G4int i) const
G4double GetInnerRadius() const
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
std::ostream & StreamInfo(std::ostream &os) 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
static G4int GetNumberOfRotationSteps()
G4int createPolyhedron(G4int Nnodes, G4int Nfaces, const G4double xyz[][3], const G4int faces[][4])