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