Geant4 Cross Reference |
>> 1 // This code implementation is the intellectual property of >> 2 // the GEANT4 collaboration. 1 // 3 // 2 // ******************************************* << 4 // By copying, distributing or modifying the Program (or any work 3 // * License and Disclaimer << 5 // based on the Program) you indicate your acceptance of this statement, 4 // * << 6 // and all its terms. 5 // * The Geant4 software is copyright of th << 7 // 6 // * the Geant4 Collaboration. It is provided << 8 // $Id: G4Cons.cc,v 1.16 2000/11/20 17:57:58 gcosmo Exp $ 7 // * conditions of the Geant4 Software License << 9 // GEANT4 tag $Name: geant4-03-00 $ 8 // * LICENSE and available at http://cern.ch/ << 10 // 9 // * include a list of copyright holders. << 11 // class G4Cons 10 // * << 11 // * Neither the authors of this software syst << 12 // * institutes,nor the agencies providing fin << 13 // * work make any representation or warran << 14 // * regarding this software system or assum << 15 // * use. Please see the license in the file << 16 // * for the full disclaimer and the limitatio << 17 // * << 18 // * This code implementation is the result << 19 // * technical work of the GEANT4 collaboratio << 20 // * By using, copying, modifying or distri << 21 // * any work based on the software) you ag << 22 // * use in resulting scientific publicati << 23 // * acceptance of all terms of the Geant4 Sof << 24 // ******************************************* << 25 // 12 // 26 // Implementation for G4Cons class 13 // Implementation for G4Cons class 27 // 14 // 28 // ~1994 P.Kent: Created, as main part of t << 15 // History: 29 // 13.09.96 V.Grichine: Review and final modif << 16 // 30 // 03.05.05 V.Grichine: SurfaceNormal(p) accor << 17 // 05.10.00 V. Grichine bugs fixed in Distance ToIn(p,v) 31 // 12.10.09 T.Nikitina: Added to DistanceToIn( << 18 // 17.08.00 V.Grichine, if one and only one Rmin=0, it'll be 1e3*kRadTolerance 32 // case of point on surfa << 19 // 08.08.00 V.Grichine, more stable roots of 2-equation in DistanceToOut(p,v,...) 33 // 03.10.16 E.Tcherniaev: use G4BoundingEnvelo << 20 // 06.03.00 V.Grichine, modifications in DistanceToOut(p,v,...) 34 // removed CreateRotatedV << 21 // 18.11.99 V.Grichine side = kNull initialisation in DistanceToOut(p,v,...) 35 // ------------------------------------------- << 22 // 28.04.99 V. Grichine bugs fixed in Distance ToOut(p,v,...) and >> 23 // Distance ToIn(p,v) >> 24 // 09.10.98 V. Grichine modifications in Distance ToOut(p,v,...) >> 25 // 13.09.96 V. Grichine: final modifications to commit >> 26 // ~1994 P. Kent: main part of geometry functions 36 27 37 #include "G4Cons.hh" 28 #include "G4Cons.hh" 38 29 39 #if !defined(G4GEOM_USE_UCONS) << 40 << 41 #include "G4GeomTools.hh" << 42 #include "G4VoxelLimits.hh" 30 #include "G4VoxelLimits.hh" 43 #include "G4AffineTransform.hh" 31 #include "G4AffineTransform.hh" 44 #include "G4BoundingEnvelope.hh" << 45 #include "G4GeometryTolerance.hh" << 46 32 47 #include "G4VPVParameterisation.hh" 33 #include "G4VPVParameterisation.hh" 48 34 49 #include "meshdefs.hh" 35 #include "meshdefs.hh" 50 36 51 #include "Randomize.hh" << 52 << 53 #include "G4VGraphicsScene.hh" 37 #include "G4VGraphicsScene.hh" >> 38 #include "G4Polyhedron.hh" >> 39 #include "G4NURBS.hh" >> 40 #include "G4NURBSbox.hh" 54 41 55 using namespace CLHEP; << 56 << 57 ////////////////////////////////////////////// 42 //////////////////////////////////////////////////////////////////////// 58 // 43 // 59 // Private enums: Not for external use << 44 // Private enum: Not for external use - used by distanceToOut 60 45 61 namespace << 46 enum ESide {kNull,kRMin,kRMax,kSPhi,kEPhi,kPZ,kMZ}; 62 { << 63 // used by DistanceToOut() << 64 // << 65 enum ESide {kNull,kRMin,kRMax,kSPhi,kEPhi,kP << 66 << 67 // used by ApproxSurfaceNormal() << 68 // << 69 enum ENorm {kNRMin,kNRMax,kNSPhi,kNEPhi,kNZ} << 70 } << 71 << 72 ////////////////////////////////////////////// << 73 // << 74 // constructor - check parameters, convert ang << 75 // - note if pDPhi>2PI then reset << 76 47 77 G4Cons::G4Cons( const G4String& pName, << 48 // used by normal 78 G4double pRmin1, G4doub << 79 G4double pRmin2, G4doub << 80 G4double pDz, << 81 G4double pSPhi, G4double << 82 : G4CSGSolid(pName), fRmin1(pRmin1), fRmin2( << 83 fRmax1(pRmax1), fRmax2(pRmax2), fDz(pDz), << 84 { << 85 kRadTolerance = G4GeometryTolerance::GetInst << 86 kAngTolerance = G4GeometryTolerance::GetInst << 87 49 88 halfCarTolerance=kCarTolerance*0.5; << 50 enum ENorm {kNRMin,kNRMax,kNSPhi,kNEPhi,kNZ}; 89 halfRadTolerance=kRadTolerance*0.5; << 90 halfAngTolerance=kAngTolerance*0.5; << 91 << 92 // Check z-len << 93 // << 94 if ( pDz < 0 ) << 95 { << 96 std::ostringstream message; << 97 message << "Invalid Z half-length for Soli << 98 << " hZ = " << pDz; << 99 G4Exception("G4Cons::G4Cons()", "GeomSolid << 100 FatalException, message); << 101 } << 102 << 103 // Check radii << 104 // << 105 if (((pRmin1>=pRmax1) || (pRmin2>=pRmax2) || << 106 { << 107 std::ostringstream message; << 108 message << "Invalid values of radii for So << 109 << " pRmin1 = " << pRmin1 < << 110 << ", pRmax1 = " << pRmax1 << ", p << 111 G4Exception("G4Cons::G4Cons()", "GeomSolid << 112 FatalException, message) ; << 113 } << 114 if( (pRmin1 == 0.0) && (pRmin2 > 0.0) ) { fR << 115 if( (pRmin2 == 0.0) && (pRmin1 > 0.0) ) { fR << 116 << 117 // Check angles << 118 // << 119 CheckPhiAngles(pSPhi, pDPhi); << 120 } << 121 51 122 ////////////////////////////////////////////// 52 /////////////////////////////////////////////////////////////////////// 123 // 53 // 124 // Fake default constructor - sets only member << 54 // Destructor 125 // for usage restri << 55 126 // << 56 G4Cons::~G4Cons() 127 G4Cons::G4Cons( __void__& a ) << 128 : G4CSGSolid(a) << 129 { 57 { >> 58 ; 130 } 59 } 131 60 132 ////////////////////////////////////////////// << 61 ////////////////////////////////////////////////////////////////////////// 133 // 62 // 134 // Destructor << 63 // constructor - check parameters, convert angles so 0<sphi+dpshi<=2_PI >> 64 // - note if pDPhi>2PI then reset to 2PI 135 65 136 G4Cons::~G4Cons() = default; << 66 G4Cons::G4Cons( const G4String& pName, >> 67 G4double pRmin1, G4double pRmax1, >> 68 G4double pRmin2, G4double pRmax2, >> 69 G4double pDz, >> 70 G4double pSPhi, G4double pDPhi) : G4CSGSolid(pName) >> 71 { >> 72 // Check z-len 137 73 138 ////////////////////////////////////////////// << 74 if ( pDz > 0 ) fDz = pDz ; 139 // << 75 else 140 // Copy constructor << 76 { >> 77 G4Exception("Error in G4Cons::G4Cons - invalid z half-length"); >> 78 } 141 79 142 G4Cons::G4Cons(const G4Cons&) = default; << 80 // Check radii 143 81 144 ////////////////////////////////////////////// << 82 if ( pRmin1 < pRmax1 && pRmin2 < pRmax2 && pRmin1 >= 0 && pRmin2 >= 0 ) 145 // << 83 { 146 // Assignment operator << 147 84 148 G4Cons& G4Cons::operator = (const G4Cons& rhs) << 85 fRmin1 = pRmin1 ; 149 { << 86 fRmax1 = pRmax1 ; 150 // Check assignment to self << 87 fRmin2 = pRmin2 ; 151 // << 88 fRmax2 = pRmax2 ; 152 if (this == &rhs) { return *this; } << 89 if( (pRmin1 == 0.0 && pRmin2 > 0.0) ) fRmin1 = 1e3*kRadTolerance ; 153 << 90 if( (pRmin2 == 0.0 && pRmin1 > 0.0) ) fRmin2 = 1e3*kRadTolerance ; 154 // Copy base class data << 91 } 155 // << 92 else G4Exception("Error in G4Cons::G4Cons - invalid radii") ; 156 G4CSGSolid::operator=(rhs); << 93 157 << 94 // Check angles 158 // Copy data << 159 // << 160 kRadTolerance = rhs.kRadTolerance; << 161 kAngTolerance = rhs.kAngTolerance; << 162 fRmin1 = rhs.fRmin1; fRmin2 = rhs.fRmin2; << 163 fRmax1 = rhs.fRmax1; fRmax2 = rhs.fRmax2; << 164 fDz = rhs.fDz; fSPhi = rhs.fSPhi; fDPhi = r << 165 sinCPhi = rhs.sinCPhi; cosCPhi = rhs.cosCPh << 166 cosHDPhiOT = rhs.cosHDPhiOT; cosHDPhiIT = r << 167 sinSPhi = rhs.sinSPhi; cosSPhi = rhs.cosSPh << 168 sinEPhi = rhs.sinEPhi; cosEPhi = rhs.cosEPh << 169 fPhiFullCone = rhs.fPhiFullCone; << 170 halfCarTolerance = rhs.halfCarTolerance; << 171 halfRadTolerance = rhs.halfRadTolerance; << 172 halfAngTolerance = rhs.halfAngTolerance; << 173 95 174 return *this; << 96 if ( pDPhi >= 2.0*M_PI ) >> 97 { >> 98 fDPhi=2*M_PI; >> 99 fSPhi=0; >> 100 } >> 101 else >> 102 { >> 103 if ( pDPhi > 0 ) fDPhi = pDPhi ; >> 104 else G4Exception("Error in G4Cons::G4Cons - invalid pDPhi") ; >> 105 >> 106 // Ensure pSPhi in 0-2PI or -2PI-0 range if shape crosses 0 >> 107 >> 108 if ( pSPhi < 0 ) fSPhi = 2.0*M_PI - fmod(fabs(pSPhi),2.0*M_PI) ; >> 109 else fSPhi = fmod(pSPhi,2.0*M_PI) ; >> 110 >> 111 if (fSPhi + fDPhi > 2.0*M_PI) fSPhi -= 2.0*M_PI ; >> 112 } 175 } 113 } 176 114 177 ////////////////////////////////////////////// 115 ///////////////////////////////////////////////////////////////////// 178 // 116 // 179 // Return whether point inside/outside/on surf 117 // Return whether point inside/outside/on surface 180 118 181 EInside G4Cons::Inside(const G4ThreeVector& p) 119 EInside G4Cons::Inside(const G4ThreeVector& p) const 182 { 120 { 183 G4double r2, rl, rh, pPhi, tolRMin, tolRMax; << 121 G4double r2, rl, rh, pPhi, tolRMin, tolRMax ; 184 EInside in; << 122 EInside in = kOutside ; 185 123 186 if (std::fabs(p.z()) > fDz + halfCarToleranc << 124 if (fabs(p.z()) <= fDz - kCarTolerance*0.5 ) 187 else if(std::fabs(p.z()) >= fDz - halfCarTol << 125 { 188 else << 126 r2 = p.x()*p.x() + p.y()*p.y() ; 189 << 127 rl = 0.5*(fRmin2*(p.z() + fDz) + fRmin1*(fDz - p.z()))/fDz ; 190 r2 = p.x()*p.x() + p.y()*p.y() ; << 191 rl = 0.5*(fRmin2*(p.z() + fDz) + fRmin1*(fDz << 192 rh = 0.5*(fRmax2*(p.z()+fDz)+fRmax1*(fDz-p.z << 193 128 194 // rh2 = rh*rh; << 129 // inner radius at z of point 195 130 196 tolRMin = rl - halfRadTolerance; << 131 rh = 0.5*(fRmax2*(p.z()+fDz)+fRmax1*(fDz-p.z()))/fDz; 197 if ( tolRMin < 0 ) { tolRMin = 0; } << 132 // outer radius at z of point 198 tolRMax = rh + halfRadTolerance; << 199 133 200 if ( (r2<tolRMin*tolRMin) || (r2>tolRMax*tol << 201 134 202 if (rl != 0.0) { tolRMin = rl + halfRadToler << 135 if (rl) tolRMin = rl + kRadTolerance*0.5 ; 203 else { tolRMin = 0.0; } << 136 else tolRMin = 0.0 ; 204 tolRMax = rh - halfRadTolerance; << 205 << 206 if (in == kInside) // else it's kSurface alr << 207 { << 208 if ( (r2 < tolRMin*tolRMin) || (r2 >= tol << 209 } << 210 if ( !fPhiFullCone && ((p.x() != 0.0) || (p. << 211 { << 212 pPhi = std::atan2(p.y(),p.x()) ; << 213 137 214 if ( pPhi < fSPhi - halfAngTolerance ) << 138 tolRMax = rh - kRadTolerance*0.5 ; 215 else if ( pPhi > fSPhi + fDPhi + halfAngTo << 139 216 << 140 if ( r2 >= tolRMin*tolRMin && r2 <= tolRMax*tolRMax ) 217 if ( (pPhi < fSPhi - halfAngTolerance) || << 218 (pPhi > fSPhi + fDPhi + halfAngTolera << 219 << 220 else if (in == kInside) // else it's kSur << 221 { 141 { 222 if ( (pPhi < fSPhi + halfAngTolerance) << 142 if ( fDPhi == 2*M_PI || r2 == 0 ) in = kInside ; 223 (pPhi > fSPhi + fDPhi - halfAngTol << 143 else >> 144 { >> 145 // Try inner tolerant phi boundaries (=>inside) >> 146 // if not inside, try outer tolerant phi boundaries >> 147 >> 148 pPhi = atan2(p.y(),p.x()) ; >> 149 >> 150 if (pPhi < 0 ) pPhi += 2*M_PI ; // 0<=pPhi<2pi >> 151 if (fSPhi >= 0) >> 152 { >> 153 if ( pPhi >= fSPhi + kAngTolerance*0.5 && >> 154 pPhi <= fSPhi + fDPhi - kAngTolerance*0.5 ) >> 155 { >> 156 in = kInside ; >> 157 } >> 158 else if ( pPhi >= fSPhi - kAngTolerance*0.5 && >> 159 pPhi <= fSPhi + fDPhi + kAngTolerance*0.5 ) >> 160 { >> 161 in = kSurface ; >> 162 } >> 163 } >> 164 else >> 165 { >> 166 if ( pPhi < fSPhi + 2*M_PI) pPhi += 2*M_PI ; >> 167 >> 168 if ( pPhi >= fSPhi + 2*M_PI + kAngTolerance*0.5 && >> 169 pPhi <= fSPhi + fDPhi + 2*M_PI - kAngTolerance*0.5 ) >> 170 { >> 171 in = kInside ; >> 172 } >> 173 else if ( pPhi >= fSPhi + 2*M_PI - kAngTolerance*0.5 && >> 174 pPhi <= fSPhi + fDPhi + 2*M_PI + kAngTolerance*0.5 ) >> 175 { >> 176 in = kSurface ; >> 177 } >> 178 } >> 179 } >> 180 } >> 181 else // Try generous boundaries >> 182 { >> 183 tolRMin = rl - kRadTolerance*0.5 ; >> 184 tolRMax = rh + kRadTolerance*0.5 ; >> 185 >> 186 if ( tolRMin < 0 ) tolRMin = 0 ; >> 187 >> 188 if (r2 >= tolRMin*tolRMin && r2 <= tolRMax*tolRMax) >> 189 { >> 190 if (fDPhi == 2*M_PI || r2 == 0) // Continuous in phi or on z-axis >> 191 { >> 192 in = kSurface ; >> 193 } >> 194 else // Try outer tolerant phi boundaries only >> 195 { >> 196 pPhi = atan2(p.y(),p.x()) ; >> 197 >> 198 if (pPhi < 0) pPhi += 2*M_PI ; // 0<=pPhi<2pi >> 199 >> 200 if ( fSPhi >= 0 ) >> 201 { >> 202 if ( pPhi >= fSPhi - kAngTolerance*0.5 && >> 203 pPhi <= fSPhi + fDPhi + kAngTolerance*0.5 ) >> 204 { >> 205 in = kSurface ; >> 206 } >> 207 } >> 208 else >> 209 { >> 210 if ( pPhi < fSPhi + 2*M_PI) pPhi += 2*M_PI ; >> 211 >> 212 if ( pPhi >= fSPhi + 2*M_PI - kAngTolerance*0.5 && >> 213 pPhi <= fSPhi + fDPhi + 2*M_PI + kAngTolerance*0.5 ) >> 214 { >> 215 in = kSurface ; >> 216 } >> 217 } >> 218 } >> 219 } >> 220 } >> 221 } >> 222 else if (fabs(p.z()) <= fDz + kCarTolerance*0.5 ) >> 223 { >> 224 // Check within tolerant r limits >> 225 >> 226 r2 = p.x()*p.x() + p.y()*p.y() ; >> 227 rl = 0.5*(fRmin2*(p.z() + fDz) + fRmin1*(fDz - p.z()))/fDz ; >> 228 >> 229 // inner radius at z of point >> 230 >> 231 rh = 0.5*(fRmax2*(p.z() + fDz) + fRmax1*(fDz - p.z()))/fDz; >> 232 >> 233 // outer radius at z of point >> 234 >> 235 tolRMin = rl - kRadTolerance*0.5 ; >> 236 >> 237 if (tolRMin < 0 ) tolRMin = 0 ; >> 238 >> 239 tolRMax = rh + kRadTolerance*0.5 ; >> 240 >> 241 if (r2 >= tolRMin*tolRMin && r2 <= tolRMax*tolRMax) >> 242 { >> 243 if ( fDPhi == 2*M_PI || r2 == 0 ) // Continuous in phi or on z-axis >> 244 { >> 245 in = kSurface ; >> 246 } >> 247 else // Try outer tolerant phi boundaries >> 248 { >> 249 pPhi = atan2(p.y(),p.x()) ; >> 250 >> 251 if ( pPhi < 0 ) pPhi += 2*M_PI ; // 0<=pPhi<2pi >> 252 if ( fSPhi >= 0 ) >> 253 { >> 254 if ( pPhi >= fSPhi - kAngTolerance*0.5 && >> 255 pPhi <= fSPhi + fDPhi + kAngTolerance*0.5 ) >> 256 { >> 257 in = kSurface ; >> 258 } >> 259 } >> 260 else >> 261 { >> 262 if ( pPhi < fSPhi + 2*M_PI) pPhi += 2*M_PI ; >> 263 if ( pPhi >= fSPhi + 2*M_PI - kAngTolerance*0.5 && >> 264 pPhi <= fSPhi + fDPhi + 2*M_PI + kAngTolerance*0.5 ) >> 265 { >> 266 in = kSurface ; >> 267 } >> 268 } >> 269 } 224 } 270 } 225 } 271 } 226 else if ( !fPhiFullCone ) { in = kSurface; << 227 << 228 return in ; 272 return in ; 229 } 273 } 230 274 231 ////////////////////////////////////////////// 275 ///////////////////////////////////////////////////////////////////////// 232 // 276 // 233 // Dispatch to parameterisation for replicatio 277 // Dispatch to parameterisation for replication mechanism dimension 234 // computation & modification. 278 // computation & modification. 235 279 236 void G4Cons::ComputeDimensions( G4VPVPara 280 void G4Cons::ComputeDimensions( G4VPVParameterisation* p, 237 const G4int 281 const G4int n, 238 const G4VPhysic 282 const G4VPhysicalVolume* pRep ) 239 { 283 { 240 p->ComputeDimensions(*this,n,pRep) ; 284 p->ComputeDimensions(*this,n,pRep) ; 241 } 285 } 242 286 243 ////////////////////////////////////////////// << 244 // << 245 // Get bounding box << 246 287 247 void G4Cons::BoundingLimits(G4ThreeVector& pMi << 288 /////////////////////////////////////////////////////////////////////////// 248 { << 249 G4double rmin = std::min(GetInnerRadiusMinus << 250 G4double rmax = std::max(GetOuterRadiusMinus << 251 G4double dz = GetZHalfLength(); << 252 << 253 // Find bounding box << 254 // << 255 if (GetDeltaPhiAngle() < twopi) << 256 { << 257 G4TwoVector vmin,vmax; << 258 G4GeomTools::DiskExtent(rmin,rmax, << 259 GetSinStartPhi(),G << 260 GetSinEndPhi(),Get << 261 vmin,vmax); << 262 pMin.set(vmin.x(),vmin.y(),-dz); << 263 pMax.set(vmax.x(),vmax.y(), dz); << 264 } << 265 else << 266 { << 267 pMin.set(-rmax,-rmax,-dz); << 268 pMax.set( rmax, rmax, dz); << 269 } << 270 << 271 // Check correctness of the bounding box << 272 // << 273 if (pMin.x() >= pMax.x() || pMin.y() >= pMax << 274 { << 275 std::ostringstream message; << 276 message << "Bad bounding box (min >= max) << 277 << GetName() << " !" << 278 << "\npMin = " << pMin << 279 << "\npMax = " << pMax; << 280 G4Exception("G4Cons::BoundingLimits()", "G << 281 JustWarning, message); << 282 DumpInfo(); << 283 } << 284 } << 285 << 286 ////////////////////////////////////////////// << 287 // 289 // 288 // Calculate extent under transform and specif 290 // Calculate extent under transform and specified limit 289 291 290 G4bool G4Cons::CalculateExtent( const EAxis 292 G4bool G4Cons::CalculateExtent( const EAxis pAxis, 291 const G4VoxelL << 293 const G4VoxelLimits& pVoxelLimit, 292 const G4Affine << 294 const G4AffineTransform& pTransform, 293 G4double << 295 G4double& pMin, 294 G4double << 296 G4double& pMax ) const 295 { 297 { 296 G4ThreeVector bmin, bmax; << 298 if ( !pTransform.IsRotated() && 297 G4bool exist; << 299 fDPhi == 2.0*M_PI && fRmin1 == 0 && fRmin2 == 0 ) 298 << 299 // Get bounding box << 300 BoundingLimits(bmin,bmax); << 301 << 302 // Check bounding box << 303 G4BoundingEnvelope bbox(bmin,bmax); << 304 #ifdef G4BBOX_EXTENT << 305 if (true) return bbox.CalculateExtent(pAxis, << 306 #endif << 307 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox << 308 { << 309 return exist = pMin < pMax; << 310 } << 311 << 312 // Get parameters of the solid << 313 G4double rmin1 = GetInnerRadiusMinusZ(); << 314 G4double rmax1 = GetOuterRadiusMinusZ(); << 315 G4double rmin2 = GetInnerRadiusPlusZ(); << 316 G4double rmax2 = GetOuterRadiusPlusZ(); << 317 G4double dz = GetZHalfLength(); << 318 G4double dphi = GetDeltaPhiAngle(); << 319 << 320 // Find bounding envelope and calculate exte << 321 // << 322 const G4int NSTEPS = 24; // numbe << 323 G4double astep = twopi/NSTEPS; // max a << 324 G4int ksteps = (dphi <= astep) ? 1 : (G4i << 325 G4double ang = dphi/ksteps; << 326 << 327 G4double sinHalf = std::sin(0.5*ang); << 328 G4double cosHalf = std::cos(0.5*ang); << 329 G4double sinStep = 2.*sinHalf*cosHalf; << 330 G4double cosStep = 1. - 2.*sinHalf*sinHalf; << 331 G4double rext1 = rmax1/cosHalf; << 332 G4double rext2 = rmax2/cosHalf; << 333 << 334 // bounding envelope for full cone without h << 335 // in other cases it is a sequence of quadri << 336 if (rmin1 == 0 && rmin2 == 0 && dphi == twop << 337 { << 338 G4double sinCur = sinHalf; << 339 G4double cosCur = cosHalf; << 340 << 341 G4ThreeVectorList baseA(NSTEPS),baseB(NSTE << 342 for (G4int k=0; k<NSTEPS; ++k) << 343 { << 344 baseA[k].set(rext1*cosCur,rext1*sinCur,- << 345 baseB[k].set(rext2*cosCur,rext2*sinCur, << 346 << 347 G4double sinTmp = sinCur; << 348 sinCur = sinCur*cosStep + cosCur*sinStep << 349 cosCur = cosCur*cosStep - sinTmp*sinStep << 350 } << 351 std::vector<const G4ThreeVectorList *> pol << 352 polygons[0] = &baseA; << 353 polygons[1] = &baseB; << 354 G4BoundingEnvelope benv(bmin,bmax,polygons << 355 exist = benv.CalculateExtent(pAxis,pVoxelL << 356 } << 357 else << 358 { 300 { 359 G4double sinStart = GetSinStartPhi(); << 301 // Special case handling for unrotated solid cones 360 G4double cosStart = GetCosStartPhi(); << 302 // Compute z/x/y mins and maxs for bounding box respecting limits, 361 G4double sinEnd = GetSinEndPhi(); << 303 // with early returns if outside limits. Then switch() on pAxis, 362 G4double cosEnd = GetCosEndPhi(); << 304 // and compute exact x and y limit for x/y case 363 G4double sinCur = sinStart*cosHalf + cos << 305 364 G4double cosCur = cosStart*cosHalf - sin << 306 G4double xoffset, xMin, xMax ; 365 << 307 G4double yoffset, yMin, yMax ; 366 // set quadrilaterals << 308 G4double zoffset, zMin, zMax ; 367 G4ThreeVectorList pols[NSTEPS+2]; << 309 368 for (G4int k=0; k<ksteps+2; ++k) pols[k].r << 310 G4double diff1, diff2, maxDiff, newMin, newMax, RMax ; 369 pols[0][0].set(rmin2*cosStart,rmin2*sinSta << 311 G4double xoff1, xoff2, yoff1, yoff2 ; 370 pols[0][1].set(rmin1*cosStart,rmin1*sinSta << 312 371 pols[0][2].set(rmax1*cosStart,rmax1*sinSta << 313 zoffset = pTransform.NetTranslation().z(); 372 pols[0][3].set(rmax2*cosStart,rmax2*sinSta << 314 zMin = zoffset - fDz ; 373 for (G4int k=1; k<ksteps+1; ++k) << 315 zMax = zoffset + fDz ; 374 { << 375 pols[k][0].set(rmin2*cosCur,rmin2*sinCur << 376 pols[k][1].set(rmin1*cosCur,rmin1*sinCur << 377 pols[k][2].set(rext1*cosCur,rext1*sinCur << 378 pols[k][3].set(rext2*cosCur,rext2*sinCur << 379 << 380 G4double sinTmp = sinCur; << 381 sinCur = sinCur*cosStep + cosCur*sinStep << 382 cosCur = cosCur*cosStep - sinTmp*sinStep << 383 } << 384 pols[ksteps+1][0].set(rmin2*cosEnd,rmin2*s << 385 pols[ksteps+1][1].set(rmin1*cosEnd,rmin1*s << 386 pols[ksteps+1][2].set(rmax1*cosEnd,rmax1*s << 387 pols[ksteps+1][3].set(rmax2*cosEnd,rmax2*s << 388 << 389 // set envelope and calculate extent << 390 std::vector<const G4ThreeVectorList *> pol << 391 polygons.resize(ksteps+2); << 392 for (G4int k=0; k<ksteps+2; ++k) polygons[ << 393 G4BoundingEnvelope benv(bmin,bmax,polygons << 394 exist = benv.CalculateExtent(pAxis,pVoxelL << 395 } << 396 return exist; << 397 } << 398 316 399 ////////////////////////////////////////////// << 317 if (pVoxelLimit.IsZLimited()) 400 // << 318 { 401 // Return unit normal of surface closest to p << 319 if( zMin > pVoxelLimit.GetMaxZExtent() + kCarTolerance || 402 // - note if point on z axis, ignore phi divid << 320 zMax < pVoxelLimit.GetMinZExtent() - kCarTolerance ) 403 // - unsafe if point close to z axis a rmin=0 << 321 { 404 << 322 return false ; 405 G4ThreeVector G4Cons::SurfaceNormal( const G4T << 323 } 406 { << 324 else 407 G4int noSurfaces = 0; << 325 { 408 G4double rho, pPhi; << 326 if ( zMin < pVoxelLimit.GetMinZExtent() ) 409 G4double distZ, distRMin, distRMax; << 327 { 410 G4double distSPhi = kInfinity, distEPhi = kI << 328 zMin = pVoxelLimit.GetMinZExtent() ; 411 G4double tanRMin, secRMin, pRMin, widRMin; << 329 } 412 G4double tanRMax, secRMax, pRMax, widRMax; << 330 if ( zMax > pVoxelLimit.GetMaxZExtent() ) >> 331 { >> 332 zMax = pVoxelLimit.GetMaxZExtent() ; >> 333 } >> 334 } >> 335 } >> 336 xoffset = pTransform.NetTranslation().x() ; >> 337 RMax = (fRmax2 >= fRmax1) ? zMax : zMin ; >> 338 xMax = xoffset + (fRmax1 + fRmax2)*0.5 + >> 339 (RMax - zoffset)*(fRmax2 - fRmax1)/(2*fDz) ; >> 340 xMin = 2*xoffset-xMax ; 413 341 414 G4ThreeVector norm, sumnorm(0.,0.,0.), nZ = << 342 if (pVoxelLimit.IsXLimited()) 415 G4ThreeVector nR, nr(0.,0.,0.), nPs, nPe; << 343 { >> 344 if ( xMin > pVoxelLimit.GetMaxXExtent() + kCarTolerance || >> 345 xMax < pVoxelLimit.GetMinXExtent() - kCarTolerance ) >> 346 { >> 347 return false ; >> 348 } >> 349 else >> 350 { >> 351 if ( xMin < pVoxelLimit.GetMinXExtent() ) >> 352 { >> 353 xMin = pVoxelLimit.GetMinXExtent() ; >> 354 } >> 355 if ( xMax > pVoxelLimit.GetMaxXExtent() ) >> 356 { >> 357 xMax=pVoxelLimit.GetMaxXExtent() ; >> 358 } >> 359 } >> 360 } >> 361 yoffset = pTransform.NetTranslation().y() ; >> 362 yMax = yoffset + (fRmax1 + fRmax2)*0.5 + >> 363 (RMax - zoffset)*(fRmax2 - fRmax1)/(2*fDz) ; >> 364 yMin = 2*yoffset-yMax ; >> 365 RMax = yMax - yoffset ; // = max radius due to Zmax/Zmin cuttings 416 366 417 distZ = std::fabs(std::fabs(p.z()) - fDz); << 367 if (pVoxelLimit.IsYLimited()) 418 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) << 368 { >> 369 if ( yMin > pVoxelLimit.GetMaxYExtent() + kCarTolerance || >> 370 yMax < pVoxelLimit.GetMinYExtent() - kCarTolerance ) >> 371 { >> 372 return false ; >> 373 } >> 374 else >> 375 { >> 376 if ( yMin < pVoxelLimit.GetMinYExtent() ) >> 377 { >> 378 yMin = pVoxelLimit.GetMinYExtent() ; >> 379 } >> 380 if ( yMax > pVoxelLimit.GetMaxYExtent() ) >> 381 { >> 382 yMax = pVoxelLimit.GetMaxYExtent() ; >> 383 } >> 384 } >> 385 } >> 386 switch (pAxis) // Known to cut cones >> 387 { >> 388 case kXAxis: >> 389 yoff1 = yoffset - yMin ; >> 390 yoff2 = yMax - yoffset ; >> 391 >> 392 if (yoff1 >= 0 && yoff2 >= 0) // Y limits cross max/min x => no change >> 393 { >> 394 pMin = xMin ; >> 395 pMax = xMax ; >> 396 } >> 397 else >> 398 { >> 399 // Y limits don't cross max/min x => compute max delta x, hence new mins/maxs >> 400 >> 401 diff1 = sqrt(RMax*RMax - yoff1*yoff1) ; >> 402 diff2 = sqrt(RMax*RMax - yoff2*yoff2) ; >> 403 maxDiff = (diff1>diff2) ? diff1:diff2 ; >> 404 newMin = xoffset - maxDiff ; >> 405 newMax = xoffset + maxDiff ; >> 406 pMin = ( newMin < xMin ) ? xMin : newMin ; >> 407 pMax = ( newMax > xMax) ? xMax : newMax ; >> 408 } >> 409 break ; 419 410 420 tanRMin = (fRmin2 - fRmin1)*0.5/fDz; << 411 case kYAxis: 421 secRMin = std::sqrt(1 + tanRMin*tanRMin); << 412 xoff1 = xoffset - xMin ; 422 pRMin = rho - p.z()*tanRMin; << 413 xoff2 = xMax - xoffset ; 423 widRMin = fRmin2 - fDz*tanRMin; << 414 424 distRMin = std::fabs(pRMin - widRMin)/secRMi << 415 if (xoff1 >= 0 && xoff2 >= 0 ) // X limits cross max/min y => no change >> 416 { >> 417 pMin = yMin ; >> 418 pMax = yMax ; >> 419 } >> 420 else >> 421 { >> 422 // X limits don't cross max/min y => compute max delta y, hence new mins/maxs >> 423 >> 424 diff1 = sqrt(RMax*RMax - xoff1*xoff1) ; >> 425 diff2 = sqrt(RMax*RMax-xoff2*xoff2) ; >> 426 maxDiff = (diff1 > diff2) ? diff1:diff2 ; >> 427 newMin = yoffset - maxDiff ; >> 428 newMax = yoffset + maxDiff ; >> 429 pMin = (newMin < yMin) ? yMin : newMin ; >> 430 pMax = (newMax > yMax) ? yMax : newMax ; >> 431 } >> 432 break ; 425 433 426 tanRMax = (fRmax2 - fRmax1)*0.5/fDz; << 434 case kZAxis: 427 secRMax = std::sqrt(1+tanRMax*tanRMax); << 435 pMin = zMin ; 428 pRMax = rho - p.z()*tanRMax; << 436 pMax = zMax ; 429 widRMax = fRmax2 - fDz*tanRMax; << 437 break ; 430 distRMax = std::fabs(pRMax - widRMax)/secRMa << 438 >> 439 default: >> 440 break ; >> 441 } >> 442 pMin -= kCarTolerance ; >> 443 pMax += kCarTolerance ; 431 444 432 if (!fPhiFullCone) // Protected against (0 << 445 return true ; >> 446 } >> 447 else // Calculate rotated vertex coordinates 433 { 448 { 434 if ( rho != 0.0 ) << 449 G4int i, noEntries, noBetweenSections4 ; 435 { << 450 G4bool existsAfterClip = false ; 436 pPhi = std::atan2(p.y(),p.x()); << 451 G4ThreeVectorList* vertices = CreateRotatedVertices(pTransform) ; 437 452 438 if (pPhi < fSPhi-halfCarTolerance) << 453 pMin = +kInfinity ; 439 else if (pPhi > fSPhi+fDPhi+halfCarToler << 454 pMax = -kInfinity ; 440 455 441 distSPhi = std::fabs( pPhi - fSPhi ); << 456 noEntries = vertices->entries() ; 442 distEPhi = std::fabs( pPhi - fSPhi - fDP << 457 noBetweenSections4 = noEntries-4 ; 443 } << 458 444 else if( ((fRmin1) == 0.0) || ((fRmin2) == << 459 for ( i = 0 ; i < noEntries ; i += 4 ) 445 { 460 { 446 distSPhi = 0.; << 461 ClipCrossSection(vertices,i,pVoxelLimit,pAxis,pMin,pMax) ; 447 distEPhi = 0.; << 448 } 462 } 449 nPs = G4ThreeVector( sinSPhi, -cosSPhi, 0 << 463 for ( i = 0 ; i < noBetweenSections4 ; i += 4 ) 450 nPe = G4ThreeVector( -sinEPhi, cosEPhi, 0 << 451 } << 452 if ( rho > halfCarTolerance ) << 453 { << 454 nR = G4ThreeVector(p.x()/rho/secRMax, p.y( << 455 if ((fRmin1 != 0.0) || (fRmin2 != 0.0)) << 456 { 464 { 457 nr = G4ThreeVector(-p.x()/rho/secRMin,-p << 465 ClipBetweenSections(vertices,i,pVoxelLimit,pAxis,pMin,pMax) ; 458 } << 466 } 459 } << 467 if ( pMin != kInfinity || pMax != -kInfinity ) 460 << 461 if( distRMax <= halfCarTolerance ) << 462 { << 463 ++noSurfaces; << 464 sumnorm += nR; << 465 } << 466 if( ((fRmin1 != 0.0) || (fRmin2 != 0.0)) && << 467 { << 468 ++noSurfaces; << 469 sumnorm += nr; << 470 } << 471 if( !fPhiFullCone ) << 472 { << 473 if (distSPhi <= halfAngTolerance) << 474 { 468 { 475 ++noSurfaces; << 469 existsAfterClip = true ; 476 sumnorm += nPs; << 470 >> 471 // Add 2*tolerance to avoid precision troubles >> 472 >> 473 pMin -= kCarTolerance ; >> 474 pMax += kCarTolerance ; 477 } 475 } 478 if (distEPhi <= halfAngTolerance) << 476 else 479 { 477 { 480 ++noSurfaces; << 478 // Check for case where completely enveloping clipping volume 481 sumnorm += nPe; << 479 // If point inside then we are confident that the solid completely >> 480 // envelopes the clipping volume. Hence set min/max extents according >> 481 // to clipping volume extents along the specified axis. >> 482 >> 483 G4ThreeVector clipCentre( >> 484 (pVoxelLimit.GetMinXExtent() + pVoxelLimit.GetMaxXExtent())*0.5, >> 485 (pVoxelLimit.GetMinYExtent() + pVoxelLimit.GetMaxYExtent())*0.5, >> 486 (pVoxelLimit.GetMinZExtent() + pVoxelLimit.GetMaxZExtent())*0.5 ) ; >> 487 >> 488 if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside) >> 489 { >> 490 existsAfterClip = true ; >> 491 pMin = pVoxelLimit.GetMinExtent(pAxis) ; >> 492 pMax = pVoxelLimit.GetMaxExtent(pAxis) ; >> 493 } 482 } 494 } >> 495 delete vertices ; >> 496 return existsAfterClip ; 483 } 497 } 484 if (distZ <= halfCarTolerance) << 485 { << 486 ++noSurfaces; << 487 if ( p.z() >= 0.) { sumnorm += nZ; } << 488 else { sumnorm -= nZ; } << 489 } << 490 if ( noSurfaces == 0 ) << 491 { << 492 #ifdef G4CSGDEBUG << 493 G4Exception("G4Cons::SurfaceNormal(p)", "G << 494 JustWarning, "Point p is not o << 495 #endif << 496 norm = ApproxSurfaceNormal(p); << 497 } << 498 else if ( noSurfaces == 1 ) { norm = sumnor << 499 else { norm = sumnor << 500 << 501 return norm ; << 502 } 498 } 503 499 504 ////////////////////////////////////////////// << 500 //////////////////////////////////////////////////////////////////////// 505 // 501 // 506 // Algorithm for SurfaceNormal() following the << 502 // Return unit normal of surface closest to p 507 // for points not on the surface << 503 // - note if point on z axis, ignore phi divided sides >> 504 // - unsafe if point close to z axis a rmin=0 - no explicit checks 508 505 509 G4ThreeVector G4Cons::ApproxSurfaceNormal( con << 506 G4ThreeVector G4Cons::SurfaceNormal( const G4ThreeVector& p) const 510 { 507 { 511 ENorm side ; 508 ENorm side ; 512 G4ThreeVector norm ; 509 G4ThreeVector norm ; 513 G4double rho, phi ; 510 G4double rho, phi ; 514 G4double distZ, distRMin, distRMax, distSPhi 511 G4double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin ; 515 G4double tanRMin, secRMin, pRMin, widRMin ; 512 G4double tanRMin, secRMin, pRMin, widRMin ; 516 G4double tanRMax, secRMax, pRMax, widRMax ; 513 G4double tanRMax, secRMax, pRMax, widRMax ; 517 514 518 distZ = std::fabs(std::fabs(p.z()) - fDz) ; << 515 distZ = fabs(fabs(p.z()) - fDz) ; 519 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) << 516 rho = sqrt(p.x()*p.x() + p.y()*p.y()) ; 520 517 521 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; 518 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; 522 secRMin = std::sqrt(1 + tanRMin*tanRMin) ; << 519 secRMin = sqrt(1 + tanRMin*tanRMin) ; 523 pRMin = rho - p.z()*tanRMin ; 520 pRMin = rho - p.z()*tanRMin ; 524 widRMin = fRmin2 - fDz*tanRMin ; 521 widRMin = fRmin2 - fDz*tanRMin ; 525 distRMin = std::fabs(pRMin - widRMin)/secRMi << 522 distRMin = fabs(pRMin - widRMin)/secRMin ; 526 523 527 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; 524 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; 528 secRMax = std::sqrt(1+tanRMax*tanRMax) ; << 525 secRMax = sqrt(1+tanRMax*tanRMax) ; 529 pRMax = rho - p.z()*tanRMax ; 526 pRMax = rho - p.z()*tanRMax ; 530 widRMax = fRmax2 - fDz*tanRMax ; 527 widRMax = fRmax2 - fDz*tanRMax ; 531 distRMax = std::fabs(pRMax - widRMax)/secRMa << 528 distRMax = fabs(pRMax - widRMax)/secRMax ; 532 529 533 if (distRMin < distRMax) // First minimum 530 if (distRMin < distRMax) // First minimum 534 { 531 { 535 if (distZ < distRMin) 532 if (distZ < distRMin) 536 { 533 { 537 distMin = distZ ; 534 distMin = distZ ; 538 side = kNZ ; 535 side = kNZ ; 539 } 536 } 540 else 537 else 541 { 538 { 542 distMin = distRMin ; 539 distMin = distRMin ; 543 side = kNRMin ; 540 side = kNRMin ; 544 } 541 } 545 } 542 } 546 else 543 else 547 { 544 { 548 if (distZ < distRMax) 545 if (distZ < distRMax) 549 { 546 { 550 distMin = distZ ; 547 distMin = distZ ; 551 side = kNZ ; 548 side = kNZ ; 552 } 549 } 553 else 550 else 554 { 551 { 555 distMin = distRMax ; 552 distMin = distRMax ; 556 side = kNRMax ; 553 side = kNRMax ; 557 } 554 } 558 } 555 } 559 if ( !fPhiFullCone && (rho != 0.0) ) // Pro << 556 if ( fDPhi < 2.0*M_PI && rho ) // Protected against (0,0,z) 560 { 557 { 561 phi = std::atan2(p.y(),p.x()) ; << 558 phi = atan2(p.y(),p.x()) ; 562 559 563 if (phi < 0) { phi += twopi; } << 560 if (phi < 0) phi += 2*M_PI ; 564 561 565 if (fSPhi < 0) { distSPhi = std::fabs(phi << 562 if (fSPhi < 0) distSPhi = fabs(phi - (fSPhi + 2.0*M_PI))*rho ; 566 else { distSPhi = std::fabs(phi << 563 else distSPhi = fabs(phi - fSPhi)*rho ; 567 564 568 distEPhi = std::fabs(phi - fSPhi - fDPhi)* << 565 distEPhi = fabs(phi - fSPhi - fDPhi)*rho ; 569 566 570 // Find new minimum << 567 // Find new minimum 571 568 572 if (distSPhi < distEPhi) 569 if (distSPhi < distEPhi) 573 { 570 { 574 if (distSPhi < distMin) { side = kNSPhi << 571 if (distSPhi < distMin) side = kNSPhi ; 575 } 572 } 576 else 573 else 577 { 574 { 578 if (distEPhi < distMin) { side = kNEPhi << 575 if (distEPhi < distMin) side = kNEPhi ; 579 } 576 } 580 } << 577 } 581 switch (side) 578 switch (side) 582 { 579 { 583 case kNRMin: // Inner radius << 580 case kNRMin: // Inner radius 584 { << 585 rho *= secRMin ; 581 rho *= secRMin ; 586 norm = G4ThreeVector(-p.x()/rho, -p.y()/ << 582 norm = G4ThreeVector(-p.x()/rho,-p.y()/rho,tanRMin/secRMin) ; 587 break ; 583 break ; 588 } << 584 case kNRMax: // Outer radius 589 case kNRMax: // Outer radius << 590 { << 591 rho *= secRMax ; 585 rho *= secRMax ; 592 norm = G4ThreeVector(p.x()/rho, p.y()/rh << 586 norm = G4ThreeVector(p.x()/rho,p.y()/rho,-tanRMax/secRMax) ; 593 break ; 587 break ; 594 } << 588 case kNZ: // +/- dz 595 case kNZ: // +/- dz << 589 if (p.z() > 0) norm = G4ThreeVector(0,0,1) ; 596 { << 590 else norm = G4ThreeVector(0,0,-1) ; 597 if (p.z() > 0) { norm = G4ThreeVector(0 << 598 else { norm = G4ThreeVector(0 << 599 break ; 591 break ; 600 } << 601 case kNSPhi: 592 case kNSPhi: 602 { << 593 norm = G4ThreeVector(sin(fSPhi),-cos(fSPhi),0) ; 603 norm = G4ThreeVector(sinSPhi, -cosSPhi, << 604 break ; 594 break ; 605 } << 606 case kNEPhi: 595 case kNEPhi: 607 { << 596 norm=G4ThreeVector(-sin(fSPhi+fDPhi),cos(fSPhi+fDPhi),0) ; 608 norm = G4ThreeVector(-sinEPhi, cosEPhi, << 609 break ; 597 break ; 610 } << 598 default: 611 default: // Should never reach th << 599 G4Exception("Logic error in G4Cons::SurfaceNormal") ; 612 { << 613 DumpInfo(); << 614 G4Exception("G4Cons::ApproxSurfaceNormal << 615 "GeomSolids1002", JustWarnin << 616 "Undefined side for valid su << 617 break ; 600 break ; 618 } << 619 } 601 } 620 return norm ; 602 return norm ; 621 } 603 } 622 604 623 ////////////////////////////////////////////// 605 //////////////////////////////////////////////////////////////////////// 624 // 606 // 625 // Calculate distance to shape from outside, a 607 // Calculate distance to shape from outside, along normalised vector 626 // - return kInfinity if no intersection, or i 608 // - return kInfinity if no intersection, or intersection distance <= tolerance 627 // 609 // 628 // - Compute the intersection with the z plane 610 // - Compute the intersection with the z planes 629 // - if at valid r, phi, return 611 // - if at valid r, phi, return 630 // 612 // 631 // -> If point is outside cone, compute inters 613 // -> If point is outside cone, compute intersection with rmax1*0.5 632 // - if at valid phi,z return 614 // - if at valid phi,z return 633 // - if inside outer cone, handle case 615 // - if inside outer cone, handle case when on tolerant outer cone 634 // boundary and heading inwards(->0 t 616 // boundary and heading inwards(->0 to in) 635 // 617 // 636 // -> Compute intersection with inner cone, ta 618 // -> Compute intersection with inner cone, taking largest +ve root 637 // - if valid (in z,phi), save intersct 619 // - if valid (in z,phi), save intersction 638 // 620 // 639 // -> If phi segmented, compute intersectio 621 // -> If phi segmented, compute intersections with phi half planes 640 // - return smallest of valid phi inter 622 // - return smallest of valid phi intersections and 641 // inner radius intersection 623 // inner radius intersection 642 // 624 // 643 // NOTE: 625 // NOTE: >> 626 // - Precalculations for phi trigonometry are Done `just in time' 644 // - `if valid' implies tolerant checking of i 627 // - `if valid' implies tolerant checking of intersection points 645 // - z, phi intersection from Tubs 628 // - z, phi intersection from Tubs 646 629 647 G4double G4Cons::DistanceToIn( const G4ThreeVe 630 G4double G4Cons::DistanceToIn( const G4ThreeVector& p, 648 const G4ThreeVe << 631 const G4ThreeVector& v ) const 649 { 632 { 650 G4double snxt = kInfinity ; // snxt = d << 633 G4double snxt = kInfinity ; // snxt = default return value 651 const G4double dRmax = 50*(fRmax1+fRmax2);// << 634 >> 635 G4bool seg ; // true if segmented in phi >> 636 G4double hDPhi,hDPhiOT,hDPhiIT,cosHDPhiOT=0.,cosHDPhiIT=0. ; >> 637 // half dphi + outer tolerance >> 638 G4double cPhi,sinCPhi=0.,cosCPhi=0. ; // central phi 652 639 653 G4double tanRMax,secRMax,rMaxAv,rMaxOAv ; / << 640 G4double tanRMax,secRMax,rMaxAv,rMaxOAv ; // Data for cones 654 G4double tanRMin,secRMin,rMinAv,rMinOAv ; << 641 G4double tanRMin,secRMin,rMinAv,rMinIAv,rMinOAv ; 655 G4double rout,rin ; 642 G4double rout,rin ; 656 643 657 G4double tolORMin,tolORMin2,tolIRMin,tolIRMi << 644 G4double tolORMin,tolORMin2 ; // `generous' radii squared 658 G4double tolORMax2,tolIRMax,tolIRMax2 ; << 645 G4double tolORMax2 ; 659 G4double tolODz,tolIDz ; 646 G4double tolODz,tolIDz ; 660 647 661 G4double Dist,sd,xi,yi,zi,ri=0.,risec,rhoi2, << 648 G4double Dist,s,xi,yi,zi,ri=0.,rho2,cosPsi ; // Intersection point variables 662 649 663 G4double t1,t2,t3,b,c,d ; // Quadratic so << 650 G4double t1,t2,t3,b,c,d ; // Quadratic solver variables 664 G4double nt1,nt2,nt3 ; 651 G4double nt1,nt2,nt3 ; 665 G4double Comp ; 652 G4double Comp ; >> 653 G4double cosSPhi,sinSPhi ; // Trig for phi start intersect >> 654 G4double ePhi,cosEPhi,sinEPhi ; // for phi end intersect 666 655 667 G4ThreeVector Normal; << 656 // >> 657 // Set phi divided flag and precalcs >> 658 // >> 659 if (fDPhi < 2.0*M_PI) >> 660 { >> 661 seg = true ; >> 662 hDPhi = 0.5*fDPhi ; // half delta phi >> 663 cPhi = fSPhi + hDPhi ; ; >> 664 hDPhiOT = hDPhi + 0.5*kAngTolerance ; // outers tol' half delta phi >> 665 hDPhiIT = hDPhi - 0.5*kAngTolerance ; >> 666 sinCPhi = sin(cPhi) ; >> 667 cosCPhi = cos(cPhi) ; >> 668 cosHDPhiOT = cos(hDPhiOT) ; >> 669 cosHDPhiIT = cos(hDPhiIT) ; >> 670 } >> 671 else seg = false ; 668 672 669 // Cone Precalcs << 673 // Cone Precalcs 670 674 671 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; 675 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; 672 secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ; << 676 secRMin = sqrt(1.0 + tanRMin*tanRMin) ; 673 rMinAv = (fRmin1 + fRmin2)*0.5 ; 677 rMinAv = (fRmin1 + fRmin2)*0.5 ; 674 678 675 if (rMinAv > halfRadTolerance) << 679 if (rMinAv > kRadTolerance*0.5) 676 { 680 { 677 rMinOAv = rMinAv - halfRadTolerance ; << 681 rMinOAv = rMinAv - kRadTolerance*0.5 ; >> 682 rMinIAv = rMinAv + kRadTolerance*0.5 ; 678 } 683 } 679 else 684 else 680 { 685 { 681 rMinOAv = 0.0 ; 686 rMinOAv = 0.0 ; >> 687 rMinIAv = 0.0 ; 682 } 688 } 683 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; 689 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; 684 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ; << 690 secRMax = sqrt(1.0 + tanRMax*tanRMax) ; 685 rMaxAv = (fRmax1 + fRmax2)*0.5 ; 691 rMaxAv = (fRmax1 + fRmax2)*0.5 ; 686 rMaxOAv = rMaxAv + halfRadTolerance ; << 692 rMaxOAv = rMaxAv + kRadTolerance*0.5 ; 687 693 688 // Intersection with z-surfaces << 694 // Intersection with Z surfaces 689 695 690 tolIDz = fDz - halfCarTolerance ; << 696 tolIDz = fDz - kCarTolerance*0.5 ; 691 tolODz = fDz + halfCarTolerance ; << 697 tolODz = fDz + kCarTolerance*0.5 ; 692 698 693 if (std::fabs(p.z()) >= tolIDz) << 699 if (fabs(p.z()) >= tolIDz) 694 { 700 { 695 if ( p.z()*v.z() < 0 ) // at +Z going i << 701 if ( p.z()*v.z() < 0 ) // at +Z going in -Z or visa versa 696 { 702 { 697 sd = (std::fabs(p.z()) - fDz)/std::fabs( << 703 s = (fabs(p.z()) - fDz)/fabs(v.z()) ; // Z intersect distance 698 704 699 if( sd < 0.0 ) { sd = 0.0; } << 705 if( s < 0.0 ) s = 0.0 ; // negative dist -> zero 700 706 701 xi = p.x() + sd*v.x() ; // Intersecti << 707 xi = p.x() + s*v.x() ; // Intersection coords 702 yi = p.y() + sd*v.y() ; << 708 yi = p.y() + s*v.y() ; 703 rhoi2 = xi*xi + yi*yi ; << 709 rho2 = xi*xi + yi*yi ; 704 710 705 // Check validity of intersection << 711 // Check validity of intersection 706 // Calculate (outer) tolerant radi^2 at << 712 // Calculate (outer) tolerant radi^2 at intersecion 707 713 708 if (v.z() > 0) 714 if (v.z() > 0) 709 { 715 { 710 tolORMin = fRmin1 - halfRadTolerance* << 716 tolORMin = fRmin1 - 0.5*kRadTolerance*secRMin ; 711 tolIRMin = fRmin1 + halfRadTolerance* << 717 tolORMax2 = (fRmax1 + 0.5*kRadTolerance*secRMax)*(fRmax1 + 0.5*kRadTolerance*secRMax) ; 712 tolIRMax = fRmax1 - halfRadTolerance* << 713 // tolORMax2 = (fRmax1 + halfRadTolera << 714 // (fRmax1 + halfRadTolera << 715 } 718 } 716 else 719 else 717 { 720 { 718 tolORMin = fRmin2 - halfRadTolerance* << 721 tolORMin = fRmin2 - 0.5*kRadTolerance*secRMin ; 719 tolIRMin = fRmin2 + halfRadTolerance* << 722 tolORMax2 = (fRmax2 + 0.5*kRadTolerance*secRMax)*(fRmax2 + 0.5*kRadTolerance*secRMax) ; 720 tolIRMax = fRmax2 - halfRadTolerance* << 721 // tolORMax2 = (fRmax2 + halfRadTolera << 722 // (fRmax2 + halfRadTolera << 723 } 723 } 724 if ( tolORMin > 0 ) << 724 if ( tolORMin > 0 ) tolORMin2 = tolORMin*tolORMin ; 725 { << 725 else tolORMin2 = 0.0 ; 726 // tolORMin2 = tolORMin*tolORMin ; << 726 727 tolIRMin2 = tolIRMin*tolIRMin ; << 727 if (tolORMin2 <= rho2 && rho2 <= tolORMax2) 728 } << 729 else << 730 { << 731 // tolORMin2 = 0.0 ; << 732 tolIRMin2 = 0.0 ; << 733 } << 734 if ( tolIRMax > 0 ) { tolIRMax2 = tolIR << 735 else { tolIRMax2 = 0.0; << 736 << 737 if ( (tolIRMin2 <= rhoi2) && (rhoi2 <= t << 738 { 728 { 739 if ( !fPhiFullCone && (rhoi2 != 0.0) ) << 729 if ( seg && rho2 ) 740 { << 730 { 741 // Psi = angle made with central (av << 731 // Psi = angle made with central (average) phi of shape 742 732 743 cosPsi = (xi*cosCPhi + yi*sinCPhi)/s << 733 cosPsi = (xi*cosCPhi + yi*sinCPhi)/sqrt(rho2) ; 744 734 745 if (cosPsi >= cosHDPhiIT) { return << 735 if (cosPsi >= cosHDPhiOT) return s ; 746 } << 736 } 747 else << 737 else return s ; 748 { << 749 return sd; << 750 } << 751 } 738 } 752 } 739 } 753 else // On/outside extent, and heading aw 740 else // On/outside extent, and heading away -> cannot intersect 754 { 741 { 755 return snxt ; << 742 return snxt ; 756 } 743 } 757 } 744 } 758 745 759 // ----> Can not intersect z surfaces 746 // ----> Can not intersect z surfaces 760 747 761 748 762 // Intersection with outer cone (possible retu 749 // Intersection with outer cone (possible return) and 763 // inner cone (must also che 750 // inner cone (must also check phi) 764 // 751 // 765 // Intersection point (xi,yi,zi) on line x=p.x 752 // Intersection point (xi,yi,zi) on line x=p.x+t*v.x etc. 766 // 753 // 767 // Intersects with x^2+y^2=(a*z+b)^2 754 // Intersects with x^2+y^2=(a*z+b)^2 768 // 755 // 769 // where a=tanRMax or tanRMin 756 // where a=tanRMax or tanRMin 770 // b=rMaxAv or rMinAv 757 // b=rMaxAv or rMinAv 771 // 758 // 772 // (vx^2+vy^2-(a*vz)^2)t^2+2t(pxvx+pyvy-a*vz(a 759 // (vx^2+vy^2-(a*vz)^2)t^2+2t(pxvx+pyvy-a*vz(a*pz+b))+px^2+py^2-(a*pz+b)^2=0 ; 773 // t1 t2 760 // t1 t2 t3 774 // 761 // 775 // \--------u-------/ \-----------v---- 762 // \--------u-------/ \-----------v----------/ \---------w--------/ 776 // 763 // 777 764 778 t1 = 1.0 - v.z()*v.z() ; 765 t1 = 1.0 - v.z()*v.z() ; 779 t2 = p.x()*v.x() + p.y()*v.y() ; 766 t2 = p.x()*v.x() + p.y()*v.y() ; 780 t3 = p.x()*p.x() + p.y()*p.y() ; 767 t3 = p.x()*p.x() + p.y()*p.y() ; 781 rin = tanRMin*p.z() + rMinAv ; 768 rin = tanRMin*p.z() + rMinAv ; 782 rout = tanRMax*p.z() + rMaxAv ; 769 rout = tanRMax*p.z() + rMaxAv ; 783 770 784 // Outer Cone Intersection << 771 // Outer Cone Intersection 785 // Must be outside/on outer cone for valid i << 772 // Must be outside/on outer cone for valid intersection 786 773 787 nt1 = t1 - (tanRMax*v.z())*(tanRMax*v.z()) ; 774 nt1 = t1 - (tanRMax*v.z())*(tanRMax*v.z()) ; 788 nt2 = t2 - tanRMax*v.z()*rout ; 775 nt2 = t2 - tanRMax*v.z()*rout ; 789 nt3 = t3 - rout*rout ; 776 nt3 = t3 - rout*rout ; 790 777 791 if (std::fabs(nt1) > kRadTolerance) // Equa << 778 if (fabs(nt1) > kRadTolerance) // Equation quadratic => 2 roots 792 { 779 { 793 b = nt2/nt1; << 780 if ( nt3 > rout*kRadTolerance*secRMax || rout < 0 ) 794 c = nt3/nt1; << 795 d = b*b-c ; << 796 if ( (nt3 > rout*rout*kRadTolerance*kRadTo << 797 || (rout < 0) ) << 798 { 781 { 799 // If outside real cone (should be rho-r << 782 // If outside real cone (should be rho-rout>kRadTolerance*0.5 NOT rho^2 etc) 800 // NOT rho^2 etc) saves a std::sqrt() at << 783 // saves a sqrt() at expense of accuracy >> 784 >> 785 b = nt2/nt1 ; >> 786 c = nt3/nt1 ; >> 787 d = b*b-c ; 801 788 802 if (d >= 0) 789 if (d >= 0) 803 { 790 { 804 << 791 805 if ((rout < 0) && (nt3 <= 0)) << 792 if (rout < 0 && nt3 <= 0 ) 806 { 793 { 807 // Inside `shadow cone' with -ve rad << 794 // Inside `shadow cone' with -ve radius -> 2nd root could be on real cone 808 // -> 2nd root could be on real cone << 809 795 810 if (b>0) { sd = c/(-b-std::sqrt(d)); << 796 s = -b + sqrt(d) ; 811 else { sd = -b + std::sqrt(d); << 797 } 812 } << 798 else 813 else << 799 { 814 { << 800 if ( b <= 0 && c >= 0 ) // both >=0, try smaller root 815 if ((b <= 0) && (c >= 0)) // both >= << 801 { 816 { << 802 s = -b - sqrt(d) ; 817 sd=c/(-b+std::sqrt(d)); << 803 } 818 } << 819 else 804 else 820 { << 805 { 821 if ( c <= 0 ) // second >=0 << 806 if ( c <= 0 ) // second >=0 822 { << 807 { 823 sd = -b + std::sqrt(d) ; << 808 s = -b + sqrt(d) ; 824 if((sd<0.0) && (sd>-halfRadToler << 809 } 825 } << 826 else // both negative, travel awa 810 else // both negative, travel away 827 { << 811 { 828 return kInfinity ; << 812 return kInfinity ; 829 } << 813 } 830 } << 814 } 831 } << 815 } 832 if ( sd >= 0 ) // If 'forwards'. Chec << 816 if ( s > 0 ) // If 'forwards'. Check z intersection 833 { << 817 { 834 if ( sd>dRmax ) // Avoid rounding er << 818 zi = p.z() + s*v.z() ; 835 { // 64 bits systems. << 819 836 G4double fTerm = sd-std::fmod(sd,d << 820 if (fabs(zi) <= tolODz) 837 sd = fTerm + DistanceToIn(p+fTerm* << 821 { 838 } << 822 // Z ok. Check phi intersection if reqd 839 zi = p.z() + sd*v.z() ; << 823 840 << 824 if ( ! seg ) return s ; 841 if (std::fabs(zi) <= tolODz) << 825 else 842 { << 826 { 843 // Z ok. Check phi intersection if << 827 xi = p.x() + s*v.x() ; 844 << 828 yi = p.y() + s*v.y() ; 845 if ( fPhiFullCone ) { return sd; << 829 ri = rMaxAv + zi*tanRMax ; 846 else << 830 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; 847 { << 831 848 xi = p.x() + sd*v.x() ; << 832 if ( cosPsi >= cosHDPhiOT ) return s ; 849 yi = p.y() + sd*v.y() ; << 833 } 850 ri = rMaxAv + zi*tanRMax ; << 834 } 851 cosPsi = (xi*cosCPhi + yi*sinCPh << 835 } // end if (s>0) 852 << 853 if ( cosPsi >= cosHDPhiIT ) { r << 854 } << 855 } << 856 } // end if (sd>0) << 857 } 836 } 858 } 837 } 859 else 838 else 860 { 839 { 861 // Inside outer cone << 840 // Inside outer cone 862 // check not inside, and heading through << 841 // check not inside, and heading through G4Cons (-> 0 to in) >> 842 >> 843 if ( t3 > (rin + kRadTolerance*0.5*secRMin)* >> 844 (rin + kRadTolerance*0.5*secRMin) && >> 845 nt2 < 0 && >> 846 fabs(p.z()) <= tolIDz ) >> 847 { >> 848 // Inside cones, delta r -ve, inside z extent 863 849 864 if ( ( t3 > (rin + halfRadTolerance*sec << 850 if (seg) 865 (rin + halfRadTolerance*sec << 866 && (nt2 < 0) && (d >= 0) && (std::fabs << 867 { << 868 // Inside cones, delta r -ve, inside z << 869 // Point is on the Surface => check Di << 870 << 871 xi = p.x() ; << 872 yi = p.y() ; << 873 risec = std::sqrt(xi*xi + yi*yi)*secR << 874 Normal = G4ThreeVector(xi/risec,yi/ris << 875 if ( !fPhiFullCone ) << 876 { 851 { 877 cosPsi = (p.x()*cosCPhi + p.y()*sinC << 852 cosPsi = (p.x()*cosCPhi + p.y()*sinCPhi)/sqrt(t3) ; 878 if ( cosPsi >= cosHDPhiIT ) << 853 879 { << 854 if (cosPsi >= cosHDPhiIT) return 0.0 ; 880 if ( Normal.dot(v) <= 0 ) { retur << 855 } 881 } << 856 else return 0.0 ; 882 } << 883 else << 884 { << 885 if ( Normal.dot(v) <= 0 ) { return << 886 } << 887 } 857 } 888 } 858 } 889 } 859 } 890 else // Single root case 860 else // Single root case 891 { 861 { 892 if ( std::fabs(nt2) > kRadTolerance ) << 862 if ( fabs(nt2) > kRadTolerance ) 893 { 863 { 894 sd = -0.5*nt3/nt2 ; << 864 s = -0.5*nt3/nt2 ; 895 865 896 if ( sd < 0 ) { return kInfinity; } / << 866 if ( s < 0 ) return kInfinity ; // travel away 897 else // sd >= 0, If 'forwards'. Check << 867 else // s >= 0, If 'forwards'. Check z intersection 898 { 868 { 899 zi = p.z() + sd*v.z() ; << 869 zi = p.z() + s*v.z() ; 900 << 901 if ((std::fabs(zi) <= tolODz) && (nt2 << 902 { << 903 // Z ok. Check phi intersection if r << 904 870 905 if ( fPhiFullCone ) { return sd; } << 871 if (fabs(zi) <= tolODz && nt2 < 0) 906 else << 872 { 907 { << 873 // Z ok. Check phi intersection if reqd 908 xi = p.x() + sd*v.x() ; << 874 909 yi = p.y() + sd*v.y() ; << 875 if ( ! seg ) return s ; 910 ri = rMaxAv + zi*tanRMax ; << 876 else 911 cosPsi = (xi*cosCPhi + yi*sinCPhi) << 877 { 912 << 878 xi = p.x() + s*v.x() ; 913 if (cosPsi >= cosHDPhiIT) { retur << 879 yi = p.y() + s*v.y() ; 914 } << 880 ri = rMaxAv + zi*tanRMax ; 915 } << 881 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; 916 } << 882 >> 883 if (cosPsi >= cosHDPhiOT) return s ; >> 884 } >> 885 } >> 886 } 917 } 887 } 918 else // travel || cone surface from it 888 else // travel || cone surface from its origin 919 { 889 { 920 sd = kInfinity ; << 890 s = kInfinity ; 921 } 891 } 922 } 892 } 923 893 924 // Inner Cone Intersection << 894 // Inner Cone Intersection 925 // o Space is divided into 3 areas: << 895 // o Space is divided into 3 areas: 926 // 1) Radius greater than real inner cone << 896 // 1) Radius greater than real inner cone & imaginary cone & outside 927 // tolerance << 897 // tolerance 928 // 2) Radius less than inner or imaginary << 898 // 2) Radius less than inner or imaginary cone & outside tolarance 929 // 3) Within tolerance of real or imaginar << 899 // 3) Within tolerance of real or imaginary cones 930 // - Extra checks needed for 3's inters << 900 // - Extra checks needed for 3's intersections => lots of duplicated code 931 // => lots of duplicated code << 932 901 933 if (rMinAv != 0.0) << 902 if (rMinAv) 934 { << 903 { 935 nt1 = t1 - (tanRMin*v.z())*(tanRMin*v.z()) 904 nt1 = t1 - (tanRMin*v.z())*(tanRMin*v.z()) ; 936 nt2 = t2 - tanRMin*v.z()*rin ; 905 nt2 = t2 - tanRMin*v.z()*rin ; 937 nt3 = t3 - rin*rin ; 906 nt3 = t3 - rin*rin ; 938 907 939 if ( nt1 != 0.0 ) << 908 if ( nt1 ) 940 { 909 { 941 if ( nt3 > rin*kRadTolerance*secRMin ) 910 if ( nt3 > rin*kRadTolerance*secRMin ) 942 { 911 { 943 // At radius greater than real & imagi << 912 // At radius greater than real & imaginary cones 944 // -> 2nd root, with zi check << 913 // -> 2nd root, with zi check 945 914 946 b = nt2/nt1 ; 915 b = nt2/nt1 ; 947 c = nt3/nt1 ; 916 c = nt3/nt1 ; 948 d = b*b-c ; << 917 d = b*b-c ; 949 if (d >= 0) // > 0 << 918 if (d > 0) 950 { << 919 { 951 if(b>0){sd = c/( -b-std::sqrt(d));} << 920 s = -b + sqrt(d) ; 952 else {sd = -b + std::sqrt(d) ;} << 921 953 << 922 if ( s > 0 ) 954 if ( sd >= 0 ) // > 0 << 923 { 955 { << 924 zi = p.z() + s*v.z() ; 956 if ( sd>dRmax ) // Avoid rounding << 925 957 { // 64 bits systems << 926 if ( fabs(zi) <= tolODz ) 958 G4double fTerm = sd-std::fmod(sd << 927 { 959 sd = fTerm + DistanceToIn(p+fTer << 928 if ( seg ) 960 } << 929 { 961 zi = p.z() + sd*v.z() ; << 930 xi = p.x() + s*v.x() ; 962 << 931 yi = p.y() + s*v.y() ; 963 if ( std::fabs(zi) <= tolODz ) << 932 ri = rMinAv + zi*tanRMin ; 964 { << 933 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; 965 if ( !fPhiFullCone ) << 934 966 { << 935 if (cosPsi >= cosHDPhiOT) snxt = s ; 967 xi = p.x() + sd*v.x() ; << 936 } 968 yi = p.y() + sd*v.y() ; << 937 else return s ; 969 ri = rMinAv + zi*tanRMin ; << 938 } 970 cosPsi = (xi*cosCPhi + yi*sinC << 939 } 971 << 940 } 972 if (cosPsi >= cosHDPhiIT) << 973 { << 974 if ( sd > halfRadTolerance ) << 975 else << 976 { << 977 // Calculate a normal vect << 978 << 979 risec = std::sqrt(xi*xi + << 980 Normal = G4ThreeVector(-xi << 981 if ( Normal.dot(v) <= 0 ) << 982 } << 983 } << 984 } << 985 else << 986 { << 987 if ( sd > halfRadTolerance ) << 988 else << 989 { << 990 // Calculate a normal vector << 991 << 992 xi = p.x() + sd*v.x() ; << 993 yi = p.y() + sd*v.y() ; << 994 risec = std::sqrt(xi*xi + y << 995 Normal = G4ThreeVector(-xi/r << 996 if ( Normal.dot(v) <= 0 ) { << 997 } << 998 } << 999 } << 1000 } << 1001 } << 1002 } 941 } 1003 else if ( nt3 < -rin*kRadTolerance*sec 942 else if ( nt3 < -rin*kRadTolerance*secRMin ) 1004 { 943 { 1005 // Within radius of inner cone (real << 944 // Within radius of inner cone (real or imaginary) 1006 // -> Try 2nd root, with checking int << 945 // -> Try 2nd root, with checking intersection is with real cone 1007 // -> If check fails, try 1st root, a << 946 // -> If check fails, try 1st root, also checking intersection is on real cone 1008 // on real cone << 1009 947 1010 b = nt2/nt1 ; 948 b = nt2/nt1 ; 1011 c = nt3/nt1 ; << 949 c = nt3/nt1 ; 1012 d = b*b - c ; << 950 d = b*b - c ; 1013 951 1014 if ( d >= 0 ) // > 0 << 952 if ( d > 0 ) 1015 { 953 { 1016 if (b>0) { sd = c/(-b-std::sqrt(d)) << 954 s = -b + sqrt(d) ; 1017 else { sd = -b + std::sqrt(d); << 955 zi = p.z() + s*v.z() ; 1018 zi = p.z() + sd*v.z() ; << 956 ri = rMinAv + zi*tanRMin ; 1019 ri = rMinAv + zi*tanRMin ; << 957 1020 << 958 if ( ri >= 0 ) 1021 if ( ri > 0 ) << 959 { 1022 { << 960 if ( s > 0 && fabs(zi) <= tolODz ) 1023 if ( (sd >= 0) && (std::fabs(zi) << 961 { 1024 { << 962 if ( seg ) 1025 if ( sd>dRmax ) // Avoid roundi << 963 { 1026 { // seen on 64 b << 964 xi = p.x() + s*v.x() ; 1027 G4double fTerm = sd-std::fmod << 965 yi = p.y() + s*v.y() ; 1028 sd = fTerm + DistanceToIn(p+f << 966 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; 1029 } << 967 1030 if ( !fPhiFullCone ) << 968 if (cosPsi >= cosHDPhiOT) snxt = s ; 1031 { << 969 } 1032 xi = p.x() + sd*v.x() ; << 970 else return s ; 1033 yi = p.y() + sd*v.y() ; << 971 } 1034 cosPsi = (xi*cosCPhi + yi*sin << 972 } 1035 << 973 else 1036 if (cosPsi >= cosHDPhiOT) << 974 { 1037 { << 975 s = -b - sqrt(d) ; 1038 if ( sd > halfRadTolerance << 976 zi = p.z() + s*v.z() ; 1039 else << 977 ri = rMinAv + zi*tanRMin ; 1040 { << 978 1041 // Calculate a normal vec << 979 if ( s > 0 && ri >= 0 && fabs(zi) <= tolODz ) 1042 << 980 { 1043 risec = std::sqrt(xi*xi << 981 if ( seg ) 1044 Normal = G4ThreeVector(-x << 982 { 1045 if ( Normal.dot(v) <= 0 ) << 983 xi = p.x() + s*v.x() ; 1046 } << 984 yi = p.y() + s*v.y() ; 1047 } << 985 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; 1048 } << 986 1049 else << 987 if (cosPsi >= cosHDPhiOT) snxt = s ; 1050 { << 988 } 1051 if( sd > halfRadTolerance ) << 989 else return s ; 1052 else << 990 } 1053 { << 991 } 1054 // Calculate a normal vecto << 992 } 1055 << 1056 xi = p.x() + sd*v.x() ; << 1057 yi = p.y() + sd*v.y() ; << 1058 risec = std::sqrt(xi*xi + << 1059 Normal = G4ThreeVector(-xi/ << 1060 if ( Normal.dot(v) <= 0 ) << 1061 } << 1062 } << 1063 } << 1064 } << 1065 else << 1066 { << 1067 if (b>0) { sd = -b - std::sqrt(d) << 1068 else { sd = c/(-b+std::sqrt(d << 1069 zi = p.z() + sd*v.z() ; << 1070 ri = rMinAv + zi*tanRMin ; << 1071 << 1072 if ( (sd >= 0) && (ri > 0) && (st << 1073 { << 1074 if ( sd>dRmax ) // Avoid roundi << 1075 { // seen on 64 b << 1076 G4double fTerm = sd-std::fmod << 1077 sd = fTerm + DistanceToIn(p+f << 1078 } << 1079 if ( !fPhiFullCone ) << 1080 { << 1081 xi = p.x() + sd*v.x() ; << 1082 yi = p.y() + sd*v.y() ; << 1083 cosPsi = (xi*cosCPhi + yi*sin << 1084 << 1085 if (cosPsi >= cosHDPhiIT) << 1086 { << 1087 if ( sd > halfRadTolerance << 1088 else << 1089 { << 1090 // Calculate a normal vec << 1091 << 1092 risec = std::sqrt(xi*xi << 1093 Normal = G4ThreeVector(-x << 1094 if ( Normal.dot(v) <= 0 ) << 1095 } << 1096 } << 1097 } << 1098 else << 1099 { << 1100 if ( sd > halfRadTolerance ) << 1101 else << 1102 { << 1103 // Calculate a normal vecto << 1104 << 1105 xi = p.x() + sd*v.x() ; << 1106 yi = p.y() + sd*v.y() ; << 1107 risec = std::sqrt(xi*xi + << 1108 Normal = G4ThreeVector(-xi/ << 1109 if ( Normal.dot(v) <= 0 ) << 1110 } << 1111 } << 1112 } << 1113 } << 1114 } << 1115 } 993 } 1116 else 994 else 1117 { 995 { 1118 // Within kRadTol*0.5 of inner cone ( << 996 // Within kRadTol*0.5 of inner cone (real OR imaginary) 1119 // ----> Check not travelling through << 997 // ----> Check not travelling through (=>0 to in) 1120 // ----> if not: << 998 // ----> if not: 1121 // -2nd root with validity check << 999 // -2nd root with validity check 1122 << 1000 1123 if ( std::fabs(p.z()) <= tolODz ) << 1001 if ( fabs(p.z()) <= tolODz ) 1124 { << 1002 { 1125 if ( nt2 > 0 ) << 1003 if ( nt2 > 0 ) 1126 { << 1004 { 1127 // Inside inner real cone, headin << 1005 // Inside inner real cone, heading outwards, inside z range 1128 << 1006 1129 if ( !fPhiFullCone ) << 1007 if ( seg ) 1130 { << 1008 { 1131 cosPsi = (p.x()*cosCPhi + p.y() << 1009 cosPsi = (p.x()*cosCPhi + p.y()*sinCPhi)/sqrt(t3) ; 1132 << 1010 1133 if (cosPsi >= cosHDPhiIT) { re << 1011 if (cosPsi >= cosHDPhiIT) return 0.0 ; 1134 } << 1012 } 1135 else { return 0.0; } << 1013 else return 0.0 ; 1136 } << 1014 } 1137 else << 1015 else 1138 { << 1016 { 1139 // Within z extent, but not trave << 1017 // Within z extent, but not travelling through 1140 // -> 2nd root or kInfinity if 1s << 1018 // -> 2nd root or kInfinity if 1st root on imaginary cone 1141 << 1019 1142 b = nt2/nt1 ; << 1020 b = nt2/nt1 ; 1143 c = nt3/nt1 ; << 1021 c = nt3/nt1 ; 1144 d = b*b - c ; << 1022 d = b*b - c ; 1145 << 1023 1146 if ( d >= 0 ) // > 0 << 1024 if ( d > 0 ) 1147 { << 1025 { 1148 if (b>0) { sd = -b - std::sqrt( << 1026 s = -b - sqrt(d) ; 1149 else { sd = c/(-b+std::sqrt << 1027 zi = p.z() + s*v.z() ; 1150 zi = p.z() + sd*v.z() ; << 1028 ri = rMinAv + zi*tanRMin ; 1151 ri = rMinAv + zi*tanRMin ; << 1029 1152 << 1030 if ( ri > 0 ) // 2nd root 1153 if ( ri > 0 ) // 2nd root << 1031 { 1154 { << 1032 s = -b + sqrt(d) ; 1155 if (b>0) { sd = c/(-b-std::sq << 1033 zi = p.z() + s*v.z() ; 1156 else { sd = -b + std::sqr << 1034 1157 << 1035 if ( s > 0 && fabs(zi) <= tolODz ) 1158 zi = p.z() + sd*v.z() ; << 1036 { 1159 << 1037 if ( seg ) 1160 if ( (sd >= 0) && (std::fabs( << 1038 { 1161 { << 1039 xi = p.x() + s*v.x() ; 1162 if ( sd>dRmax ) // Avoid ro << 1040 yi = p.y() + s*v.y() ; 1163 { // seen on << 1041 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; 1164 G4double fTerm = sd-std:: << 1042 1165 sd = fTerm + DistanceToIn << 1043 if ( cosPsi >= cosHDPhiOT ) snxt = s ; 1166 } << 1044 } 1167 if ( !fPhiFullCone ) << 1045 else return s ; 1168 { << 1046 } 1169 xi = p.x() + sd*v.x() << 1047 } 1170 yi = p.y() + sd*v.y() << 1048 else return kInfinity ; 1171 ri = rMinAv + zi*tanR << 1049 } 1172 cosPsi = (xi*cosCPhi + yi << 1050 } 1173 << 1051 } 1174 if ( cosPsi >= cosHDPhiIT << 1175 } << 1176 else { return sd; } << 1177 } << 1178 } << 1179 else { return kInfinity; } << 1180 } << 1181 } << 1182 } << 1183 else // 2nd root 1052 else // 2nd root 1184 { << 1053 { 1185 b = nt2/nt1 ; << 1054 b = nt2/nt1 ; 1186 c = nt3/nt1 ; << 1055 c = nt3/nt1 ; 1187 d = b*b - c ; << 1056 d = b*b - c ; 1188 << 1057 1189 if ( d > 0 ) << 1058 if ( d > 0 ) 1190 { << 1059 { 1191 if (b>0) { sd = c/(-b-std::sqrt(d << 1060 s = -b + sqrt(d) ; 1192 else { sd = -b + std::sqrt(d) << 1061 zi = p.z() + s*v.z() ; 1193 zi = p.z() + sd*v.z() ; << 1062 1194 << 1063 if ( s > 0 && fabs(zi) <= tolODz ) 1195 if ( (sd >= 0) && (std::fabs(zi) << 1064 { 1196 { << 1065 if ( seg ) 1197 if ( sd>dRmax ) // Avoid roundi << 1066 { 1198 { // seen on 64 b << 1067 xi = p.x() + s*v.x() ; 1199 G4double fTerm = sd-std::fmod << 1068 yi = p.y() + s*v.y() ; 1200 sd = fTerm + DistanceToIn(p+f << 1069 cosPsi = (xi*cosCPhi + yi*sinCPhi)/ri ; 1201 } << 1070 1202 if ( !fPhiFullCone ) << 1071 if (cosPsi >= cosHDPhiOT) snxt = s ; 1203 { << 1072 } 1204 xi = p.x() + sd*v.x(); << 1073 else return s ; 1205 yi = p.y() + sd*v.y(); << 1074 } 1206 ri = rMinAv + zi*tanRMin << 1075 } 1207 cosPsi = (xi*cosCPhi + yi*sin << 1076 } 1208 << 1209 if (cosPsi >= cosHDPhiIT) { << 1210 } << 1211 else { return sd; } << 1212 } << 1213 } << 1214 } << 1215 } 1077 } 1216 } 1078 } 1217 } 1079 } 1218 1080 1219 // Phi segment intersection << 1081 // Phi segment intersection 1220 // << 1082 // 1221 // o Tolerant of points inside phi planes b << 1083 // o Tolerant of points inside phi planes by up to kCarTolerance*0.5 1222 // << 1084 // 1223 // o NOTE: Large duplication of code betwee << 1085 // o NOTE: Large duplication of code between sphi & ephi checks 1224 // -> only diffs: sphi -> ephi, Com << 1086 // -> only diffs: sphi -> ephi, Comp -> -Comp and half-plane 1225 // intersection check <=0 -> >=0 << 1087 // intersection check <=0 -> >=0 1226 // -> Should use some form of loop << 1088 // -> Should use some form of loop Construct 1227 1089 1228 if ( !fPhiFullCone ) << 1090 if ( seg ) 1229 { 1091 { 1230 // First phi surface (starting phi) << 1092 // First phi surface (`S'tarting phi) 1231 1093 >> 1094 sinSPhi = sin(fSPhi) ; >> 1095 cosSPhi = cos(fSPhi) ; 1232 Comp = v.x()*sinSPhi - v.y()*cosSPhi ; 1096 Comp = v.x()*sinSPhi - v.y()*cosSPhi ; 1233 << 1097 1234 if ( Comp < 0 ) // Component in outwar 1098 if ( Comp < 0 ) // Component in outwards normal dirn 1235 { 1099 { 1236 Dist = (p.y()*cosSPhi - p.x()*sinSPhi) 1100 Dist = (p.y()*cosSPhi - p.x()*sinSPhi) ; 1237 1101 1238 if (Dist < halfCarTolerance) << 1102 if (Dist < kCarTolerance*0.5) 1239 { 1103 { 1240 sd = Dist/Comp ; << 1104 s = Dist/Comp ; 1241 << 1242 if ( sd < snxt ) << 1243 { << 1244 if ( sd < 0 ) { sd = 0.0; } << 1245 << 1246 zi = p.z() + sd*v.z() ; << 1247 << 1248 if ( std::fabs(zi) <= tolODz ) << 1249 { << 1250 xi = p.x() + sd*v.x() ; << 1251 yi = p.y() + sd*v.y() ; << 1252 rhoi2 = xi*xi + yi*yi ; << 1253 tolORMin2 = (rMinOAv + zi*tanRMin << 1254 tolORMax2 = (rMaxOAv + zi*tanRMax << 1255 << 1256 if ( (rhoi2 >= tolORMin2) && (rho << 1257 { << 1258 // z and r intersections good - << 1259 // correct half-plane << 1260 << 1261 if ((yi*cosCPhi - xi*sinCPhi) < << 1262 } << 1263 } << 1264 } << 1265 } << 1266 } << 1267 << 1268 // Second phi surface (Ending phi) << 1269 1105 >> 1106 if ( s < snxt ) >> 1107 { >> 1108 if ( s < 0 ) s = 0.0 ; >> 1109 >> 1110 zi = p.z() + s*v.z() ; >> 1111 >> 1112 if ( fabs(zi) <= tolODz ) >> 1113 { >> 1114 xi = p.x() + s*v.x() ; >> 1115 yi = p.y() + s*v.y() ; >> 1116 rho2 = xi*xi + yi*yi ; >> 1117 tolORMin2 = (rMinOAv + zi*tanRMin)*(rMinOAv + zi*tanRMin) ; >> 1118 tolORMax2 = (rMaxOAv + zi*tanRMax)*(rMaxOAv + zi*tanRMax) ; >> 1119 >> 1120 if ( rho2 >= tolORMin2 && rho2 <= tolORMax2 ) >> 1121 { >> 1122 // z and r intersections good - check intersecting with correct half-plane >> 1123 >> 1124 if ((yi*cosCPhi - xi*sinCPhi) <= 0 ) snxt = s ; >> 1125 } >> 1126 } >> 1127 } >> 1128 } >> 1129 } >> 1130 // Second phi surface (`E'nding phi) >> 1131 >> 1132 ePhi = fSPhi + fDPhi ; >> 1133 sinEPhi = sin(ePhi) ; >> 1134 cosEPhi = cos(ePhi) ; 1270 Comp = -(v.x()*sinEPhi - v.y()*cosEPhi 1135 Comp = -(v.x()*sinEPhi - v.y()*cosEPhi) ; 1271 << 1136 1272 if ( Comp < 0 ) // Component in outward 1137 if ( Comp < 0 ) // Component in outwards normal dirn 1273 { 1138 { 1274 Dist = -(p.y()*cosEPhi - p.x()*sinEPhi) 1139 Dist = -(p.y()*cosEPhi - p.x()*sinEPhi) ; 1275 if (Dist < halfCarTolerance) << 1140 if (Dist < kCarTolerance*0.5) 1276 { 1141 { 1277 sd = Dist/Comp ; << 1142 s = Dist/Comp ; 1278 1143 1279 if ( sd < snxt ) << 1144 if ( s < snxt ) 1280 { << 1145 { 1281 if ( sd < 0 ) { sd = 0.0; } << 1146 if ( s < 0 ) s = 0.0 ; 1282 1147 1283 zi = p.z() + sd*v.z() ; << 1148 zi = p.z() + s*v.z() ; 1284 1149 1285 if (std::fabs(zi) <= tolODz) << 1150 if (fabs(zi) <= tolODz) 1286 { << 1151 { 1287 xi = p.x() + sd*v.x() ; << 1152 xi = p.x() + s*v.x() ; 1288 yi = p.y() + sd*v.y() ; << 1153 yi = p.y() + s*v.y() ; 1289 rhoi2 = xi*xi + yi*yi ; << 1154 rho2 = xi*xi + yi*yi ; 1290 tolORMin2 = (rMinOAv + zi*tanRMin << 1155 tolORMin2 = (rMinOAv + zi*tanRMin)*(rMinOAv + zi*tanRMin) ; 1291 tolORMax2 = (rMaxOAv + zi*tanRMax << 1156 tolORMax2 = (rMaxOAv + zi*tanRMax)*(rMaxOAv + zi*tanRMax) ; 1292 1157 1293 if ( (rhoi2 >= tolORMin2) && (rho << 1158 if ( rho2 >= tolORMin2 && rho2 <= tolORMax2 ) 1294 { << 1159 { 1295 // z and r intersections good - << 1160 // z and r intersections good - check intersecting with correct half-plane 1296 // correct half-plane << 1297 1161 1298 if ( (yi*cosCPhi - xi*sinCPhi) << 1162 if ( (yi*cosCPhi - xi*sinCPhi) >= 0.0 ) snxt = s ; 1299 } << 1163 } 1300 } << 1164 } 1301 } << 1165 } 1302 } 1166 } 1303 } 1167 } 1304 } 1168 } 1305 if (snxt < halfCarTolerance) { snxt = 0.; << 1169 if (snxt < kCarTolerance*0.5) snxt = 0.; 1306 << 1307 return snxt ; 1170 return snxt ; 1308 } 1171 } 1309 1172 1310 ///////////////////////////////////////////// 1173 ////////////////////////////////////////////////////////////////////////////// 1311 // 1174 // 1312 // Calculate distance (<= actual) to closest 1175 // Calculate distance (<= actual) to closest surface of shape from outside 1313 // - Calculate distance to z, radial planes 1176 // - Calculate distance to z, radial planes 1314 // - Only to phi planes if outside phi extent 1177 // - Only to phi planes if outside phi extent 1315 // - Return 0 if point inside 1178 // - Return 0 if point inside 1316 1179 1317 G4double G4Cons::DistanceToIn(const G4ThreeVe 1180 G4double G4Cons::DistanceToIn(const G4ThreeVector& p) const 1318 { 1181 { 1319 G4double safe=0.0, rho, safeR1, safeR2, saf << 1182 G4double safe, rho, safeR1, safeR2, safeZ ; 1320 G4double tanRMin, secRMin, pRMin ; 1183 G4double tanRMin, secRMin, pRMin ; 1321 G4double tanRMax, secRMax, pRMax ; 1184 G4double tanRMax, secRMax, pRMax ; >> 1185 G4double phiC, cosPhiC, sinPhiC, safePhi, ePhi ; >> 1186 G4double cosPsi ; 1322 1187 1323 rho = std::sqrt(p.x()*p.x() + p.y()*p.y() << 1188 rho = sqrt(p.x()*p.x() + p.y()*p.y()) ; 1324 safeZ = std::fabs(p.z()) - fDz ; << 1189 safeZ = fabs(p.z()) - fDz ; 1325 1190 1326 if ( (fRmin1 != 0.0) || (fRmin2 != 0.0) ) << 1191 if ( fRmin1 || fRmin2 ) 1327 { 1192 { 1328 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; 1193 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; 1329 secRMin = std::sqrt(1.0 + tanRMin*tanRMin << 1194 secRMin = sqrt(1.0 + tanRMin*tanRMin) ; 1330 pRMin = tanRMin*p.z() + (fRmin1 + fRmin 1195 pRMin = tanRMin*p.z() + (fRmin1 + fRmin2)*0.5 ; 1331 safeR1 = (pRMin - rho)/secRMin ; 1196 safeR1 = (pRMin - rho)/secRMin ; 1332 1197 1333 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; 1198 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; 1334 secRMax = std::sqrt(1.0 + tanRMax*tanRMax << 1199 secRMax = sqrt(1.0 + tanRMax*tanRMax) ; 1335 pRMax = tanRMax*p.z() + (fRmax1 + fRmax 1200 pRMax = tanRMax*p.z() + (fRmax1 + fRmax2)*0.5 ; 1336 safeR2 = (rho - pRMax)/secRMax ; 1201 safeR2 = (rho - pRMax)/secRMax ; 1337 1202 1338 if ( safeR1 > safeR2) { safe = safeR1; } << 1203 if ( safeR1 > safeR2) safe = safeR1 ; 1339 else { safe = safeR2; } << 1204 else safe = safeR2 ; 1340 } 1205 } 1341 else 1206 else 1342 { 1207 { 1343 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; 1208 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; 1344 secRMax = std::sqrt(1.0 + tanRMax*tanRMax << 1209 secRMax = sqrt(1.0 + tanRMax*tanRMax) ; 1345 pRMax = tanRMax*p.z() + (fRmax1 + fRmax 1210 pRMax = tanRMax*p.z() + (fRmax1 + fRmax2)*0.5 ; 1346 safe = (rho - pRMax)/secRMax ; 1211 safe = (rho - pRMax)/secRMax ; 1347 } 1212 } 1348 if ( safeZ > safe ) { safe = safeZ; } << 1213 if ( safeZ > safe ) safe = safeZ ; 1349 1214 1350 if ( !fPhiFullCone && (rho != 0.0) ) << 1215 if ( fDPhi < 2.0*M_PI && rho ) 1351 { 1216 { 1352 // Psi=angle from central phi to point << 1217 phiC = fSPhi + fDPhi*0.5 ; >> 1218 cosPhiC = cos(phiC) ; >> 1219 sinPhiC = sin(phiC) ; 1353 1220 1354 cosPsi = (p.x()*cosCPhi + p.y()*sinCPhi)/ << 1221 // Psi=angle from central phi to point 1355 1222 1356 if ( cosPsi < cosHDPhi ) // Point lies ou << 1223 cosPsi = (p.x()*cosPhiC + p.y()*sinPhiC)/rho ; >> 1224 >> 1225 if ( cosPsi < cos(fDPhi*0.5) ) // Point lies outside phi range 1357 { 1226 { 1358 if ( (p.y()*cosCPhi - p.x()*sinCPhi) <= << 1227 if ( (p.y()*cosPhiC - p.x()*sinPhiC) <= 0.0 ) 1359 { 1228 { 1360 safePhi = std::fabs(p.x()*sinSPhi-p.y << 1229 safePhi = fabs(p.x()*sin(fSPhi) - p.y()*cos(fSPhi)) ; 1361 } 1230 } 1362 else 1231 else 1363 { 1232 { 1364 safePhi = std::fabs(p.x()*sinEPhi-p.y << 1233 ePhi = fSPhi + fDPhi ; >> 1234 safePhi = fabs(p.x()*sin(ePhi) - p.y()*cos(ePhi)) ; 1365 } 1235 } 1366 if ( safePhi > safe ) { safe = safePhi << 1236 if ( safePhi > safe ) safe = safePhi ; 1367 } 1237 } 1368 } 1238 } 1369 if ( safe < 0.0 ) { safe = 0.0; } << 1239 if ( safe < 0.0 ) safe = 0.0 ; 1370 1240 1371 return safe ; 1241 return safe ; 1372 } 1242 } 1373 1243 1374 ///////////////////////////////////////////// 1244 /////////////////////////////////////////////////////////////// 1375 // 1245 // 1376 // Calculate distance to surface of shape fro << 1246 // Calculate distance to surface of shape from `inside', allowing for tolerance 1377 // - Only Calc rmax intersection if no valid 1247 // - Only Calc rmax intersection if no valid rmin intersection 1378 1248 1379 G4double G4Cons::DistanceToOut( const G4Three 1249 G4double G4Cons::DistanceToOut( const G4ThreeVector& p, 1380 const G4Three << 1250 const G4ThreeVector& v, 1381 const G4bool << 1251 const G4bool calcNorm, 1382 G4bool* << 1252 G4bool *validNorm, 1383 G4Three << 1253 G4ThreeVector *n) const 1384 { 1254 { 1385 ESide side = kNull, sider = kNull, sidephi 1255 ESide side = kNull, sider = kNull, sidephi = kNull; 1386 1256 1387 G4double snxt,srd,sphi,pdist ; << 1257 G4double snxt,sr,sphi,pdist ; 1388 1258 1389 G4double tanRMax, secRMax, rMaxAv ; // Dat << 1259 G4double tanRMax, secRMax, rMaxAv ; // Data for outer cone 1390 G4double tanRMin, secRMin, rMinAv ; // Dat << 1260 G4double tanRMin, secRMin, rMinAv ; // Data for inner cone 1391 1261 1392 G4double t1, t2, t3, rout, rin, nt1, nt2, n 1262 G4double t1, t2, t3, rout, rin, nt1, nt2, nt3 ; 1393 G4double b, c, d, sr2, sr3 ; 1263 G4double b, c, d, sr2, sr3 ; 1394 1264 1395 // Vars for intersection within tolerance << 1265 // Vars for intersection within tolerance 1396 1266 1397 ESide sidetol = kNull ; << 1267 ESide sidetol ; 1398 G4double slentol = kInfinity ; 1268 G4double slentol = kInfinity ; 1399 1269 1400 // Vars for phi intersection: << 1270 // Vars for phi intersection: 1401 1271 >> 1272 G4double sinSPhi, cosSPhi, ePhi, sinEPhi, cosEPhi ; >> 1273 G4double cPhi, sinCPhi, cosCPhi ; 1402 G4double pDistS, compS, pDistE, compE, sphi 1274 G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, risec, vphi ; 1403 G4double zi, ri, deltaRoi2 ; 1275 G4double zi, ri, deltaRoi2 ; 1404 1276 1405 // Z plane intersection << 1277 // Z plane intersection 1406 1278 1407 if ( v.z() > 0.0 ) 1279 if ( v.z() > 0.0 ) 1408 { 1280 { 1409 pdist = fDz - p.z() ; 1281 pdist = fDz - p.z() ; 1410 1282 1411 if (pdist > halfCarTolerance) << 1283 if (pdist > kCarTolerance*0.5) 1412 { 1284 { 1413 snxt = pdist/v.z() ; 1285 snxt = pdist/v.z() ; 1414 side = kPZ ; 1286 side = kPZ ; 1415 } 1287 } 1416 else 1288 else 1417 { 1289 { 1418 if (calcNorm) 1290 if (calcNorm) 1419 { 1291 { 1420 *n = G4ThreeVector(0,0,1) ; << 1292 *n = G4ThreeVector(0,0,1) ; 1421 *validNorm = true ; << 1293 *validNorm = true ; 1422 } 1294 } 1423 return snxt = 0.0; << 1295 return snxt = 0.0 ; 1424 } 1296 } 1425 } 1297 } 1426 else if ( v.z() < 0.0 ) 1298 else if ( v.z() < 0.0 ) 1427 { 1299 { 1428 pdist = fDz + p.z() ; 1300 pdist = fDz + p.z() ; 1429 1301 1430 if ( pdist > halfCarTolerance) << 1302 if ( pdist > kCarTolerance*0.5) 1431 { 1303 { 1432 snxt = -pdist/v.z() ; 1304 snxt = -pdist/v.z() ; 1433 side = kMZ ; 1305 side = kMZ ; 1434 } 1306 } 1435 else 1307 else 1436 { 1308 { 1437 if ( calcNorm ) 1309 if ( calcNorm ) 1438 { 1310 { 1439 *n = G4ThreeVector(0,0,-1) ; << 1311 *n = G4ThreeVector(0,0,-1) ; 1440 *validNorm = true ; << 1312 *validNorm = true ; 1441 } 1313 } 1442 return snxt = 0.0 ; 1314 return snxt = 0.0 ; 1443 } 1315 } 1444 } 1316 } 1445 else // Travel perpendicular to z axis 1317 else // Travel perpendicular to z axis 1446 { 1318 { 1447 snxt = kInfinity ; << 1319 snxt = kInfinity ; 1448 side = kNull ; 1320 side = kNull ; 1449 } 1321 } 1450 1322 1451 // Radial Intersections << 1323 // Radial Intersections 1452 // << 1324 // 1453 // Intersection with outer cone (possible r << 1325 // Intersection with outer cone (possible return) and 1454 // inner cone (must also << 1326 // inner cone (must also check phi) 1455 // << 1327 // 1456 // Intersection point (xi,yi,zi) on line x= << 1328 // Intersection point (xi,yi,zi) on line x=p.x+t*v.x etc. 1457 // << 1329 // 1458 // Intersects with x^2+y^2=(a*z+b)^2 << 1330 // Intersects with x^2+y^2=(a*z+b)^2 1459 // << 1331 // 1460 // where a=tanRMax or tanRMin << 1332 // where a=tanRMax or tanRMin 1461 // b=rMaxAv or rMinAv << 1333 // b=rMaxAv or rMinAv 1462 // << 1334 // 1463 // (vx^2+vy^2-(a*vz)^2)t^2+2t(pxvx+pyvy-a*v << 1335 // (vx^2+vy^2-(a*vz)^2)t^2+2t(pxvx+pyvy-a*vz(a*pz+b))+px^2+py^2-(a*pz+b)^2=0 ; 1464 // t1 t2 << 1336 // t1 t2 t3 1465 // << 1337 // 1466 // \--------u-------/ \-----------v- << 1338 // \--------u-------/ \-----------v----------/ \---------w--------/ 1467 1339 1468 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; 1340 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; 1469 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) << 1341 secRMax = sqrt(1.0 + tanRMax*tanRMax) ; 1470 rMaxAv = (fRmax1 + fRmax2)*0.5 ; 1342 rMaxAv = (fRmax1 + fRmax2)*0.5 ; 1471 1343 1472 1344 1473 t1 = 1.0 - v.z()*v.z() ; // since v << 1345 t1 = 1.0 - v.z()*v.z() ; // since v normalised 1474 t2 = p.x()*v.x() + p.y()*v.y() ; 1346 t2 = p.x()*v.x() + p.y()*v.y() ; 1475 t3 = p.x()*p.x() + p.y()*p.y() ; 1347 t3 = p.x()*p.x() + p.y()*p.y() ; 1476 rout = tanRMax*p.z() + rMaxAv ; 1348 rout = tanRMax*p.z() + rMaxAv ; 1477 1349 1478 nt1 = t1 - (tanRMax*v.z())*(tanRMax*v.z()) 1350 nt1 = t1 - (tanRMax*v.z())*(tanRMax*v.z()) ; 1479 nt2 = t2 - tanRMax*v.z()*rout ; 1351 nt2 = t2 - tanRMax*v.z()*rout ; 1480 nt3 = t3 - rout*rout ; 1352 nt3 = t3 - rout*rout ; 1481 1353 1482 if (v.z() > 0.0) 1354 if (v.z() > 0.0) 1483 { 1355 { 1484 deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3 << 1356 deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3 - fRmax2*(fRmax2 + kRadTolerance*secRMax); 1485 - fRmax2*(fRmax2 + kRadTolera << 1486 } 1357 } 1487 else if (v.z() < 0.0) << 1358 else if ( v.z() < 0.0 ) 1488 { << 1489 deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3 << 1490 - fRmax1*(fRmax1 + kRadTolera << 1491 } << 1492 else << 1493 { 1359 { 1494 deltaRoi2 = 1.0; << 1360 deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3 - fRmax1*(fRmax1 + kRadTolerance*secRMax); 1495 } 1361 } >> 1362 else deltaRoi2 = 1.0 ; 1496 1363 1497 if ( (nt1 != 0.0) && (deltaRoi2 > 0.0) ) << 1364 if ( nt1 && deltaRoi2 > 0.0 ) 1498 { 1365 { 1499 // Equation quadratic => 2 roots : second << 1366 // Equation quadratic => 2 roots : second root must be leaving 1500 1367 1501 b = nt2/nt1 ; 1368 b = nt2/nt1 ; 1502 c = nt3/nt1 ; 1369 c = nt3/nt1 ; 1503 d = b*b - c ; 1370 d = b*b - c ; 1504 1371 1505 if ( d >= 0 ) 1372 if ( d >= 0 ) 1506 { 1373 { 1507 // Check if on outer cone & heading out << 1374 // Check if on outer cone & heading outwards 1508 // NOTE: Should use rho-rout>-kRadToler << 1375 // NOTE: Should use rho-rout>-kRadtolerance*0.5 1509 << 1376 1510 if (nt3 > -halfRadTolerance && nt2 >= 0 << 1377 if (nt3 > -kRadTolerance*0.5 && nt2 >= 0 ) 1511 { << 1378 { 1512 if (calcNorm) << 1379 if (calcNorm) 1513 { << 1380 { 1514 risec = std::sqrt(t3)*secRMax << 1381 risec = sqrt(t3)*secRMax ; 1515 *validNorm = true ; << 1382 *validNorm = true ; 1516 *n = G4ThreeVector(p.x()/ri << 1383 *n = G4ThreeVector(p.x()/risec,p.y()/risec,-tanRMax/secRMax) ; 1517 } << 1384 } 1518 return snxt=0 ; << 1385 return snxt=0 ; 1519 } 1386 } 1520 else 1387 else 1521 { 1388 { 1522 sider = kRMax ; << 1389 sider = kRMax ; 1523 if (b>0) { srd = -b - std::sqrt(d); << 1390 sr = -b - sqrt(d) ; // was +srqrt(d), vmg 28.04.99 1524 else { srd = c/(-b+std::sqrt(d)) << 1391 zi = p.z() + sr*v.z() ; 1525 << 1392 ri = tanRMax*zi + rMaxAv ; 1526 zi = p.z() + srd*v.z() ; << 1393 1527 ri = tanRMax*zi + rMaxAv ; << 1394 if ( (ri >= 0) && (-kRadTolerance*0.5 <= sr) && 1528 << 1395 ( sr <= kRadTolerance*0.5) ) 1529 if ((ri >= 0) && (-halfRadTolerance < << 1396 { 1530 { << 1397 // An intersection within the tolerance 1531 // An intersection within the toler << 1398 // we will Store it in case it is good - 1532 // we will Store it in case it is << 1399 // 1533 // << 1400 slentol = sr ; 1534 slentol = srd ; << 1401 sidetol = kRMax ; 1535 sidetol = kRMax ; << 1402 } 1536 } << 1403 if ( (ri < 0) || (sr < kRadTolerance*0.5) ) 1537 if ( (ri < 0) || (srd < halfRadTolera << 1404 { 1538 { << 1405 // Safety: if both roots -ve ensure that sr cannot `win' distance to out 1539 // Safety: if both roots -ve ensure << 1406 1540 // distance to out << 1407 sr2 = -b + sqrt(d) ; 1541 << 1408 zi = p.z() + sr2*v.z() ; 1542 if (b>0) { sr2 = c/(-b-std::sqrt(d) << 1409 ri = tanRMax*zi + rMaxAv ; 1543 else { sr2 = -b + std::sqrt(d); << 1410 1544 zi = p.z() + sr2*v.z() ; << 1411 if (ri >= 0 && sr2 > kRadTolerance*0.5) sr = sr2 ; 1545 ri = tanRMax*zi + rMaxAv ; << 1412 else 1546 << 1413 { 1547 if ((ri >= 0) && (sr2 > halfRadTole << 1414 sr = kInfinity ; 1548 { << 1415 1549 srd = sr2; << 1416 if( (-kRadTolerance*0.5 <= sr2) 1550 } << 1417 && ( sr2 <= kRadTolerance*0.5) ) 1551 else << 1418 { 1552 { << 1419 // An intersection within the tolerance. Storing it in case it is good. 1553 srd = kInfinity ; << 1420 1554 << 1421 slentol = sr2 ; 1555 if( (-halfRadTolerance <= sr2) && << 1422 sidetol = kRMax ; 1556 { << 1423 } 1557 // An intersection within the t << 1424 } 1558 // Storing it in case it is goo << 1425 } 1559 << 1560 slentol = sr2 ; << 1561 sidetol = kRMax ; << 1562 } << 1563 } << 1564 } << 1565 } 1426 } 1566 } 1427 } 1567 else 1428 else 1568 { 1429 { 1569 // No intersection with outer cone & no << 1430 // No intersection with outer cone & not parallel -> already outside, no 1570 // -> already outside, no intersection << 1431 // intersection 1571 1432 1572 if ( calcNorm ) 1433 if ( calcNorm ) 1573 { 1434 { 1574 risec = std::sqrt(t3)*secRMax; << 1435 risec = sqrt(t3)*secRMax ; 1575 *validNorm = true; << 1436 *validNorm = true ; 1576 *n = G4ThreeVector(p.x()/rise << 1437 *n = G4ThreeVector(p.x()/risec,p.y()/risec,-tanRMax/secRMax) ; 1577 } 1438 } 1578 return snxt = 0.0 ; 1439 return snxt = 0.0 ; 1579 } 1440 } 1580 } 1441 } 1581 else if ( (nt2 != 0.0) && (deltaRoi2 > 0.0) << 1442 else if ( nt2 && deltaRoi2 > 0.0 ) 1582 { 1443 { 1583 // Linear case (only one intersection) => << 1444 // Linear case (only one intersection) => point outside outer cone 1584 1445 1585 if ( calcNorm ) 1446 if ( calcNorm ) 1586 { 1447 { 1587 risec = std::sqrt(t3)*secRMax; << 1448 risec = sqrt(t3)*secRMax ; 1588 *validNorm = true; << 1449 *validNorm = true ; 1589 *n = G4ThreeVector(p.x()/risec, << 1450 *n = G4ThreeVector(p.x()/risec,p.y()/risec,-tanRMax/secRMax) ; 1590 } 1451 } 1591 return snxt = 0.0 ; 1452 return snxt = 0.0 ; 1592 } 1453 } 1593 else 1454 else 1594 { 1455 { 1595 // No intersection -> parallel to outer c << 1456 // No intersection -> parallel to outer cone => Z or inner cone intersection 1596 // => Z or inner cone intersection << 1597 1457 1598 srd = kInfinity ; << 1458 sr = kInfinity ; 1599 } 1459 } 1600 1460 1601 // Check possible intersection within toler << 1461 // Check possible intersection within tolerance 1602 1462 1603 if ( slentol <= halfCarTolerance ) << 1463 if ( slentol <= kCarTolerance*0.5 ) 1604 { 1464 { 1605 // An intersection within the tolerance w << 1465 // An intersection within the tolerance was found. 1606 // We must accept it only if the momentum << 1466 // We must accept it only if the momentum points outwards. 1607 // << 1467 // 1608 // G4ThreeVector ptTol ; // The point of << 1468 // G4ThreeVector ptTol ; // The point of the intersection 1609 // ptTol= p + slentol*v ; << 1469 // ptTol= p + slentol*v ; 1610 // ri=tanRMax*zi+rMaxAv ; << 1470 // ri=tanRMax*zi+rMaxAv ; 1611 // << 1471 // 1612 // Calculate a normal vector, as below << 1472 // Calculate a normal vector, as below 1613 1473 1614 xi = p.x() + slentol*v.x(); << 1474 xi = p.x() + slentol*v.x() ; 1615 yi = p.y() + slentol*v.y(); << 1475 yi = p.y() + slentol*v.y() ; 1616 risec = std::sqrt(xi*xi + yi*yi)*secRMax; << 1476 risec = sqrt(xi*xi + yi*yi)*secRMax ; 1617 G4ThreeVector Normal = G4ThreeVector(xi/r << 1477 G4ThreeVector Normal = G4ThreeVector(xi/risec,yi/risec,-tanRMax/secRMax) ; 1618 1478 1619 if ( Normal.dot(v) > 0 ) // We will le 1479 if ( Normal.dot(v) > 0 ) // We will leave the Cone immediatelly 1620 { 1480 { 1621 if ( calcNorm ) 1481 if ( calcNorm ) 1622 { 1482 { 1623 *n = Normal.unit() ; << 1483 *n = Normal.unit() ; 1624 *validNorm = true ; << 1484 *validNorm = true ; 1625 } 1485 } 1626 return snxt = 0.0 ; 1486 return snxt = 0.0 ; 1627 } 1487 } 1628 else // On the surface, but not heading o 1488 else // On the surface, but not heading out so we ignore this intersection 1629 { // << 1489 { // (as it is within tolerance). 1630 slentol = kInfinity ; 1490 slentol = kInfinity ; 1631 } 1491 } 1632 } 1492 } 1633 1493 1634 // Inner Cone intersection << 1494 // Inner Cone intersection 1635 1495 1636 if ( (fRmin1 != 0.0) || (fRmin2 != 0.0) ) << 1496 if ( fRmin1 || fRmin2 ) 1637 { 1497 { 1638 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; 1498 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; 1639 nt1 = t1 - (tanRMin*v.z())*(tanRMin*v 1499 nt1 = t1 - (tanRMin*v.z())*(tanRMin*v.z()) ; 1640 1500 1641 if ( nt1 != 0.0 ) << 1501 if ( nt1 ) 1642 { 1502 { 1643 secRMin = std::sqrt(1.0 + tanRMin*tanRM << 1503 secRMin = sqrt(1.0 + tanRMin*tanRMin) ; 1644 rMinAv = (fRmin1 + fRmin2)*0.5 ; 1504 rMinAv = (fRmin1 + fRmin2)*0.5 ; 1645 rin = tanRMin*p.z() + rMinAv ; 1505 rin = tanRMin*p.z() + rMinAv ; 1646 nt2 = t2 - tanRMin*v.z()*rin ; 1506 nt2 = t2 - tanRMin*v.z()*rin ; 1647 nt3 = t3 - rin*rin ; 1507 nt3 = t3 - rin*rin ; 1648 << 1508 1649 // Equation quadratic => 2 roots : firs << 1509 // Equation quadratic => 2 roots : first root must be leaving 1650 1510 1651 b = nt2/nt1 ; 1511 b = nt2/nt1 ; 1652 c = nt3/nt1 ; 1512 c = nt3/nt1 ; 1653 d = b*b - c ; 1513 d = b*b - c ; 1654 1514 1655 if ( d >= 0.0 ) << 1515 if (d >= 0.0 ) 1656 { 1516 { 1657 // NOTE: should be rho-rin<kRadTolera << 1517 // NOTE: should be rho-rin<kRadTolerance*0.5, but using squared versions 1658 // but using squared versions f << 1518 // for efficiency 1659 1519 1660 if (nt3 < kRadTolerance*(rin + kRadTo 1520 if (nt3 < kRadTolerance*(rin + kRadTolerance*0.25)) 1661 { << 1521 { 1662 if ( nt2 < 0.0 ) << 1522 if ( nt2 < 0.0 ) 1663 { << 1523 { 1664 if (calcNorm) { *validNorm = fal << 1524 if (calcNorm) *validNorm = false ; 1665 return snxt = 0.0; << 1525 return snxt = 0.0 ; 1666 } << 1526 } 1667 } << 1527 } 1668 else << 1528 else 1669 { << 1529 { 1670 if (b>0) { sr2 = -b - std::sqrt(d); << 1530 sr2 = -b - sqrt(d) ; 1671 else { sr2 = c/(-b+std::sqrt(d) << 1531 zi = p.z() + sr2*v.z() ; 1672 zi = p.z() + sr2*v.z() ; << 1532 ri = tanRMin*zi + rMinAv ; 1673 ri = tanRMin*zi + rMinAv ; << 1533 1674 << 1534 if( (ri >= 0.0) && (-kRadTolerance*0.5 <= sr2) && 1675 if( (ri>=0.0)&&(-halfRadTolerance<= << 1535 ( sr2 <= kRadTolerance*0.5) ) 1676 { << 1536 { 1677 // An intersection within the tol << 1537 // An intersection within the tolerance storing it in case it is good. 1678 // storing it in case it is good. << 1538 1679 << 1539 slentol = sr2 ; 1680 slentol = sr2 ; << 1540 sidetol = kRMax ; 1681 sidetol = kRMax ; << 1541 } 1682 } << 1542 if( (ri<0) || (sr2 < kRadTolerance*0.5) ) 1683 if( (ri<0) || (sr2 < halfRadToleran << 1543 { 1684 { << 1544 sr3 = -b + sqrt(d) ; 1685 if (b>0) { sr3 = c/(-b-std::sqrt( << 1545 1686 else { sr3 = -b + std::sqrt(d << 1546 // Safety: if both roots -ve ensure that sr cannot `win' distancetoout 1687 << 1547 1688 // Safety: if both roots -ve ensu << 1548 if ( sr3 > kCarTolerance*0.5 ) 1689 // distancetoout << 1549 { 1690 << 1550 if( sr3 < sr ) 1691 if ( sr3 > halfRadTolerance ) << 1551 { 1692 { << 1552 zi = p.z() + sr3*v.z() ; 1693 if( sr3 < srd ) << 1553 ri = tanRMin*zi + rMinAv ; 1694 { << 1554 1695 zi = p.z() + sr3*v.z() ; << 1555 if ( ri >= 0.0 ) 1696 ri = tanRMin*zi + rMinAv ; << 1556 { 1697 << 1557 sr=sr3 ; 1698 if ( ri >= 0.0 ) << 1558 sider=kRMin ; 1699 { << 1559 } 1700 srd=sr3 ; << 1560 } 1701 sider=kRMin ; << 1561 } 1702 } << 1562 else if ( sr3 > -kCarTolerance*0.5 ) 1703 } << 1563 { 1704 } << 1564 // Intersection in tolerance. Store to check if it's good 1705 else if ( sr3 > -halfRadTolerance << 1565 1706 { << 1566 slentol = sr3 ; 1707 // Intersection in tolerance. S << 1567 sidetol = kRMin ; 1708 << 1568 } 1709 slentol = sr3 ; << 1569 } 1710 sidetol = kRMin ; << 1570 else if ( sr2 < sr && sr2 > kCarTolerance*0.5 ) 1711 } << 1571 { 1712 } << 1572 sr = sr2 ; 1713 else if ( (sr2 < srd) && (sr2 > hal << 1573 sider = kRMin ; 1714 { << 1574 } 1715 srd = sr2 ; << 1575 else if (sr2 > -kCarTolerance*0.5) 1716 sider = kRMin ; << 1576 { 1717 } << 1577 // Intersection in tolerance. Store to check if it's good 1718 else if (sr2 > -halfCarTolerance) << 1578 1719 { << 1579 slentol = sr2 ; 1720 // Intersection in tolerance. Sto << 1580 sidetol = kRMin ; 1721 << 1581 } 1722 slentol = sr2 ; << 1582 if( slentol <= kCarTolerance*0.5 ) 1723 sidetol = kRMin ; << 1583 { 1724 } << 1584 // An intersection within the tolerance was found. 1725 if( slentol <= halfCarTolerance ) << 1585 // We must accept it only if the momentum points outwards. 1726 { << 1586 1727 // An intersection within the tol << 1587 G4ThreeVector Normal ; 1728 // We must accept it only if the << 1588 1729 << 1589 // Calculate a normal vector, as below 1730 G4ThreeVector Normal ; << 1590 1731 << 1591 xi = p.x() + slentol*v.x() ; 1732 // Calculate a normal vector, as << 1592 yi = p.y() + slentol*v.y() ; 1733 << 1593 risec = sqrt(xi*xi + yi*yi)*secRMin ; 1734 xi = p.x() + slentol*v.x() ; << 1594 Normal = G4ThreeVector(xi/risec,yi/risec,-tanRMin/secRMin) ; 1735 yi = p.y() + slentol*v.y() ; << 1595 1736 if( sidetol==kRMax ) << 1596 if( Normal.dot(v) > 0 ) 1737 { << 1597 { 1738 risec = std::sqrt(xi*xi + yi*y << 1598 // We will leave the Cone immediatelly 1739 Normal = G4ThreeVector(xi/risec << 1599 if( calcNorm ) 1740 } << 1600 { 1741 else << 1601 *n = Normal.unit() ; 1742 { << 1602 *validNorm = true ; 1743 risec = std::sqrt(xi*xi + yi*y << 1603 } 1744 Normal = G4ThreeVector(-xi/rise << 1604 return snxt = 0.0 ; 1745 } << 1605 } 1746 if( Normal.dot(v) > 0 ) << 1606 else 1747 { << 1607 { 1748 // We will leave the cone immed << 1608 // On the surface, but not heading out so we ignore this 1749 << 1609 // intersection (as it is within tolerance). 1750 if( calcNorm ) << 1610 1751 { << 1611 slentol = kInfinity ; 1752 *n = Normal.unit() ; << 1612 } 1753 *validNorm = true ; << 1613 } 1754 } << 1614 } 1755 return snxt = 0.0 ; << 1615 } 1756 } << 1616 } 1757 else << 1617 } 1758 { << 1618 1759 // On the surface, but not head << 1619 // Linear case => point outside inner cone ---> outer cone intersect 1760 // intersection (as it is withi << 1620 // 1761 << 1621 // Phi Intersection 1762 slentol = kInfinity ; << 1763 } << 1764 } << 1765 } << 1766 } << 1767 } << 1768 } << 1769 << 1770 // Linear case => point outside inner cone << 1771 // << 1772 // Phi Intersection << 1773 1622 1774 if ( !fPhiFullCone ) << 1623 if ( fDPhi < 2.0*M_PI ) 1775 { 1624 { 1776 // add angle calculation with correction << 1625 sinSPhi = sin(fSPhi) ; 1777 // of the difference in domain of atan2 a << 1626 cosSPhi = cos(fSPhi) ; 1778 << 1627 ePhi = fSPhi + fDPhi ; 1779 vphi = std::atan2(v.y(),v.x()) ; << 1628 sinEPhi = sin(ePhi) ; >> 1629 cosEPhi = cos(ePhi) ; >> 1630 cPhi = fSPhi + fDPhi*0.5 ; >> 1631 sinCPhi = sin(cPhi) ; >> 1632 cosCPhi = cos(cPhi) ; 1780 1633 1781 if ( vphi < fSPhi - halfAngTolerance ) << 1634 if ( p.x() || p.y() ) // Check if on z axis (rho not needed later) 1782 else if ( vphi > fSPhi + fDPhi + halfAngT << 1783 << 1784 if ( (p.x() != 0.0) || (p.y() != 0.0) ) << 1785 { 1635 { 1786 // pDist -ve when inside << 1636 // pDist -ve when inside 1787 1637 1788 pDistS = p.x()*sinSPhi - p.y()*cosSPhi 1638 pDistS = p.x()*sinSPhi - p.y()*cosSPhi ; 1789 pDistE = -p.x()*sinEPhi + p.y()*cosEPhi 1639 pDistE = -p.x()*sinEPhi + p.y()*cosEPhi ; 1790 1640 1791 // Comp -ve when in direction of outwar << 1641 // Comp -ve when in direction of outwards normal 1792 1642 1793 compS = -sinSPhi*v.x() + cosSPhi*v.y() 1643 compS = -sinSPhi*v.x() + cosSPhi*v.y() ; 1794 compE = sinEPhi*v.x() - cosEPhi*v.y() ; 1644 compE = sinEPhi*v.x() - cosEPhi*v.y() ; 1795 1645 1796 sidephi = kNull ; 1646 sidephi = kNull ; 1797 1647 1798 if( ( (fDPhi <= pi) && ( (pDistS <= hal << 1648 if (pDistS <= 0 && pDistE <= 0) 1799 && (pDistE <= hal << 1800 || ( (fDPhi > pi) && ((pDistS <= h << 1801 || (pDistE <= << 1802 { 1649 { 1803 // Inside both phi *full* planes << 1650 // Inside both phi *full* planes 1804 if ( compS < 0 ) << 1805 { << 1806 sphi = pDistS/compS ; << 1807 if (sphi >= -halfCarTolerance) << 1808 { << 1809 xi = p.x() + sphi*v.x() ; << 1810 yi = p.y() + sphi*v.y() ; << 1811 << 1812 // Check intersecting with correc << 1813 // (if not -> no intersect) << 1814 // << 1815 if ( (std::fabs(xi)<=kCarToleranc << 1816 && (std::fabs(yi)<=kCarToleranc << 1817 { << 1818 sidephi= kSPhi; << 1819 if ( ( fSPhi-halfAngTolerance < << 1820 && ( fSPhi+fDPhi+halfAngToler << 1821 { << 1822 sphi = kInfinity; << 1823 } << 1824 } << 1825 else << 1826 if ( (yi*cosCPhi-xi*sinCPhi)>=0 ) << 1827 { << 1828 sphi = kInfinity ; << 1829 } << 1830 else << 1831 { << 1832 sidephi = kSPhi ; << 1833 if ( pDistS > -halfCarTolerance << 1834 { << 1835 sphi = 0.0 ; // Leave by sphi << 1836 } << 1837 } << 1838 } << 1839 else << 1840 { << 1841 sphi = kInfinity ; << 1842 } << 1843 } << 1844 else << 1845 { << 1846 sphi = kInfinity ; << 1847 } << 1848 1651 1849 if ( compE < 0 ) << 1652 if (compS < 0) 1850 { 1653 { 1851 sphi2 = pDistE/compE ; << 1654 sphi = pDistS/compS ; 1852 << 1655 xi = p.x() + sphi*v.x() ; 1853 // Only check further if < starting << 1656 yi = p.y() + sphi*v.y() ; 1854 // << 1657 1855 if ( (sphi2 > -halfCarTolerance) && << 1658 // Check intersecting with correct half-plane (if not -> no intersect) 1856 { << 1659 1857 xi = p.x() + sphi2*v.x() ; << 1660 if ( (yi*cosCPhi - xi*sinCPhi) >= 0.0 ) sphi = kInfinity ; 1858 yi = p.y() + sphi2*v.y() ; << 1661 else 1859 << 1662 { 1860 // Check intersecting with correc << 1663 sidephi = kSPhi ; 1861 << 1664 1862 if ( (std::fabs(xi)<=kCarToleranc << 1665 if ( pDistS > -kCarTolerance*0.5 ) // Leave by sphi immediately 1863 && (std::fabs(yi)<=kCarToleranc << 1666 { 1864 { << 1667 sphi = 0.0 ; 1865 // Leaving via ending phi << 1668 } 1866 << 1669 } 1867 if( (fSPhi-halfAngTolerance > v << 1670 } 1868 || (fSPhi+fDPhi+halfAngToler << 1671 else sphi = kInfinity ; 1869 { << 1672 1870 sidephi = kEPhi ; << 1673 if ( compE < 0.0 ) 1871 if ( pDistE <= -halfCarTolera << 1674 { 1872 else << 1675 // Only check further if < starting phi intersection 1873 } << 1676 1874 } << 1677 sphi2 = pDistE/compE ; 1875 else // Check intersecting with c << 1678 1876 if ( yi*cosCPhi-xi*sinCPhi >= 0 ) << 1679 if ( sphi2 < sphi ) 1877 { << 1680 { 1878 // Leaving via ending phi << 1681 xi = p.x() + sphi2*v.x() ; 1879 << 1682 yi = p.y() + sphi2*v.y() ; 1880 sidephi = kEPhi ; << 1683 1881 if ( pDistE <= -halfCarToleranc << 1684 // Check intersecting with correct half-plane 1882 else << 1685 1883 } << 1686 if ( (yi*cosCPhi - xi*sinCPhi) >= 0.0 ) // Leaving via ending phi 1884 } << 1687 { 1885 } << 1688 sidephi = kEPhi ; >> 1689 >> 1690 if ( pDistE <= -kCarTolerance*0.5 ) sphi = sphi2 ; >> 1691 else sphi = 0.0 ; >> 1692 } >> 1693 } >> 1694 } >> 1695 } >> 1696 else if ( pDistS >= 0 && pDistE >= 0 ) >> 1697 { >> 1698 // Outside both *full* phi planes >> 1699 >> 1700 if ( pDistS <= pDistE ) sidephi = kSPhi ; >> 1701 else sidephi = kEPhi ; >> 1702 >> 1703 if ( fDPhi > M_PI ) >> 1704 { >> 1705 if (compS < 0 && compE < 0) sphi = 0.0 ; >> 1706 else sphi = kInfinity ; >> 1707 } >> 1708 else >> 1709 { >> 1710 // if towards both >=0 then once inside (after error) will remain inside >> 1711 >> 1712 if ( compS >= 0.0 && compE >= 0.0 ) sphi = kInfinity ; >> 1713 else sphi = 0.0 ; >> 1714 } >> 1715 } >> 1716 else if ( pDistS > 0.0 && pDistE < 0.0 ) >> 1717 { >> 1718 // Outside full starting plane, inside full ending plane >> 1719 >> 1720 if ( fDPhi > M_PI ) >> 1721 { >> 1722 if ( compE < 0.0 ) >> 1723 { >> 1724 sphi = pDistE/compE ; >> 1725 xi = p.x() + sphi*v.x() ; >> 1726 yi = p.y() + sphi*v.y() ; >> 1727 >> 1728 // Check intersection in correct half-plane (if not -> not leaving phi extent) >> 1729 >> 1730 if ( (yi*cosCPhi - xi*sinCPhi) <= 0.0 ) >> 1731 { >> 1732 sphi = kInfinity ; >> 1733 } >> 1734 else // Leaving via Ending phi >> 1735 { >> 1736 sidephi = kEPhi ; >> 1737 >> 1738 if ( pDistE > -kCarTolerance*0.5 ) sphi = 0.0 ; >> 1739 } >> 1740 } >> 1741 else sphi = kInfinity ; >> 1742 } >> 1743 else // fDPhi <= pi >> 1744 { >> 1745 if (compS >= 0.0 ) >> 1746 { >> 1747 if ( compE < 0.0 ) >> 1748 { >> 1749 sphi = pDistE/compE ; >> 1750 xi = p.x() + sphi*v.x() ; >> 1751 yi = p.y() + sphi*v.y() ; >> 1752 >> 1753 // Check intersection in correct half-plane (if not -> remain in extent) >> 1754 >> 1755 if ( (yi*cosCPhi - xi*sinCPhi) <= 0.0 ) >> 1756 { >> 1757 sphi = kInfinity ; >> 1758 } >> 1759 else // otherwise leaving via Ending phi >> 1760 { >> 1761 sidephi = kEPhi ; >> 1762 } >> 1763 } >> 1764 else sphi = kInfinity ; >> 1765 } >> 1766 else // leaving immediately by starting phi >> 1767 { >> 1768 sidephi = kSPhi ; >> 1769 sphi = 0.0 ; >> 1770 } >> 1771 } 1886 } 1772 } 1887 else 1773 else 1888 { 1774 { 1889 sphi = kInfinity ; << 1775 // Must be pDistS<0&&pDistE>0 1890 } << 1776 // Inside full starting plane, outside full ending plane >> 1777 >> 1778 if (fDPhi > M_PI) >> 1779 { >> 1780 if ( compS < 0.0 ) >> 1781 { >> 1782 sphi = pDistS/compS ; >> 1783 xi = p.x() + sphi*v.x() ; >> 1784 yi = p.y() + sphi*v.y() ; >> 1785 >> 1786 // Check intersection in correct half-plane (if not -> not leaving phi extent) >> 1787 >> 1788 if ( (yi*cosCPhi - xi*sinCPhi) >= 0.0 ) sphi = kInfinity ; >> 1789 else // Leaving via Starting phi >> 1790 { >> 1791 sidephi = kSPhi ; >> 1792 >> 1793 if ( pDistS > -kCarTolerance*0.5 ) sphi = 0.0 ; >> 1794 } >> 1795 } >> 1796 else sphi = kInfinity ; >> 1797 } >> 1798 else // fDPhi <= pi >> 1799 { >> 1800 if ( compE >= 0.0 ) >> 1801 { >> 1802 if ( compS < 0.0 ) >> 1803 { >> 1804 >> 1805 sphi = pDistS/compS ; >> 1806 xi = p.x() + sphi*v.x() ; >> 1807 yi = p.y() + sphi*v.y() ; >> 1808 >> 1809 // Check intersection in correct half-plane (if not -> remain in extent) >> 1810 >> 1811 if ( (yi*cosCPhi - xi*sinCPhi) >= 0.0 ) sphi = kInfinity ; >> 1812 else // otherwise leaving via Starting phi >> 1813 { >> 1814 sidephi = kSPhi ; >> 1815 } >> 1816 } >> 1817 else sphi = kInfinity ; >> 1818 } >> 1819 else // CompE < 0, leaving immediately by ending >> 1820 { >> 1821 sidephi = kEPhi ; >> 1822 sphi = 0.0 ; >> 1823 } >> 1824 } >> 1825 } 1891 } 1826 } 1892 else 1827 else 1893 { 1828 { 1894 // On z axis + travel not || to z axis << 1829 // On z axis + travel not || to z axis -> if phi of vector direction 1895 // within phi of shape, Step limited by << 1830 // within phi of shape, Step limited by rmax, else Step =0 1896 1831 1897 if ( (fSPhi-halfAngTolerance <= vphi) << 1832 vphi = atan2(v.y(),v.x()) ; 1898 && (vphi <= fSPhi+fDPhi+halfAngTolera << 1833 1899 { << 1834 if ( fSPhi < vphi && vphi < fSPhi + fDPhi ) sphi = kInfinity ; 1900 sphi = kInfinity ; << 1901 } << 1902 else 1835 else 1903 { 1836 { 1904 sidephi = kSPhi ; // arbitrary 1837 sidephi = kSPhi ; // arbitrary 1905 sphi = 0.0 ; << 1838 sphi = 0.0 ; 1906 } 1839 } 1907 } << 1840 } 1908 if ( sphi < snxt ) // Order intersecttio 1841 if ( sphi < snxt ) // Order intersecttions 1909 { 1842 { 1910 snxt = sphi ; << 1843 snxt=sphi ; 1911 side = sidephi ; << 1844 side=sidephi ; 1912 } 1845 } 1913 } 1846 } 1914 if ( srd < snxt ) // Order intersections << 1847 if ( sr < snxt ) // Order intersections 1915 { 1848 { 1916 snxt = srd ; << 1849 snxt = sr ; 1917 side = sider ; 1850 side = sider ; 1918 } 1851 } 1919 if (calcNorm) 1852 if (calcNorm) 1920 { 1853 { 1921 switch(side) 1854 switch(side) 1922 { // Note: returned v << 1855 { 1923 case kRMax: // (divide by frmax << 1856 case kRMax: 1924 xi = p.x() + snxt*v.x() ; << 1857 // Note: returned vector not normalised 1925 yi = p.y() + snxt*v.y() ; << 1858 // (divide by frmax for unit vector) 1926 risec = std::sqrt(xi*xi + yi*yi) << 1859 xi = p.x() + snxt*v.x() ; 1927 *n = G4ThreeVector(xi/risec,y << 1860 yi = p.y() + snxt*v.y() ; 1928 *validNorm = true ; << 1861 risec = sqrt(xi*xi + yi*yi)*secRMax ; 1929 break ; << 1862 *n = G4ThreeVector(xi/risec,yi/risec,-tanRMax/secRMax) ; 1930 case kRMin: << 1863 *validNorm = true ; 1931 *validNorm = false ; // Rmin is inco << 1864 break ; 1932 break ; << 1865 case kRMin: 1933 case kSPhi: << 1866 *validNorm=false ; // Rmin is inconvex 1934 if ( fDPhi <= pi ) << 1867 break ; 1935 { << 1868 case kSPhi: 1936 *n = G4ThreeVector(sinSPhi, << 1869 if ( fDPhi <= M_PI ) 1937 *validNorm = true ; << 1870 { 1938 } << 1871 *n = G4ThreeVector(sin(fSPhi),-cos(fSPhi),0) ; 1939 else << 1872 *validNorm = true ; 1940 { << 1873 } 1941 *validNorm = false ; << 1874 else *validNorm = false ; 1942 } << 1875 break ; 1943 break ; << 1876 case kEPhi: 1944 case kEPhi: << 1877 if ( fDPhi <= M_PI ) 1945 if ( fDPhi <= pi ) << 1878 { 1946 { << 1879 *n = G4ThreeVector(-sin(fSPhi+fDPhi),cos(fSPhi+fDPhi),0) ; 1947 *n = G4ThreeVector(-sinEPhi, cosEPh << 1880 *validNorm = true ; 1948 *validNorm = true ; << 1881 } 1949 } << 1882 else *validNorm = false ; 1950 else << 1883 break ; 1951 { << 1884 case kPZ: 1952 *validNorm = false ; << 1885 *n = G4ThreeVector(0,0,1) ; 1953 } << 1886 *validNorm = true ; 1954 break ; << 1887 break ; 1955 case kPZ: << 1888 case kMZ: 1956 *n = G4ThreeVector(0,0,1) ; << 1889 *n = G4ThreeVector(0,0,-1) ; 1957 *validNorm = true ; << 1890 *validNorm = true ; 1958 break ; << 1891 break ; 1959 case kMZ: << 1892 default: 1960 *n = G4ThreeVector(0,0,-1) ; << 1893 G4cout.precision(16) ; 1961 *validNorm = true ; << 1894 G4cout << G4endl ; 1962 break ; << 1895 G4cout << "Cons parameters:" << G4endl << G4endl ; 1963 default: << 1896 G4cout << "fRmin1 = " << fRmin1/mm << " mm" << G4endl ; 1964 G4cout << G4endl ; << 1897 G4cout << "fRmax1 = " << fRmax1/mm << " mm" << G4endl ; 1965 DumpInfo(); << 1898 G4cout << "fRmin2 = " << fRmin2/mm << " mm" << G4endl ; 1966 std::ostringstream message; << 1899 G4cout << "fRmax2 = " << fRmax2/mm << " mm" << G4endl ; 1967 G4long oldprc = message.precision(16) << 1900 G4cout << "fDz = " << fDz/mm << " mm" << G4endl ; 1968 message << "Undefined side for valid << 1901 G4cout << "fSPhi = " << fSPhi/degree << " degree" << G4endl ; 1969 << G4endl << 1902 G4cout << "fDPhi = " << fDPhi/degree << " degree" << G4endl ; 1970 << "Position:" << G4endl << << 1903 G4cout << "Position:" << G4endl << G4endl ; 1971 << "p.x() = " << p.x()/mm < << 1904 G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl ; 1972 << "p.y() = " << p.y()/mm < << 1905 G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl ; 1973 << "p.z() = " << p.z()/mm < << 1906 G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl ; 1974 << "pho at z = " << std::sq << 1907 G4cout << "Direction:" << G4endl << G4endl ; 1975 << " mm" << G4endl << G4endl << 1908 G4cout << "v.x() = " << v.x() << G4endl ; 1976 if( p.x() != 0. || p.y() != 0.) << 1909 G4cout << "v.y() = " << v.y() << G4endl ; 1977 { << 1910 G4cout << "v.z() = " << v.z() << G4endl<< G4endl ; 1978 message << "point phi = " << std << 1911 G4cout << "Proposed distance :" << G4endl<< G4endl ; 1979 << " degrees" << G4endl << << 1912 G4cout << "snxt = " << snxt/mm << " mm" << G4endl << G4endl ; 1980 } << 1913 G4Exception("Invalid enum in G4Cons::DistanceToOut") ; 1981 message << "Direction:" << G4endl << << 1914 break ; 1982 << "v.x() = " << v.x() << G << 1983 << "v.y() = " << v.y() << G << 1984 << "v.z() = " << v.z() << G << 1985 << "Proposed distance :" << G << 1986 << "snxt = " << snxt/mm << << 1987 message.precision(oldprc) ; << 1988 G4Exception("G4Cons::DistanceToOut(p, << 1989 JustWarning, message) ; << 1990 break ; << 1991 } 1915 } 1992 } 1916 } 1993 if (snxt < halfCarTolerance) { snxt = 0.; << 1917 if (snxt < kCarTolerance*0.5) snxt = 0.; 1994 << 1995 return snxt ; 1918 return snxt ; 1996 } 1919 } 1997 1920 1998 ///////////////////////////////////////////// 1921 ////////////////////////////////////////////////////////////////// 1999 // 1922 // 2000 // Calculate distance (<=actual) to closest s 1923 // Calculate distance (<=actual) to closest surface of shape from inside 2001 1924 2002 G4double G4Cons::DistanceToOut(const G4ThreeV 1925 G4double G4Cons::DistanceToOut(const G4ThreeVector& p) const 2003 { 1926 { 2004 G4double safe=0.0, rho, safeR1, safeR2, saf << 1927 G4double safe,rho,safeR1,safeR2,safeZ ; 2005 G4double tanRMin, secRMin, pRMin; << 1928 G4double tanRMin,secRMin,pRMin ; 2006 G4double tanRMax, secRMax, pRMax; << 1929 G4double tanRMax,secRMax,pRMax ; 2007 << 1930 G4double safePhi,phiC,cosPhiC,sinPhiC,ePhi ; 2008 #ifdef G4CSGDEBUG << 1931 /* 2009 if( Inside(p) == kOutside ) 1932 if( Inside(p) == kOutside ) 2010 { 1933 { 2011 G4int oldprc=G4cout.precision(16) ; << 1934 G4cout.precision(16) ; 2012 G4cout << G4endl ; 1935 G4cout << G4endl ; 2013 DumpInfo(); << 1936 G4cout << "Cons parameters:" << G4endl << G4endl ; >> 1937 G4cout << "fRmin1 = " << fRmin1/mm << " mm" << G4endl ; >> 1938 G4cout << "fRmax1 = " << fRmax1/mm << " mm" << G4endl ; >> 1939 G4cout << "fRmin2 = " << fRmin2/mm << " mm" << G4endl ; >> 1940 G4cout << "fRmax2 = " << fRmax2/mm << " mm" << G4endl ; >> 1941 G4cout << "fDz = " << fDz/mm << " mm" << G4endl ; >> 1942 G4cout << "fSPhi = " << fSPhi/degree << " degree" << G4endl ; >> 1943 G4cout << "fDPhi = " << fDPhi/degree << " degree" << G4endl << G4endl ; 2014 G4cout << "Position:" << G4endl << G4end 1944 G4cout << "Position:" << G4endl << G4endl ; 2015 G4cout << "p.x() = " << p.x()/mm << " m 1945 G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl ; 2016 G4cout << "p.y() = " << p.y()/mm << " m 1946 G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl ; 2017 G4cout << "p.z() = " << p.z()/mm << " m 1947 G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl ; 2018 G4cout << "pho at z = " << std::sqrt( p << 1948 // G4Exception("Invalid call in G4Cons::DistanceToOut(p), p is outside") ; 2019 << " mm" << G4endl << G4endl ; << 1949 G4cout << "G4Cons::DistanceToOut(p), p is outside ?!" << G4endl ; 2020 if( (p.x() != 0.) || (p.x() != 0.) ) << 2021 { << 2022 G4cout << "point phi = " << std::atan << 2023 << " degrees" << G4endl << G4end << 2024 } << 2025 G4cout.precision(oldprc) ; << 2026 G4Exception("G4Cons::DistanceToOut(p)", " << 2027 JustWarning, "Point p is outs << 2028 } 1950 } 2029 #endif << 1951 */ >> 1952 rho = sqrt(p.x()*p.x() + p.y()*p.y()) ; >> 1953 safeZ = fDz - fabs(p.z()) ; 2030 1954 2031 rho = std::sqrt(p.x()*p.x() + p.y()*p.y()) << 1955 if (fRmin1 || fRmin2) 2032 safeZ = fDz - std::fabs(p.z()) ; << 2033 << 2034 if ((fRmin1 != 0.0) || (fRmin2 != 0.0)) << 2035 { 1956 { 2036 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; 1957 tanRMin = (fRmin2 - fRmin1)*0.5/fDz ; 2037 secRMin = std::sqrt(1.0 + tanRMin*tanRMin << 1958 secRMin = sqrt(1.0 + tanRMin*tanRMin) ; 2038 pRMin = tanRMin*p.z() + (fRmin1 + fRmin 1959 pRMin = tanRMin*p.z() + (fRmin1 + fRmin2)*0.5 ; 2039 safeR1 = (rho - pRMin)/secRMin ; 1960 safeR1 = (rho - pRMin)/secRMin ; 2040 } 1961 } 2041 else << 1962 else safeR1 = kInfinity ; 2042 { << 2043 safeR1 = kInfinity ; << 2044 } << 2045 1963 2046 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; 1964 tanRMax = (fRmax2 - fRmax1)*0.5/fDz ; 2047 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) << 1965 secRMax = sqrt(1.0 + tanRMax*tanRMax) ; 2048 pRMax = tanRMax*p.z() + (fRmax1+fRmax2)*0 1966 pRMax = tanRMax*p.z() + (fRmax1+fRmax2)*0.5 ; 2049 safeR2 = (pRMax - rho)/secRMax ; 1967 safeR2 = (pRMax - rho)/secRMax ; 2050 1968 2051 if (safeR1 < safeR2) { safe = safeR1; } << 1969 if (safeR1 < safeR2) safe = safeR1 ; 2052 else { safe = safeR2; } << 1970 else safe = safeR2 ; 2053 if (safeZ < safe) { safe = safeZ ; } << 1971 if (safeZ < safe) safe = safeZ ; 2054 1972 2055 // Check if phi divided, Calc distances clo << 1973 // Check if phi divided, Calc distances closest phi plane 2056 1974 2057 if (!fPhiFullCone) << 1975 if (fDPhi < 2.0*M_PI) 2058 { 1976 { 2059 // Above/below central phi of G4Cons? << 1977 // Above/below central phi of G4Cons? >> 1978 >> 1979 phiC = fSPhi + fDPhi*0.5 ; >> 1980 cosPhiC = cos(phiC) ; >> 1981 sinPhiC = sin(phiC) ; 2060 1982 2061 if ( (p.y()*cosCPhi - p.x()*sinCPhi) <= 0 << 1983 if ( (p.y()*cosPhiC - p.x()*sinPhiC) <= 0 ) 2062 { 1984 { 2063 safePhi = -(p.x()*sinSPhi - p.y()*cosSP << 1985 safePhi = -(p.x()*sin(fSPhi) - p.y()*cos(fSPhi)) ; 2064 } 1986 } 2065 else 1987 else 2066 { 1988 { 2067 safePhi = (p.x()*sinEPhi - p.y()*cosEPh << 1989 ePhi = fSPhi + fDPhi ; >> 1990 safePhi = (p.x()*sin(ePhi) - p.y()*cos(ePhi)) ; 2068 } 1991 } 2069 if (safePhi < safe) { safe = safePhi; } << 1992 if (safePhi < safe) safe = safePhi ; 2070 } 1993 } 2071 if ( safe < 0 ) { safe = 0; } << 1994 if ( safe < 0 ) safe = 0 ; 2072 << 1995 return safe ; 2073 return safe ; << 2074 } 1996 } 2075 1997 2076 ///////////////////////////////////////////// << 1998 //////////////////////////////////////////////////////////////////////////// 2077 // << 2078 // GetEntityType << 2079 << 2080 G4GeometryType G4Cons::GetEntityType() const << 2081 { << 2082 return {"G4Cons"}; << 2083 } << 2084 << 2085 ///////////////////////////////////////////// << 2086 // << 2087 // Make a clone of the object << 2088 // << 2089 G4VSolid* G4Cons::Clone() const << 2090 { << 2091 return new G4Cons(*this); << 2092 } << 2093 << 2094 ///////////////////////////////////////////// << 2095 // 1999 // 2096 // Stream object contents to an output stream << 2000 // Create a List containing the transformed vertices >> 2001 // Ordering [0-3] -fDz cross section >> 2002 // [4-7] +fDz cross section such that [0] is below [4], >> 2003 // [1] below [5] etc. >> 2004 // Note: >> 2005 // Caller has deletion resposibility >> 2006 // Potential improvement: For last slice, use actual ending angle >> 2007 // to avoid rounding error problems. 2097 2008 2098 std::ostream& G4Cons::StreamInfo(std::ostream << 2009 G4ThreeVectorList* >> 2010 G4Cons::CreateRotatedVertices(const G4AffineTransform& pTransform) const 2099 { 2011 { 2100 G4long oldprc = os.precision(16); << 2012 G4ThreeVectorList* vertices ; 2101 os << "------------------------------------ << 2013 G4ThreeVector vertex0, vertex1, vertex2, vertex3 ; 2102 << " *** Dump for solid - " << GetNam << 2014 G4double meshAngle, meshRMax1, meshRMax2, crossAngle; 2103 << " ================================ << 2015 G4double cosCrossAngle, sinCrossAngle, sAngle ; 2104 << " Solid type: G4Cons\n" << 2016 G4double rMaxX1, rMaxX2, rMaxY1, rMaxY2, rMinX1, rMinX2, rMinY1, rMinY2 ; 2105 << " Parameters: \n" << 2017 G4int crossSection, noCrossSections ; 2106 << " inside -fDz radius: " << fRmin1 << 2107 << " outside -fDz radius: " << fRmax1 << 2108 << " inside +fDz radius: " << fRmin2 << 2109 << " outside +fDz radius: " << fRmax2 << 2110 << " half length in Z : " << fDz/mm << 2111 << " starting angle of segment: " << f << 2112 << " delta angle of segment : " << f << 2113 << "------------------------------------ << 2114 os.precision(oldprc); << 2115 2018 2116 return os; << 2019 // Compute no of cross-sections necessary to mesh cone 2117 } << 2020 >> 2021 noCrossSections = G4int(fDPhi/kMeshAngleDefault) + 1 ; 2118 2022 >> 2023 if (noCrossSections < kMinMeshSections) >> 2024 { >> 2025 noCrossSections = kMinMeshSections ; >> 2026 } >> 2027 else if (noCrossSections > kMaxMeshSections) >> 2028 { >> 2029 noCrossSections = kMaxMeshSections ; >> 2030 } >> 2031 meshAngle = fDPhi/(noCrossSections - 1) ; 2119 2032 >> 2033 // G4double RMax = (fRmax2 >= fRmax1) ? fRmax2 : fRmax1 ; 2120 2034 2121 ///////////////////////////////////////////// << 2035 meshRMax1 = fRmax1/cos(meshAngle*0.5) ; 2122 // << 2036 meshRMax2 = fRmax2/cos(meshAngle*0.5) ; 2123 // GetPointOnSurface << 2124 2037 2125 G4ThreeVector G4Cons::GetPointOnSurface() con << 2038 // If complete in phi, set start angle such that mesh will be at RMax 2126 { << 2039 // on the x axis. Will give better extent calculations when not rotated. 2127 // declare working variables << 2128 // << 2129 G4double rone = (fRmax1-fRmax2)/(2.*fDz); << 2130 G4double rtwo = (fRmin1-fRmin2)/(2.*fDz); << 2131 G4double qone = (fRmax1 == fRmax2) ? 0. : f << 2132 G4double qtwo = (fRmin1 == fRmin2) ? 0. : f << 2133 << 2134 G4double slin = std::hypot(fRmin1-fRmin2, << 2135 G4double slout = std::hypot(fRmax1-fRmax2, << 2136 G4double Aone = 0.5*fDPhi*(fRmax2 + fRmax << 2137 G4double Atwo = 0.5*fDPhi*(fRmin2 + fRmin << 2138 G4double Athree = 0.5*fDPhi*(fRmax1*fRmax1- << 2139 G4double Afour = 0.5*fDPhi*(fRmax2*fRmax2- << 2140 G4double Afive = fDz*(fRmax1-fRmin1+fRmax2 << 2141 << 2142 G4double phi = G4RandFlat::shoot(fSPhi,f << 2143 G4double cosu = std::cos(phi); << 2144 G4double sinu = std::sin(phi); << 2145 G4double rRand1 = GetRadiusInRing(fRmin1, f << 2146 G4double rRand2 = GetRadiusInRing(fRmin2, f << 2147 << 2148 if ( (fSPhi == 0.) && fPhiFullCone ) { Afi << 2149 G4double chose = G4RandFlat::shoot(0.,Aone << 2150 2040 2151 if( (chose >= 0.) && (chose < Aone) ) // ou << 2041 if (fDPhi == M_PI*2.0 && fSPhi == 0.0 ) 2152 { 2042 { 2153 if(fRmax1 != fRmax2) << 2043 sAngle = -meshAngle*0.5 ; 2154 { << 2155 G4double zRand = G4RandFlat::shoot(-1.* << 2156 return { rone*cosu*(qone-zRand), rone*s << 2157 } << 2158 else << 2159 { << 2160 return { fRmax1*cosu, fRmax2*sinu, G4Ra << 2161 } << 2162 } 2044 } 2163 else if( (chose >= Aone) && (chose < Aone + << 2045 else 2164 { 2046 { 2165 if(fRmin1 != fRmin2) << 2047 sAngle = fSPhi ; 2166 { << 2048 } 2167 G4double zRand = G4RandFlat::shoot(-1.* << 2049 vertices = new G4ThreeVectorList(noCrossSections*4) ; 2168 return { rtwo*cosu*(qtwo-zRand), rtwo*s << 2050 2169 } << 2051 if (vertices) 2170 else << 2052 { 2171 { << 2053 for (crossSection = 0 ; crossSection < noCrossSections ; crossSection++) 2172 return { fRmin1*cosu, fRmin2*sinu, G4Ra << 2054 { >> 2055 // Compute coordinates of cross section at section crossSection >> 2056 >> 2057 crossAngle = sAngle + crossSection*meshAngle ; >> 2058 cosCrossAngle = cos(crossAngle) ; >> 2059 sinCrossAngle = sin(crossAngle) ; >> 2060 >> 2061 rMaxX1 = meshRMax1*cosCrossAngle ; >> 2062 rMaxY1 = meshRMax1*sinCrossAngle ; >> 2063 rMaxX2 = meshRMax2*cosCrossAngle ; >> 2064 rMaxY2 = meshRMax2*sinCrossAngle ; >> 2065 >> 2066 // G4double RMin = (fRmin2 <= fRmin1) ? fRmin2 : fRmin1 ; >> 2067 >> 2068 rMinX1 = fRmin1*cosCrossAngle ; >> 2069 rMinY1 = fRmin1*sinCrossAngle ; >> 2070 rMinX2 = fRmin2*cosCrossAngle ; >> 2071 rMinY2 = fRmin2*sinCrossAngle ; >> 2072 >> 2073 vertex0 = G4ThreeVector(rMinX1,rMinY1,-fDz) ; >> 2074 vertex1 = G4ThreeVector(rMaxX1,rMaxY1,-fDz) ; >> 2075 vertex2 = G4ThreeVector(rMaxX2,rMaxY2,+fDz) ; >> 2076 vertex3 = G4ThreeVector(rMinX2,rMinY2,+fDz) ; >> 2077 >> 2078 vertices->insert(pTransform.TransformPoint(vertex0)) ; >> 2079 vertices->insert(pTransform.TransformPoint(vertex1)) ; >> 2080 vertices->insert(pTransform.TransformPoint(vertex2)) ; >> 2081 vertices->insert(pTransform.TransformPoint(vertex3)) ; 2173 } 2082 } 2174 } 2083 } 2175 else if( (chose >= Aone + Atwo) && (chose < << 2084 else 2176 { << 2177 return {rRand1*cosu, rRand1*sinu, -1*fDz} << 2178 } << 2179 else if( (chose >= Aone + Atwo + Athree) << 2180 && (chose < Aone + Atwo + Athree + Af << 2181 { << 2182 return { rRand2*cosu, rRand2*sinu, fDz }; << 2183 } << 2184 else if( (chose >= Aone + Atwo + Athree + A << 2185 && (chose < Aone + Atwo + Athree + Af << 2186 { << 2187 G4double zRand = G4RandFlat::shoot(-1.*f << 2188 rRand1 = G4RandFlat::shoot(fRmin2-((zRand << 2189 fRmax2-((zRand << 2190 return { rRand1*cosSPhi, rRand1*sinSPhi, << 2191 } << 2192 else // SPhi+DPhi section << 2193 { 2085 { 2194 G4double zRand = G4RandFlat::shoot(-1.*f << 2086 G4Exception("G4Cons::CreateRotatedVertices Out of memory - Cant alloc vertices"); 2195 rRand1 = G4RandFlat::shoot(fRmin2-((zRand << 2196 fRmax2-((zRand << 2197 return { rRand1*cosEPhi, rRand1*sinEPhi, << 2198 } 2087 } >> 2088 return vertices ; 2199 } 2089 } 2200 2090 2201 ///////////////////////////////////////////// 2091 ////////////////////////////////////////////////////////////////////////// 2202 // 2092 // 2203 // Methods for visualisation 2093 // Methods for visualisation 2204 2094 2205 void G4Cons::DescribeYourselfTo (G4VGraphicsS 2095 void G4Cons::DescribeYourselfTo (G4VGraphicsScene& scene) const 2206 { 2096 { 2207 scene.AddSolid (*this); << 2097 scene.AddThis (*this); 2208 } 2098 } 2209 2099 2210 G4Polyhedron* G4Cons::CreatePolyhedron () con 2100 G4Polyhedron* G4Cons::CreatePolyhedron () const 2211 { 2101 { 2212 return new G4PolyhedronCons(fRmin1,fRmax1,f << 2102 return new G4PolyhedronCons(fRmin1, fRmax1, fRmin2, fRmax2, fDz, fSPhi, >> 2103 fDPhi); 2213 } 2104 } 2214 2105 2215 #endif << 2106 G4NURBS* G4Cons::CreateNURBS () const >> 2107 { >> 2108 G4double RMax = (fRmax2 >= fRmax1) ? fRmax2 : fRmax1 ; >> 2109 >> 2110 return new G4NURBSbox (RMax, RMax, fDz); // Box for now!!! >> 2111 } >> 2112 >> 2113 // >> 2114 // >> 2115 /////////////////////////////// End of G4Cons.cc file ////////////////////// >> 2116 >> 2117 >> 2118 >> 2119 >> 2120 >> 2121 2216 2122