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