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