Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // Implementation for G4Box class 26 // Implementation for G4Box class 27 // 27 // 28 // 30.06.95 - P.Kent: First version 28 // 30.06.95 - P.Kent: First version 29 // 20.09.98 - V.Grichine: new algorithm of Di 29 // 20.09.98 - V.Grichine: new algorithm of DistanceToIn(p,v) 30 // 18.04.17 - E.Tcherniaev: complete revision 30 // 18.04.17 - E.Tcherniaev: complete revision, speed-up 31 // ------------------------------------------- 31 // -------------------------------------------------------------------- 32 32 33 #include "G4Box.hh" 33 #include "G4Box.hh" 34 34 35 #if !defined(G4GEOM_USE_UBOX) 35 #if !defined(G4GEOM_USE_UBOX) 36 36 37 #include "G4SystemOfUnits.hh" 37 #include "G4SystemOfUnits.hh" 38 #include "G4VoxelLimits.hh" 38 #include "G4VoxelLimits.hh" 39 #include "G4AffineTransform.hh" 39 #include "G4AffineTransform.hh" 40 #include "G4BoundingEnvelope.hh" 40 #include "G4BoundingEnvelope.hh" 41 #include "G4QuickRand.hh" 41 #include "G4QuickRand.hh" 42 42 43 #include "G4VPVParameterisation.hh" 43 #include "G4VPVParameterisation.hh" 44 44 45 #include "G4VGraphicsScene.hh" 45 #include "G4VGraphicsScene.hh" 46 #include "G4VisExtent.hh" 46 #include "G4VisExtent.hh" 47 47 48 ////////////////////////////////////////////// 48 //////////////////////////////////////////////////////////////////////// 49 // 49 // 50 // Constructor - check & set half widths 50 // Constructor - check & set half widths 51 51 52 G4Box::G4Box(const G4String& pName, 52 G4Box::G4Box(const G4String& pName, 53 G4double pX, 53 G4double pX, 54 G4double pY, 54 G4double pY, 55 G4double pZ) 55 G4double pZ) 56 : G4CSGSolid(pName), fDx(pX), fDy(pY), fDz(p 56 : G4CSGSolid(pName), fDx(pX), fDy(pY), fDz(pZ) 57 { 57 { 58 delta = 0.5*kCarTolerance; 58 delta = 0.5*kCarTolerance; 59 if (pX < 2*kCarTolerance || 59 if (pX < 2*kCarTolerance || 60 pY < 2*kCarTolerance || 60 pY < 2*kCarTolerance || 61 pZ < 2*kCarTolerance) // limit to thick 61 pZ < 2*kCarTolerance) // limit to thickness of surfaces 62 { 62 { 63 std::ostringstream message; 63 std::ostringstream message; 64 message << "Dimensions too small for Solid 64 message << "Dimensions too small for Solid: " << GetName() << "!" << G4endl 65 << " hX, hY, hZ = " << pX << " 65 << " hX, hY, hZ = " << pX << ", " << pY << ", " << pZ; 66 G4Exception("G4Box::G4Box()", "GeomSolids0 66 G4Exception("G4Box::G4Box()", "GeomSolids0002", FatalException, message); 67 } 67 } 68 } 68 } 69 69 70 ////////////////////////////////////////////// 70 ////////////////////////////////////////////////////////////////////////// 71 // 71 // 72 // Fake default constructor - sets only member 72 // Fake default constructor - sets only member data and allocates memory 73 // for usage restri 73 // for usage restricted to object persistency 74 74 75 G4Box::G4Box( __void__& a ) 75 G4Box::G4Box( __void__& a ) 76 : G4CSGSolid(a) << 76 : G4CSGSolid(a), delta(0.) 77 { 77 { 78 } 78 } 79 79 80 ////////////////////////////////////////////// 80 ////////////////////////////////////////////////////////////////////////// 81 // 81 // 82 // Destructor 82 // Destructor 83 83 84 G4Box::~G4Box() = default; << 84 G4Box::~G4Box() >> 85 { >> 86 } 85 87 86 ////////////////////////////////////////////// 88 ////////////////////////////////////////////////////////////////////////// 87 // 89 // 88 // Copy constructor 90 // Copy constructor 89 91 90 G4Box::G4Box(const G4Box&) = default; << 92 G4Box::G4Box(const G4Box& rhs) >> 93 : G4CSGSolid(rhs), fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz), delta(rhs.delta) >> 94 { >> 95 } 91 96 92 ////////////////////////////////////////////// 97 ////////////////////////////////////////////////////////////////////////// 93 // 98 // 94 // Assignment operator 99 // Assignment operator 95 100 96 G4Box& G4Box::operator = (const G4Box& rhs) 101 G4Box& G4Box::operator = (const G4Box& rhs) 97 { 102 { 98 // Check assignment to self 103 // Check assignment to self 99 // 104 // 100 if (this == &rhs) { return *this; } 105 if (this == &rhs) { return *this; } 101 106 102 // Copy base class data 107 // Copy base class data 103 // 108 // 104 G4CSGSolid::operator=(rhs); 109 G4CSGSolid::operator=(rhs); 105 110 106 // Copy data 111 // Copy data 107 // 112 // 108 fDx = rhs.fDx; 113 fDx = rhs.fDx; 109 fDy = rhs.fDy; 114 fDy = rhs.fDy; 110 fDz = rhs.fDz; 115 fDz = rhs.fDz; 111 delta = rhs.delta; 116 delta = rhs.delta; 112 117 113 return *this; 118 return *this; 114 } 119 } 115 120 116 ////////////////////////////////////////////// 121 ////////////////////////////////////////////////////////////////////////// 117 // 122 // 118 // Set X dimension 123 // Set X dimension 119 124 120 void G4Box::SetXHalfLength(G4double dx) 125 void G4Box::SetXHalfLength(G4double dx) 121 { 126 { 122 if(dx > 2*kCarTolerance) // limit to thickn 127 if(dx > 2*kCarTolerance) // limit to thickness of surfaces 123 { 128 { 124 fDx = dx; 129 fDx = dx; 125 } 130 } 126 else 131 else 127 { 132 { 128 std::ostringstream message; 133 std::ostringstream message; 129 message << "Dimension X too small for soli 134 message << "Dimension X too small for solid: " << GetName() << "!" 130 << G4endl 135 << G4endl 131 << " hX = " << dx; 136 << " hX = " << dx; 132 G4Exception("G4Box::SetXHalfLength()", "Ge 137 G4Exception("G4Box::SetXHalfLength()", "GeomSolids0002", 133 FatalException, message); 138 FatalException, message); 134 } 139 } 135 fCubicVolume = 0.; 140 fCubicVolume = 0.; 136 fSurfaceArea = 0.; 141 fSurfaceArea = 0.; 137 fRebuildPolyhedron = true; 142 fRebuildPolyhedron = true; 138 } 143 } 139 144 140 ////////////////////////////////////////////// 145 ////////////////////////////////////////////////////////////////////////// 141 // 146 // 142 // Set Y dimension 147 // Set Y dimension 143 148 144 void G4Box::SetYHalfLength(G4double dy) 149 void G4Box::SetYHalfLength(G4double dy) 145 { 150 { 146 if(dy > 2*kCarTolerance) // limit to thickn 151 if(dy > 2*kCarTolerance) // limit to thickness of surfaces 147 { 152 { 148 fDy = dy; 153 fDy = dy; 149 } 154 } 150 else 155 else 151 { 156 { 152 std::ostringstream message; 157 std::ostringstream message; 153 message << "Dimension Y too small for soli 158 message << "Dimension Y too small for solid: " << GetName() << "!\n" 154 << " hY = " << dy; 159 << " hY = " << dy; 155 G4Exception("G4Box::SetYHalfLength()", "Ge 160 G4Exception("G4Box::SetYHalfLength()", "GeomSolids0002", 156 FatalException, message); 161 FatalException, message); 157 } 162 } 158 fCubicVolume = 0.; 163 fCubicVolume = 0.; 159 fSurfaceArea = 0.; 164 fSurfaceArea = 0.; 160 fRebuildPolyhedron = true; 165 fRebuildPolyhedron = true; 161 } 166 } 162 167 163 ////////////////////////////////////////////// 168 ////////////////////////////////////////////////////////////////////////// 164 // 169 // 165 // Set Z dimension 170 // Set Z dimension 166 171 167 void G4Box::SetZHalfLength(G4double dz) 172 void G4Box::SetZHalfLength(G4double dz) 168 { 173 { 169 if(dz > 2*kCarTolerance) // limit to thickn 174 if(dz > 2*kCarTolerance) // limit to thickness of surfaces 170 { 175 { 171 fDz = dz; 176 fDz = dz; 172 } 177 } 173 else 178 else 174 { 179 { 175 std::ostringstream message; 180 std::ostringstream message; 176 message << "Dimension Z too small for soli 181 message << "Dimension Z too small for solid: " << GetName() << "!\n" 177 << " hZ = " << dz; 182 << " hZ = " << dz; 178 G4Exception("G4Box::SetZHalfLength()", "Ge 183 G4Exception("G4Box::SetZHalfLength()", "GeomSolids0002", 179 FatalException, message); 184 FatalException, message); 180 } 185 } 181 fCubicVolume = 0.; 186 fCubicVolume = 0.; 182 fSurfaceArea = 0.; 187 fSurfaceArea = 0.; 183 fRebuildPolyhedron = true; 188 fRebuildPolyhedron = true; 184 } 189 } 185 190 186 ////////////////////////////////////////////// 191 ////////////////////////////////////////////////////////////////////////// 187 // 192 // 188 // Dispatch to parameterisation for replicatio 193 // Dispatch to parameterisation for replication mechanism dimension 189 // computation & modification. 194 // computation & modification. 190 195 191 void G4Box::ComputeDimensions(G4VPVParameteris 196 void G4Box::ComputeDimensions(G4VPVParameterisation* p, 192 const G4int n, 197 const G4int n, 193 const G4VPhysica 198 const G4VPhysicalVolume* pRep) 194 { 199 { 195 p->ComputeDimensions(*this,n,pRep); 200 p->ComputeDimensions(*this,n,pRep); 196 } 201 } 197 202 198 ////////////////////////////////////////////// 203 ////////////////////////////////////////////////////////////////////////// 199 // 204 // 200 // Get bounding box 205 // Get bounding box 201 206 202 void G4Box::BoundingLimits(G4ThreeVector& pMin 207 void G4Box::BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const 203 { 208 { 204 pMin.set(-fDx,-fDy,-fDz); 209 pMin.set(-fDx,-fDy,-fDz); 205 pMax.set( fDx, fDy, fDz); 210 pMax.set( fDx, fDy, fDz); 206 211 207 // Check correctness of the bounding box 212 // Check correctness of the bounding box 208 // 213 // 209 if (pMin.x() >= pMax.x() || pMin.y() >= pMax 214 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z()) 210 { 215 { 211 std::ostringstream message; 216 std::ostringstream message; 212 message << "Bad bounding box (min >= max) 217 message << "Bad bounding box (min >= max) for solid: " 213 << GetName() << " !" 218 << GetName() << " !" 214 << "\npMin = " << pMin 219 << "\npMin = " << pMin 215 << "\npMax = " << pMax; 220 << "\npMax = " << pMax; 216 G4Exception("G4Box::BoundingLimits()", "Ge 221 G4Exception("G4Box::BoundingLimits()", "GeomMgt0001", JustWarning, message); 217 DumpInfo(); 222 DumpInfo(); 218 } 223 } 219 } 224 } 220 225 221 ////////////////////////////////////////////// 226 ////////////////////////////////////////////////////////////////////////// 222 // 227 // 223 // Calculate extent under transform and specif 228 // Calculate extent under transform and specified limit 224 229 225 G4bool G4Box::CalculateExtent(const EAxis pAxi 230 G4bool G4Box::CalculateExtent(const EAxis pAxis, 226 const G4VoxelLim 231 const G4VoxelLimits& pVoxelLimit, 227 const G4AffineTr 232 const G4AffineTransform& pTransform, 228 G4double& 233 G4double& pMin, G4double& pMax) const 229 { 234 { 230 G4ThreeVector bmin, bmax; 235 G4ThreeVector bmin, bmax; 231 236 232 // Get bounding box 237 // Get bounding box 233 BoundingLimits(bmin,bmax); 238 BoundingLimits(bmin,bmax); 234 239 235 // Find extent 240 // Find extent 236 G4BoundingEnvelope bbox(bmin,bmax); 241 G4BoundingEnvelope bbox(bmin,bmax); 237 return bbox.CalculateExtent(pAxis,pVoxelLimi 242 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax); 238 } 243 } 239 244 240 ////////////////////////////////////////////// 245 ////////////////////////////////////////////////////////////////////////// 241 // 246 // 242 // Return whether point inside/outside/on surf 247 // Return whether point inside/outside/on surface, using tolerance 243 248 244 EInside G4Box::Inside(const G4ThreeVector& p) 249 EInside G4Box::Inside(const G4ThreeVector& p) const 245 { 250 { 246 G4double dist = std::max(std::max( 251 G4double dist = std::max(std::max( 247 std::abs(p.x())-fDx, 252 std::abs(p.x())-fDx, 248 std::abs(p.y())-fDy), 253 std::abs(p.y())-fDy), 249 std::abs(p.z())-fDz); 254 std::abs(p.z())-fDz); 250 return (dist > delta) ? kOutside : 255 return (dist > delta) ? kOutside : 251 ((dist > -delta) ? kSurface : kInside); 256 ((dist > -delta) ? kSurface : kInside); 252 } 257 } 253 258 254 ////////////////////////////////////////////// 259 ////////////////////////////////////////////////////////////////////////// 255 // 260 // 256 // Detect the side(s) and return corresponding 261 // Detect the side(s) and return corresponding normal 257 262 258 G4ThreeVector G4Box::SurfaceNormal( const G4Th 263 G4ThreeVector G4Box::SurfaceNormal( const G4ThreeVector& p) const 259 { 264 { 260 G4ThreeVector norm(0,0,0); 265 G4ThreeVector norm(0,0,0); 261 G4double px = p.x(); 266 G4double px = p.x(); 262 if (std::abs(std::abs(px) - fDx) <= delta) n 267 if (std::abs(std::abs(px) - fDx) <= delta) norm.setX(px < 0 ? -1. : 1.); 263 G4double py = p.y(); 268 G4double py = p.y(); 264 if (std::abs(std::abs(py) - fDy) <= delta) n 269 if (std::abs(std::abs(py) - fDy) <= delta) norm.setY(py < 0 ? -1. : 1.); 265 G4double pz = p.z(); 270 G4double pz = p.z(); 266 if (std::abs(std::abs(pz) - fDz) <= delta) n 271 if (std::abs(std::abs(pz) - fDz) <= delta) norm.setZ(pz < 0 ? -1. : 1.); 267 272 268 G4double nside = norm.mag2(); // number of s 273 G4double nside = norm.mag2(); // number of sides = magnitude squared 269 if (nside == 1) 274 if (nside == 1) 270 return norm; 275 return norm; 271 else if (nside > 1) 276 else if (nside > 1) 272 return norm.unit(); // edge or corner 277 return norm.unit(); // edge or corner 273 else 278 else 274 { 279 { 275 // Point is not on the surface 280 // Point is not on the surface 276 // 281 // 277 #ifdef G4CSGDEBUG 282 #ifdef G4CSGDEBUG 278 std::ostringstream message; 283 std::ostringstream message; 279 G4int oldprc = message.precision(16); 284 G4int oldprc = message.precision(16); 280 message << "Point p is not on surface (!?) 285 message << "Point p is not on surface (!?) of solid: " 281 << GetName() << G4endl; 286 << GetName() << G4endl; 282 message << "Position:\n"; 287 message << "Position:\n"; 283 message << " p.x() = " << p.x()/mm << " 288 message << " p.x() = " << p.x()/mm << " mm\n"; 284 message << " p.y() = " << p.y()/mm << " 289 message << " p.y() = " << p.y()/mm << " mm\n"; 285 message << " p.z() = " << p.z()/mm << " 290 message << " p.z() = " << p.z()/mm << " mm"; 286 G4cout.precision(oldprc); 291 G4cout.precision(oldprc); 287 G4Exception("G4Box::SurfaceNormal(p)", "Ge 292 G4Exception("G4Box::SurfaceNormal(p)", "GeomSolids1002", 288 JustWarning, message ); 293 JustWarning, message ); 289 DumpInfo(); 294 DumpInfo(); 290 #endif 295 #endif 291 return ApproxSurfaceNormal(p); 296 return ApproxSurfaceNormal(p); 292 } 297 } 293 } 298 } 294 299 295 ////////////////////////////////////////////// 300 ////////////////////////////////////////////////////////////////////////// 296 // 301 // 297 // Algorithm for SurfaceNormal() following the 302 // Algorithm for SurfaceNormal() following the original specification 298 // for points not on the surface 303 // for points not on the surface 299 304 300 G4ThreeVector G4Box::ApproxSurfaceNormal(const 305 G4ThreeVector G4Box::ApproxSurfaceNormal(const G4ThreeVector& p) const 301 { 306 { 302 G4double distx = std::abs(p.x()) - fDx; 307 G4double distx = std::abs(p.x()) - fDx; 303 G4double disty = std::abs(p.y()) - fDy; 308 G4double disty = std::abs(p.y()) - fDy; 304 G4double distz = std::abs(p.z()) - fDz; 309 G4double distz = std::abs(p.z()) - fDz; 305 310 306 if (distx >= disty && distx >= distz) 311 if (distx >= disty && distx >= distz) 307 return {std::copysign(1.,p.x()), 0., 0.}; << 312 return G4ThreeVector(std::copysign(1.,p.x()), 0., 0.); 308 if (disty >= distx && disty >= distz) 313 if (disty >= distx && disty >= distz) 309 return {0., std::copysign(1.,p.y()), 0.}; << 314 return G4ThreeVector(0., std::copysign(1.,p.y()), 0.); 310 else 315 else 311 return {0., 0., std::copysign(1.,p.z())}; << 316 return G4ThreeVector(0., 0., std::copysign(1.,p.z())); 312 } 317 } 313 318 314 ////////////////////////////////////////////// 319 ////////////////////////////////////////////////////////////////////////// 315 // 320 // 316 // Calculate distance to box from an outside p 321 // Calculate distance to box from an outside point 317 // - return kInfinity if no intersection 322 // - return kInfinity if no intersection 318 // 323 // 319 324 320 G4double G4Box::DistanceToIn(const G4ThreeVect 325 G4double G4Box::DistanceToIn(const G4ThreeVector& p, 321 const G4ThreeVect 326 const G4ThreeVector& v) const 322 { 327 { 323 // Check if point is on the surface and trav 328 // Check if point is on the surface and traveling away 324 // 329 // 325 if ((std::abs(p.x()) - fDx) >= -delta && p.x 330 if ((std::abs(p.x()) - fDx) >= -delta && p.x()*v.x() >= 0) return kInfinity; 326 if ((std::abs(p.y()) - fDy) >= -delta && p.y 331 if ((std::abs(p.y()) - fDy) >= -delta && p.y()*v.y() >= 0) return kInfinity; 327 if ((std::abs(p.z()) - fDz) >= -delta && p.z 332 if ((std::abs(p.z()) - fDz) >= -delta && p.z()*v.z() >= 0) return kInfinity; 328 333 329 // Find intersection 334 // Find intersection 330 // 335 // 331 G4double invx = (v.x() == 0) ? DBL_MAX : -1. 336 G4double invx = (v.x() == 0) ? DBL_MAX : -1./v.x(); 332 G4double dx = std::copysign(fDx,invx); 337 G4double dx = std::copysign(fDx,invx); 333 G4double txmin = (p.x() - dx)*invx; 338 G4double txmin = (p.x() - dx)*invx; 334 G4double txmax = (p.x() + dx)*invx; 339 G4double txmax = (p.x() + dx)*invx; 335 340 336 G4double invy = (v.y() == 0) ? DBL_MAX : -1. 341 G4double invy = (v.y() == 0) ? DBL_MAX : -1./v.y(); 337 G4double dy = std::copysign(fDy,invy); 342 G4double dy = std::copysign(fDy,invy); 338 G4double tymin = std::max(txmin,(p.y() - dy) 343 G4double tymin = std::max(txmin,(p.y() - dy)*invy); 339 G4double tymax = std::min(txmax,(p.y() + dy) 344 G4double tymax = std::min(txmax,(p.y() + dy)*invy); 340 345 341 G4double invz = (v.z() == 0) ? DBL_MAX : -1. 346 G4double invz = (v.z() == 0) ? DBL_MAX : -1./v.z(); 342 G4double dz = std::copysign(fDz,invz); 347 G4double dz = std::copysign(fDz,invz); 343 G4double tmin = std::max(tymin,(p.z() - dz)* 348 G4double tmin = std::max(tymin,(p.z() - dz)*invz); 344 G4double tmax = std::min(tymax,(p.z() + dz)* 349 G4double tmax = std::min(tymax,(p.z() + dz)*invz); 345 350 346 if (tmax <= tmin + delta) return kInfinity; 351 if (tmax <= tmin + delta) return kInfinity; // touch or no hit 347 return (tmin < delta) ? 0. : tmin; 352 return (tmin < delta) ? 0. : tmin; 348 } 353 } 349 354 350 ////////////////////////////////////////////// 355 ////////////////////////////////////////////////////////////////////////// 351 // 356 // 352 // Appoximate distance to box. 357 // Appoximate distance to box. 353 // Returns largest perpendicular distance to t 358 // Returns largest perpendicular distance to the closest x/y/z sides of 354 // the box, which is the most fast estimation 359 // the box, which is the most fast estimation of the shortest distance to box 355 // - If inside return 0 360 // - If inside return 0 356 361 357 G4double G4Box::DistanceToIn(const G4ThreeVect 362 G4double G4Box::DistanceToIn(const G4ThreeVector& p) const 358 { 363 { 359 G4double dist = std::max(std::max( 364 G4double dist = std::max(std::max( 360 std::abs(p.x())-fDx, 365 std::abs(p.x())-fDx, 361 std::abs(p.y())-fDy), 366 std::abs(p.y())-fDy), 362 std::abs(p.z())-fDz); 367 std::abs(p.z())-fDz); 363 return (dist > 0) ? dist : 0.; 368 return (dist > 0) ? dist : 0.; 364 } 369 } 365 370 366 ////////////////////////////////////////////// 371 ////////////////////////////////////////////////////////////////////////// 367 // 372 // 368 // Calculate distance to surface of the box fr 373 // Calculate distance to surface of the box from inside and 369 // find normal at exit point, if required 374 // find normal at exit point, if required 370 // - when leaving the surface, return 0 375 // - when leaving the surface, return 0 371 376 372 G4double G4Box::DistanceToOut( const G4ThreeVe 377 G4double G4Box::DistanceToOut( const G4ThreeVector& p, 373 const G4ThreeVe 378 const G4ThreeVector& v, 374 const G4bool ca 379 const G4bool calcNorm, 375 G4bool* validNo 380 G4bool* validNorm, G4ThreeVector* n) const 376 { 381 { 377 // Check if point is on the surface and trav 382 // Check if point is on the surface and traveling away 378 // 383 // 379 if ((std::abs(p.x()) - fDx) >= -delta && p.x 384 if ((std::abs(p.x()) - fDx) >= -delta && p.x()*v.x() > 0) 380 { 385 { 381 if (calcNorm) 386 if (calcNorm) 382 { 387 { 383 *validNorm = true; 388 *validNorm = true; 384 n->set((p.x() < 0) ? -1. : 1., 0., 0.); 389 n->set((p.x() < 0) ? -1. : 1., 0., 0.); 385 } 390 } 386 return 0.; 391 return 0.; 387 } 392 } 388 if ((std::abs(p.y()) - fDy) >= -delta && p.y 393 if ((std::abs(p.y()) - fDy) >= -delta && p.y()*v.y() > 0) 389 { 394 { 390 if (calcNorm) 395 if (calcNorm) 391 { 396 { 392 *validNorm = true; 397 *validNorm = true; 393 n->set(0., (p.y() < 0) ? -1. : 1., 0.); 398 n->set(0., (p.y() < 0) ? -1. : 1., 0.); 394 } 399 } 395 return 0.; 400 return 0.; 396 } 401 } 397 if ((std::abs(p.z()) - fDz) >= -delta && p.z 402 if ((std::abs(p.z()) - fDz) >= -delta && p.z()*v.z() > 0) 398 { 403 { 399 if (calcNorm) 404 if (calcNorm) 400 { 405 { 401 *validNorm = true; 406 *validNorm = true; 402 n->set(0., 0., (p.z() < 0) ? -1. : 1.); 407 n->set(0., 0., (p.z() < 0) ? -1. : 1.); 403 } 408 } 404 return 0.; 409 return 0.; 405 } 410 } 406 411 407 // Find intersection 412 // Find intersection 408 // 413 // 409 G4double vx = v.x(); 414 G4double vx = v.x(); 410 G4double tx = (vx == 0) ? DBL_MAX : (std::co 415 G4double tx = (vx == 0) ? DBL_MAX : (std::copysign(fDx,vx) - p.x())/vx; 411 416 412 G4double vy = v.y(); 417 G4double vy = v.y(); 413 G4double ty = (vy == 0) ? tx : (std::copysig 418 G4double ty = (vy == 0) ? tx : (std::copysign(fDy,vy) - p.y())/vy; 414 G4double txy = std::min(tx,ty); 419 G4double txy = std::min(tx,ty); 415 420 416 G4double vz = v.z(); 421 G4double vz = v.z(); 417 G4double tz = (vz == 0) ? txy : (std::copysi 422 G4double tz = (vz == 0) ? txy : (std::copysign(fDz,vz) - p.z())/vz; 418 G4double tmax = std::min(txy,tz); 423 G4double tmax = std::min(txy,tz); 419 424 420 // Set normal, if required, and return dista 425 // Set normal, if required, and return distance 421 // 426 // 422 if (calcNorm) 427 if (calcNorm) 423 { 428 { 424 *validNorm = true; 429 *validNorm = true; 425 if (tmax == tx) n->set((v.x() < 0) ? 430 if (tmax == tx) n->set((v.x() < 0) ? -1. : 1., 0., 0.); 426 else if (tmax == ty) n->set(0., (v.y() < 0 431 else if (tmax == ty) n->set(0., (v.y() < 0) ? -1. : 1., 0.); 427 else n->set(0., 0., (v.z() 432 else n->set(0., 0., (v.z() < 0) ? -1. : 1.); 428 } 433 } 429 return tmax; 434 return tmax; 430 } 435 } 431 436 432 ////////////////////////////////////////////// 437 //////////////////////////////////////////////////////////////////////////// 433 // 438 // 434 // Calculate exact shortest distance to any bo 439 // Calculate exact shortest distance to any boundary from inside 435 // - if outside return 0 440 // - if outside return 0 436 441 437 G4double G4Box::DistanceToOut(const G4ThreeVec 442 G4double G4Box::DistanceToOut(const G4ThreeVector& p) const 438 { 443 { 439 #ifdef G4CSGDEBUG 444 #ifdef G4CSGDEBUG 440 if( Inside(p) == kOutside ) 445 if( Inside(p) == kOutside ) 441 { 446 { 442 std::ostringstream message; 447 std::ostringstream message; 443 G4int oldprc = message.precision(16); 448 G4int oldprc = message.precision(16); 444 message << "Point p is outside (!?) of sol 449 message << "Point p is outside (!?) of solid: " << GetName() << G4endl; 445 message << "Position:\n"; 450 message << "Position:\n"; 446 message << " p.x() = " << p.x()/mm << " 451 message << " p.x() = " << p.x()/mm << " mm\n"; 447 message << " p.y() = " << p.y()/mm << " 452 message << " p.y() = " << p.y()/mm << " mm\n"; 448 message << " p.z() = " << p.z()/mm << " 453 message << " p.z() = " << p.z()/mm << " mm"; 449 G4cout.precision(oldprc); 454 G4cout.precision(oldprc); 450 G4Exception("G4Box::DistanceToOut(p)", "Ge 455 G4Exception("G4Box::DistanceToOut(p)", "GeomSolids1002", 451 JustWarning, message ); 456 JustWarning, message ); 452 DumpInfo(); 457 DumpInfo(); 453 } 458 } 454 #endif 459 #endif 455 G4double dist = std::min(std::min( 460 G4double dist = std::min(std::min( 456 fDx-std::abs(p.x()), 461 fDx-std::abs(p.x()), 457 fDy-std::abs(p.y())), 462 fDy-std::abs(p.y())), 458 fDz-std::abs(p.z())); 463 fDz-std::abs(p.z())); 459 return (dist > 0) ? dist : 0.; 464 return (dist > 0) ? dist : 0.; 460 } 465 } 461 466 462 ////////////////////////////////////////////// 467 ////////////////////////////////////////////////////////////////////////// 463 // 468 // 464 // GetEntityType 469 // GetEntityType 465 470 466 G4GeometryType G4Box::GetEntityType() const 471 G4GeometryType G4Box::GetEntityType() const 467 { 472 { 468 return {"G4Box"}; << 473 return G4String("G4Box"); 469 } << 470 << 471 ////////////////////////////////////////////// << 472 // << 473 // IsFaceted << 474 << 475 G4bool G4Box::IsFaceted() const << 476 { << 477 return true; << 478 } 474 } 479 475 480 ////////////////////////////////////////////// 476 ////////////////////////////////////////////////////////////////////////// 481 // 477 // 482 // Stream object contents to an output stream 478 // Stream object contents to an output stream 483 479 484 std::ostream& G4Box::StreamInfo(std::ostream& 480 std::ostream& G4Box::StreamInfo(std::ostream& os) const 485 { 481 { 486 G4long oldprc = os.precision(16); << 482 G4int oldprc = os.precision(16); 487 os << "------------------------------------- 483 os << "-----------------------------------------------------------\n" 488 << " *** Dump for solid - " << GetName 484 << " *** Dump for solid - " << GetName() << " ***\n" 489 << " ================================= 485 << " ===================================================\n" 490 << "Solid type: G4Box\n" 486 << "Solid type: G4Box\n" 491 << "Parameters: \n" 487 << "Parameters: \n" 492 << " half length X: " << fDx/mm << " mm 488 << " half length X: " << fDx/mm << " mm \n" 493 << " half length Y: " << fDy/mm << " mm 489 << " half length Y: " << fDy/mm << " mm \n" 494 << " half length Z: " << fDz/mm << " mm 490 << " half length Z: " << fDz/mm << " mm \n" 495 << "------------------------------------- 491 << "-----------------------------------------------------------\n"; 496 os.precision(oldprc); 492 os.precision(oldprc); 497 return os; 493 return os; 498 } 494 } 499 495 500 ////////////////////////////////////////////// 496 ////////////////////////////////////////////////////////////////////////// 501 // 497 // 502 // Return a point randomly and uniformly selec 498 // Return a point randomly and uniformly selected on the surface 503 499 504 G4ThreeVector G4Box::GetPointOnSurface() const 500 G4ThreeVector G4Box::GetPointOnSurface() const 505 { 501 { 506 G4double sxy = fDx*fDy, sxz = fDx*fDz, syz = 502 G4double sxy = fDx*fDy, sxz = fDx*fDz, syz = fDy*fDz; 507 G4double select = (sxy + sxz + syz)*G4QuickR 503 G4double select = (sxy + sxz + syz)*G4QuickRand(); 508 G4double u = 2.*G4QuickRand() - 1.; 504 G4double u = 2.*G4QuickRand() - 1.; 509 G4double v = 2.*G4QuickRand() - 1.; 505 G4double v = 2.*G4QuickRand() - 1.; 510 506 511 if (select < sxy) 507 if (select < sxy) 512 return { u*fDx, v*fDy, ((select < 0.5*sxy) << 508 return G4ThreeVector(u*fDx, >> 509 v*fDy, >> 510 ((select < 0.5*sxy) ? -fDz : fDz)); 513 else if (select < sxy + sxz) 511 else if (select < sxy + sxz) 514 return { u*fDx, ((select < sxy + 0.5*sxz) << 512 return G4ThreeVector(u*fDx, >> 513 ((select < sxy + 0.5*sxz) ? -fDy : fDy), >> 514 v*fDz); 515 else 515 else 516 return { ((select < sxy + sxz + 0.5*syz) ? << 516 return G4ThreeVector(((select < sxy + sxz + 0.5*syz) ? -fDx : fDx), >> 517 u*fDy, >> 518 v*fDz); 517 } 519 } 518 520 519 ////////////////////////////////////////////// 521 ////////////////////////////////////////////////////////////////////////// 520 // 522 // 521 // Make a clone of the object 523 // Make a clone of the object 522 // 524 // 523 G4VSolid* G4Box::Clone() const 525 G4VSolid* G4Box::Clone() const 524 { 526 { 525 return new G4Box(*this); 527 return new G4Box(*this); 526 } 528 } 527 529 528 ////////////////////////////////////////////// 530 ////////////////////////////////////////////////////////////////////////// 529 // 531 // 530 // Methods for visualisation 532 // Methods for visualisation 531 533 532 void G4Box::DescribeYourselfTo (G4VGraphicsSce 534 void G4Box::DescribeYourselfTo (G4VGraphicsScene& scene) const 533 { 535 { 534 scene.AddSolid (*this); 536 scene.AddSolid (*this); 535 } 537 } 536 538 537 G4VisExtent G4Box::GetExtent() const 539 G4VisExtent G4Box::GetExtent() const 538 { 540 { 539 return { -fDx, fDx, -fDy, fDy, -fDz, fDz }; << 541 return G4VisExtent (-fDx, fDx, -fDy, fDy, -fDz, fDz); 540 } 542 } 541 543 542 G4Polyhedron* G4Box::CreatePolyhedron () const 544 G4Polyhedron* G4Box::CreatePolyhedron () const 543 { 545 { 544 return new G4PolyhedronBox (fDx, fDy, fDz); 546 return new G4PolyhedronBox (fDx, fDy, fDz); 545 } 547 } 546 #endif 548 #endif 547 549