Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer << 3 // * DISCLAIMER * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th << 5 // * The following disclaimer summarizes all the specific disclaimers * 6 // * the Geant4 Collaboration. It is provided << 6 // * of contributors to this software. The specific disclaimers,which * 7 // * conditions of the Geant4 Software License << 7 // * govern, are listed with their locations in: * 8 // * LICENSE and available at http://cern.ch/ << 8 // * http://cern.ch/geant4/license * 9 // * include a list of copyright holders. << 10 // * 9 // * * 11 // * Neither the authors of this software syst 10 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 11 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 12 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 13 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file << 14 // * use. * 16 // * for the full disclaimer and the limitatio << 17 // * 15 // * * 18 // * This code implementation is the result << 16 // * This code implementation is the intellectual property of the * 19 // * technical work of the GEANT4 collaboratio << 17 // * GEANT4 collaboration. * 20 // * By using, copying, modifying or distri << 18 // * By copying, distributing or modifying the Program (or any work * 21 // * any work based on the software) you ag << 19 // * based on the Program) you indicate your acceptance of this * 22 // * use in resulting scientific publicati << 20 // * statement, and all its terms. * 23 // * acceptance of all terms of the Geant4 Sof << 24 // ******************************************* 21 // ******************************************************************** 25 // 22 // >> 23 // >> 24 // $Id: G4Box.cc,v 1.39 2005/06/08 16:14:25 gcosmo Exp $ >> 25 // GEANT4 tag $Name: geant4-07-01 $ >> 26 // >> 27 // >> 28 // 26 // Implementation for G4Box class 29 // Implementation for G4Box class 27 // 30 // 28 // 30.06.95 - P.Kent: First version << 31 // 24.06.98 - V. Grichine: insideEdge in DistanceToIn(p,v) 29 // 20.09.98 - V.Grichine: new algorithm of Di 32 // 20.09.98 - V.Grichine: new algorithm of DistanceToIn(p,v) 30 // 18.04.17 - E.Tcherniaev: complete revision << 33 // 07.05.00 - V.Grichine: d= DistanceToIn(p,v), if d<e/2, d=0 >> 34 // 09.06.00 - V.Grichine: safety in DistanceToIn(p) against Inside(p)=kOutside >> 35 // and information before exception in DistanceToOut(p,v,...) >> 36 // 15.11.00 - D.Williams, V.Grichine: bug fixed in CalculateExtent - change >> 37 // algorithm for rotated vertices 31 // ------------------------------------------- 38 // -------------------------------------------------------------------- 32 39 33 #include "G4Box.hh" 40 #include "G4Box.hh" 34 41 35 #if !defined(G4GEOM_USE_UBOX) << 36 << 37 #include "G4SystemOfUnits.hh" << 38 #include "G4VoxelLimits.hh" 42 #include "G4VoxelLimits.hh" 39 #include "G4AffineTransform.hh" 43 #include "G4AffineTransform.hh" 40 #include "G4BoundingEnvelope.hh" << 44 #include "Randomize.hh" 41 #include "G4QuickRand.hh" << 42 45 43 #include "G4VPVParameterisation.hh" 46 #include "G4VPVParameterisation.hh" 44 47 45 #include "G4VGraphicsScene.hh" 48 #include "G4VGraphicsScene.hh" >> 49 #include "G4Polyhedron.hh" >> 50 #include "G4NURBS.hh" >> 51 #include "G4NURBSbox.hh" 46 #include "G4VisExtent.hh" 52 #include "G4VisExtent.hh" 47 53 48 ////////////////////////////////////////////// 54 //////////////////////////////////////////////////////////////////////// 49 // 55 // 50 // Constructor - check & set half widths 56 // Constructor - check & set half widths 51 57 52 G4Box::G4Box(const G4String& pName, 58 G4Box::G4Box(const G4String& pName, 53 G4double pX, 59 G4double pX, 54 G4double pY, 60 G4double pY, 55 G4double pZ) 61 G4double pZ) 56 : G4CSGSolid(pName), fDx(pX), fDy(pY), fDz(p << 62 : G4CSGSolid(pName) 57 { 63 { 58 delta = 0.5*kCarTolerance; << 64 if ( (pX > 2*kCarTolerance) 59 if (pX < 2*kCarTolerance || << 65 && (pY > 2*kCarTolerance) 60 pY < 2*kCarTolerance || << 66 && (pZ > 2*kCarTolerance) ) 61 pZ < 2*kCarTolerance) // limit to thick << 67 { 62 { << 68 fDx = pX ; 63 std::ostringstream message; << 69 fDy = pY ; 64 message << "Dimensions too small for Solid << 70 fDz = pZ ; 65 << " hX, hY, hZ = " << pX << " << 71 } 66 G4Exception("G4Box::G4Box()", "GeomSolids0 << 72 else >> 73 { >> 74 G4cerr << "ERROR - G4Box()::G4Box(): " << GetName() << G4endl >> 75 << " Dimensions too small ! - " >> 76 << pX << ", " << pY << ", " << pZ << G4endl; >> 77 G4Exception("G4Box::G4Box()", "InvalidSetup", >> 78 FatalException, "Invalid dimensions. Too small."); 67 } 79 } 68 } << 69 << 70 ////////////////////////////////////////////// << 71 // << 72 // Fake default constructor - sets only member << 73 // for usage restri << 74 << 75 G4Box::G4Box( __void__& a ) << 76 : G4CSGSolid(a) << 77 { << 78 } 80 } 79 81 80 ////////////////////////////////////////////// 82 ////////////////////////////////////////////////////////////////////////// 81 // 83 // 82 // Destructor 84 // Destructor 83 85 84 G4Box::~G4Box() = default; << 86 G4Box::~G4Box() 85 << 86 ////////////////////////////////////////////// << 87 // << 88 // Copy constructor << 89 << 90 G4Box::G4Box(const G4Box&) = default; << 91 << 92 ////////////////////////////////////////////// << 93 // << 94 // Assignment operator << 95 << 96 G4Box& G4Box::operator = (const G4Box& rhs) << 97 { 87 { 98 // Check assignment to self << 99 // << 100 if (this == &rhs) { return *this; } << 101 << 102 // Copy base class data << 103 // << 104 G4CSGSolid::operator=(rhs); << 105 << 106 // Copy data << 107 // << 108 fDx = rhs.fDx; << 109 fDy = rhs.fDy; << 110 fDz = rhs.fDz; << 111 delta = rhs.delta; << 112 << 113 return *this; << 114 } 88 } 115 89 116 ////////////////////////////////////////////// << 90 ////////////////////////////////////////////////////////////////////////////// 117 // << 118 // Set X dimension << 119 91 120 void G4Box::SetXHalfLength(G4double dx) 92 void G4Box::SetXHalfLength(G4double dx) 121 { 93 { 122 if(dx > 2*kCarTolerance) // limit to thickn << 94 if(dx > 2*kCarTolerance) 123 { << 124 fDx = dx; 95 fDx = dx; 125 } << 126 else 96 else 127 { 97 { 128 std::ostringstream message; << 98 G4cerr << "ERROR - G4Box()::SetXHalfLength(): " << GetName() << G4endl 129 message << "Dimension X too small for soli << 99 << " Dimension X too small ! - " 130 << G4endl << 100 << dx << G4endl; 131 << " hX = " << dx; << 101 G4Exception("G4Box::SetXHalfLength()", "InvalidSetup", 132 G4Exception("G4Box::SetXHalfLength()", "Ge << 102 FatalException, "Invalid dimensions. Too small."); 133 FatalException, message); << 103 } 134 } << 104 fCubicVolume= 0.; 135 fCubicVolume = 0.; << 105 fpPolyhedron = 0; 136 fSurfaceArea = 0.; << 106 } 137 fRebuildPolyhedron = true; << 138 } << 139 107 140 ////////////////////////////////////////////// << 108 void G4Box::SetYHalfLength(G4double dy) 141 // << 142 // Set Y dimension << 143 << 144 void G4Box::SetYHalfLength(G4double dy) << 145 { 109 { 146 if(dy > 2*kCarTolerance) // limit to thickn << 110 if(dy > 2*kCarTolerance) 147 { << 148 fDy = dy; 111 fDy = dy; 149 } << 150 else 112 else 151 { 113 { 152 std::ostringstream message; << 114 G4cerr << "ERROR - G4Box()::SetYHalfLength(): " << GetName() << G4endl 153 message << "Dimension Y too small for soli << 115 << " Dimension Y too small ! - " 154 << " hY = " << dy; << 116 << dy << G4endl; 155 G4Exception("G4Box::SetYHalfLength()", "Ge << 117 G4Exception("G4Box::SetYHalfLength()", "InvalidSetup", 156 FatalException, message); << 118 FatalException, "Invalid dimensions. Too small."); 157 } << 119 } 158 fCubicVolume = 0.; << 120 fCubicVolume= 0.; 159 fSurfaceArea = 0.; << 121 fpPolyhedron = 0; 160 fRebuildPolyhedron = true; << 122 } 161 } << 162 << 163 ////////////////////////////////////////////// << 164 // << 165 // Set Z dimension << 166 123 167 void G4Box::SetZHalfLength(G4double dz) << 124 void G4Box::SetZHalfLength(G4double dz) 168 { 125 { 169 if(dz > 2*kCarTolerance) // limit to thickn << 126 if(dz > 2*kCarTolerance) 170 { << 171 fDz = dz; 127 fDz = dz; 172 } << 173 else 128 else 174 { 129 { 175 std::ostringstream message; << 130 G4cerr << "ERROR - G4Box()::SetZHalfLength(): " << GetName() << G4endl 176 message << "Dimension Z too small for soli << 131 << " Dimension Z too small ! - " 177 << " hZ = " << dz; << 132 << dz << G4endl; 178 G4Exception("G4Box::SetZHalfLength()", "Ge << 133 G4Exception("G4Box::SetZHalfLength()", "InvalidSetup", 179 FatalException, message); << 134 FatalException, "Invalid dimensions. Too small."); 180 } << 135 } 181 fCubicVolume = 0.; << 136 fCubicVolume= 0.; 182 fSurfaceArea = 0.; << 137 fpPolyhedron = 0; 183 fRebuildPolyhedron = true; << 138 } 184 } << 139 185 140 186 ////////////////////////////////////////////// << 141 >> 142 //////////////////////////////////////////////////////////////////////// 187 // 143 // 188 // Dispatch to parameterisation for replicatio 144 // Dispatch to parameterisation for replication mechanism dimension 189 // computation & modification. 145 // computation & modification. 190 146 191 void G4Box::ComputeDimensions(G4VPVParameteris 147 void G4Box::ComputeDimensions(G4VPVParameterisation* p, 192 const G4int n, 148 const G4int n, 193 const G4VPhysica 149 const G4VPhysicalVolume* pRep) 194 { 150 { 195 p->ComputeDimensions(*this,n,pRep); 151 p->ComputeDimensions(*this,n,pRep); 196 } 152 } 197 153 198 ////////////////////////////////////////////// 154 ////////////////////////////////////////////////////////////////////////// 199 // 155 // 200 // Get bounding box << 201 << 202 void G4Box::BoundingLimits(G4ThreeVector& pMin << 203 { << 204 pMin.set(-fDx,-fDy,-fDz); << 205 pMax.set( fDx, fDy, fDz); << 206 << 207 // Check correctness of the bounding box << 208 // << 209 if (pMin.x() >= pMax.x() || pMin.y() >= pMax << 210 { << 211 std::ostringstream message; << 212 message << "Bad bounding box (min >= max) << 213 << GetName() << " !" << 214 << "\npMin = " << pMin << 215 << "\npMax = " << pMax; << 216 G4Exception("G4Box::BoundingLimits()", "Ge << 217 DumpInfo(); << 218 } << 219 } << 220 << 221 ////////////////////////////////////////////// << 222 // << 223 // Calculate extent under transform and specif 156 // Calculate extent under transform and specified limit 224 157 225 G4bool G4Box::CalculateExtent(const EAxis pAxi 158 G4bool G4Box::CalculateExtent(const EAxis pAxis, 226 const G4VoxelLim 159 const G4VoxelLimits& pVoxelLimit, 227 const G4AffineTr 160 const G4AffineTransform& pTransform, 228 G4double& 161 G4double& pMin, G4double& pMax) const 229 { 162 { 230 G4ThreeVector bmin, bmax; << 163 if (!pTransform.IsRotated()) >> 164 { >> 165 // Special case handling for unrotated boxes >> 166 // Compute x/y/z mins and maxs respecting limits, with early returns >> 167 // if outside limits. Then switch() on pAxis 231 168 232 // Get bounding box << 169 G4double xoffset,xMin,xMax; 233 BoundingLimits(bmin,bmax); << 170 G4double yoffset,yMin,yMax; >> 171 G4double zoffset,zMin,zMax; 234 172 235 // Find extent << 173 xoffset = pTransform.NetTranslation().x() ; 236 G4BoundingEnvelope bbox(bmin,bmax); << 174 xMin = xoffset - fDx ; 237 return bbox.CalculateExtent(pAxis,pVoxelLimi << 175 xMax = xoffset + fDx ; 238 } << 239 176 240 ////////////////////////////////////////////// << 177 if (pVoxelLimit.IsXLimited()) >> 178 { >> 179 if ( xMin > pVoxelLimit.GetMaxXExtent()+kCarTolerance || >> 180 xMax < pVoxelLimit.GetMinXExtent()-kCarTolerance ) return false ; >> 181 else >> 182 { >> 183 if (xMin < pVoxelLimit.GetMinXExtent()) >> 184 { >> 185 xMin = pVoxelLimit.GetMinXExtent() ; >> 186 } >> 187 if (xMax > pVoxelLimit.GetMaxXExtent()) >> 188 { >> 189 xMax = pVoxelLimit.GetMaxXExtent() ; >> 190 } >> 191 } >> 192 } >> 193 yoffset = pTransform.NetTranslation().y() ; >> 194 yMin = yoffset - fDy ; >> 195 yMax = yoffset + fDy ; >> 196 >> 197 if (pVoxelLimit.IsYLimited()) >> 198 { >> 199 if ( yMin > pVoxelLimit.GetMaxYExtent()+kCarTolerance || >> 200 yMax < pVoxelLimit.GetMinYExtent()-kCarTolerance ) return false ; >> 201 else >> 202 { >> 203 if (yMin < pVoxelLimit.GetMinYExtent()) >> 204 { >> 205 yMin = pVoxelLimit.GetMinYExtent() ; >> 206 } >> 207 if (yMax > pVoxelLimit.GetMaxYExtent()) >> 208 { >> 209 yMax = pVoxelLimit.GetMaxYExtent() ; >> 210 } >> 211 } >> 212 } >> 213 zoffset = pTransform.NetTranslation().z() ; >> 214 zMin = zoffset - fDz ; >> 215 zMax = zoffset + fDz ; >> 216 >> 217 if (pVoxelLimit.IsZLimited()) >> 218 { >> 219 if ( zMin > pVoxelLimit.GetMaxZExtent()+kCarTolerance || >> 220 zMax < pVoxelLimit.GetMinZExtent()-kCarTolerance ) return false ; >> 221 else >> 222 { >> 223 if (zMin < pVoxelLimit.GetMinZExtent()) >> 224 { >> 225 zMin = pVoxelLimit.GetMinZExtent() ; >> 226 } >> 227 if (zMax > pVoxelLimit.GetMaxZExtent()) >> 228 { >> 229 zMax = pVoxelLimit.GetMaxZExtent() ; >> 230 } >> 231 } >> 232 } >> 233 switch (pAxis) >> 234 { >> 235 case kXAxis: >> 236 pMin = xMin ; >> 237 pMax = xMax ; >> 238 break ; >> 239 case kYAxis: >> 240 pMin=yMin; >> 241 pMax=yMax; >> 242 break; >> 243 case kZAxis: >> 244 pMin=zMin; >> 245 pMax=zMax; >> 246 break; >> 247 default: >> 248 break; >> 249 } >> 250 pMin -= kCarTolerance ; >> 251 pMax += kCarTolerance ; >> 252 >> 253 return true; >> 254 } >> 255 else // General rotated case - create and clip mesh to boundaries >> 256 { >> 257 G4bool existsAfterClip = false ; >> 258 G4ThreeVectorList* vertices ; >> 259 >> 260 pMin = +kInfinity ; >> 261 pMax = -kInfinity ; >> 262 >> 263 // Calculate rotated vertex coordinates >> 264 >> 265 vertices = CreateRotatedVertices(pTransform) ; >> 266 ClipCrossSection(vertices,0,pVoxelLimit,pAxis,pMin,pMax) ; >> 267 ClipCrossSection(vertices,4,pVoxelLimit,pAxis,pMin,pMax) ; >> 268 ClipBetweenSections(vertices,0,pVoxelLimit,pAxis,pMin,pMax) ; >> 269 >> 270 if (pVoxelLimit.IsLimited(pAxis) == false) >> 271 { >> 272 if ( pMin != kInfinity || pMax != -kInfinity ) >> 273 { >> 274 existsAfterClip = true ; >> 275 >> 276 // Add 2*tolerance to avoid precision troubles >> 277 >> 278 pMin -= kCarTolerance; >> 279 pMax += kCarTolerance; >> 280 } >> 281 } >> 282 else >> 283 { >> 284 G4ThreeVector clipCentre( >> 285 ( pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5, >> 286 ( pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5, >> 287 ( pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5); >> 288 >> 289 if ( pMin != kInfinity || pMax != -kInfinity ) >> 290 { >> 291 existsAfterClip = true ; >> 292 >> 293 >> 294 // Check to see if endpoints are in the solid >> 295 >> 296 clipCentre(pAxis) = pVoxelLimit.GetMinExtent(pAxis); >> 297 >> 298 if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside) >> 299 { >> 300 pMin = pVoxelLimit.GetMinExtent(pAxis); >> 301 } >> 302 else >> 303 { >> 304 pMin -= kCarTolerance; >> 305 } >> 306 clipCentre(pAxis) = pVoxelLimit.GetMaxExtent(pAxis); >> 307 >> 308 if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside) >> 309 { >> 310 pMax = pVoxelLimit.GetMaxExtent(pAxis); >> 311 } >> 312 else >> 313 { >> 314 pMax += kCarTolerance; >> 315 } >> 316 } >> 317 >> 318 // Check for case where completely enveloping clipping volume >> 319 // If point inside then we are confident that the solid completely >> 320 // envelopes the clipping volume. Hence set min/max extents according >> 321 // to clipping volume extents along the specified axis. >> 322 >> 323 else if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) >> 324 != kOutside) >> 325 { >> 326 existsAfterClip = true ; >> 327 pMin = pVoxelLimit.GetMinExtent(pAxis) ; >> 328 pMax = pVoxelLimit.GetMaxExtent(pAxis) ; >> 329 } >> 330 } >> 331 delete vertices; >> 332 return existsAfterClip; >> 333 } >> 334 } >> 335 >> 336 ///////////////////////////////////////////////////////////////////////// 241 // 337 // 242 // Return whether point inside/outside/on surf 338 // Return whether point inside/outside/on surface, using tolerance 243 339 244 EInside G4Box::Inside(const G4ThreeVector& p) 340 EInside G4Box::Inside(const G4ThreeVector& p) const 245 { 341 { 246 G4double dist = std::max(std::max( << 342 EInside in = kOutside ; 247 std::abs(p.x())-fDx, << 343 248 std::abs(p.y())-fDy), << 344 if ( std::fabs(p.x()) <= fDx - kCarTolerance*0.5 ) 249 std::abs(p.z())-fDz); << 345 { 250 return (dist > delta) ? kOutside : << 346 if (std::fabs(p.y()) <= fDy - kCarTolerance*0.5 ) 251 ((dist > -delta) ? kSurface : kInside); << 347 { >> 348 if (std::fabs(p.z()) <= fDz - kCarTolerance*0.5 ) in = kInside ; >> 349 else if (std::fabs(p.z()) <= fDz + kCarTolerance*0.5 ) in = kSurface ; >> 350 } >> 351 else if (std::fabs(p.y()) <= fDy + kCarTolerance*0.5 ) >> 352 { >> 353 if (std::fabs(p.z()) <= fDz + kCarTolerance*0.5 ) in = kSurface ; >> 354 } >> 355 } >> 356 else if (std::fabs(p.x()) <= fDx + kCarTolerance*0.5 ) >> 357 { >> 358 if (std::fabs(p.y()) <= fDy + kCarTolerance*0.5 ) >> 359 { >> 360 if (std::fabs(p.z()) <= fDz + kCarTolerance*0.5) in = kSurface ; >> 361 } >> 362 } >> 363 return in ; 252 } 364 } 253 365 254 ////////////////////////////////////////////// << 366 /////////////////////////////////////////////////////////////////////// 255 // 367 // 256 // Detect the side(s) and return corresponding << 368 // Calculate side nearest to p, and return normal >> 369 // If two sides are equidistant, normal of first side (x/y/z) >> 370 // encountered returned 257 371 258 G4ThreeVector G4Box::SurfaceNormal( const G4Th 372 G4ThreeVector G4Box::SurfaceNormal( const G4ThreeVector& p) const 259 { 373 { 260 G4ThreeVector norm(0,0,0); << 374 G4double distx, disty, distz ; 261 G4double px = p.x(); << 375 G4ThreeVector norm ; 262 if (std::abs(std::abs(px) - fDx) <= delta) n << 376 263 G4double py = p.y(); << 377 // Calculate distances as if in 1st octant 264 if (std::abs(std::abs(py) - fDy) <= delta) n << 378 265 G4double pz = p.z(); << 379 distx = std::fabs(std::fabs(p.x()) - fDx) ; 266 if (std::abs(std::abs(pz) - fDz) <= delta) n << 380 disty = std::fabs(std::fabs(p.y()) - fDy) ; 267 << 381 distz = std::fabs(std::fabs(p.z()) - fDz) ; 268 G4double nside = norm.mag2(); // number of s << 382 269 if (nside == 1) << 383 // New code for particle on surface including edges and corners with specific 270 return norm; << 384 // normals 271 else if (nside > 1) << 385 272 return norm.unit(); // edge or corner << 386 const G4double delta = 0.5*kCarTolerance; 273 else << 387 const G4ThreeVector nX = G4ThreeVector( 1.0, 0,0 ); >> 388 const G4ThreeVector nmX = G4ThreeVector(-1.0, 0,0 ); >> 389 const G4ThreeVector nY = G4ThreeVector( 0, 1.0,0 ); >> 390 const G4ThreeVector nmY = G4ThreeVector( 0,-1.0,0 ); >> 391 const G4ThreeVector nZ = G4ThreeVector( 0, 0, 1.0); >> 392 const G4ThreeVector nmZ = G4ThreeVector( 0, 0,- 1.0); >> 393 >> 394 G4ThreeVector normX(0.,0.,0.), normY(0.,0.,0.), normZ(0.,0.,0.); >> 395 G4ThreeVector sumnorm(0., 0., 0.); >> 396 G4int noSurfaces=0; >> 397 >> 398 if (distx <= delta) // on X/mX surface and around >> 399 { >> 400 noSurfaces ++; >> 401 if ( p.x() >= 0.){ // on +X surface >> 402 normX= nX ; // G4ThreeVector( 1.0, 0., 0. ); >> 403 }else{ >> 404 normX= nmX; // G4ThreeVector(-1.0, 0., 0. ); >> 405 } >> 406 sumnorm= normX; >> 407 } >> 408 >> 409 if (disty <= delta) // on one of the +Y or -Y surfaces 274 { 410 { 275 // Point is not on the surface << 411 noSurfaces ++; 276 // << 412 if ( p.y() >= 0.){ // on +Y surface >> 413 normY= nY; >> 414 }else{ >> 415 normY = nmY; >> 416 } >> 417 sumnorm += normY; >> 418 } >> 419 >> 420 if (distz <= delta) // on one of the +Z or -Z surfaces >> 421 { >> 422 noSurfaces ++; >> 423 if ( p.z() >= 0.){ // on +Z surface >> 424 normZ= nZ; >> 425 }else{ >> 426 normZ = nmZ; >> 427 } >> 428 sumnorm += normZ; >> 429 } >> 430 >> 431 // sumnorm= normX + normY + normZ; >> 432 const G4double invSqrt2 = 1.0 / std::sqrt( 2.0); >> 433 const G4double invSqrt3 = 1.0 / std::sqrt( 3.0); >> 434 >> 435 norm= G4ThreeVector( 0., 0., 0.); >> 436 if( noSurfaces > 0 ) >> 437 { >> 438 if( noSurfaces == 1 ){ >> 439 norm= sumnorm; >> 440 }else{ >> 441 // norm = sumnorm . unit(); >> 442 if( noSurfaces == 2 ) { >> 443 // 2 surfaces -> on edge >> 444 norm = invSqrt2 * sumnorm; >> 445 } else { >> 446 // 3 surfaces (on corner) >> 447 norm = invSqrt3 * sumnorm; >> 448 } >> 449 } >> 450 }else{ 277 #ifdef G4CSGDEBUG 451 #ifdef G4CSGDEBUG 278 std::ostringstream message; << 452 G4Exception("G4Box::SurfaceNormal(p)", "Notification", JustWarning, 279 G4int oldprc = message.precision(16); << 453 "Point p is not on surface !?" ); 280 message << "Point p is not on surface (!?) << 454 #endif 281 << GetName() << G4endl; << 455 norm = ApproxSurfaceNormal(p); 282 message << "Position:\n"; << 283 message << " p.x() = " << p.x()/mm << " << 284 message << " p.y() = " << p.y()/mm << " << 285 message << " p.z() = " << p.z()/mm << " << 286 G4cout.precision(oldprc); << 287 G4Exception("G4Box::SurfaceNormal(p)", "Ge << 288 JustWarning, message ); << 289 DumpInfo(); << 290 #endif << 291 return ApproxSurfaceNormal(p); << 292 } 456 } >> 457 >> 458 return norm; 293 } 459 } 294 460 295 ////////////////////////////////////////////// 461 ////////////////////////////////////////////////////////////////////////// 296 // 462 // 297 // Algorithm for SurfaceNormal() following the 463 // Algorithm for SurfaceNormal() following the original specification 298 // for points not on the surface 464 // for points not on the surface 299 465 300 G4ThreeVector G4Box::ApproxSurfaceNormal(const << 466 G4ThreeVector G4Box::ApproxSurfaceNormal( const G4ThreeVector& p ) const 301 { 467 { 302 G4double distx = std::abs(p.x()) - fDx; << 468 G4double distx, disty, distz ; 303 G4double disty = std::abs(p.y()) - fDy; << 469 G4ThreeVector norm ; 304 G4double distz = std::abs(p.z()) - fDz; << 470 305 << 471 // Calculate distances as if in 1st octant 306 if (distx >= disty && distx >= distz) << 472 307 return {std::copysign(1.,p.x()), 0., 0.}; << 473 distx = std::fabs(std::fabs(p.x()) - fDx) ; 308 if (disty >= distx && disty >= distz) << 474 disty = std::fabs(std::fabs(p.y()) - fDy) ; 309 return {0., std::copysign(1.,p.y()), 0.}; << 475 distz = std::fabs(std::fabs(p.z()) - fDz) ; >> 476 >> 477 if ( distx <= disty ) >> 478 { >> 479 if ( distx <= distz ) // Closest to X >> 480 { >> 481 if ( p.x() < 0 ) norm = G4ThreeVector(-1.0,0,0) ; >> 482 else norm = G4ThreeVector( 1.0,0,0) ; >> 483 } >> 484 else // Closest to Z >> 485 { >> 486 if ( p.z() < 0 ) norm = G4ThreeVector(0,0,-1.0) ; >> 487 else norm = G4ThreeVector(0,0, 1.0) ; >> 488 } >> 489 } 310 else 490 else 311 return {0., 0., std::copysign(1.,p.z())}; << 491 { >> 492 if ( disty <= distz ) // Closest to Y >> 493 { >> 494 if ( p.y() < 0 ) norm = G4ThreeVector(0,-1.0,0) ; >> 495 else norm = G4ThreeVector(0, 1.0,0) ; >> 496 } >> 497 else // Closest to Z >> 498 { >> 499 if ( p.z() < 0 ) norm = G4ThreeVector(0,0,-1.0) ; >> 500 else norm = G4ThreeVector(0,0, 1.0) ; >> 501 } >> 502 } >> 503 return norm; 312 } 504 } 313 505 314 ////////////////////////////////////////////// << 506 /////////////////////////////////////////////////////////////////////////// 315 // 507 // 316 // Calculate distance to box from an outside p 508 // Calculate distance to box from an outside point 317 // - return kInfinity if no intersection << 509 // - return kInfinity if no intersection. >> 510 // >> 511 // ALGORITHM: >> 512 // >> 513 // Check that if point lies outside x/y/z extent of box, travel is towards >> 514 // the box (ie. there is a possibility of an intersection) 318 // 515 // >> 516 // Calculate pairs of minimum and maximum distances for x/y/z travel for >> 517 // intersection with the box's x/y/z extent. >> 518 // If there is a valid intersection, it is given by the maximum min distance >> 519 // (ie. distance to satisfy x/y/z intersections) *if* <= minimum max distance >> 520 // (ie. distance after which 1+ of x/y/z intersections not satisfied) >> 521 // >> 522 // NOTE: >> 523 // >> 524 // `Inside' safe - meaningful answers given if point is inside the exact >> 525 // shape. 319 526 320 G4double G4Box::DistanceToIn(const G4ThreeVect << 527 G4double G4Box::DistanceToIn(const G4ThreeVector& p,const G4ThreeVector& v) const 321 const G4ThreeVect << 322 { 528 { 323 // Check if point is on the surface and trav << 529 G4double safx, safy, safz ; 324 // << 530 G4double smin=0.0, sminy, sminz ; // , sminx ; 325 if ((std::abs(p.x()) - fDx) >= -delta && p.x << 531 G4double smax=kInfinity, smaxy, smaxz ; // , smaxx ; // they always > 0 326 if ((std::abs(p.y()) - fDy) >= -delta && p.y << 532 G4double stmp ; 327 if ((std::abs(p.z()) - fDz) >= -delta && p.z << 533 G4double sOut=kInfinity, sOuty=kInfinity, sOutz=kInfinity ; 328 << 534 329 // Find intersection << 535 safx = std::fabs(p.x()) - fDx ; // minimum distance to x surface of shape 330 // << 536 safy = std::fabs(p.y()) - fDy ; 331 G4double invx = (v.x() == 0) ? DBL_MAX : -1. << 537 safz = std::fabs(p.z()) - fDz ; 332 G4double dx = std::copysign(fDx,invx); << 333 G4double txmin = (p.x() - dx)*invx; << 334 G4double txmax = (p.x() + dx)*invx; << 335 << 336 G4double invy = (v.y() == 0) ? DBL_MAX : -1. << 337 G4double dy = std::copysign(fDy,invy); << 338 G4double tymin = std::max(txmin,(p.y() - dy) << 339 G4double tymax = std::min(txmax,(p.y() + dy) << 340 << 341 G4double invz = (v.z() == 0) ? DBL_MAX : -1. << 342 G4double dz = std::copysign(fDz,invz); << 343 G4double tmin = std::max(tymin,(p.z() - dz)* << 344 G4double tmax = std::min(tymax,(p.z() + dz)* << 345 538 346 if (tmax <= tmin + delta) return kInfinity; << 539 // Will we intersect? 347 return (tmin < delta) ? 0. : tmin; << 540 // If safx/y/z is >-tol/2 the point is outside/on the box's x/y/z extent. >> 541 // If both p.x/y/z and v.x/y/z repectively are both positive/negative, >> 542 // travel is in a direction away from the shape. >> 543 >> 544 if ( ((p.x()*v.x() >= 0.0) && safx > -kCarTolerance*0.5) >> 545 || ((p.y()*v.y() >= 0.0) && safy > -kCarTolerance*0.5) >> 546 || ((p.z()*v.z() >= 0.0) && safz > -kCarTolerance*0.5) ) >> 547 { >> 548 return kInfinity ; // travel away or parallel within tolerance >> 549 } >> 550 >> 551 // Compute min / max distances for x/y/z travel: >> 552 // X Planes >> 553 >> 554 if ( v.x()) >> 555 { >> 556 stmp = 1.0/std::fabs(v.x()) ; >> 557 >> 558 if (safx >= 0.0) >> 559 { >> 560 smin = safx*stmp ; >> 561 smax = (fDx+std::fabs(p.x()))*stmp ; >> 562 } >> 563 else >> 564 { >> 565 if (v.x() > 0) sOut = (fDx - p.x())*stmp ; >> 566 if (v.x() < 0) sOut = (fDx + p.x())*stmp ; >> 567 } >> 568 } >> 569 >> 570 // Y Planes >> 571 >> 572 if ( v.y()) >> 573 { >> 574 stmp = 1.0/std::fabs(v.y()) ; >> 575 >> 576 if (safy >= 0.0) >> 577 { >> 578 sminy = safy*stmp ; >> 579 smaxy = (fDy+std::fabs(p.y()))*stmp ; >> 580 >> 581 if (sminy > smin) smin=sminy ; >> 582 if (smaxy < smax) smax=smaxy ; >> 583 >> 584 if (smin >= smax-kCarTolerance*0.5) >> 585 { >> 586 return kInfinity ; // touch XY corner >> 587 } >> 588 } >> 589 else >> 590 { >> 591 if (v.y() > 0) sOuty = (fDy - p.y())*stmp ; >> 592 if (v.y() < 0) sOuty = (fDy + p.y())*stmp ; >> 593 if( sOuty < sOut ) sOut = sOuty ; >> 594 } >> 595 } >> 596 >> 597 // Z planes >> 598 >> 599 if ( v.z() ) >> 600 { >> 601 stmp = 1.0/std::fabs(v.z()) ; >> 602 >> 603 if ( safz >= 0.0) >> 604 { >> 605 sminz = safz*stmp ; >> 606 smaxz = (fDz+std::fabs(p.z()))*stmp ; >> 607 >> 608 if (sminz > smin) smin = sminz ; >> 609 if (smaxz < smax) smax = smaxz ; >> 610 >> 611 if (smin >= smax-kCarTolerance*0.5) >> 612 { >> 613 return kInfinity ; // touch ZX or ZY corners >> 614 } >> 615 } >> 616 else >> 617 { >> 618 if (v.z() > 0) sOutz = (fDz - p.z())*stmp ; >> 619 if (v.z() < 0) sOutz = (fDz + p.z())*stmp ; >> 620 if( sOutz < sOut ) sOut = sOutz ; >> 621 } >> 622 } >> 623 >> 624 if ( sOut <= smin + 0.5*kCarTolerance) // travel over edge >> 625 { >> 626 return kInfinity ; >> 627 } >> 628 if (smin < 0.5*kCarTolerance) smin = 0.0 ; >> 629 >> 630 return smin ; 348 } 631 } 349 632 350 ////////////////////////////////////////////// 633 ////////////////////////////////////////////////////////////////////////// 351 // << 634 // 352 // Appoximate distance to box. 635 // Appoximate distance to box. 353 // Returns largest perpendicular distance to t 636 // Returns largest perpendicular distance to the closest x/y/z sides of 354 // the box, which is the most fast estimation 637 // the box, which is the most fast estimation of the shortest distance to box 355 // - If inside return 0 638 // - If inside return 0 356 639 357 G4double G4Box::DistanceToIn(const G4ThreeVect 640 G4double G4Box::DistanceToIn(const G4ThreeVector& p) const 358 { 641 { 359 G4double dist = std::max(std::max( << 642 G4double safex, safey, safez, safe = 0.0 ; 360 std::abs(p.x())-fDx, << 643 361 std::abs(p.y())-fDy), << 644 safex = std::fabs(p.x()) - fDx ; 362 std::abs(p.z())-fDz); << 645 safey = std::fabs(p.y()) - fDy ; 363 return (dist > 0) ? dist : 0.; << 646 safez = std::fabs(p.z()) - fDz ; >> 647 >> 648 if (safex > safe) safe = safex ; >> 649 if (safey > safe) safe = safey ; >> 650 if (safez > safe) safe = safez ; >> 651 >> 652 return safe ; 364 } 653 } 365 654 366 ////////////////////////////////////////////// << 655 ///////////////////////////////////////////////////////////////////////// 367 // 656 // 368 // Calculate distance to surface of the box fr << 657 // Calcluate distance to surface of box from inside 369 // find normal at exit point, if required << 658 // by calculating distances to box's x/y/z planes. 370 // - when leaving the surface, return 0 << 659 // Smallest distance is exact distance to exiting. >> 660 // - Eliminate one side of each pair by considering direction of v >> 661 // - when leaving a surface & v.close, return 0 371 662 372 G4double G4Box::DistanceToOut( const G4ThreeVe << 663 G4double G4Box::DistanceToOut( const G4ThreeVector& p,const G4ThreeVector& v, 373 const G4ThreeVe << 374 const G4bool ca 664 const G4bool calcNorm, 375 G4bool* validNo << 665 G4bool *validNorm,G4ThreeVector *n) const 376 { 666 { 377 // Check if point is on the surface and trav << 667 ESide side = kUndefined ; 378 // << 668 G4double pdist,stmp,snxt; 379 if ((std::abs(p.x()) - fDx) >= -delta && p.x << 669 >> 670 if (calcNorm) *validNorm = true ; // All normals are valid >> 671 >> 672 if (v.x() > 0) // X planes 380 { 673 { 381 if (calcNorm) << 674 pdist = fDx - p.x() ; >> 675 >> 676 if (pdist > kCarTolerance*0.5) >> 677 { >> 678 snxt = pdist/v.x() ; >> 679 side = kPX ; >> 680 } >> 681 else 382 { 682 { 383 *validNorm = true; << 683 if (calcNorm) *n = G4ThreeVector(1,0,0) ; 384 n->set((p.x() < 0) ? -1. : 1., 0., 0.); << 684 return snxt = 0 ; 385 } 685 } 386 return 0.; << 387 } 686 } 388 if ((std::abs(p.y()) - fDy) >= -delta && p.y << 687 else if (v.x() < 0) 389 { 688 { 390 if (calcNorm) << 689 pdist = fDx + p.x() ; >> 690 >> 691 if (pdist > kCarTolerance*0.5) >> 692 { >> 693 snxt = -pdist/v.x() ; >> 694 side = kMX ; >> 695 } >> 696 else 391 { 697 { 392 *validNorm = true; << 698 if (calcNorm) *n = G4ThreeVector(-1,0,0) ; 393 n->set(0., (p.y() < 0) ? -1. : 1., 0.); << 699 return snxt = 0 ; 394 } 700 } 395 return 0.; << 396 } 701 } 397 if ((std::abs(p.z()) - fDz) >= -delta && p.z << 702 else snxt = kInfinity ; >> 703 >> 704 if ( v.y() > 0 ) // Y planes 398 { 705 { 399 if (calcNorm) << 706 pdist=fDy-p.y(); >> 707 >> 708 if (pdist>kCarTolerance*0.5) >> 709 { >> 710 stmp=pdist/v.y(); >> 711 >> 712 if (stmp<snxt) >> 713 { >> 714 snxt=stmp; >> 715 side=kPY; >> 716 } >> 717 } >> 718 else 400 { 719 { 401 *validNorm = true; << 720 if (calcNorm) *n = G4ThreeVector(0,1,0) ; 402 n->set(0., 0., (p.z() < 0) ? -1. : 1.); << 721 return snxt = 0 ; 403 } 722 } 404 return 0.; << 405 } 723 } >> 724 else if ( v.y() < 0 ) >> 725 { >> 726 pdist = fDy + p.y() ; 406 727 407 // Find intersection << 728 if (pdist > kCarTolerance*0.5) 408 // << 729 { 409 G4double vx = v.x(); << 730 stmp=-pdist/v.y(); 410 G4double tx = (vx == 0) ? DBL_MAX : (std::co << 411 731 412 G4double vy = v.y(); << 732 if (stmp<snxt) 413 G4double ty = (vy == 0) ? tx : (std::copysig << 733 { 414 G4double txy = std::min(tx,ty); << 734 snxt=stmp; >> 735 side=kMY; >> 736 } >> 737 } >> 738 else >> 739 { >> 740 if (calcNorm) *n = G4ThreeVector(0,-1,0) ; >> 741 return snxt = 0 ; >> 742 } >> 743 } >> 744 if (v.z()>0) // Z planes >> 745 { >> 746 pdist=fDz-p.z(); 415 747 416 G4double vz = v.z(); << 748 if (pdist > kCarTolerance*0.5) 417 G4double tz = (vz == 0) ? txy : (std::copysi << 749 { 418 G4double tmax = std::min(txy,tz); << 750 stmp=pdist/v.z(); 419 751 420 // Set normal, if required, and return dista << 752 if (stmp < snxt) 421 // << 753 { 422 if (calcNorm) << 754 snxt=stmp; >> 755 side=kPZ; >> 756 } >> 757 } >> 758 else >> 759 { >> 760 if (calcNorm) *n = G4ThreeVector(0,0,1) ; >> 761 return snxt = 0 ; >> 762 } >> 763 } >> 764 else if (v.z()<0) 423 { 765 { 424 *validNorm = true; << 766 pdist = fDz + p.z() ; 425 if (tmax == tx) n->set((v.x() < 0) ? << 767 426 else if (tmax == ty) n->set(0., (v.y() < 0 << 768 if (pdist > kCarTolerance*0.5) 427 else n->set(0., 0., (v.z() << 769 { >> 770 stmp=-pdist/v.z(); >> 771 >> 772 if (stmp < snxt) >> 773 { >> 774 snxt=stmp; >> 775 side=kMZ; >> 776 } >> 777 } >> 778 else >> 779 { >> 780 if (calcNorm) *n = G4ThreeVector(0,0,-1) ; >> 781 return snxt = 0 ; >> 782 } >> 783 } >> 784 if (calcNorm) >> 785 { >> 786 switch (side) >> 787 { >> 788 case kPX: >> 789 *n=G4ThreeVector(1,0,0); >> 790 break; >> 791 case kMX: >> 792 *n=G4ThreeVector(-1,0,0); >> 793 break; >> 794 case kPY: >> 795 *n=G4ThreeVector(0,1,0); >> 796 break; >> 797 case kMY: >> 798 *n=G4ThreeVector(0,-1,0); >> 799 break; >> 800 case kPZ: >> 801 *n=G4ThreeVector(0,0,1); >> 802 break; >> 803 case kMZ: >> 804 *n=G4ThreeVector(0,0,-1); >> 805 break; >> 806 default: >> 807 G4cout.precision(16); >> 808 G4cout << G4endl; >> 809 DumpInfo(); >> 810 G4cout << "Position:" << G4endl << G4endl; >> 811 G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl; >> 812 G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl; >> 813 G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl; >> 814 G4cout << "Direction:" << G4endl << G4endl; >> 815 G4cout << "v.x() = " << v.x() << G4endl; >> 816 G4cout << "v.y() = " << v.y() << G4endl; >> 817 G4cout << "v.z() = " << v.z() << G4endl << G4endl; >> 818 G4cout << "Proposed distance :" << G4endl << G4endl; >> 819 G4cout << "snxt = " << snxt/mm << " mm" << G4endl << G4endl; >> 820 G4Exception("G4Box::DistanceToOut(p,v,..)","Notification",JustWarning, >> 821 "Undefined side for valid surface normal to solid."); >> 822 break; >> 823 } 428 } 824 } 429 return tmax; << 825 return snxt; 430 } 826 } 431 827 432 ////////////////////////////////////////////// 828 //////////////////////////////////////////////////////////////////////////// 433 // 829 // 434 // Calculate exact shortest distance to any bo 830 // Calculate exact shortest distance to any boundary from inside 435 // - if outside return 0 << 831 // - If outside return 0 436 832 437 G4double G4Box::DistanceToOut(const G4ThreeVec 833 G4double G4Box::DistanceToOut(const G4ThreeVector& p) const 438 { 834 { >> 835 G4double safx1,safx2,safy1,safy2,safz1,safz2,safe=0.0; >> 836 439 #ifdef G4CSGDEBUG 837 #ifdef G4CSGDEBUG 440 if( Inside(p) == kOutside ) 838 if( Inside(p) == kOutside ) 441 { 839 { 442 std::ostringstream message; << 840 G4cout.precision(16) ; 443 G4int oldprc = message.precision(16); << 841 G4cout << G4endl ; 444 message << "Point p is outside (!?) of sol << 842 DumpInfo(); 445 message << "Position:\n"; << 843 G4cout << "Position:" << G4endl << G4endl ; 446 message << " p.x() = " << p.x()/mm << " << 844 G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl ; 447 message << " p.y() = " << p.y()/mm << " << 845 G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl ; 448 message << " p.z() = " << p.z()/mm << " << 846 G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl ; 449 G4cout.precision(oldprc); << 847 G4Exception("G4Box::DistanceToOut(p)", "Notification", JustWarning, 450 G4Exception("G4Box::DistanceToOut(p)", "Ge << 848 "Point p is outside !?" ); 451 JustWarning, message ); << 452 DumpInfo(); << 453 } 849 } 454 #endif 850 #endif 455 G4double dist = std::min(std::min( << 851 456 fDx-std::abs(p.x()), << 852 safx1 = fDx - p.x() ; 457 fDy-std::abs(p.y())), << 853 safx2 = fDx + p.x() ; 458 fDz-std::abs(p.z())); << 854 safy1 = fDy - p.y() ; 459 return (dist > 0) ? dist : 0.; << 855 safy2 = fDy + p.y() ; >> 856 safz1 = fDz - p.z() ; >> 857 safz2 = fDz + p.z() ; >> 858 >> 859 // shortest Dist to any boundary now MIN(safx1,safx2,safy1..) >> 860 >> 861 if (safx2 < safx1) safe = safx2 ; >> 862 else safe = safx1 ; >> 863 if (safy1 < safe) safe = safy1 ; >> 864 if (safy2 < safe) safe = safy2 ; >> 865 if (safz1 < safe) safe = safz1 ; >> 866 if (safz2 < safe) safe = safz2 ; >> 867 >> 868 if (safe < 0) safe = 0 ; >> 869 return safe ; 460 } 870 } 461 871 462 ////////////////////////////////////////////// << 872 //////////////////////////////////////////////////////////////////////// 463 // 873 // 464 // GetEntityType << 874 // Create a List containing the transformed vertices 465 << 875 // Ordering [0-3] -fDz cross section 466 G4GeometryType G4Box::GetEntityType() const << 876 // [4-7] +fDz cross section such that [0] is below [4], 467 { << 877 // [1] below [5] etc. 468 return {"G4Box"}; << 878 // Note: >> 879 // Caller has deletion resposibility >> 880 >> 881 G4ThreeVectorList* >> 882 G4Box::CreateRotatedVertices(const G4AffineTransform& pTransform) const >> 883 { >> 884 G4ThreeVectorList* vertices = new G4ThreeVectorList(); >> 885 vertices->reserve(8); >> 886 >> 887 if (vertices) >> 888 { >> 889 G4ThreeVector vertex0(-fDx,-fDy,-fDz) ; >> 890 G4ThreeVector vertex1(fDx,-fDy,-fDz) ; >> 891 G4ThreeVector vertex2(fDx,fDy,-fDz) ; >> 892 G4ThreeVector vertex3(-fDx,fDy,-fDz) ; >> 893 G4ThreeVector vertex4(-fDx,-fDy,fDz) ; >> 894 G4ThreeVector vertex5(fDx,-fDy,fDz) ; >> 895 G4ThreeVector vertex6(fDx,fDy,fDz) ; >> 896 G4ThreeVector vertex7(-fDx,fDy,fDz) ; >> 897 >> 898 vertices->push_back(pTransform.TransformPoint(vertex0)); >> 899 vertices->push_back(pTransform.TransformPoint(vertex1)); >> 900 vertices->push_back(pTransform.TransformPoint(vertex2)); >> 901 vertices->push_back(pTransform.TransformPoint(vertex3)); >> 902 vertices->push_back(pTransform.TransformPoint(vertex4)); >> 903 vertices->push_back(pTransform.TransformPoint(vertex5)); >> 904 vertices->push_back(pTransform.TransformPoint(vertex6)); >> 905 vertices->push_back(pTransform.TransformPoint(vertex7)); >> 906 } >> 907 else >> 908 { >> 909 DumpInfo(); >> 910 G4Exception("G4Box::CreateRotatedVertices()", >> 911 "FatalError", FatalException, >> 912 "Error in allocation of vertices. Out of memory !"); >> 913 } >> 914 return vertices; 469 } 915 } 470 916 471 ////////////////////////////////////////////// 917 ////////////////////////////////////////////////////////////////////////// 472 // 918 // 473 // IsFaceted << 919 // GetEntityType 474 920 475 G4bool G4Box::IsFaceted() const << 921 G4GeometryType G4Box::GetEntityType() const 476 { 922 { 477 return true; << 923 return G4String("G4Box"); 478 } 924 } 479 925 480 ////////////////////////////////////////////// 926 ////////////////////////////////////////////////////////////////////////// 481 // 927 // 482 // Stream object contents to an output stream 928 // Stream object contents to an output stream 483 929 484 std::ostream& G4Box::StreamInfo(std::ostream& 930 std::ostream& G4Box::StreamInfo(std::ostream& os) const 485 { 931 { 486 G4long oldprc = os.precision(16); << 487 os << "------------------------------------- 932 os << "-----------------------------------------------------------\n" 488 << " *** Dump for solid - " << GetName 933 << " *** Dump for solid - " << GetName() << " ***\n" 489 << " ================================= 934 << " ===================================================\n" 490 << "Solid type: G4Box\n" << 935 << " Solid type: G4Box\n" 491 << "Parameters: \n" << 936 << " Parameters: \n" 492 << " half length X: " << fDx/mm << " mm << 937 << " half length X: " << fDx/mm << " mm \n" 493 << " half length Y: " << fDy/mm << " mm << 938 << " half length Y: " << fDy/mm << " mm \n" 494 << " half length Z: " << fDz/mm << " mm << 939 << " half length Z: " << fDz/mm << " mm \n" 495 << "------------------------------------- 940 << "-----------------------------------------------------------\n"; 496 os.precision(oldprc); << 941 497 return os; 942 return os; 498 } 943 } 499 944 500 ////////////////////////////////////////////// 945 ////////////////////////////////////////////////////////////////////////// 501 // 946 // 502 // Return a point randomly and uniformly selec << 947 // Methods for visualisation 503 948 504 G4ThreeVector G4Box::GetPointOnSurface() const << 949 void G4Box::DescribeYourselfTo (G4VGraphicsScene& scene) const 505 { 950 { 506 G4double sxy = fDx*fDy, sxz = fDx*fDz, syz = << 951 scene.AddSolid (*this); 507 G4double select = (sxy + sxz + syz)*G4QuickR << 508 G4double u = 2.*G4QuickRand() - 1.; << 509 G4double v = 2.*G4QuickRand() - 1.; << 510 << 511 if (select < sxy) << 512 return { u*fDx, v*fDy, ((select < 0.5*sxy) << 513 else if (select < sxy + sxz) << 514 return { u*fDx, ((select < sxy + 0.5*sxz) << 515 else << 516 return { ((select < sxy + sxz + 0.5*syz) ? << 517 } 952 } 518 953 519 ////////////////////////////////////////////// << 954 G4VisExtent G4Box::GetExtent() const 520 // << 521 // Make a clone of the object << 522 // << 523 G4VSolid* G4Box::Clone() const << 524 { 955 { 525 return new G4Box(*this); << 956 return G4VisExtent (-fDx, fDx, -fDy, fDy, -fDz, fDz); 526 } 957 } 527 958 528 ////////////////////////////////////////////// << 959 G4Polyhedron* G4Box::CreatePolyhedron () const 529 // << 530 // Methods for visualisation << 531 << 532 void G4Box::DescribeYourselfTo (G4VGraphicsSce << 533 { 960 { 534 scene.AddSolid (*this); << 961 return new G4PolyhedronBox (fDx, fDy, fDz); 535 } 962 } 536 963 537 G4VisExtent G4Box::GetExtent() const << 964 G4NURBS* G4Box::CreateNURBS () const 538 { 965 { 539 return { -fDx, fDx, -fDy, fDy, -fDz, fDz }; << 966 return new G4NURBSbox (fDx, fDy, fDz); 540 } 967 } >> 968 >> 969 ///////////////////////////////////////////////////////////////////////////// >> 970 // >> 971 // Return a point (G4ThreeVector) randomly and uniformly selected on the solid surface 541 972 542 G4Polyhedron* G4Box::CreatePolyhedron () const << 973 G4ThreeVector G4Box::GetPointOnSurface() const 543 { 974 { 544 return new G4PolyhedronBox (fDx, fDy, fDz); << 975 G4double px, py, pz, select, sumS; >> 976 G4double Sxy = fDx*fDy, Sxz = fDx*fDz, Syz = fDy*fDz; >> 977 >> 978 sumS = Sxy + Sxz + Syz; >> 979 select = sumS*G4UniformRand(); >> 980 >> 981 if( select < Sxy ) >> 982 { >> 983 px = -fDx +2*fDx*G4UniformRand(); >> 984 py = -fDy +2*fDy*G4UniformRand(); >> 985 >> 986 if(G4UniformRand() > 0.5) pz = fDz; >> 987 else pz = -fDz; >> 988 } >> 989 else if ( ( select - Sxy ) < Sxz ) >> 990 { >> 991 px = -fDx +2*fDx*G4UniformRand(); >> 992 pz = -fDz +2*fDz*G4UniformRand(); >> 993 >> 994 if(G4UniformRand() > 0.5) py = fDy; >> 995 else py = -fDy; >> 996 } >> 997 else >> 998 { >> 999 py = -fDy +2*fDy*G4UniformRand(); >> 1000 pz = -fDz +2*fDz*G4UniformRand(); >> 1001 >> 1002 if(G4UniformRand() > 0.5) px = fDx; >> 1003 else px = -fDx; >> 1004 } >> 1005 return G4ThreeVector(px,py,pz); 545 } 1006 } 546 #endif << 1007 547 1008