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