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) 77 { 77 { 78 } 78 } 79 79 80 ////////////////////////////////////////////// 80 ////////////////////////////////////////////////////////////////////////// 81 // 81 // 82 // Destructor 82 // Destructor 83 83 84 G4Box::~G4Box() = default; 84 G4Box::~G4Box() = default; 85 85 86 ////////////////////////////////////////////// 86 ////////////////////////////////////////////////////////////////////////// 87 // 87 // 88 // Copy constructor 88 // Copy constructor 89 89 90 G4Box::G4Box(const G4Box&) = default; 90 G4Box::G4Box(const G4Box&) = default; 91 91 92 ////////////////////////////////////////////// 92 ////////////////////////////////////////////////////////////////////////// 93 // 93 // 94 // Assignment operator 94 // Assignment operator 95 95 96 G4Box& G4Box::operator = (const G4Box& rhs) 96 G4Box& G4Box::operator = (const G4Box& rhs) 97 { 97 { 98 // Check assignment to self 98 // Check assignment to self 99 // 99 // 100 if (this == &rhs) { return *this; } 100 if (this == &rhs) { return *this; } 101 101 102 // Copy base class data 102 // Copy base class data 103 // 103 // 104 G4CSGSolid::operator=(rhs); 104 G4CSGSolid::operator=(rhs); 105 105 106 // Copy data 106 // Copy data 107 // 107 // 108 fDx = rhs.fDx; 108 fDx = rhs.fDx; 109 fDy = rhs.fDy; 109 fDy = rhs.fDy; 110 fDz = rhs.fDz; 110 fDz = rhs.fDz; 111 delta = rhs.delta; 111 delta = rhs.delta; 112 112 113 return *this; 113 return *this; 114 } 114 } 115 115 116 ////////////////////////////////////////////// 116 ////////////////////////////////////////////////////////////////////////// 117 // 117 // 118 // Set X dimension 118 // Set X dimension 119 119 120 void G4Box::SetXHalfLength(G4double dx) 120 void G4Box::SetXHalfLength(G4double dx) 121 { 121 { 122 if(dx > 2*kCarTolerance) // limit to thickn 122 if(dx > 2*kCarTolerance) // limit to thickness of surfaces 123 { 123 { 124 fDx = dx; 124 fDx = dx; 125 } 125 } 126 else 126 else 127 { 127 { 128 std::ostringstream message; 128 std::ostringstream message; 129 message << "Dimension X too small for soli 129 message << "Dimension X too small for solid: " << GetName() << "!" 130 << G4endl 130 << G4endl 131 << " hX = " << dx; 131 << " hX = " << dx; 132 G4Exception("G4Box::SetXHalfLength()", "Ge 132 G4Exception("G4Box::SetXHalfLength()", "GeomSolids0002", 133 FatalException, message); 133 FatalException, message); 134 } 134 } 135 fCubicVolume = 0.; 135 fCubicVolume = 0.; 136 fSurfaceArea = 0.; 136 fSurfaceArea = 0.; 137 fRebuildPolyhedron = true; 137 fRebuildPolyhedron = true; 138 } 138 } 139 139 140 ////////////////////////////////////////////// 140 ////////////////////////////////////////////////////////////////////////// 141 // 141 // 142 // Set Y dimension 142 // Set Y dimension 143 143 144 void G4Box::SetYHalfLength(G4double dy) 144 void G4Box::SetYHalfLength(G4double dy) 145 { 145 { 146 if(dy > 2*kCarTolerance) // limit to thickn 146 if(dy > 2*kCarTolerance) // limit to thickness of surfaces 147 { 147 { 148 fDy = dy; 148 fDy = dy; 149 } 149 } 150 else 150 else 151 { 151 { 152 std::ostringstream message; 152 std::ostringstream message; 153 message << "Dimension Y too small for soli 153 message << "Dimension Y too small for solid: " << GetName() << "!\n" 154 << " hY = " << dy; 154 << " hY = " << dy; 155 G4Exception("G4Box::SetYHalfLength()", "Ge 155 G4Exception("G4Box::SetYHalfLength()", "GeomSolids0002", 156 FatalException, message); 156 FatalException, message); 157 } 157 } 158 fCubicVolume = 0.; 158 fCubicVolume = 0.; 159 fSurfaceArea = 0.; 159 fSurfaceArea = 0.; 160 fRebuildPolyhedron = true; 160 fRebuildPolyhedron = true; 161 } 161 } 162 162 163 ////////////////////////////////////////////// 163 ////////////////////////////////////////////////////////////////////////// 164 // 164 // 165 // Set Z dimension 165 // Set Z dimension 166 166 167 void G4Box::SetZHalfLength(G4double dz) 167 void G4Box::SetZHalfLength(G4double dz) 168 { 168 { 169 if(dz > 2*kCarTolerance) // limit to thickn 169 if(dz > 2*kCarTolerance) // limit to thickness of surfaces 170 { 170 { 171 fDz = dz; 171 fDz = dz; 172 } 172 } 173 else 173 else 174 { 174 { 175 std::ostringstream message; 175 std::ostringstream message; 176 message << "Dimension Z too small for soli 176 message << "Dimension Z too small for solid: " << GetName() << "!\n" 177 << " hZ = " << dz; 177 << " hZ = " << dz; 178 G4Exception("G4Box::SetZHalfLength()", "Ge 178 G4Exception("G4Box::SetZHalfLength()", "GeomSolids0002", 179 FatalException, message); 179 FatalException, message); 180 } 180 } 181 fCubicVolume = 0.; 181 fCubicVolume = 0.; 182 fSurfaceArea = 0.; 182 fSurfaceArea = 0.; 183 fRebuildPolyhedron = true; 183 fRebuildPolyhedron = true; 184 } 184 } 185 185 186 ////////////////////////////////////////////// 186 ////////////////////////////////////////////////////////////////////////// 187 // 187 // 188 // Dispatch to parameterisation for replicatio 188 // Dispatch to parameterisation for replication mechanism dimension 189 // computation & modification. 189 // computation & modification. 190 190 191 void G4Box::ComputeDimensions(G4VPVParameteris 191 void G4Box::ComputeDimensions(G4VPVParameterisation* p, 192 const G4int n, 192 const G4int n, 193 const G4VPhysica 193 const G4VPhysicalVolume* pRep) 194 { 194 { 195 p->ComputeDimensions(*this,n,pRep); 195 p->ComputeDimensions(*this,n,pRep); 196 } 196 } 197 197 198 ////////////////////////////////////////////// 198 ////////////////////////////////////////////////////////////////////////// 199 // 199 // 200 // Get bounding box 200 // Get bounding box 201 201 202 void G4Box::BoundingLimits(G4ThreeVector& pMin 202 void G4Box::BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const 203 { 203 { 204 pMin.set(-fDx,-fDy,-fDz); 204 pMin.set(-fDx,-fDy,-fDz); 205 pMax.set( fDx, fDy, fDz); 205 pMax.set( fDx, fDy, fDz); 206 206 207 // Check correctness of the bounding box 207 // Check correctness of the bounding box 208 // 208 // 209 if (pMin.x() >= pMax.x() || pMin.y() >= pMax 209 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z()) 210 { 210 { 211 std::ostringstream message; 211 std::ostringstream message; 212 message << "Bad bounding box (min >= max) 212 message << "Bad bounding box (min >= max) for solid: " 213 << GetName() << " !" 213 << GetName() << " !" 214 << "\npMin = " << pMin 214 << "\npMin = " << pMin 215 << "\npMax = " << pMax; 215 << "\npMax = " << pMax; 216 G4Exception("G4Box::BoundingLimits()", "Ge 216 G4Exception("G4Box::BoundingLimits()", "GeomMgt0001", JustWarning, message); 217 DumpInfo(); 217 DumpInfo(); 218 } 218 } 219 } 219 } 220 220 221 ////////////////////////////////////////////// 221 ////////////////////////////////////////////////////////////////////////// 222 // 222 // 223 // Calculate extent under transform and specif 223 // Calculate extent under transform and specified limit 224 224 225 G4bool G4Box::CalculateExtent(const EAxis pAxi 225 G4bool G4Box::CalculateExtent(const EAxis pAxis, 226 const G4VoxelLim 226 const G4VoxelLimits& pVoxelLimit, 227 const G4AffineTr 227 const G4AffineTransform& pTransform, 228 G4double& 228 G4double& pMin, G4double& pMax) const 229 { 229 { 230 G4ThreeVector bmin, bmax; 230 G4ThreeVector bmin, bmax; 231 231 232 // Get bounding box 232 // Get bounding box 233 BoundingLimits(bmin,bmax); 233 BoundingLimits(bmin,bmax); 234 234 235 // Find extent 235 // Find extent 236 G4BoundingEnvelope bbox(bmin,bmax); 236 G4BoundingEnvelope bbox(bmin,bmax); 237 return bbox.CalculateExtent(pAxis,pVoxelLimi 237 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax); 238 } 238 } 239 239 240 ////////////////////////////////////////////// 240 ////////////////////////////////////////////////////////////////////////// 241 // 241 // 242 // Return whether point inside/outside/on surf 242 // Return whether point inside/outside/on surface, using tolerance 243 243 244 EInside G4Box::Inside(const G4ThreeVector& p) 244 EInside G4Box::Inside(const G4ThreeVector& p) const 245 { 245 { 246 G4double dist = std::max(std::max( 246 G4double dist = std::max(std::max( 247 std::abs(p.x())-fDx, 247 std::abs(p.x())-fDx, 248 std::abs(p.y())-fDy), 248 std::abs(p.y())-fDy), 249 std::abs(p.z())-fDz); 249 std::abs(p.z())-fDz); 250 return (dist > delta) ? kOutside : 250 return (dist > delta) ? kOutside : 251 ((dist > -delta) ? kSurface : kInside); 251 ((dist > -delta) ? kSurface : kInside); 252 } 252 } 253 253 254 ////////////////////////////////////////////// 254 ////////////////////////////////////////////////////////////////////////// 255 // 255 // 256 // Detect the side(s) and return corresponding 256 // Detect the side(s) and return corresponding normal 257 257 258 G4ThreeVector G4Box::SurfaceNormal( const G4Th 258 G4ThreeVector G4Box::SurfaceNormal( const G4ThreeVector& p) const 259 { 259 { 260 G4ThreeVector norm(0,0,0); 260 G4ThreeVector norm(0,0,0); 261 G4double px = p.x(); 261 G4double px = p.x(); 262 if (std::abs(std::abs(px) - fDx) <= delta) n 262 if (std::abs(std::abs(px) - fDx) <= delta) norm.setX(px < 0 ? -1. : 1.); 263 G4double py = p.y(); 263 G4double py = p.y(); 264 if (std::abs(std::abs(py) - fDy) <= delta) n 264 if (std::abs(std::abs(py) - fDy) <= delta) norm.setY(py < 0 ? -1. : 1.); 265 G4double pz = p.z(); 265 G4double pz = p.z(); 266 if (std::abs(std::abs(pz) - fDz) <= delta) n 266 if (std::abs(std::abs(pz) - fDz) <= delta) norm.setZ(pz < 0 ? -1. : 1.); 267 267 268 G4double nside = norm.mag2(); // number of s 268 G4double nside = norm.mag2(); // number of sides = magnitude squared 269 if (nside == 1) 269 if (nside == 1) 270 return norm; 270 return norm; 271 else if (nside > 1) 271 else if (nside > 1) 272 return norm.unit(); // edge or corner 272 return norm.unit(); // edge or corner 273 else 273 else 274 { 274 { 275 // Point is not on the surface 275 // Point is not on the surface 276 // 276 // 277 #ifdef G4CSGDEBUG 277 #ifdef G4CSGDEBUG 278 std::ostringstream message; 278 std::ostringstream message; 279 G4int oldprc = message.precision(16); 279 G4int oldprc = message.precision(16); 280 message << "Point p is not on surface (!?) 280 message << "Point p is not on surface (!?) of solid: " 281 << GetName() << G4endl; 281 << GetName() << G4endl; 282 message << "Position:\n"; 282 message << "Position:\n"; 283 message << " p.x() = " << p.x()/mm << " 283 message << " p.x() = " << p.x()/mm << " mm\n"; 284 message << " p.y() = " << p.y()/mm << " 284 message << " p.y() = " << p.y()/mm << " mm\n"; 285 message << " p.z() = " << p.z()/mm << " 285 message << " p.z() = " << p.z()/mm << " mm"; 286 G4cout.precision(oldprc); 286 G4cout.precision(oldprc); 287 G4Exception("G4Box::SurfaceNormal(p)", "Ge 287 G4Exception("G4Box::SurfaceNormal(p)", "GeomSolids1002", 288 JustWarning, message ); 288 JustWarning, message ); 289 DumpInfo(); 289 DumpInfo(); 290 #endif 290 #endif 291 return ApproxSurfaceNormal(p); 291 return ApproxSurfaceNormal(p); 292 } 292 } 293 } 293 } 294 294 295 ////////////////////////////////////////////// 295 ////////////////////////////////////////////////////////////////////////// 296 // 296 // 297 // Algorithm for SurfaceNormal() following the 297 // Algorithm for SurfaceNormal() following the original specification 298 // for points not on the surface 298 // for points not on the surface 299 299 300 G4ThreeVector G4Box::ApproxSurfaceNormal(const 300 G4ThreeVector G4Box::ApproxSurfaceNormal(const G4ThreeVector& p) const 301 { 301 { 302 G4double distx = std::abs(p.x()) - fDx; 302 G4double distx = std::abs(p.x()) - fDx; 303 G4double disty = std::abs(p.y()) - fDy; 303 G4double disty = std::abs(p.y()) - fDy; 304 G4double distz = std::abs(p.z()) - fDz; 304 G4double distz = std::abs(p.z()) - fDz; 305 305 306 if (distx >= disty && distx >= distz) 306 if (distx >= disty && distx >= distz) 307 return {std::copysign(1.,p.x()), 0., 0.}; 307 return {std::copysign(1.,p.x()), 0., 0.}; 308 if (disty >= distx && disty >= distz) 308 if (disty >= distx && disty >= distz) 309 return {0., std::copysign(1.,p.y()), 0.}; 309 return {0., std::copysign(1.,p.y()), 0.}; 310 else 310 else 311 return {0., 0., std::copysign(1.,p.z())}; 311 return {0., 0., std::copysign(1.,p.z())}; 312 } 312 } 313 313 314 ////////////////////////////////////////////// 314 ////////////////////////////////////////////////////////////////////////// 315 // 315 // 316 // Calculate distance to box from an outside p 316 // Calculate distance to box from an outside point 317 // - return kInfinity if no intersection 317 // - return kInfinity if no intersection 318 // 318 // 319 319 320 G4double G4Box::DistanceToIn(const G4ThreeVect 320 G4double G4Box::DistanceToIn(const G4ThreeVector& p, 321 const G4ThreeVect 321 const G4ThreeVector& v) const 322 { 322 { 323 // Check if point is on the surface and trav 323 // Check if point is on the surface and traveling away 324 // 324 // 325 if ((std::abs(p.x()) - fDx) >= -delta && p.x 325 if ((std::abs(p.x()) - fDx) >= -delta && p.x()*v.x() >= 0) return kInfinity; 326 if ((std::abs(p.y()) - fDy) >= -delta && p.y 326 if ((std::abs(p.y()) - fDy) >= -delta && p.y()*v.y() >= 0) return kInfinity; 327 if ((std::abs(p.z()) - fDz) >= -delta && p.z 327 if ((std::abs(p.z()) - fDz) >= -delta && p.z()*v.z() >= 0) return kInfinity; 328 328 329 // Find intersection 329 // Find intersection 330 // 330 // 331 G4double invx = (v.x() == 0) ? DBL_MAX : -1. 331 G4double invx = (v.x() == 0) ? DBL_MAX : -1./v.x(); 332 G4double dx = std::copysign(fDx,invx); 332 G4double dx = std::copysign(fDx,invx); 333 G4double txmin = (p.x() - dx)*invx; 333 G4double txmin = (p.x() - dx)*invx; 334 G4double txmax = (p.x() + dx)*invx; 334 G4double txmax = (p.x() + dx)*invx; 335 335 336 G4double invy = (v.y() == 0) ? DBL_MAX : -1. 336 G4double invy = (v.y() == 0) ? DBL_MAX : -1./v.y(); 337 G4double dy = std::copysign(fDy,invy); 337 G4double dy = std::copysign(fDy,invy); 338 G4double tymin = std::max(txmin,(p.y() - dy) 338 G4double tymin = std::max(txmin,(p.y() - dy)*invy); 339 G4double tymax = std::min(txmax,(p.y() + dy) 339 G4double tymax = std::min(txmax,(p.y() + dy)*invy); 340 340 341 G4double invz = (v.z() == 0) ? DBL_MAX : -1. 341 G4double invz = (v.z() == 0) ? DBL_MAX : -1./v.z(); 342 G4double dz = std::copysign(fDz,invz); 342 G4double dz = std::copysign(fDz,invz); 343 G4double tmin = std::max(tymin,(p.z() - dz)* 343 G4double tmin = std::max(tymin,(p.z() - dz)*invz); 344 G4double tmax = std::min(tymax,(p.z() + dz)* 344 G4double tmax = std::min(tymax,(p.z() + dz)*invz); 345 345 346 if (tmax <= tmin + delta) return kInfinity; 346 if (tmax <= tmin + delta) return kInfinity; // touch or no hit 347 return (tmin < delta) ? 0. : tmin; 347 return (tmin < delta) ? 0. : tmin; 348 } 348 } 349 349 350 ////////////////////////////////////////////// 350 ////////////////////////////////////////////////////////////////////////// 351 // 351 // 352 // Appoximate distance to box. 352 // Appoximate distance to box. 353 // Returns largest perpendicular distance to t 353 // Returns largest perpendicular distance to the closest x/y/z sides of 354 // the box, which is the most fast estimation 354 // the box, which is the most fast estimation of the shortest distance to box 355 // - If inside return 0 355 // - If inside return 0 356 356 357 G4double G4Box::DistanceToIn(const G4ThreeVect 357 G4double G4Box::DistanceToIn(const G4ThreeVector& p) const 358 { 358 { 359 G4double dist = std::max(std::max( 359 G4double dist = std::max(std::max( 360 std::abs(p.x())-fDx, 360 std::abs(p.x())-fDx, 361 std::abs(p.y())-fDy), 361 std::abs(p.y())-fDy), 362 std::abs(p.z())-fDz); 362 std::abs(p.z())-fDz); 363 return (dist > 0) ? dist : 0.; 363 return (dist > 0) ? dist : 0.; 364 } 364 } 365 365 366 ////////////////////////////////////////////// 366 ////////////////////////////////////////////////////////////////////////// 367 // 367 // 368 // Calculate distance to surface of the box fr 368 // Calculate distance to surface of the box from inside and 369 // find normal at exit point, if required 369 // find normal at exit point, if required 370 // - when leaving the surface, return 0 370 // - when leaving the surface, return 0 371 371 372 G4double G4Box::DistanceToOut( const G4ThreeVe 372 G4double G4Box::DistanceToOut( const G4ThreeVector& p, 373 const G4ThreeVe 373 const G4ThreeVector& v, 374 const G4bool ca 374 const G4bool calcNorm, 375 G4bool* validNo 375 G4bool* validNorm, G4ThreeVector* n) const 376 { 376 { 377 // Check if point is on the surface and trav 377 // Check if point is on the surface and traveling away 378 // 378 // 379 if ((std::abs(p.x()) - fDx) >= -delta && p.x 379 if ((std::abs(p.x()) - fDx) >= -delta && p.x()*v.x() > 0) 380 { 380 { 381 if (calcNorm) 381 if (calcNorm) 382 { 382 { 383 *validNorm = true; 383 *validNorm = true; 384 n->set((p.x() < 0) ? -1. : 1., 0., 0.); 384 n->set((p.x() < 0) ? -1. : 1., 0., 0.); 385 } 385 } 386 return 0.; 386 return 0.; 387 } 387 } 388 if ((std::abs(p.y()) - fDy) >= -delta && p.y 388 if ((std::abs(p.y()) - fDy) >= -delta && p.y()*v.y() > 0) 389 { 389 { 390 if (calcNorm) 390 if (calcNorm) 391 { 391 { 392 *validNorm = true; 392 *validNorm = true; 393 n->set(0., (p.y() < 0) ? -1. : 1., 0.); 393 n->set(0., (p.y() < 0) ? -1. : 1., 0.); 394 } 394 } 395 return 0.; 395 return 0.; 396 } 396 } 397 if ((std::abs(p.z()) - fDz) >= -delta && p.z 397 if ((std::abs(p.z()) - fDz) >= -delta && p.z()*v.z() > 0) 398 { 398 { 399 if (calcNorm) 399 if (calcNorm) 400 { 400 { 401 *validNorm = true; 401 *validNorm = true; 402 n->set(0., 0., (p.z() < 0) ? -1. : 1.); 402 n->set(0., 0., (p.z() < 0) ? -1. : 1.); 403 } 403 } 404 return 0.; 404 return 0.; 405 } 405 } 406 406 407 // Find intersection 407 // Find intersection 408 // 408 // 409 G4double vx = v.x(); 409 G4double vx = v.x(); 410 G4double tx = (vx == 0) ? DBL_MAX : (std::co 410 G4double tx = (vx == 0) ? DBL_MAX : (std::copysign(fDx,vx) - p.x())/vx; 411 411 412 G4double vy = v.y(); 412 G4double vy = v.y(); 413 G4double ty = (vy == 0) ? tx : (std::copysig 413 G4double ty = (vy == 0) ? tx : (std::copysign(fDy,vy) - p.y())/vy; 414 G4double txy = std::min(tx,ty); 414 G4double txy = std::min(tx,ty); 415 415 416 G4double vz = v.z(); 416 G4double vz = v.z(); 417 G4double tz = (vz == 0) ? txy : (std::copysi 417 G4double tz = (vz == 0) ? txy : (std::copysign(fDz,vz) - p.z())/vz; 418 G4double tmax = std::min(txy,tz); 418 G4double tmax = std::min(txy,tz); 419 419 420 // Set normal, if required, and return dista 420 // Set normal, if required, and return distance 421 // 421 // 422 if (calcNorm) 422 if (calcNorm) 423 { 423 { 424 *validNorm = true; 424 *validNorm = true; 425 if (tmax == tx) n->set((v.x() < 0) ? 425 if (tmax == tx) n->set((v.x() < 0) ? -1. : 1., 0., 0.); 426 else if (tmax == ty) n->set(0., (v.y() < 0 426 else if (tmax == ty) n->set(0., (v.y() < 0) ? -1. : 1., 0.); 427 else n->set(0., 0., (v.z() 427 else n->set(0., 0., (v.z() < 0) ? -1. : 1.); 428 } 428 } 429 return tmax; 429 return tmax; 430 } 430 } 431 431 432 ////////////////////////////////////////////// 432 //////////////////////////////////////////////////////////////////////////// 433 // 433 // 434 // Calculate exact shortest distance to any bo 434 // Calculate exact shortest distance to any boundary from inside 435 // - if outside return 0 435 // - if outside return 0 436 436 437 G4double G4Box::DistanceToOut(const G4ThreeVec 437 G4double G4Box::DistanceToOut(const G4ThreeVector& p) const 438 { 438 { 439 #ifdef G4CSGDEBUG 439 #ifdef G4CSGDEBUG 440 if( Inside(p) == kOutside ) 440 if( Inside(p) == kOutside ) 441 { 441 { 442 std::ostringstream message; 442 std::ostringstream message; 443 G4int oldprc = message.precision(16); 443 G4int oldprc = message.precision(16); 444 message << "Point p is outside (!?) of sol 444 message << "Point p is outside (!?) of solid: " << GetName() << G4endl; 445 message << "Position:\n"; 445 message << "Position:\n"; 446 message << " p.x() = " << p.x()/mm << " 446 message << " p.x() = " << p.x()/mm << " mm\n"; 447 message << " p.y() = " << p.y()/mm << " 447 message << " p.y() = " << p.y()/mm << " mm\n"; 448 message << " p.z() = " << p.z()/mm << " 448 message << " p.z() = " << p.z()/mm << " mm"; 449 G4cout.precision(oldprc); 449 G4cout.precision(oldprc); 450 G4Exception("G4Box::DistanceToOut(p)", "Ge 450 G4Exception("G4Box::DistanceToOut(p)", "GeomSolids1002", 451 JustWarning, message ); 451 JustWarning, message ); 452 DumpInfo(); 452 DumpInfo(); 453 } 453 } 454 #endif 454 #endif 455 G4double dist = std::min(std::min( 455 G4double dist = std::min(std::min( 456 fDx-std::abs(p.x()), 456 fDx-std::abs(p.x()), 457 fDy-std::abs(p.y())), 457 fDy-std::abs(p.y())), 458 fDz-std::abs(p.z())); 458 fDz-std::abs(p.z())); 459 return (dist > 0) ? dist : 0.; 459 return (dist > 0) ? dist : 0.; 460 } 460 } 461 461 462 ////////////////////////////////////////////// 462 ////////////////////////////////////////////////////////////////////////// 463 // 463 // 464 // GetEntityType 464 // GetEntityType 465 465 466 G4GeometryType G4Box::GetEntityType() const 466 G4GeometryType G4Box::GetEntityType() const 467 { 467 { 468 return {"G4Box"}; 468 return {"G4Box"}; 469 } 469 } 470 470 471 ////////////////////////////////////////////// 471 ////////////////////////////////////////////////////////////////////////// 472 // 472 // 473 // IsFaceted << 474 << 475 G4bool G4Box::IsFaceted() const << 476 { << 477 return true; << 478 } << 479 << 480 ////////////////////////////////////////////// << 481 // << 482 // Stream object contents to an output stream 473 // Stream object contents to an output stream 483 474 484 std::ostream& G4Box::StreamInfo(std::ostream& 475 std::ostream& G4Box::StreamInfo(std::ostream& os) const 485 { 476 { 486 G4long oldprc = os.precision(16); 477 G4long oldprc = os.precision(16); 487 os << "------------------------------------- 478 os << "-----------------------------------------------------------\n" 488 << " *** Dump for solid - " << GetName 479 << " *** Dump for solid - " << GetName() << " ***\n" 489 << " ================================= 480 << " ===================================================\n" 490 << "Solid type: G4Box\n" 481 << "Solid type: G4Box\n" 491 << "Parameters: \n" 482 << "Parameters: \n" 492 << " half length X: " << fDx/mm << " mm 483 << " half length X: " << fDx/mm << " mm \n" 493 << " half length Y: " << fDy/mm << " mm 484 << " half length Y: " << fDy/mm << " mm \n" 494 << " half length Z: " << fDz/mm << " mm 485 << " half length Z: " << fDz/mm << " mm \n" 495 << "------------------------------------- 486 << "-----------------------------------------------------------\n"; 496 os.precision(oldprc); 487 os.precision(oldprc); 497 return os; 488 return os; 498 } 489 } 499 490 500 ////////////////////////////////////////////// 491 ////////////////////////////////////////////////////////////////////////// 501 // 492 // 502 // Return a point randomly and uniformly selec 493 // Return a point randomly and uniformly selected on the surface 503 494 504 G4ThreeVector G4Box::GetPointOnSurface() const 495 G4ThreeVector G4Box::GetPointOnSurface() const 505 { 496 { 506 G4double sxy = fDx*fDy, sxz = fDx*fDz, syz = 497 G4double sxy = fDx*fDy, sxz = fDx*fDz, syz = fDy*fDz; 507 G4double select = (sxy + sxz + syz)*G4QuickR 498 G4double select = (sxy + sxz + syz)*G4QuickRand(); 508 G4double u = 2.*G4QuickRand() - 1.; 499 G4double u = 2.*G4QuickRand() - 1.; 509 G4double v = 2.*G4QuickRand() - 1.; 500 G4double v = 2.*G4QuickRand() - 1.; 510 501 511 if (select < sxy) 502 if (select < sxy) 512 return { u*fDx, v*fDy, ((select < 0.5*sxy) 503 return { u*fDx, v*fDy, ((select < 0.5*sxy) ? -fDz : fDz) }; 513 else if (select < sxy + sxz) 504 else if (select < sxy + sxz) 514 return { u*fDx, ((select < sxy + 0.5*sxz) 505 return { u*fDx, ((select < sxy + 0.5*sxz) ? -fDy : fDy), v*fDz }; 515 else 506 else 516 return { ((select < sxy + sxz + 0.5*syz) ? 507 return { ((select < sxy + sxz + 0.5*syz) ? -fDx : fDx), u*fDy, v*fDz }; 517 } 508 } 518 509 519 ////////////////////////////////////////////// 510 ////////////////////////////////////////////////////////////////////////// 520 // 511 // 521 // Make a clone of the object 512 // Make a clone of the object 522 // 513 // 523 G4VSolid* G4Box::Clone() const 514 G4VSolid* G4Box::Clone() const 524 { 515 { 525 return new G4Box(*this); 516 return new G4Box(*this); 526 } 517 } 527 518 528 ////////////////////////////////////////////// 519 ////////////////////////////////////////////////////////////////////////// 529 // 520 // 530 // Methods for visualisation 521 // Methods for visualisation 531 522 532 void G4Box::DescribeYourselfTo (G4VGraphicsSce 523 void G4Box::DescribeYourselfTo (G4VGraphicsScene& scene) const 533 { 524 { 534 scene.AddSolid (*this); 525 scene.AddSolid (*this); 535 } 526 } 536 527 537 G4VisExtent G4Box::GetExtent() const 528 G4VisExtent G4Box::GetExtent() const 538 { 529 { 539 return { -fDx, fDx, -fDy, fDy, -fDz, fDz }; 530 return { -fDx, fDx, -fDy, fDy, -fDz, fDz }; 540 } 531 } 541 532 542 G4Polyhedron* G4Box::CreatePolyhedron () const 533 G4Polyhedron* G4Box::CreatePolyhedron () const 543 { 534 { 544 return new G4PolyhedronBox (fDx, fDy, fDz); 535 return new G4PolyhedronBox (fDx, fDy, fDz); 545 } 536 } 546 #endif 537 #endif 547 538