58 using namespace CLHEP;
70 :
G4OTubs(pName, pRMin, pRMax, pDz, pSPhi, pDPhi),
85 if ( ( !pLowNorm.x()) && ( !pLowNorm.y())
86 && ( !pHighNorm.x()) && (!pHighNorm.y()) )
88 std::ostringstream message;
89 message <<
"Inexisting Low/High Normal to Z plane or Parallel to Z."
91 <<
"Normals to Z plane are (" << pLowNorm <<
" and "
92 << pHighNorm <<
") in solid: " <<
GetName();
93 G4Exception(
"G4CutTubs::G4CutTubs()",
"GeomSolids1001",
99 if (pLowNorm.mag2() == 0.) { pLowNorm.setZ(-1.); }
100 if (pHighNorm.mag2()== 0.) { pHighNorm.setZ(1.); }
105 if (pLowNorm.mag2() != 1.) { pLowNorm = pLowNorm.unit(); }
106 if (pHighNorm.mag2()!= 1.) { pHighNorm = pHighNorm.unit(); }
110 if( (pLowNorm.mag2() != 0.) && (pHighNorm.mag2()!= 0. ) )
112 if( ( pLowNorm.z()>= 0. ) || ( pHighNorm.z() <= 0.))
114 std::ostringstream message;
115 message <<
"Invalid Low or High Normal to Z plane; "
116 "has to point outside Solid." <<
G4endl
117 <<
"Invalid Norm to Z plane (" << pLowNorm <<
" or "
118 << pHighNorm <<
") in solid: " <<
GetName();
119 G4Exception(
"G4CutTubs::G4CutTubs()",
"GeomSolids0002",
151 halfCarTolerance(0.), halfRadTolerance(0.), halfAngTolerance(0.)
168 :
G4OTubs(rhs), fLowNorm(rhs.fLowNorm), fHighNorm(rhs.fHighNorm),
169 fPhiFullCutTube(rhs.fPhiFullCutTube),
170 halfCarTolerance(rhs.halfCarTolerance),
171 halfRadTolerance(rhs.halfRadTolerance),
172 halfAngTolerance(rhs.halfAngTolerance)
184 if (
this == &rhs) {
return *
this; }
216 xynorm = std::sqrt(norm.x()*norm.x()+norm.y()*norm.y());
217 znorm = std::abs(norm.z());
218 G4double zmin = -(dz + rmax*xynorm/znorm);
222 xynorm = std::sqrt(norm.x()*norm.x()+norm.y()*norm.y());
223 znorm = std::abs(norm.z());
224 G4double zmax = dz + rmax*xynorm/znorm;
235 pMin.set(vmin.x(),vmin.y(), zmin);
236 pMax.set(vmax.x(),vmax.y(), zmax);
240 pMin.set(-rmax,-rmax, zmin);
241 pMax.set( rmax, rmax, zmax);
246 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
248 std::ostringstream message;
249 message <<
"Bad bounding box (min >= max) for solid: "
251 <<
"\npMin = " << pMin
252 <<
"\npMax = " << pMax;
277 if (
true)
return bbox.
CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
281 return exist = (pMin < pMax) ?
true :
false;
293 const G4int NSTEPS = 24;
295 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-
deg)/astep) + 1;
298 G4double sinHalf = std::sin(0.5*ang);
299 G4double cosHalf = std::cos(0.5*ang);
300 G4double sinStep = 2.*sinHalf*cosHalf;
301 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
306 if (rmin == 0 && dphi ==
twopi)
312 for (
G4int k=0; k<NSTEPS; ++k)
314 baseA[k].set(rext*cosCur,rext*sinCur,zmin);
315 baseB[k].set(rext*cosCur,rext*sinCur,zmax);
318 sinCur = sinCur*cosStep + cosCur*sinStep;
319 cosCur = cosCur*cosStep - sinTmp*sinStep;
321 std::vector<const G4ThreeVectorList *> polygons(2);
322 polygons[0] = &baseA;
323 polygons[1] = &baseB;
333 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
334 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
338 for (
G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
339 pols[0][0].set(rmin*cosStart,rmin*sinStart,zmax);
340 pols[0][1].set(rmin*cosStart,rmin*sinStart,zmin);
341 pols[0][2].set(rmax*cosStart,rmax*sinStart,zmin);
342 pols[0][3].set(rmax*cosStart,rmax*sinStart,zmax);
343 for (
G4int k=1; k<ksteps+1; ++k)
345 pols[k][0].set(rmin*cosCur,rmin*sinCur,zmax);
346 pols[k][1].set(rmin*cosCur,rmin*sinCur,zmin);
347 pols[k][2].set(rext*cosCur,rext*sinCur,zmin);
348 pols[k][3].set(rext*cosCur,rext*sinCur,zmax);
351 sinCur = sinCur*cosStep + cosCur*sinStep;
352 cosCur = cosCur*cosStep - sinTmp*sinStep;
354 pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd,zmax);
355 pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,zmin);
356 pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,zmin);
357 pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd,zmax);
360 std::vector<const G4ThreeVectorList *> polygons;
361 polygons.resize(ksteps+2);
362 for (
G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
394 r2 = p.x()*p.x() + p.y()*p.y() ;
400 if ( tolRMin < 0 ) { tolRMin = 0; }
402 if ( ((r2 < tolRMin*tolRMin) || (r2 > tolRMax*tolRMax))
403 && (r2 >=halfRadTolerance*halfRadTolerance) ) {
return kOutside; }
417 pPhi = std::atan2(p.y(),p.x()) ;
463 else { tolRMin = 0 ; }
465 if ( ((r2 <= tolRMin*tolRMin) || (r2 >= tolRMax*tolRMax))&&
482 G4int noSurfaces = 0;
484 G4double distZLow,distZHigh, distRMin, distRMax;
492 rho = std::sqrt(p.x()*p.x() + p.y()*p.y());
494 distRMin = std::fabs(rho -
fRMin);
495 distRMax = std::fabs(rho -
fRMax);
499 distZLow =std::fabs((p+vZ).dot(
fLowNorm));
503 distZHigh = std::fabs((p-vZ).dot(
fHighNorm));
509 pPhi = std::atan2(p.y(),p.x());
514 distSPhi = std::fabs(pPhi -
fSPhi);
560 if ( noSurfaces == 0 )
563 G4Exception(
"G4CutTubs::SurfaceNormal(p)",
"GeomSolids1002",
566 G4cout<<
"G4CutTubs::SN ( "<<p.x()<<
", "<<p.y()<<
", "<<p.z()<<
" ); "
568 G4cout.precision(oldprc) ;
572 else if ( noSurfaces == 1 ) { norm = sumnorm; }
573 else { norm = sumnorm.unit(); }
589 G4double distRMin, distRMax, distSPhi, distEPhi, distMin ;
592 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
594 distRMin = std::fabs(rho -
fRMin) ;
595 distRMax = std::fabs(rho -
fRMax) ;
599 distZLow =std::fabs((p+vZ).dot(
fLowNorm));
603 distZHigh = std::fabs((p-vZ).dot(
fHighNorm));
606 if (distRMin < distRMax)
608 if ( distZ < distRMin )
621 if ( distZ < distRMax )
634 phi = std::atan2(p.y(),p.x()) ;
636 if ( phi < 0 ) { phi +=
twopi; }
640 distSPhi = std::fabs(phi - (
fSPhi +
twopi))*rho ;
644 distSPhi = std::fabs(phi -
fSPhi)*rho ;
646 distEPhi = std::fabs(phi -
fSPhi -
fDPhi)*rho ;
648 if (distSPhi < distEPhi)
650 if ( distSPhi < distMin )
657 if ( distEPhi < distMin )
677 if ( distZHigh > distZLow ) { norm =
fHighNorm ; }
696 "Undefined side for valid surface normal to solid.");
736 G4double Dist, sd=0, xi, yi, zi, rho2, inum, iden, cosPsi, Comp,calf ;
770 if(sd < 0.0) { sd = 0.0; }
772 xi = p.x() + sd*v.x() ;
773 yi = p.y() + sd*v.y() ;
774 rho2 = xi*xi + yi*yi ;
778 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
785 iden = std::sqrt(rho2) ;
810 sd = -distZHigh/calf;
812 if(sd < 0.0) { sd = 0.0; }
814 xi = p.x() + sd*v.x() ;
815 yi = p.y() + sd*v.y() ;
816 rho2 = xi*xi + yi*yi ;
820 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
827 iden = std::sqrt(rho2) ;
858 t1 = 1.0 - v.z()*v.z() ;
859 t2 = p.x()*v.x() + p.y()*v.y() ;
860 t3 = p.x()*p.x() + p.y()*p.y() ;
866 if ((t3 >= tolORMax2) && (t2<0))
875 sd = c/(-b+std::sqrt(d));
880 G4double fTerm = sd-std::fmod(sd,dRmax);
885 zi = p.z() + sd*v.z() ;
886 xi = p.x() + sd*v.x() ;
887 yi = p.y() + sd*v.y() ;
902 xi = p.x() + sd*v.x() ;
903 yi = p.y() + sd*v.y() ;
916 if ((t3 > tolIRMin2) && (t2 < 0)
924 iden = std::sqrt(t3) ;
945 snxt = c/(-b+std::sqrt(d));
965 c = t3 - fRMax*
fRMax;
976 snxt= c/(-b+std::sqrt(d));
999 sd =( b > 0. )? c/(-b - std::sqrt(d)) : (-b + std::sqrt(d));
1004 if (sd < 0.0) { sd = 0.0; }
1007 G4double fTerm = sd-std::fmod(sd,dRmax);
1010 zi = p.z() + sd*v.z() ;
1011 xi = p.x() + sd*v.x() ;
1012 yi = p.y() + sd*v.y() ;
1068 if ( sd < 0 ) { sd = 0.0; }
1069 zi = p.z() + sd*v.z() ;
1070 xi = p.x() + sd*v.x() ;
1071 yi = p.y() + sd*v.y() ;
1078 rho2 = xi*xi + yi*yi ;
1079 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1080 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1083 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1112 if ( sd < 0 ) { sd = 0; }
1113 zi = p.z() + sd*v.z() ;
1114 xi = p.x() + sd*v.x() ;
1115 yi = p.y() + sd*v.y() ;
1122 xi = p.x() + sd*v.x() ;
1123 yi = p.y() + sd*v.y() ;
1124 rho2 = xi*xi + yi*yi ;
1125 if ( ( (rho2 >= tolIRMin2) && (rho2 <= tolIRMax2) )
1126 || ( (rho2 > tolORMin2) && (rho2 < tolIRMin2)
1129 || ( (rho2 > tolIRMax2) && (rho2 < tolORMax2)
1180 G4double safRMin,safRMax,safZLow,safZHigh,safePhi,safe,rho,cosPsi;
1185 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
1187 safRMin =
fRMin- rho ;
1188 safRMax = rho -
fRMax ;
1202 if ( safRMin > safe ) { safe = safRMin; }
1203 if ( safRMax> safe ) { safe = safRMax; }
1213 if ( cosPsi < std::cos(
fDPhi*0.5) )
1225 if ( safePhi > safe ) { safe = safePhi; }
1228 if ( safe < 0 ) { safe = 0; }
1246 G4double deltaR, t1, t2, t3, b, c,
d2, roMin2 ;
1247 G4double distZLow,distZHigh,calfH,calfL;
1252 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
1272 snxt = -distZHigh/calfH ;
1290 sz = -distZLow/calfL ;
1307 if((calfH<=0)&&(calfL<=0))
1323 t1 = 1.0 - v.z()*v.z() ;
1324 t2 = p.x()*v.x() + p.y()*v.y() ;
1325 t3 = p.x()*p.x() + p.y()*p.y() ;
1328 else { roi2 = snxt*snxt*t1 + 2*snxt*t2 + t3; }
1348 if( d2 >= 0 ) { srd = c/( -b - std::sqrt(d2)); }
1367 roMin2 = t3 - t2*t2/t1 ;
1383 srd = c/(-b+std::sqrt(d2));
1388 if ( calcNorm ) { *validNorm =
false; }
1399 srd = -b + std::sqrt(d2) ;
1423 srd = -b + std::sqrt(d2) ;
1445 vphi = std::atan2(v.y(),v.x()) ;
1451 if ( p.x() || p.y() )
1474 sphi = pDistS/compS ;
1478 xi = p.x() + sphi*v.x() ;
1479 yi = p.y() + sphi*v.y() ;
1519 sphi2 = pDistE/compE ;
1525 xi = p.x() + sphi2*v.x() ;
1526 yi = p.y() + sphi2*v.y() ;
1537 else { sphi = 0.0 ; }
1548 else { sphi = 0.0 ; }
1594 xi = p.x() + snxt*v.x() ;
1595 yi = p.y() + snxt*v.y() ;
1601 *validNorm = false ;
1612 *validNorm = false ;
1624 *validNorm = false ;
1641 std::ostringstream message;
1642 G4int oldprc = message.precision(16);
1643 message <<
"Undefined side for valid surface normal to solid."
1645 <<
"Position:" << G4endl << G4endl
1646 <<
"p.x() = " << p.x()/
mm <<
" mm" << G4endl
1647 <<
"p.y() = " << p.y()/
mm <<
" mm" << G4endl
1648 <<
"p.z() = " << p.z()/
mm <<
" mm" << G4endl << G4endl
1649 <<
"Direction:" << G4endl << G4endl
1650 <<
"v.x() = " << v.x() << G4endl
1651 <<
"v.y() = " << v.y() << G4endl
1652 <<
"v.z() = " << v.z() << G4endl << G4endl
1653 <<
"Proposed distance :" << G4endl << G4endl
1654 <<
"snxt = " << snxt/
mm <<
" mm" <<
G4endl ;
1655 message.precision(oldprc) ;
1656 G4Exception(
"G4CutTubs::DistanceToOut(p,v,..)",
"GeomSolids1002",
1671 G4double safRMin,safRMax,safZLow,safZHigh,safePhi,safe,rho;
1674 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) ;
1676 safRMin = rho -
fRMin ;
1677 safRMax =
fRMax - rho ;
1683 safZLow = std::fabs((p+vZ).dot(
fLowNorm));
1687 safZHigh = std::fabs((p-vZ).dot(
fHighNorm));
1690 if ( safRMin < safe ) { safe = safRMin; }
1691 if ( safRMax< safe ) { safe = safRMax; }
1705 if (safePhi < safe) { safe = safePhi ; }
1707 if ( safe < 0 ) { safe = 0; }
1736 G4int oldprc = os.precision(16);
1737 os <<
"-----------------------------------------------------------\n"
1738 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1739 <<
" ===================================================\n"
1740 <<
" Solid type: G4CutTubs\n"
1741 <<
" Parameters: \n"
1742 <<
" inner radius : " <<
fRMin/
mm <<
" mm \n"
1743 <<
" outer radius : " <<
fRMax/
mm <<
" mm \n"
1744 <<
" half length Z: " <<
fDz/
mm <<
" mm \n"
1745 <<
" starting phi : " <<
fSPhi/
degree <<
" degrees \n"
1746 <<
" delta phi : " <<
fDPhi/
degree <<
" degrees \n"
1747 <<
" low Norm : " <<
fLowNorm <<
" \n"
1749 <<
"-----------------------------------------------------------\n";
1750 os.precision(oldprc);
1761 G4double xRand, yRand, zRand, phi, cosphi, sinphi, chose,
1762 aOne, aTwo, aThr, aFou;
1771 cosphi = std::cos(phi);
1772 sinphi = std::sin(phi);
1780 if( (chose >=0) && (chose < aOne) )
1782 xRand = fRMax*cosphi;
1783 yRand = fRMax*sinphi;
1788 else if( (chose >= aOne) && (chose < aOne + aTwo) )
1790 xRand = fRMin*cosphi;
1791 yRand = fRMin*sinphi;
1796 else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
1798 xRand = rRand*cosphi;
1799 yRand = rRand*sinphi;
1803 else if( (chose >= aOne + aTwo + aThr) && (chose < aOne + aTwo + 2.*aThr) )
1805 xRand = rRand*cosphi;
1806 yRand = rRand*sinphi;
1810 else if( (chose >= aOne + aTwo + 2.*aThr)
1811 && (chose < aOne + aTwo + 2.*aThr + aFou) )
1813 xRand = rRand*std::cos(
fSPhi);
1814 yRand = rRand*std::sin(
fSPhi);
1841 typedef G4int G4int4[4];
1845 G4int nn=ph1->GetNoVertices();
1846 G4int nf=ph1->GetNoFacets();
1847 G4double3* xyz =
new G4double3[
nn];
1848 G4int4* faces =
new G4int4[nf] ;
1852 xyz[i][0]=ph1->GetVertex(i+1).x();
1853 xyz[i][1]=ph1->GetVertex(i+1).y();
1854 G4double tmpZ=ph1->GetVertex(i+1).z();
1871 for(
G4int i=0;i<nf;i++)
1873 ph1->GetFacet(i+1,n,iNodes,iEdge);
1876 faces[i][k]=iNodes[k];
1878 for(
G4int k=n;k<4;k++)
1883 ph->createPolyhedron(nn,nf,xyz,faces);
1900 G4double zXLow1,zXLow2,zYLow1,zYLow2;
1901 G4double zXHigh1,zXHigh2,zYHigh1,zYHigh2;
1911 if ( (zXLow1>zXHigh1) ||(zXLow2>zXHigh2)
1912 || (zYLow1>zYHigh1) ||(zYLow2>zYHigh2)) {
return true; }
1953 G4bool in_range_low =
false;
1954 G4bool in_range_hi =
false;
1959 if (phiLow<0) { phiLow+=
twopi; }
1961 if (ddp<0) { ddp +=
twopi; }
1964 xc =
fRMin*std::cos(phiLow);
1965 yc =
fRMin*std::sin(phiLow);
1967 xc =
fRMax*std::cos(phiLow);
1968 yc =
fRMax*std::sin(phiLow);
1970 if (in_range_low) { zmin =
std::min(zmin, z1); }
1972 in_range_low =
true;
1979 if (phiHigh<0) { phiHigh+=
twopi; }
1981 if (ddp<0) { ddp +=
twopi; }
1984 xc =
fRMin*std::cos(phiHigh);
1985 yc =
fRMin*std::sin(phiHigh);
1987 xc =
fRMax*std::cos(phiHigh);
1988 yc =
fRMax*std::sin(phiHigh);
1990 if (in_range_hi) { zmax =
std::min(zmax, z1); }
2021 for (i = 1; i < 4; i++)
2023 if(z[i] < z[i-1])z1=z[i];
2035 for (i = 1; i < 4; i++)
2037 if(z[4+i] > z[4+i-1]) { z1=z[4+i]; }
2040 if (in_range_hi) { zmax =
std::max(zmax, z1); }
G4double GetCosStartPhi() const
ThreeVector shoot(const G4int Ap, const G4int Af)
static constexpr double mm
static const G4double kInfinity
CLHEP::Hep3Vector G4ThreeVector
std::vector< ExP01TrackerHit * > a
G4double GetSinStartPhi() const
G4double GetRadiusInRing(G4double rmin, G4double rmax) const
G4ThreeVector GetLowNorm() const
void GetMaxMinZ(G4double &zmin, G4double &zmax) const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
virtual void AddSolid(const G4Box &)=0
static constexpr double twopi
EInside Inside(const G4ThreeVector &p) const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
G4CutTubs & operator=(const G4CutTubs &rhs)
G4OTubs & operator=(const G4OTubs &rhs)
G4GLOB_DLL std::ostream G4cout
static constexpr double degree
G4double GetRadialTolerance() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4double GetSinEndPhi() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
std::ostream & StreamInfo(std::ostream &os) const
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
std::vector< G4ThreeVector > G4ThreeVectorList
G4double GetZHalfLength() const
G4double halfRadTolerance
G4Polyhedron * CreatePolyhedron() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
G4double GetOuterRadius() const
G4bool IsCrossingCutPlanes() const
G4GeometryType GetEntityType() const
T max(const T t1, const T t2)
brief Return the largest of the two arguments
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4double halfCarTolerance
G4double GetCosEndPhi() const
G4ThreeVector GetHighNorm() const
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
G4double GetInnerRadius() const
CLHEP::Hep2Vector G4TwoVector
static constexpr double pi
G4double halfAngTolerance
void Extent(G4ThreeVector &pMin, G4ThreeVector &pMax) const
G4double GetDeltaPhiAngle() const
G4Polyhedron * CreatePolyhedron() const
static constexpr double deg
G4ThreeVector GetPointOnSurface() const
G4double GetAngularTolerance() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
static G4GeometryTolerance * GetInstance()
G4CutTubs(const G4String &pName, G4double pRMin, G4double pRMax, G4double pDz, G4double pSPhi, G4double pDPhi, G4ThreeVector pLowNorm, G4ThreeVector pHighNorm)
G4double GetCutZ(const G4ThreeVector &p) const