Geant4 Cross Reference |
1 // ******************************************* 1 // ******************************************************************** 2 // * License and Disclaimer 2 // * License and Disclaimer * 3 // * 3 // * * 4 // * The Geant4 software is copyright of th 4 // * The Geant4 software is copyright of the Copyright Holders of * 5 // * the Geant4 Collaboration. It is provided 5 // * the Geant4 Collaboration. It is provided under the terms and * 6 // * conditions of the Geant4 Software License 6 // * conditions of the Geant4 Software License, included in the file * 7 // * LICENSE and available at http://cern.ch/ 7 // * LICENSE and available at http://cern.ch/geant4/license . These * 8 // * include a list of copyright holders. 8 // * include a list of copyright holders. * 9 // * 9 // * * 10 // * Neither the authors of this software syst 10 // * Neither the authors of this software system, nor their employing * 11 // * institutes,nor the agencies providing fin 11 // * institutes,nor the agencies providing financial support for this * 12 // * work make any representation or warran 12 // * work make any representation or warranty, express or implied, * 13 // * regarding this software system or assum 13 // * regarding this software system or assume any liability for its * 14 // * use. Please see the license in the file 14 // * use. Please see the license in the file LICENSE and URL above * 15 // * for the full disclaimer and the limitatio 15 // * for the full disclaimer and the limitation of liability. * 16 // * 16 // * * 17 // * This code implementation is the result 17 // * This code implementation is the result of the scientific and * 18 // * technical work of the GEANT4 collaboratio 18 // * technical work of the GEANT4 collaboration. * 19 // * By using, copying, modifying or distri 19 // * By using, copying, modifying or distributing the software (or * 20 // * any work based on the software) you ag 20 // * any work based on the software) you agree to acknowledge its * 21 // * use in resulting scientific publicati 21 // * use in resulting scientific publications, and indicate your * 22 // * acceptance of all terms of the Geant4 Sof 22 // * acceptance of all terms of the Geant4 Software license. * 23 // ******************************************* 23 // ******************************************************************** 24 // 24 // 25 // Implementation for G4Orb class 25 // Implementation for G4Orb class 26 // 26 // 27 // 20.08.03 V.Grichine - created 27 // 20.08.03 V.Grichine - created 28 // 08.08.17 E.Tcherniaev - complete revision, 28 // 08.08.17 E.Tcherniaev - complete revision, speed-up 29 // ------------------------------------------- 29 // -------------------------------------------------------------------- 30 30 31 #include "G4Orb.hh" 31 #include "G4Orb.hh" 32 32 33 #if !defined(G4GEOM_USE_UORB) 33 #if !defined(G4GEOM_USE_UORB) 34 34 35 #include "G4TwoVector.hh" 35 #include "G4TwoVector.hh" 36 #include "G4VoxelLimits.hh" 36 #include "G4VoxelLimits.hh" 37 #include "G4AffineTransform.hh" 37 #include "G4AffineTransform.hh" 38 #include "G4GeometryTolerance.hh" 38 #include "G4GeometryTolerance.hh" 39 #include "G4BoundingEnvelope.hh" 39 #include "G4BoundingEnvelope.hh" 40 40 41 #include "G4VPVParameterisation.hh" 41 #include "G4VPVParameterisation.hh" 42 42 43 #include "G4RandomDirection.hh" 43 #include "G4RandomDirection.hh" 44 #include "Randomize.hh" 44 #include "Randomize.hh" 45 45 46 #include "G4VGraphicsScene.hh" 46 #include "G4VGraphicsScene.hh" 47 #include "G4VisExtent.hh" 47 #include "G4VisExtent.hh" 48 48 49 using namespace CLHEP; 49 using namespace CLHEP; 50 50 51 ////////////////////////////////////////////// 51 ////////////////////////////////////////////////////////////////////////// 52 // 52 // 53 // Constructor 53 // Constructor 54 54 55 G4Orb::G4Orb( const G4String& pName, G4double 55 G4Orb::G4Orb( const G4String& pName, G4double pRmax ) 56 : G4CSGSolid(pName), fRmax(pRmax) 56 : G4CSGSolid(pName), fRmax(pRmax) 57 { 57 { 58 Initialize(); 58 Initialize(); 59 } 59 } 60 60 61 ////////////////////////////////////////////// 61 ////////////////////////////////////////////////////////////////////////// 62 // 62 // 63 // Fake default constructor - sets only member 63 // Fake default constructor - sets only member data and allocates memory 64 // for usage restri 64 // for usage restricted to object persistency 65 65 66 G4Orb::G4Orb( __void__& a ) 66 G4Orb::G4Orb( __void__& a ) 67 : G4CSGSolid(a) 67 : G4CSGSolid(a) 68 { 68 { 69 } 69 } 70 70 71 ////////////////////////////////////////////// 71 ////////////////////////////////////////////////////////////////////////// 72 // 72 // 73 // Destructor 73 // Destructor 74 74 75 G4Orb::~G4Orb() = default; << 75 G4Orb::~G4Orb() >> 76 { >> 77 } 76 78 77 ////////////////////////////////////////////// 79 ////////////////////////////////////////////////////////////////////////// 78 // 80 // 79 // Copy constructor 81 // Copy constructor 80 82 81 G4Orb::G4Orb(const G4Orb&) = default; << 83 G4Orb::G4Orb(const G4Orb& rhs) >> 84 : G4CSGSolid(rhs), fRmax(rhs.fRmax), halfRmaxTol(rhs.halfRmaxTol), >> 85 sqrRmaxPlusTol(rhs.sqrRmaxPlusTol), sqrRmaxMinusTol(rhs.sqrRmaxMinusTol) >> 86 { >> 87 } 82 88 83 ////////////////////////////////////////////// 89 ////////////////////////////////////////////////////////////////////////// 84 // 90 // 85 // Assignment operator 91 // Assignment operator 86 92 87 G4Orb& G4Orb::operator = (const G4Orb& rhs) 93 G4Orb& G4Orb::operator = (const G4Orb& rhs) 88 { 94 { 89 // Check assignment to self 95 // Check assignment to self 90 // 96 // 91 if (this == &rhs) { return *this; } 97 if (this == &rhs) { return *this; } 92 98 93 // Copy base class data 99 // Copy base class data 94 // 100 // 95 G4CSGSolid::operator=(rhs); 101 G4CSGSolid::operator=(rhs); 96 102 97 // Copy data 103 // Copy data 98 // 104 // 99 fRmax = rhs.fRmax; 105 fRmax = rhs.fRmax; 100 halfRmaxTol = rhs.halfRmaxTol; 106 halfRmaxTol = rhs.halfRmaxTol; 101 sqrRmaxPlusTol = rhs.sqrRmaxPlusTol; 107 sqrRmaxPlusTol = rhs.sqrRmaxPlusTol; 102 sqrRmaxMinusTol = rhs.sqrRmaxMinusTol; 108 sqrRmaxMinusTol = rhs.sqrRmaxMinusTol; 103 109 104 return *this; 110 return *this; 105 } 111 } 106 112 107 ////////////////////////////////////////////// 113 ////////////////////////////////////////////////////////////////////////// 108 // 114 // 109 // Check radius and initialize dada members 115 // Check radius and initialize dada members 110 116 111 void G4Orb::Initialize() 117 void G4Orb::Initialize() 112 { 118 { 113 const G4double fEpsilon = 2.e-11; // relati 119 const G4double fEpsilon = 2.e-11; // relative tolerance of fRmax 114 120 115 // Check radius 121 // Check radius 116 // 122 // 117 if ( fRmax < 10*kCarTolerance ) 123 if ( fRmax < 10*kCarTolerance ) 118 { 124 { 119 G4Exception("G4Orb::Initialize()", "GeomSo 125 G4Exception("G4Orb::Initialize()", "GeomSolids0002", FatalException, 120 "Invalid radius < 10*kCarToler 126 "Invalid radius < 10*kCarTolerance."); 121 } 127 } 122 halfRmaxTol = 0.5 * std::max(kCarTolerance, 128 halfRmaxTol = 0.5 * std::max(kCarTolerance, fEpsilon*fRmax); 123 G4double rmaxPlusTol = fRmax + halfRmaxTol; 129 G4double rmaxPlusTol = fRmax + halfRmaxTol; 124 G4double rmaxMinusTol = fRmax - halfRmaxTol; 130 G4double rmaxMinusTol = fRmax - halfRmaxTol; 125 sqrRmaxPlusTol = rmaxPlusTol*rmaxPlusTol; 131 sqrRmaxPlusTol = rmaxPlusTol*rmaxPlusTol; 126 sqrRmaxMinusTol = rmaxMinusTol*rmaxMinusTol; 132 sqrRmaxMinusTol = rmaxMinusTol*rmaxMinusTol; 127 } 133 } 128 134 129 ////////////////////////////////////////////// 135 ////////////////////////////////////////////////////////////////////////// 130 // 136 // 131 // Dispatch to parameterisation for replicatio 137 // Dispatch to parameterisation for replication mechanism dimension 132 // computation & modification 138 // computation & modification 133 139 134 void G4Orb::ComputeDimensions( G4VPVPara 140 void G4Orb::ComputeDimensions( G4VPVParameterisation* p, 135 const G4int n, 141 const G4int n, 136 const G4VPhysic 142 const G4VPhysicalVolume* pRep ) 137 { 143 { 138 p->ComputeDimensions(*this,n,pRep); 144 p->ComputeDimensions(*this,n,pRep); 139 } 145 } 140 146 141 ////////////////////////////////////////////// 147 ////////////////////////////////////////////////////////////////////////// 142 // 148 // 143 // Get bounding box 149 // Get bounding box 144 150 145 void G4Orb::BoundingLimits(G4ThreeVector& pMin 151 void G4Orb::BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const 146 { 152 { 147 G4double radius = GetRadius(); 153 G4double radius = GetRadius(); 148 pMin.set(-radius,-radius,-radius); 154 pMin.set(-radius,-radius,-radius); 149 pMax.set( radius, radius, radius); 155 pMax.set( radius, radius, radius); 150 156 151 // Check correctness of the bounding box 157 // Check correctness of the bounding box 152 // 158 // 153 if (pMin.x() >= pMax.x() || pMin.y() >= pMax 159 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z()) 154 { 160 { 155 std::ostringstream message; 161 std::ostringstream message; 156 message << "Bad bounding box (min >= max) 162 message << "Bad bounding box (min >= max) for solid: " 157 << GetName() << " !" 163 << GetName() << " !" 158 << "\npMin = " << pMin 164 << "\npMin = " << pMin 159 << "\npMax = " << pMax; 165 << "\npMax = " << pMax; 160 G4Exception("G4Orb::BoundingLimits()", "Ge 166 G4Exception("G4Orb::BoundingLimits()", "GeomMgt0001", 161 JustWarning, message); 167 JustWarning, message); 162 DumpInfo(); 168 DumpInfo(); 163 } 169 } 164 } 170 } 165 171 166 ////////////////////////////////////////////// 172 ////////////////////////////////////////////////////////////////////////// 167 // 173 // 168 // Calculate extent under transform and specif 174 // Calculate extent under transform and specified limit 169 175 170 G4bool G4Orb::CalculateExtent(const EAxis pAxi 176 G4bool G4Orb::CalculateExtent(const EAxis pAxis, 171 const G4VoxelLim 177 const G4VoxelLimits& pVoxelLimit, 172 const G4AffineTr 178 const G4AffineTransform& pTransform, 173 G4doub 179 G4double& pMin, G4double& pMax) const 174 { 180 { 175 G4ThreeVector bmin, bmax; 181 G4ThreeVector bmin, bmax; 176 G4bool exist; 182 G4bool exist; 177 183 178 // Get bounding box 184 // Get bounding box 179 BoundingLimits(bmin,bmax); 185 BoundingLimits(bmin,bmax); 180 186 181 // Check bounding box 187 // Check bounding box 182 G4BoundingEnvelope bbox(bmin,bmax); 188 G4BoundingEnvelope bbox(bmin,bmax); 183 #ifdef G4BBOX_EXTENT 189 #ifdef G4BBOX_EXTENT 184 return bbox.CalculateExtent(pAxis,pVoxelLimi 190 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax); 185 #endif 191 #endif 186 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox 192 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax)) 187 { 193 { 188 return exist = pMin < pMax; << 194 return exist = (pMin < pMax) ? true : false; 189 } 195 } 190 196 191 // Find bounding envelope and calculate exte 197 // Find bounding envelope and calculate extent 192 // 198 // 193 static const G4int NTHETA = 8; // number of 199 static const G4int NTHETA = 8; // number of steps along Theta 194 static const G4int NPHI = 16; // number of 200 static const G4int NPHI = 16; // number of steps along Phi 195 static const G4double sinHalfTheta = std::si 201 static const G4double sinHalfTheta = std::sin(halfpi/NTHETA); 196 static const G4double cosHalfTheta = std::co 202 static const G4double cosHalfTheta = std::cos(halfpi/NTHETA); 197 static const G4double sinHalfPhi = std::si 203 static const G4double sinHalfPhi = std::sin(pi/NPHI); 198 static const G4double cosHalfPhi = std::co 204 static const G4double cosHalfPhi = std::cos(pi/NPHI); 199 static const G4double sinStepTheta = 2.*sinH 205 static const G4double sinStepTheta = 2.*sinHalfTheta*cosHalfTheta; 200 static const G4double cosStepTheta = 1. - 2. 206 static const G4double cosStepTheta = 1. - 2.*sinHalfTheta*sinHalfTheta; 201 static const G4double sinStepPhi = 2.*sinH 207 static const G4double sinStepPhi = 2.*sinHalfPhi*cosHalfPhi; 202 static const G4double cosStepPhi = 1. - 2. 208 static const G4double cosStepPhi = 1. - 2.*sinHalfPhi*sinHalfPhi; 203 209 204 G4double radius = GetRadius(); 210 G4double radius = GetRadius(); 205 G4double rtheta = radius/cosHalfTheta; 211 G4double rtheta = radius/cosHalfTheta; 206 G4double rphi = rtheta/cosHalfPhi; 212 G4double rphi = rtheta/cosHalfPhi; 207 213 208 // set reference circle 214 // set reference circle 209 G4TwoVector xy[NPHI]; 215 G4TwoVector xy[NPHI]; 210 G4double sinCurPhi = sinHalfPhi; 216 G4double sinCurPhi = sinHalfPhi; 211 G4double cosCurPhi = cosHalfPhi; 217 G4double cosCurPhi = cosHalfPhi; 212 for (auto & k : xy) << 218 for (G4int k=0; k<NPHI; ++k) 213 { 219 { 214 k.set(cosCurPhi,sinCurPhi); << 220 xy[k].set(cosCurPhi,sinCurPhi); 215 G4double sinTmpPhi = sinCurPhi; 221 G4double sinTmpPhi = sinCurPhi; 216 sinCurPhi = sinCurPhi*cosStepPhi + cosCurP 222 sinCurPhi = sinCurPhi*cosStepPhi + cosCurPhi*sinStepPhi; 217 cosCurPhi = cosCurPhi*cosStepPhi - sinTmpP 223 cosCurPhi = cosCurPhi*cosStepPhi - sinTmpPhi*sinStepPhi; 218 } 224 } 219 225 220 // set bounding circles 226 // set bounding circles 221 G4ThreeVectorList circles[NTHETA]; 227 G4ThreeVectorList circles[NTHETA]; 222 for (auto & circle : circles) { circle.resiz << 228 for (G4int i=0; i<NTHETA; ++i) { circles[i].resize(NPHI); } 223 229 224 G4double sinCurTheta = sinHalfTheta; 230 G4double sinCurTheta = sinHalfTheta; 225 G4double cosCurTheta = cosHalfTheta; 231 G4double cosCurTheta = cosHalfTheta; 226 for (auto & circle : circles) << 232 for (G4int i=0; i<NTHETA; ++i) 227 { 233 { 228 G4double z = rtheta*cosCurTheta; 234 G4double z = rtheta*cosCurTheta; 229 G4double rho = rphi*sinCurTheta; 235 G4double rho = rphi*sinCurTheta; 230 for (G4int k=0; k<NPHI; ++k) 236 for (G4int k=0; k<NPHI; ++k) 231 { 237 { 232 circle[k].set(rho*xy[k].x(),rho*xy[k].y( << 238 circles[i][k].set(rho*xy[k].x(),rho*xy[k].y(),z); 233 } 239 } 234 G4double sinTmpTheta = sinCurTheta; 240 G4double sinTmpTheta = sinCurTheta; 235 sinCurTheta = sinCurTheta*cosStepTheta + c 241 sinCurTheta = sinCurTheta*cosStepTheta + cosCurTheta*sinStepTheta; 236 cosCurTheta = cosCurTheta*cosStepTheta - s 242 cosCurTheta = cosCurTheta*cosStepTheta - sinTmpTheta*sinStepTheta; 237 } 243 } 238 244 239 // set envelope and calculate extent 245 // set envelope and calculate extent 240 std::vector<const G4ThreeVectorList *> polyg 246 std::vector<const G4ThreeVectorList *> polygons; 241 polygons.resize(NTHETA); 247 polygons.resize(NTHETA); 242 for (G4int i=0; i<NTHETA; ++i) { polygons[i] 248 for (G4int i=0; i<NTHETA; ++i) { polygons[i] = &circles[i]; } 243 249 244 G4BoundingEnvelope benv(bmin,bmax,polygons); 250 G4BoundingEnvelope benv(bmin,bmax,polygons); 245 exist = benv.CalculateExtent(pAxis,pVoxelLim 251 exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax); 246 return exist; 252 return exist; 247 } 253 } 248 254 249 ////////////////////////////////////////////// 255 ////////////////////////////////////////////////////////////////////////// 250 // 256 // 251 // Return whether point is inside/outside/on s 257 // Return whether point is inside/outside/on surface 252 258 253 EInside G4Orb::Inside( const G4ThreeVector& p 259 EInside G4Orb::Inside( const G4ThreeVector& p ) const 254 { 260 { 255 G4double rr = p.mag2(); 261 G4double rr = p.mag2(); 256 if (rr > sqrRmaxPlusTol) return kOutside; 262 if (rr > sqrRmaxPlusTol) return kOutside; 257 return (rr > sqrRmaxMinusTol) ? kSurface : k 263 return (rr > sqrRmaxMinusTol) ? kSurface : kInside; 258 } 264 } 259 265 260 ////////////////////////////////////////////// 266 ////////////////////////////////////////////////////////////////////////// 261 // 267 // 262 // Return unit normal of surface closest to p 268 // Return unit normal of surface closest to p 263 269 264 G4ThreeVector G4Orb::SurfaceNormal( const G4Th 270 G4ThreeVector G4Orb::SurfaceNormal( const G4ThreeVector& p ) const 265 { 271 { 266 return (1/p.mag())*p; 272 return (1/p.mag())*p; 267 } 273 } 268 274 269 ////////////////////////////////////////////// 275 ////////////////////////////////////////////////////////////////////////// 270 // 276 // 271 // Calculate distance to the surface of the or 277 // Calculate distance to the surface of the orb from outside 272 // - return kInfinity if no intersection or 278 // - return kInfinity if no intersection or 273 // intersection distance <= tolerance 279 // intersection distance <= tolerance 274 280 275 G4double G4Orb::DistanceToIn( const G4ThreeVec 281 G4double G4Orb::DistanceToIn( const G4ThreeVector& p, 276 const G4ThreeVec 282 const G4ThreeVector& v ) const 277 { 283 { 278 // Check if point is on the surface and trav 284 // Check if point is on the surface and traveling away 279 // 285 // 280 G4double rr = p.mag2(); 286 G4double rr = p.mag2(); 281 G4double pv = p.dot(v); 287 G4double pv = p.dot(v); 282 if (rr >= sqrRmaxMinusTol && pv >= 0) return 288 if (rr >= sqrRmaxMinusTol && pv >= 0) return kInfinity; 283 289 284 // Find intersection 290 // Find intersection 285 // 291 // 286 // Sphere eqn: x^2 + y^2 + z^2 = R^2 292 // Sphere eqn: x^2 + y^2 + z^2 = R^2 287 // 293 // 288 // => (px + t*vx)^2 + (py + t*vy)^2 + (pz 294 // => (px + t*vx)^2 + (py + t*vy)^2 + (pz + t*vz)^2 = R^2 289 // => r^2 + 2t(p.v) + t^2 = R^2 295 // => r^2 + 2t(p.v) + t^2 = R^2 290 // => tmin = -(p.v) - Sqrt((p.v)^2 - (r^2 296 // => tmin = -(p.v) - Sqrt((p.v)^2 - (r^2 - R^2)) 291 // 297 // 292 G4double D = pv*pv - rr + fRmax*fRmax; 298 G4double D = pv*pv - rr + fRmax*fRmax; 293 if (D < 0) return kInfinity; // no intersect 299 if (D < 0) return kInfinity; // no intersection 294 300 295 G4double sqrtD = std::sqrt(D); 301 G4double sqrtD = std::sqrt(D); 296 G4double dist = -pv - sqrtD; 302 G4double dist = -pv - sqrtD; 297 303 298 // Avoid rounding errors due to precision is 304 // Avoid rounding errors due to precision issues seen on 64 bits systems. 299 // Split long distances and recompute 305 // Split long distances and recompute 300 // 306 // 301 G4double Dmax = 32*fRmax; 307 G4double Dmax = 32*fRmax; 302 if (dist > Dmax) 308 if (dist > Dmax) 303 { 309 { 304 dist = dist - 1.e-8*dist - fRmax; // to s 310 dist = dist - 1.e-8*dist - fRmax; // to stay outside after the move 305 dist += DistanceToIn(p + dist*v, v); 311 dist += DistanceToIn(p + dist*v, v); 306 return (dist >= kInfinity) ? kInfinity : d 312 return (dist >= kInfinity) ? kInfinity : dist; 307 } 313 } 308 314 309 if (sqrtD*2 <= halfRmaxTol) return kInfinity 315 if (sqrtD*2 <= halfRmaxTol) return kInfinity; // touch 310 return (dist < halfRmaxTol) ? 0. : dist; 316 return (dist < halfRmaxTol) ? 0. : dist; 311 } 317 } 312 318 313 ////////////////////////////////////////////// 319 ////////////////////////////////////////////////////////////////////////// 314 // 320 // 315 // Calculate shortest distance to the boundary 321 // Calculate shortest distance to the boundary from outside 316 // - Return 0 if point is inside 322 // - Return 0 if point is inside 317 323 318 G4double G4Orb::DistanceToIn( const G4ThreeVec 324 G4double G4Orb::DistanceToIn( const G4ThreeVector& p ) const 319 { 325 { 320 G4double dist = p.mag() - fRmax; 326 G4double dist = p.mag() - fRmax; 321 return (dist > 0) ? dist : 0.; 327 return (dist > 0) ? dist : 0.; 322 } 328 } 323 329 324 ////////////////////////////////////////////// 330 ////////////////////////////////////////////////////////////////////////// 325 // 331 // 326 // Calculate distance to the surface of the or 332 // Calculate distance to the surface of the orb from inside and 327 // find normal at exit point, if required 333 // find normal at exit point, if required 328 // - when leaving the surface, return 0 334 // - when leaving the surface, return 0 329 335 330 G4double G4Orb::DistanceToOut( const G4ThreeVe 336 G4double G4Orb::DistanceToOut( const G4ThreeVector& p, 331 const G4ThreeVe 337 const G4ThreeVector& v, 332 const G4bool ca 338 const G4bool calcNorm, 333 G4bool* v 339 G4bool* validNorm, 334 G4ThreeVe 340 G4ThreeVector* n ) const 335 { 341 { 336 // Check if point is on the surface and trav 342 // Check if point is on the surface and traveling away 337 // 343 // 338 G4double rr = p.mag2(); 344 G4double rr = p.mag2(); 339 G4double pv = p.dot(v); 345 G4double pv = p.dot(v); 340 if (rr >= sqrRmaxMinusTol && pv > 0) 346 if (rr >= sqrRmaxMinusTol && pv > 0) 341 { 347 { 342 if (calcNorm) 348 if (calcNorm) 343 { 349 { 344 *validNorm = true; 350 *validNorm = true; 345 *n = p*(1./std::sqrt(rr)); 351 *n = p*(1./std::sqrt(rr)); 346 } 352 } 347 return 0.; 353 return 0.; 348 } 354 } 349 355 350 // Find intersection 356 // Find intersection 351 // 357 // 352 // Sphere eqn: x^2 + y^2 + z^2 = R^2 358 // Sphere eqn: x^2 + y^2 + z^2 = R^2 353 // 359 // 354 // => (px + t*vx)^2 + (py + t*vy)^2 + (pz 360 // => (px + t*vx)^2 + (py + t*vy)^2 + (pz + t*vz)^2 = R^2 355 // => r^2 + 2t(p.v) + t^2 = R^2 361 // => r^2 + 2t(p.v) + t^2 = R^2 356 // => tmax = -(p.v) + Sqrt((p.v)^2 - (r^2 362 // => tmax = -(p.v) + Sqrt((p.v)^2 - (r^2 - R^2)) 357 // 363 // 358 G4double D = pv*pv - rr + fRmax*fRmax; 364 G4double D = pv*pv - rr + fRmax*fRmax; 359 G4double tmax = (D <= 0) ? 0. : std::sqrt(D) 365 G4double tmax = (D <= 0) ? 0. : std::sqrt(D) - pv; 360 if (tmax < halfRmaxTol) tmax = 0.; 366 if (tmax < halfRmaxTol) tmax = 0.; 361 if (calcNorm) 367 if (calcNorm) 362 { 368 { 363 *validNorm = true; 369 *validNorm = true; 364 G4ThreeVector ptmax = p + tmax*v; 370 G4ThreeVector ptmax = p + tmax*v; 365 *n = ptmax*(1./ptmax.mag()); 371 *n = ptmax*(1./ptmax.mag()); 366 } 372 } 367 return tmax; 373 return tmax; 368 } 374 } 369 375 370 ////////////////////////////////////////////// 376 ////////////////////////////////////////////////////////////////////////// 371 // 377 // 372 // Calculate distance (<=actual) to closest su 378 // Calculate distance (<=actual) to closest surface of shape from inside 373 379 374 G4double G4Orb::DistanceToOut( const G4ThreeVe 380 G4double G4Orb::DistanceToOut( const G4ThreeVector& p ) const 375 { 381 { 376 #ifdef G4CSGDEBUG 382 #ifdef G4CSGDEBUG 377 if( Inside(p) == kOutside ) 383 if( Inside(p) == kOutside ) 378 { 384 { 379 std::ostringstream message; 385 std::ostringstream message; 380 G4int oldprc = message.precision(16); 386 G4int oldprc = message.precision(16); 381 message << "Point p is outside (!?) of sol 387 message << "Point p is outside (!?) of solid: " << GetName() << "\n"; 382 message << "Position:\n"; 388 message << "Position:\n"; 383 message << " p.x() = " << p.x()/mm << " 389 message << " p.x() = " << p.x()/mm << " mm\n"; 384 message << " p.y() = " << p.y()/mm << " 390 message << " p.y() = " << p.y()/mm << " mm\n"; 385 message << " p.z() = " << p.z()/mm << " 391 message << " p.z() = " << p.z()/mm << " mm"; 386 G4cout.precision(oldprc); 392 G4cout.precision(oldprc); 387 G4Exception("G4Trap::DistanceToOut(p)", "G 393 G4Exception("G4Trap::DistanceToOut(p)", "GeomSolids1002", 388 JustWarning, message ); 394 JustWarning, message ); 389 DumpInfo(); 395 DumpInfo(); 390 } 396 } 391 #endif 397 #endif 392 G4double dist = fRmax - p.mag(); 398 G4double dist = fRmax - p.mag(); 393 return (dist > 0) ? dist : 0.; 399 return (dist > 0) ? dist : 0.; 394 } 400 } 395 401 396 ////////////////////////////////////////////// 402 ////////////////////////////////////////////////////////////////////////// 397 // 403 // 398 // G4EntityType 404 // G4EntityType 399 405 400 G4GeometryType G4Orb::GetEntityType() const 406 G4GeometryType G4Orb::GetEntityType() const 401 { 407 { 402 return {"G4Orb"}; << 408 return G4String("G4Orb"); 403 } 409 } 404 410 405 ////////////////////////////////////////////// 411 ////////////////////////////////////////////////////////////////////////// 406 // 412 // 407 // Make a clone of the object 413 // Make a clone of the object 408 414 409 G4VSolid* G4Orb::Clone() const 415 G4VSolid* G4Orb::Clone() const 410 { 416 { 411 return new G4Orb(*this); 417 return new G4Orb(*this); 412 } 418 } 413 419 414 ////////////////////////////////////////////// 420 ////////////////////////////////////////////////////////////////////////// 415 // 421 // 416 // Stream object contents to an output stream 422 // Stream object contents to an output stream 417 423 418 std::ostream& G4Orb::StreamInfo( std::ostream& 424 std::ostream& G4Orb::StreamInfo( std::ostream& os ) const 419 { 425 { 420 G4long oldprc = os.precision(16); << 426 G4int oldprc = os.precision(16); 421 os << "------------------------------------- 427 os << "-----------------------------------------------------------\n" 422 << " *** Dump for solid - " << GetName 428 << " *** Dump for solid - " << GetName() << " ***\n" 423 << " ================================= 429 << " ===================================================\n" 424 << " Solid type: G4Orb\n" 430 << " Solid type: G4Orb\n" 425 << " Parameters: \n" 431 << " Parameters: \n" 426 << " outer radius: " << fRmax/mm << " 432 << " outer radius: " << fRmax/mm << " mm \n" 427 << "------------------------------------- 433 << "-----------------------------------------------------------\n"; 428 os.precision(oldprc); 434 os.precision(oldprc); 429 return os; 435 return os; 430 } 436 } 431 437 432 ////////////////////////////////////////////// 438 ////////////////////////////////////////////////////////////////////////// 433 // 439 // 434 // GetPointOnSurface 440 // GetPointOnSurface 435 441 436 G4ThreeVector G4Orb::GetPointOnSurface() const 442 G4ThreeVector G4Orb::GetPointOnSurface() const 437 { 443 { 438 return fRmax * G4RandomDirection(); 444 return fRmax * G4RandomDirection(); 439 } 445 } 440 446 441 ////////////////////////////////////////////// 447 ////////////////////////////////////////////////////////////////////////// 442 // 448 // 443 // Methods for visualisation 449 // Methods for visualisation 444 450 445 void G4Orb::DescribeYourselfTo ( G4VGraphicsSc 451 void G4Orb::DescribeYourselfTo ( G4VGraphicsScene& scene ) const 446 { 452 { 447 scene.AddSolid (*this); 453 scene.AddSolid (*this); 448 } 454 } 449 455 450 G4VisExtent G4Orb::GetExtent() const 456 G4VisExtent G4Orb::GetExtent() const 451 { 457 { 452 return {-fRmax, fRmax, -fRmax, fRmax, -fRmax << 458 return G4VisExtent (-fRmax, fRmax, -fRmax, fRmax, -fRmax, fRmax); 453 } 459 } 454 460 455 G4Polyhedron* G4Orb::CreatePolyhedron () const 461 G4Polyhedron* G4Orb::CreatePolyhedron () const 456 { 462 { 457 return new G4PolyhedronSphere (0., fRmax, 0. 463 return new G4PolyhedronSphere (0., fRmax, 0., 2*pi, 0., pi); 458 } 464 } 459 465 460 #endif 466 #endif 461 467