Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // Implementation of the base class for solids 26 // Implementation of the base class for solids created by Boolean 27 // operations between other solids 27 // operations between other solids 28 // 28 // 29 // 1998.09.10 V.Grichine - created 29 // 1998.09.10 V.Grichine - created 30 // ------------------------------------------- 30 // -------------------------------------------------------------------- 31 31 32 #include "G4BooleanSolid.hh" 32 #include "G4BooleanSolid.hh" 33 #include "G4VSolid.hh" 33 #include "G4VSolid.hh" 34 #include "G4DisplacedSolid.hh" 34 #include "G4DisplacedSolid.hh" 35 #include "G4ReflectedSolid.hh" 35 #include "G4ReflectedSolid.hh" 36 #include "G4ScaledSolid.hh" 36 #include "G4ScaledSolid.hh" 37 #include "G4Polyhedron.hh" 37 #include "G4Polyhedron.hh" 38 #include "HepPolyhedronProcessor.h" 38 #include "HepPolyhedronProcessor.h" 39 #include "G4QuickRand.hh" 39 #include "G4QuickRand.hh" 40 40 41 #include "G4AutoLock.hh" 41 #include "G4AutoLock.hh" 42 42 43 namespace 43 namespace 44 { 44 { 45 G4RecursiveMutex polyhedronMutex = G4MUTEX_I 45 G4RecursiveMutex polyhedronMutex = G4MUTEX_INITIALIZER; 46 } 46 } 47 47 48 G4VBooleanProcessor* G4BooleanSolid::fExternal 48 G4VBooleanProcessor* G4BooleanSolid::fExternalBoolProcessor = nullptr; 49 49 50 ////////////////////////////////////////////// 50 ////////////////////////////////////////////////////////////////// 51 // 51 // 52 // Constructor 52 // Constructor 53 53 54 G4BooleanSolid::G4BooleanSolid( const G4String 54 G4BooleanSolid::G4BooleanSolid( const G4String& pName, 55 G4VSolid* pSol 55 G4VSolid* pSolidA , 56 G4VSolid* pSol 56 G4VSolid* pSolidB ) 57 : G4VSolid(pName), fPtrSolidA(pSolidA), fPtr 57 : G4VSolid(pName), fPtrSolidA(pSolidA), fPtrSolidB(pSolidB) 58 { 58 { 59 } 59 } 60 60 61 ////////////////////////////////////////////// 61 ////////////////////////////////////////////////////////////////// 62 // 62 // 63 // Constructor 63 // Constructor 64 64 65 G4BooleanSolid::G4BooleanSolid( const G4String 65 G4BooleanSolid::G4BooleanSolid( const G4String& pName, 66 G4VSolid 66 G4VSolid* pSolidA , 67 G4VSolid 67 G4VSolid* pSolidB , 68 G4Rotati 68 G4RotationMatrix* rotMatrix, 69 const G4ThreeV 69 const G4ThreeVector& transVector ) 70 : G4VSolid(pName), createdDisplacedSolid(tru 70 : G4VSolid(pName), createdDisplacedSolid(true) 71 { 71 { 72 fPtrSolidA = pSolidA ; 72 fPtrSolidA = pSolidA ; 73 fPtrSolidB = new G4DisplacedSolid("placedB", 73 fPtrSolidB = new G4DisplacedSolid("placedB",pSolidB,rotMatrix,transVector) ; 74 } 74 } 75 75 76 ////////////////////////////////////////////// 76 ////////////////////////////////////////////////////////////////// 77 // 77 // 78 // Constructor 78 // Constructor 79 79 80 G4BooleanSolid::G4BooleanSolid( const G4String 80 G4BooleanSolid::G4BooleanSolid( const G4String& pName, 81 G4VSolid 81 G4VSolid* pSolidA , 82 G4VSolid 82 G4VSolid* pSolidB , 83 const G4Transf 83 const G4Transform3D& transform ) 84 : G4VSolid(pName), createdDisplacedSolid(tru 84 : G4VSolid(pName), createdDisplacedSolid(true) 85 { 85 { 86 fPtrSolidA = pSolidA ; 86 fPtrSolidA = pSolidA ; 87 fPtrSolidB = new G4DisplacedSolid("placedB", 87 fPtrSolidB = new G4DisplacedSolid("placedB",pSolidB,transform) ; 88 } 88 } 89 89 90 ////////////////////////////////////////////// 90 /////////////////////////////////////////////////////////////// 91 // 91 // 92 // Fake default constructor - sets only member 92 // Fake default constructor - sets only member data and allocates memory 93 // for usage restri 93 // for usage restricted to object persistency. 94 94 95 G4BooleanSolid::G4BooleanSolid( __void__& a ) 95 G4BooleanSolid::G4BooleanSolid( __void__& a ) 96 : G4VSolid(a) 96 : G4VSolid(a) 97 { 97 { 98 } 98 } 99 99 100 ////////////////////////////////////////////// 100 /////////////////////////////////////////////////////////////// 101 // 101 // 102 // Destructor deletes transformation contents 102 // Destructor deletes transformation contents of the created displaced solid 103 103 104 G4BooleanSolid::~G4BooleanSolid() 104 G4BooleanSolid::~G4BooleanSolid() 105 { 105 { 106 if(createdDisplacedSolid) 106 if(createdDisplacedSolid) 107 { 107 { 108 ((G4DisplacedSolid*)fPtrSolidB)->CleanTran 108 ((G4DisplacedSolid*)fPtrSolidB)->CleanTransformations(); 109 } 109 } 110 delete fpPolyhedron; fpPolyhedron = nullptr; 110 delete fpPolyhedron; fpPolyhedron = nullptr; 111 } 111 } 112 112 113 ////////////////////////////////////////////// 113 /////////////////////////////////////////////////////////////// 114 // 114 // 115 // Copy constructor 115 // Copy constructor 116 116 117 G4BooleanSolid::G4BooleanSolid(const G4Boolean 117 G4BooleanSolid::G4BooleanSolid(const G4BooleanSolid& rhs) 118 : G4VSolid (rhs), fPtrSolidA(rhs.fPtrSolidA) 118 : G4VSolid (rhs), fPtrSolidA(rhs.fPtrSolidA), fPtrSolidB(rhs.fPtrSolidB), 119 fCubicVolume(rhs.fCubicVolume), fSurfaceAr 119 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea), 120 fCubVolStatistics(rhs.fCubVolStatistics), 120 fCubVolStatistics(rhs.fCubVolStatistics), 121 fAreaStatistics(rhs.fAreaStatistics), 121 fAreaStatistics(rhs.fAreaStatistics), 122 fCubVolEpsilon(rhs.fCubVolEpsilon), 122 fCubVolEpsilon(rhs.fCubVolEpsilon), 123 fAreaAccuracy(rhs.fAreaAccuracy), 123 fAreaAccuracy(rhs.fAreaAccuracy), 124 createdDisplacedSolid(rhs.createdDisplaced 124 createdDisplacedSolid(rhs.createdDisplacedSolid) 125 { 125 { 126 fPrimitives.resize(0); fPrimitivesSurfaceAre 126 fPrimitives.resize(0); fPrimitivesSurfaceArea = 0.; 127 } 127 } 128 128 129 ////////////////////////////////////////////// 129 /////////////////////////////////////////////////////////////// 130 // 130 // 131 // Assignment operator 131 // Assignment operator 132 132 133 G4BooleanSolid& G4BooleanSolid::operator = (co 133 G4BooleanSolid& G4BooleanSolid::operator = (const G4BooleanSolid& rhs) 134 { 134 { 135 // Check assignment to self 135 // Check assignment to self 136 // 136 // 137 if (this == &rhs) { return *this; } 137 if (this == &rhs) { return *this; } 138 138 139 // Copy base class data 139 // Copy base class data 140 // 140 // 141 G4VSolid::operator=(rhs); 141 G4VSolid::operator=(rhs); 142 142 143 // Copy data 143 // Copy data 144 // 144 // 145 fPtrSolidA= rhs.fPtrSolidA; fPtrSolidB= rhs. 145 fPtrSolidA= rhs.fPtrSolidA; fPtrSolidB= rhs.fPtrSolidB; 146 fCubicVolume= rhs.fCubicVolume; fSurfaceArea 146 fCubicVolume= rhs.fCubicVolume; fSurfaceArea= rhs.fSurfaceArea; 147 fCubVolStatistics = rhs.fCubVolStatistics; f 147 fCubVolStatistics = rhs.fCubVolStatistics; fCubVolEpsilon = rhs.fCubVolEpsilon; 148 fAreaStatistics = rhs.fAreaStatistics; fArea 148 fAreaStatistics = rhs.fAreaStatistics; fAreaAccuracy = rhs.fAreaAccuracy; 149 createdDisplacedSolid= rhs.createdDisplacedS 149 createdDisplacedSolid= rhs.createdDisplacedSolid; 150 150 151 fRebuildPolyhedron = false; 151 fRebuildPolyhedron = false; 152 delete fpPolyhedron; fpPolyhedron = nullptr; 152 delete fpPolyhedron; fpPolyhedron = nullptr; 153 fPrimitives.resize(0); fPrimitivesSurfaceAre 153 fPrimitives.resize(0); fPrimitivesSurfaceArea = 0.; 154 154 155 return *this; 155 return *this; 156 } 156 } 157 157 158 ////////////////////////////////////////////// 158 /////////////////////////////////////////////////////////////// 159 // 159 // 160 // If solid is made up from a Boolean operatio 160 // If solid is made up from a Boolean operation of two solids, 161 // return the corresponding solid (for no=0 an 161 // return the corresponding solid (for no=0 and 1) 162 // If the solid is not a "Boolean", return 0 162 // If the solid is not a "Boolean", return 0 163 163 164 const G4VSolid* G4BooleanSolid::GetConstituent 164 const G4VSolid* G4BooleanSolid::GetConstituentSolid(G4int no) const 165 { 165 { 166 const G4VSolid* subSolid = nullptr; 166 const G4VSolid* subSolid = nullptr; 167 if( no == 0 ) 167 if( no == 0 ) 168 subSolid = fPtrSolidA; 168 subSolid = fPtrSolidA; 169 else if( no == 1 ) 169 else if( no == 1 ) 170 subSolid = fPtrSolidB; 170 subSolid = fPtrSolidB; 171 else 171 else 172 { 172 { 173 DumpInfo(); 173 DumpInfo(); 174 G4Exception("G4BooleanSolid::GetConstituen 174 G4Exception("G4BooleanSolid::GetConstituentSolid()", 175 "GeomSolids0002", FatalExcepti 175 "GeomSolids0002", FatalException, "Invalid solid index."); 176 } 176 } 177 return subSolid; 177 return subSolid; 178 } 178 } 179 179 180 ////////////////////////////////////////////// 180 /////////////////////////////////////////////////////////////// 181 // 181 // 182 // If solid is made up from a Boolean operatio 182 // If solid is made up from a Boolean operation of two solids, 183 // return the corresponding solid (for no=0 an 183 // return the corresponding solid (for no=0 and 1) 184 // If the solid is not a "Boolean", return 0 184 // If the solid is not a "Boolean", return 0 185 185 186 G4VSolid* G4BooleanSolid::GetConstituentSolid( 186 G4VSolid* G4BooleanSolid::GetConstituentSolid(G4int no) 187 { 187 { 188 G4VSolid* subSolid = nullptr; 188 G4VSolid* subSolid = nullptr; 189 if( no == 0 ) 189 if( no == 0 ) 190 subSolid = fPtrSolidA; 190 subSolid = fPtrSolidA; 191 else if( no == 1 ) 191 else if( no == 1 ) 192 subSolid = fPtrSolidB; 192 subSolid = fPtrSolidB; 193 else 193 else 194 { 194 { 195 DumpInfo(); 195 DumpInfo(); 196 G4Exception("G4BooleanSolid::GetConstituen 196 G4Exception("G4BooleanSolid::GetConstituentSolid()", 197 "GeomSolids0002", FatalExcepti 197 "GeomSolids0002", FatalException, "Invalid solid index."); 198 } 198 } 199 return subSolid; 199 return subSolid; 200 } 200 } 201 201 202 ////////////////////////////////////////////// 202 ////////////////////////////////////////////////////////////////////////// 203 // 203 // 204 // Returns entity type 204 // Returns entity type 205 205 206 G4GeometryType G4BooleanSolid::GetEntityType() 206 G4GeometryType G4BooleanSolid::GetEntityType() const 207 { 207 { 208 return {"G4BooleanSolid"}; 208 return {"G4BooleanSolid"}; 209 } 209 } 210 210 211 ////////////////////////////////////////////// 211 ////////////////////////////////////////////////////////////////////////// 212 // 212 // 213 // Set number of random points to be used for << 214 << 215 void G4BooleanSolid::SetCubVolStatistics(G4int << 216 { << 217 if (st != fCubVolStatistics) { fCubicVolume << 218 fCubVolStatistics = st; << 219 << 220 // Propagate st to all components of the 1st << 221 if (fPtrSolidA->GetNumOfConstituents() > 1) << 222 { << 223 G4VSolid* ptr = fPtrSolidA; << 224 while(true) << 225 { << 226 G4String type = ptr->GetEntityType(); << 227 if (type == "G4DisplacedSolid") << 228 { << 229 ptr = ((G4DisplacedSolid*)ptr)->GetCon << 230 continue; << 231 } << 232 if (type == "G4ReflectedSolid") << 233 { << 234 ptr = ((G4ReflectedSolid*)ptr)->GetCon << 235 continue; << 236 } << 237 if (type == "G4ScaledSolid") << 238 { << 239 ptr = ((G4ScaledSolid*)ptr)->GetUnscal << 240 continue; << 241 } << 242 if (type != "G4MultiUnion") // G4MultiUn << 243 { << 244 ((G4BooleanSolid*)ptr)->SetCubVolStatistics( << 245 } << 246 break; << 247 } << 248 } << 249 << 250 // Propagate st to all components of the 2nd << 251 if (fPtrSolidB->GetNumOfConstituents() > 1) << 252 { << 253 G4VSolid* ptr = fPtrSolidB; << 254 while(true) << 255 { << 256 G4String type = ptr->GetEntityType(); << 257 if (type == "G4DisplacedSolid") << 258 { << 259 ptr = ((G4DisplacedSolid*)ptr)->GetCon << 260 continue; << 261 } << 262 if (type == "G4ReflectedSolid") << 263 { << 264 ptr = ((G4ReflectedSolid*)ptr)->GetCon << 265 continue; << 266 } << 267 if (type == "G4ScaledSolid") << 268 { << 269 ptr = ((G4ScaledSolid*)ptr)->GetUnscal << 270 continue; << 271 } << 272 if (type != "G4MultiUnion") // G4MultiUn << 273 { << 274 ((G4BooleanSolid*)ptr)->SetCubVolStatistics( << 275 } << 276 break; << 277 } << 278 } << 279 } << 280 << 281 ////////////////////////////////////////////// << 282 // << 283 // Set epsilon for computing cubic volume << 284 << 285 void G4BooleanSolid::SetCubVolEpsilon(G4double << 286 { << 287 if (ep != fCubVolEpsilon) { fCubicVolume = - << 288 fCubVolEpsilon = ep; << 289 << 290 // Propagate ep to all components of the 1st << 291 if (fPtrSolidA->GetNumOfConstituents() > 1) << 292 { << 293 G4VSolid* ptr = fPtrSolidA; << 294 while(true) << 295 { << 296 G4String type = ptr->GetEntityType(); << 297 if (type == "G4DisplacedSolid") << 298 { << 299 ptr = ((G4DisplacedSolid*)ptr)->GetCon << 300 continue; << 301 } << 302 if (type == "G4ReflectedSolid") << 303 { << 304 ptr = ((G4ReflectedSolid*)ptr)->GetCon << 305 continue; << 306 } << 307 if (type == "G4ScaledSolid") << 308 { << 309 ptr = ((G4ScaledSolid*)ptr)->GetUnscal << 310 continue; << 311 } << 312 if (type != "G4MultiUnion") // G4MultiUn << 313 { << 314 ((G4BooleanSolid*)ptr)->SetCubVolEpsilon(ep) << 315 } << 316 break; << 317 } << 318 } << 319 << 320 // Propagate ep to all components of the 2nd << 321 if (fPtrSolidB->GetNumOfConstituents() > 1) << 322 { << 323 G4VSolid* ptr = fPtrSolidB; << 324 while(true) << 325 { << 326 G4String type = ptr->GetEntityType(); << 327 if (type == "G4DisplacedSolid") << 328 { << 329 ptr = ((G4DisplacedSolid*)ptr)->GetCon << 330 continue; << 331 } << 332 if (type == "G4ReflectedSolid") << 333 { << 334 ptr = ((G4ReflectedSolid*)ptr)->GetCon << 335 continue; << 336 } << 337 if (type == "G4ScaledSolid") << 338 { << 339 ptr = ((G4ScaledSolid*)ptr)->GetUnscal << 340 continue; << 341 } << 342 if (type != "G4MultiUnion") // G4MultiUn << 343 { << 344 ((G4BooleanSolid*)ptr)->SetCubVolEpsilon(ep) << 345 } << 346 break; << 347 } << 348 } << 349 } << 350 << 351 ////////////////////////////////////////////// << 352 // << 353 // Stream object contents to an output stream 213 // Stream object contents to an output stream 354 214 355 std::ostream& G4BooleanSolid::StreamInfo(std:: 215 std::ostream& G4BooleanSolid::StreamInfo(std::ostream& os) const 356 { 216 { 357 os << "------------------------------------- 217 os << "-----------------------------------------------------------\n" 358 << " *** Dump for Boolean solid - " << 218 << " *** Dump for Boolean solid - " << GetName() << " ***\n" 359 << " ================================= 219 << " ===================================================\n" 360 << " Solid type: " << GetEntityType() << 220 << " Solid type: " << GetEntityType() << "\n" 361 << " Parameters of constituent solids: \n 221 << " Parameters of constituent solids: \n" 362 << "===================================== 222 << "===========================================================\n"; 363 fPtrSolidA->StreamInfo(os); 223 fPtrSolidA->StreamInfo(os); 364 fPtrSolidB->StreamInfo(os); 224 fPtrSolidB->StreamInfo(os); 365 os << "===================================== 225 os << "===========================================================\n"; 366 226 367 return os; 227 return os; 368 } 228 } 369 229 370 ////////////////////////////////////////////// 230 ////////////////////////////////////////////////////////////////////////// 371 // 231 // 372 // Creates list of constituent primitives of a 232 // Creates list of constituent primitives of and their placements 373 233 374 void G4BooleanSolid::GetListOfPrimitives( 234 void G4BooleanSolid::GetListOfPrimitives( 375 std::vector<std::pair<G4VSolid*,G4Trans 235 std::vector<std::pair<G4VSolid*,G4Transform3D>>& primitives, 376 const G4Transform3D& curPlacement) cons 236 const G4Transform3D& curPlacement) const 377 { 237 { 378 G4Transform3D transform; 238 G4Transform3D transform; 379 G4VSolid* solid; 239 G4VSolid* solid; 380 G4String type; 240 G4String type; 381 241 382 // Repeat two times, first time for fPtrSoli 242 // Repeat two times, first time for fPtrSolidA and then for fPtrSolidB 383 // 243 // 384 for (auto i=0; i<2; ++i) 244 for (auto i=0; i<2; ++i) 385 { 245 { 386 transform = curPlacement; 246 transform = curPlacement; 387 solid = (i == 0) ? fPtrSolidA : fPtrSo 247 solid = (i == 0) ? fPtrSolidA : fPtrSolidB; 388 type = solid->GetEntityType(); 248 type = solid->GetEntityType(); 389 249 390 // While current solid is a trasformed sol 250 // While current solid is a trasformed solid just modify transform 391 // 251 // 392 while (type == "G4DisplacedSolid" || 252 while (type == "G4DisplacedSolid" || 393 type == "G4ReflectedSolid" || 253 type == "G4ReflectedSolid" || 394 type == "G4ScaledSolid") 254 type == "G4ScaledSolid") 395 { 255 { 396 if (type == "G4DisplacedSolid") 256 if (type == "G4DisplacedSolid") 397 { 257 { 398 transform = transform * G4Transform3D( 258 transform = transform * G4Transform3D( 399 ((G4DisplacedSolid*)solid) 259 ((G4DisplacedSolid*)solid)->GetObjectRotation(), 400 ((G4DisplacedSolid*)solid) 260 ((G4DisplacedSolid*)solid)->GetObjectTranslation()); 401 solid = ((G4DisplacedSolid*)solid) 261 solid = ((G4DisplacedSolid*)solid)->GetConstituentMovedSolid(); 402 } 262 } 403 else if (type == "G4ReflectedSolid") 263 else if (type == "G4ReflectedSolid") 404 { 264 { 405 transform= transform*((G4ReflectedSoli 265 transform= transform*((G4ReflectedSolid*)solid)->GetDirectTransform3D(); 406 solid = ((G4ReflectedSolid*)solid)- 266 solid = ((G4ReflectedSolid*)solid)->GetConstituentMovedSolid(); 407 } 267 } 408 else if (type == "G4ScaledSolid") 268 else if (type == "G4ScaledSolid") 409 { 269 { 410 transform = transform * ((G4ScaledSoli 270 transform = transform * ((G4ScaledSolid*)solid)->GetScaleTransform(); 411 solid = ((G4ScaledSolid*)solid)->G 271 solid = ((G4ScaledSolid*)solid)->GetUnscaledSolid(); 412 } 272 } 413 type = solid->GetEntityType(); 273 type = solid->GetEntityType(); 414 } 274 } 415 275 416 // If current solid is a Boolean solid the 276 // If current solid is a Boolean solid then continue recursion, 417 // otherwise add it to the list of primiti 277 // otherwise add it to the list of primitives 418 // 278 // 419 if (type == "G4UnionSolid" || 279 if (type == "G4UnionSolid" || 420 type == "G4SubtractionSolid" || 280 type == "G4SubtractionSolid" || 421 type == "G4IntersectionSolid" || 281 type == "G4IntersectionSolid" || 422 type == "G4BooleanSolid") 282 type == "G4BooleanSolid") 423 { 283 { 424 ((G4BooleanSolid *)solid)->GetListOfPrim 284 ((G4BooleanSolid *)solid)->GetListOfPrimitives(primitives,transform); 425 } 285 } 426 else 286 else 427 { 287 { 428 primitives.emplace_back(solid,transform) 288 primitives.emplace_back(solid,transform); 429 } 289 } 430 } 290 } 431 } 291 } 432 292 433 ////////////////////////////////////////////// 293 ////////////////////////////////////////////////////////////////////////// 434 // 294 // 435 // Returns a point (G4ThreeVector) randomly an 295 // Returns a point (G4ThreeVector) randomly and uniformly selected 436 // on the surface of the solid 296 // on the surface of the solid 437 297 438 G4ThreeVector G4BooleanSolid::GetPointOnSurfac 298 G4ThreeVector G4BooleanSolid::GetPointOnSurface() const 439 { 299 { 440 std::size_t nprims = fPrimitives.size(); 300 std::size_t nprims = fPrimitives.size(); 441 std::pair<G4VSolid *, G4Transform3D> prim; 301 std::pair<G4VSolid *, G4Transform3D> prim; 442 302 443 // Get list of primitives and find the total 303 // Get list of primitives and find the total area of their surfaces 444 // 304 // 445 if (nprims == 0) 305 if (nprims == 0) 446 { 306 { 447 GetListOfPrimitives(fPrimitives, G4Transfo 307 GetListOfPrimitives(fPrimitives, G4Transform3D()); 448 nprims = fPrimitives.size(); 308 nprims = fPrimitives.size(); 449 fPrimitivesSurfaceArea = 0.; 309 fPrimitivesSurfaceArea = 0.; 450 for (std::size_t i=0; i<nprims; ++i) 310 for (std::size_t i=0; i<nprims; ++i) 451 { 311 { 452 fPrimitivesSurfaceArea += fPrimitives[i] 312 fPrimitivesSurfaceArea += fPrimitives[i].first->GetSurfaceArea(); 453 } 313 } 454 } 314 } 455 315 456 // Select random primitive, get random point 316 // Select random primitive, get random point on its surface and 457 // check that the point belongs to the surfa 317 // check that the point belongs to the surface of the solid 458 // 318 // 459 G4ThreeVector p; 319 G4ThreeVector p; 460 for (std::size_t k=0; k<100000; ++k) // try 320 for (std::size_t k=0; k<100000; ++k) // try 100k times 461 { 321 { 462 G4double rand = fPrimitivesSurfaceArea * 322 G4double rand = fPrimitivesSurfaceArea * G4QuickRand(); 463 G4double area = 0.; 323 G4double area = 0.; 464 for (std::size_t i=0; i<nprims; ++i) 324 for (std::size_t i=0; i<nprims; ++i) 465 { 325 { 466 prim = fPrimitives[i]; 326 prim = fPrimitives[i]; 467 area += prim.first->GetSurfaceArea(); 327 area += prim.first->GetSurfaceArea(); 468 if (rand < area) break; 328 if (rand < area) break; 469 } 329 } 470 p = prim.first->GetPointOnSurface(); 330 p = prim.first->GetPointOnSurface(); 471 p = prim.second * G4Point3D(p); 331 p = prim.second * G4Point3D(p); 472 if (Inside(p) == kSurface) return p; 332 if (Inside(p) == kSurface) return p; 473 } 333 } 474 std::ostringstream message; 334 std::ostringstream message; 475 message << "Solid - " << GetName() << "\n" 335 message << "Solid - " << GetName() << "\n" 476 << "All 100k attempts to generate a 336 << "All 100k attempts to generate a point on the surface have failed!\n" 477 << "The solid created may be an inva 337 << "The solid created may be an invalid Boolean construct!"; 478 G4Exception("G4BooleanSolid::GetPointOnSurfa 338 G4Exception("G4BooleanSolid::GetPointOnSurface()", 479 "GeomSolids1001", JustWarning, m 339 "GeomSolids1001", JustWarning, message); 480 return p; 340 return p; 481 } << 482 << 483 ////////////////////////////////////////////// << 484 // << 485 // Return total number of constituents used fo << 486 << 487 G4int G4BooleanSolid::GetNumOfConstituents() c << 488 { << 489 return (fPtrSolidA->GetNumOfConstituents() + << 490 } << 491 << 492 ////////////////////////////////////////////// << 493 // << 494 // Return true if the resulting solid has only << 495 << 496 G4bool G4BooleanSolid::IsFaceted() const << 497 { << 498 return (fPtrSolidA->IsFaceted() && fPtrSolid << 499 } 341 } 500 342 501 ////////////////////////////////////////////// 343 ////////////////////////////////////////////////////////////////////////// 502 // 344 // 503 // Returns polyhedron for visualization 345 // Returns polyhedron for visualization 504 346 505 G4Polyhedron* G4BooleanSolid::GetPolyhedron () 347 G4Polyhedron* G4BooleanSolid::GetPolyhedron () const 506 { 348 { 507 if (fpPolyhedron == nullptr || 349 if (fpPolyhedron == nullptr || 508 fRebuildPolyhedron || 350 fRebuildPolyhedron || 509 fpPolyhedron->GetNumberOfRotationStepsAt 351 fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() != 510 fpPolyhedron->GetNumberOfRotationSteps() 352 fpPolyhedron->GetNumberOfRotationSteps()) 511 { 353 { 512 G4RecursiveAutoLock l(&polyhedronMutex); 354 G4RecursiveAutoLock l(&polyhedronMutex); 513 delete fpPolyhedron; 355 delete fpPolyhedron; 514 fpPolyhedron = CreatePolyhedron(); 356 fpPolyhedron = CreatePolyhedron(); 515 fRebuildPolyhedron = false; 357 fRebuildPolyhedron = false; 516 l.unlock(); 358 l.unlock(); 517 } 359 } 518 return fpPolyhedron; 360 return fpPolyhedron; 519 } 361 } 520 362 521 ////////////////////////////////////////////// 363 ////////////////////////////////////////////////////////////////////////// 522 // 364 // 523 // Stacks polyhedra for processing. Returns to 365 // Stacks polyhedra for processing. Returns top polyhedron. 524 366 525 G4Polyhedron* 367 G4Polyhedron* 526 G4BooleanSolid::StackPolyhedron(HepPolyhedronP 368 G4BooleanSolid::StackPolyhedron(HepPolyhedronProcessor& processor, 527 const G4VSolid 369 const G4VSolid* solid) const 528 { 370 { 529 HepPolyhedronProcessor::Operation operation; 371 HepPolyhedronProcessor::Operation operation; 530 const G4String& type = solid->GetEntityType( 372 const G4String& type = solid->GetEntityType(); 531 if (type == "G4UnionSolid") 373 if (type == "G4UnionSolid") 532 { operation = HepPolyhedronProcessor::UNIO 374 { operation = HepPolyhedronProcessor::UNION; } 533 else if (type == "G4IntersectionSolid") 375 else if (type == "G4IntersectionSolid") 534 { operation = HepPolyhedronProcessor::INTE 376 { operation = HepPolyhedronProcessor::INTERSECTION; } 535 else if (type == "G4SubtractionSolid") 377 else if (type == "G4SubtractionSolid") 536 { operation = HepPolyhedronProcessor::SUBT 378 { operation = HepPolyhedronProcessor::SUBTRACTION; } 537 else 379 else 538 { 380 { 539 std::ostringstream message; 381 std::ostringstream message; 540 message << "Solid - " << solid->GetName() 382 message << "Solid - " << solid->GetName() 541 << " - Unrecognised composite soli 383 << " - Unrecognised composite solid" << G4endl 542 << " Returning NULL !"; 384 << " Returning NULL !"; 543 G4Exception("StackPolyhedron()", "GeomSoli 385 G4Exception("StackPolyhedron()", "GeomSolids1001", JustWarning, message); 544 return nullptr; 386 return nullptr; 545 } 387 } 546 388 547 G4Polyhedron* top = nullptr; 389 G4Polyhedron* top = nullptr; 548 const G4VSolid* solidA = solid->GetConstitue 390 const G4VSolid* solidA = solid->GetConstituentSolid(0); 549 const G4VSolid* solidB = solid->GetConstitue 391 const G4VSolid* solidB = solid->GetConstituentSolid(1); 550 392 551 if (solidA->GetConstituentSolid(0) != nullpt 393 if (solidA->GetConstituentSolid(0) != nullptr) 552 { 394 { 553 top = StackPolyhedron(processor, solidA); 395 top = StackPolyhedron(processor, solidA); 554 } 396 } 555 else 397 else 556 { 398 { 557 top = solidA->GetPolyhedron(); 399 top = solidA->GetPolyhedron(); 558 } 400 } 559 G4Polyhedron* operand = solidB->GetPolyhedro 401 G4Polyhedron* operand = solidB->GetPolyhedron(); 560 if (operand != nullptr) 402 if (operand != nullptr) 561 { 403 { 562 processor.push_back (operation, *operand); 404 processor.push_back (operation, *operand); 563 } 405 } 564 else 406 else 565 { 407 { 566 std::ostringstream message; 408 std::ostringstream message; 567 message << "Solid - " << solid->GetName() 409 message << "Solid - " << solid->GetName() 568 << " - No G4Polyhedron for Boolean 410 << " - No G4Polyhedron for Boolean component"; 569 G4Exception("G4BooleanSolid::StackPolyhedr 411 G4Exception("G4BooleanSolid::StackPolyhedron()", 570 "GeomSolids2001", JustWarning, 412 "GeomSolids2001", JustWarning, message); 571 } 413 } 572 414 573 return top; 415 return top; 574 } 416 } 575 417 576 418 577 ////////////////////////////////////////////// 419 ////////////////////////////////////////////////////////////////////////// 578 // 420 // 579 // Estimate Cubic Volume (capacity) and cache 421 // Estimate Cubic Volume (capacity) and cache it for reuse. 580 422 581 G4double G4BooleanSolid::GetCubicVolume() 423 G4double G4BooleanSolid::GetCubicVolume() 582 { 424 { 583 if(fCubicVolume < 0.) 425 if(fCubicVolume < 0.) 584 { 426 { 585 fCubicVolume = EstimateCubicVolume(fCubVol 427 fCubicVolume = EstimateCubicVolume(fCubVolStatistics, fCubVolEpsilon); 586 } 428 } 587 return fCubicVolume; 429 return fCubicVolume; 588 } 430 } 589 431 590 ////////////////////////////////////////////// 432 ////////////////////////////////////////////////////////////////////////// 591 // 433 // 592 // Set external Boolean processor. 434 // Set external Boolean processor. 593 435 594 void 436 void 595 G4BooleanSolid::SetExternalBooleanProcessor(G4 437 G4BooleanSolid::SetExternalBooleanProcessor(G4VBooleanProcessor* extProcessor) 596 { 438 { 597 fExternalBoolProcessor = extProcessor; 439 fExternalBoolProcessor = extProcessor; 598 } 440 } 599 441 600 ////////////////////////////////////////////// 442 ////////////////////////////////////////////////////////////////////////// 601 // 443 // 602 // Get external Boolean processor. 444 // Get external Boolean processor. 603 445 604 G4VBooleanProcessor* G4BooleanSolid::GetExtern 446 G4VBooleanProcessor* G4BooleanSolid::GetExternalBooleanProcessor() 605 { 447 { 606 return fExternalBoolProcessor; 448 return fExternalBoolProcessor; 607 } 449 } 608 450