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 // G4GenericPolycone implementation 26 // G4GenericPolycone implementation 27 // 27 // 28 // Authors: T.Nikitina, G.Cosmo - CERN 28 // Authors: T.Nikitina, G.Cosmo - CERN 29 // ------------------------------------------- 29 // -------------------------------------------------------------------- 30 30 31 #include "G4GenericPolycone.hh" 31 #include "G4GenericPolycone.hh" 32 32 33 #if !defined(G4GEOM_USE_UGENERICPOLYCONE) 33 #if !defined(G4GEOM_USE_UGENERICPOLYCONE) 34 34 35 #include "G4PolyconeSide.hh" 35 #include "G4PolyconeSide.hh" 36 #include "G4PolyPhiFace.hh" 36 #include "G4PolyPhiFace.hh" 37 37 38 #include "G4GeomTools.hh" 38 #include "G4GeomTools.hh" 39 #include "G4VoxelLimits.hh" 39 #include "G4VoxelLimits.hh" 40 #include "G4AffineTransform.hh" 40 #include "G4AffineTransform.hh" 41 #include "G4BoundingEnvelope.hh" 41 #include "G4BoundingEnvelope.hh" 42 42 43 #include "G4QuickRand.hh" 43 #include "G4QuickRand.hh" 44 44 45 #include "G4Polyhedron.hh" 45 #include "G4Polyhedron.hh" 46 #include "G4EnclosingCylinder.hh" 46 #include "G4EnclosingCylinder.hh" 47 #include "G4ReduciblePolygon.hh" 47 #include "G4ReduciblePolygon.hh" 48 #include "G4VPVParameterisation.hh" 48 #include "G4VPVParameterisation.hh" 49 49 50 namespace 50 namespace 51 { 51 { 52 G4Mutex surface_elementsMutex = G4MUTEX_INIT 52 G4Mutex surface_elementsMutex = G4MUTEX_INITIALIZER; 53 } 53 } 54 54 55 using namespace CLHEP; 55 using namespace CLHEP; 56 56 57 // Constructor (generic parameters) 57 // Constructor (generic parameters) 58 // 58 // 59 G4GenericPolycone::G4GenericPolycone( const G4 59 G4GenericPolycone::G4GenericPolycone( const G4String& name, 60 G4double phiStar 60 G4double phiStart, 61 G4double phiTota 61 G4double phiTotal, 62 G4int numRZ, 62 G4int numRZ, 63 const G4double r[], 63 const G4double r[], 64 const G4double z[] ) 64 const G4double z[] ) 65 : G4VCSGfaceted( name ) 65 : G4VCSGfaceted( name ) 66 { 66 { 67 67 68 auto rz = new G4ReduciblePolygon( r, z, numR << 68 G4ReduciblePolygon *rz = new G4ReduciblePolygon( r, z, numRZ ); 69 69 70 Create( phiStart, phiTotal, rz ); 70 Create( phiStart, phiTotal, rz ); 71 71 72 // Set original_parameters struct for consis 72 // Set original_parameters struct for consistency 73 // 73 // 74 //SetOriginalParameters(rz); 74 //SetOriginalParameters(rz); 75 75 76 delete rz; 76 delete rz; 77 } 77 } 78 78 79 // Create 79 // Create 80 // 80 // 81 // Generic create routine, called by each cons 81 // Generic create routine, called by each constructor after 82 // conversion of arguments 82 // conversion of arguments 83 // 83 // 84 void G4GenericPolycone::Create( G4double phiSt 84 void G4GenericPolycone::Create( G4double phiStart, 85 G4double phiTo 85 G4double phiTotal, 86 G4ReduciblePol 86 G4ReduciblePolygon *rz ) 87 { 87 { 88 // 88 // 89 // Perform checks of rz values 89 // Perform checks of rz values 90 // 90 // 91 if (rz->Amin() < 0.0) 91 if (rz->Amin() < 0.0) 92 { 92 { 93 std::ostringstream message; 93 std::ostringstream message; 94 message << "Illegal input parameters - " < 94 message << "Illegal input parameters - " << GetName() << G4endl 95 << " All R values must be > 95 << " All R values must be >= 0 !"; 96 G4Exception("G4GenericPolycone::Create()", 96 G4Exception("G4GenericPolycone::Create()", "GeomSolids0002", 97 FatalErrorInArgument, message) 97 FatalErrorInArgument, message); 98 } 98 } 99 99 100 G4double rzArea = rz->Area(); 100 G4double rzArea = rz->Area(); 101 if (rzArea < -kCarTolerance) 101 if (rzArea < -kCarTolerance) 102 { 102 { 103 rz->ReverseOrder(); 103 rz->ReverseOrder(); 104 } 104 } 105 else if (rzArea < kCarTolerance) 105 else if (rzArea < kCarTolerance) 106 { 106 { 107 std::ostringstream message; 107 std::ostringstream message; 108 message << "Illegal input parameters - " < 108 message << "Illegal input parameters - " << GetName() << G4endl 109 << " R/Z cross section is z 109 << " R/Z cross section is zero or near zero: " << rzArea; 110 G4Exception("G4GenericPolycone::Create()", 110 G4Exception("G4GenericPolycone::Create()", "GeomSolids0002", 111 FatalErrorInArgument, message) 111 FatalErrorInArgument, message); 112 } 112 } 113 113 114 if ( (!rz->RemoveDuplicateVertices( kCarTole 114 if ( (!rz->RemoveDuplicateVertices( kCarTolerance )) 115 || (!rz->RemoveRedundantVertices( kCarTole 115 || (!rz->RemoveRedundantVertices( kCarTolerance )) ) 116 { 116 { 117 std::ostringstream message; 117 std::ostringstream message; 118 message << "Illegal input parameters - " < 118 message << "Illegal input parameters - " << GetName() << G4endl 119 << " Too few unique R/Z val 119 << " Too few unique R/Z values !"; 120 G4Exception("G4GenericPolycone::Create()", 120 G4Exception("G4GenericPolycone::Create()", "GeomSolids0002", 121 FatalErrorInArgument, message) 121 FatalErrorInArgument, message); 122 } 122 } 123 123 124 if (rz->CrossesItself(1/kInfinity)) 124 if (rz->CrossesItself(1/kInfinity)) 125 { 125 { 126 std::ostringstream message; 126 std::ostringstream message; 127 message << "Illegal input parameters - " < 127 message << "Illegal input parameters - " << GetName() << G4endl 128 << " R/Z segments cross !"; 128 << " R/Z segments cross !"; 129 G4Exception("G4GenericPolycone::Create()", 129 G4Exception("G4GenericPolycone::Create()", "GeomSolids0002", 130 FatalErrorInArgument, message) 130 FatalErrorInArgument, message); 131 } 131 } 132 132 133 numCorner = rz->NumVertices(); 133 numCorner = rz->NumVertices(); 134 134 135 // 135 // 136 // Phi opening? Account for some possible ro 136 // Phi opening? Account for some possible roundoff, and interpret 137 // nonsense value as representing no phi ope 137 // nonsense value as representing no phi opening 138 // 138 // 139 if (phiTotal <= 0 || phiTotal > twopi-1E-10) 139 if (phiTotal <= 0 || phiTotal > twopi-1E-10) 140 { 140 { 141 phiIsOpen = false; 141 phiIsOpen = false; 142 startPhi = 0; 142 startPhi = 0; 143 endPhi = twopi; 143 endPhi = twopi; 144 } 144 } 145 else 145 else 146 { 146 { 147 phiIsOpen = true; 147 phiIsOpen = true; 148 148 149 // 149 // 150 // Convert phi into our convention 150 // Convert phi into our convention 151 // 151 // 152 startPhi = phiStart; 152 startPhi = phiStart; 153 while( startPhi < 0 ) // Loop checking, 153 while( startPhi < 0 ) // Loop checking, 13.08.2015, G.Cosmo 154 startPhi += twopi; 154 startPhi += twopi; 155 155 156 endPhi = phiStart+phiTotal; 156 endPhi = phiStart+phiTotal; 157 while( endPhi < startPhi ) // Loop chec 157 while( endPhi < startPhi ) // Loop checking, 13.08.2015, G.Cosmo 158 endPhi += twopi; 158 endPhi += twopi; 159 } 159 } 160 160 161 // 161 // 162 // Allocate corner array. 162 // Allocate corner array. 163 // 163 // 164 corners = new G4PolyconeSideRZ[numCorner]; 164 corners = new G4PolyconeSideRZ[numCorner]; 165 165 166 // 166 // 167 // Copy corners 167 // Copy corners 168 // 168 // 169 G4ReduciblePolygonIterator iterRZ(rz); 169 G4ReduciblePolygonIterator iterRZ(rz); 170 170 171 G4PolyconeSideRZ* next = corners; 171 G4PolyconeSideRZ* next = corners; 172 iterRZ.Begin(); 172 iterRZ.Begin(); 173 do // Loop checking, 13.08.2015, G.Cosmo 173 do // Loop checking, 13.08.2015, G.Cosmo 174 { 174 { 175 next->r = iterRZ.GetA(); 175 next->r = iterRZ.GetA(); 176 next->z = iterRZ.GetB(); 176 next->z = iterRZ.GetB(); 177 } while( ++next, iterRZ.Next() ); 177 } while( ++next, iterRZ.Next() ); 178 178 179 // 179 // 180 // Allocate face pointer array 180 // Allocate face pointer array 181 // 181 // 182 numFace = phiIsOpen ? numCorner+2 : numCorne 182 numFace = phiIsOpen ? numCorner+2 : numCorner; 183 faces = new G4VCSGface*[numFace]; 183 faces = new G4VCSGface*[numFace]; 184 184 185 // 185 // 186 // Construct conical faces 186 // Construct conical faces 187 // 187 // 188 // But! Don't construct a face if both point 188 // But! Don't construct a face if both points are at zero radius! 189 // 189 // 190 G4PolyconeSideRZ *corner = corners, 190 G4PolyconeSideRZ *corner = corners, 191 *prev = corners + numCorner 191 *prev = corners + numCorner-1, 192 *nextNext; 192 *nextNext; 193 G4VCSGface** face = faces; 193 G4VCSGface** face = faces; 194 do // Loop checking, 13.08.2015, G.Cosmo 194 do // Loop checking, 13.08.2015, G.Cosmo 195 { 195 { 196 next = corner+1; 196 next = corner+1; 197 if (next >= corners+numCorner) next = corn 197 if (next >= corners+numCorner) next = corners; 198 nextNext = next+1; 198 nextNext = next+1; 199 if (nextNext >= corners+numCorner) nextNex 199 if (nextNext >= corners+numCorner) nextNext = corners; 200 200 201 if (corner->r < 1/kInfinity && next->r < 1 201 if (corner->r < 1/kInfinity && next->r < 1/kInfinity) continue; 202 202 203 // 203 // 204 // We must decide here if we can dare decl 204 // We must decide here if we can dare declare one of our faces 205 // as having a "valid" normal (i.e. allBeh 205 // as having a "valid" normal (i.e. allBehind = true). This 206 // is never possible if the face faces "in 206 // is never possible if the face faces "inward" in r. 207 // 207 // 208 G4bool allBehind; 208 G4bool allBehind; 209 if (corner->z > next->z) 209 if (corner->z > next->z) 210 { 210 { 211 allBehind = false; 211 allBehind = false; 212 } 212 } 213 else 213 else 214 { 214 { 215 // 215 // 216 // Otherwise, it is only true if the lin 216 // Otherwise, it is only true if the line passing 217 // through the two points of the segment 217 // through the two points of the segment do not 218 // split the r/z cross section 218 // split the r/z cross section 219 // 219 // 220 allBehind = !rz->BisectedBy( corner->r, 220 allBehind = !rz->BisectedBy( corner->r, corner->z, 221 next->r, next->z, kCarToleran 221 next->r, next->z, kCarTolerance ); 222 } 222 } 223 223 224 *face++ = new G4PolyconeSide( prev, corner 224 *face++ = new G4PolyconeSide( prev, corner, next, nextNext, 225 startPhi, endPhi-startPhi, phi 225 startPhi, endPhi-startPhi, phiIsOpen, allBehind ); 226 } while( prev=corner, corner=next, corner > 226 } while( prev=corner, corner=next, corner > corners ); 227 227 228 if (phiIsOpen) 228 if (phiIsOpen) 229 { 229 { 230 // 230 // 231 // Construct phi open edges 231 // Construct phi open edges 232 // 232 // 233 *face++ = new G4PolyPhiFace( rz, startPhi, 233 *face++ = new G4PolyPhiFace( rz, startPhi, 0, endPhi ); 234 *face++ = new G4PolyPhiFace( rz, endPhi, 234 *face++ = new G4PolyPhiFace( rz, endPhi, 0, startPhi ); 235 } 235 } 236 236 237 // 237 // 238 // We might have dropped a face or two: reca 238 // We might have dropped a face or two: recalculate numFace 239 // 239 // 240 numFace = (G4int)(face-faces); 240 numFace = (G4int)(face-faces); 241 241 242 // 242 // 243 // Make enclosingCylinder 243 // Make enclosingCylinder 244 // 244 // 245 enclosingCylinder = 245 enclosingCylinder = 246 new G4EnclosingCylinder( rz, phiIsOpen, ph 246 new G4EnclosingCylinder( rz, phiIsOpen, phiStart, phiTotal ); 247 } 247 } 248 248 249 // Fake default constructor - sets only member 249 // Fake default constructor - sets only member data and allocates memory 250 // for usage restri 250 // for usage restricted to object persistency. 251 // 251 // 252 G4GenericPolycone::G4GenericPolycone( __void__ 252 G4GenericPolycone::G4GenericPolycone( __void__& a ) 253 : G4VCSGfaceted(a), startPhi(0.), endPhi(0.) 253 : G4VCSGfaceted(a), startPhi(0.), endPhi(0.), numCorner(0) 254 { 254 { 255 } 255 } 256 256 257 // Destructor 257 // Destructor 258 // 258 // 259 G4GenericPolycone::~G4GenericPolycone() 259 G4GenericPolycone::~G4GenericPolycone() 260 { 260 { 261 delete [] corners; 261 delete [] corners; 262 delete enclosingCylinder; 262 delete enclosingCylinder; 263 delete fElements; 263 delete fElements; 264 delete fpPolyhedron; 264 delete fpPolyhedron; 265 corners = nullptr; 265 corners = nullptr; 266 enclosingCylinder = nullptr; 266 enclosingCylinder = nullptr; 267 fElements = nullptr; 267 fElements = nullptr; 268 fpPolyhedron = nullptr; 268 fpPolyhedron = nullptr; 269 } 269 } 270 270 271 // Copy constructor 271 // Copy constructor 272 // 272 // 273 G4GenericPolycone::G4GenericPolycone( const G4 273 G4GenericPolycone::G4GenericPolycone( const G4GenericPolycone& source ) 274 : G4VCSGfaceted( source ) 274 : G4VCSGfaceted( source ) 275 { 275 { 276 CopyStuff( source ); 276 CopyStuff( source ); 277 } 277 } 278 278 279 // Assignment operator 279 // Assignment operator 280 // 280 // 281 G4GenericPolycone& 281 G4GenericPolycone& 282 G4GenericPolycone::operator=( const G4GenericP 282 G4GenericPolycone::operator=( const G4GenericPolycone& source ) 283 { 283 { 284 if (this == &source) return *this; 284 if (this == &source) return *this; 285 285 286 G4VCSGfaceted::operator=( source ); 286 G4VCSGfaceted::operator=( source ); 287 287 288 delete [] corners; 288 delete [] corners; 289 // if (original_parameters) delete original_ 289 // if (original_parameters) delete original_parameters; 290 290 291 delete enclosingCylinder; 291 delete enclosingCylinder; 292 292 293 CopyStuff( source ); 293 CopyStuff( source ); 294 294 295 return *this; 295 return *this; 296 } 296 } 297 297 298 // CopyStuff 298 // CopyStuff 299 // 299 // 300 void G4GenericPolycone::CopyStuff( const G4Gen 300 void G4GenericPolycone::CopyStuff( const G4GenericPolycone& source ) 301 { 301 { 302 // 302 // 303 // Simple stuff 303 // Simple stuff 304 // 304 // 305 startPhi = source.startPhi; 305 startPhi = source.startPhi; 306 endPhi = source.endPhi; 306 endPhi = source.endPhi; 307 phiIsOpen = source.phiIsOpen; 307 phiIsOpen = source.phiIsOpen; 308 numCorner = source.numCorner; 308 numCorner = source.numCorner; 309 309 310 // 310 // 311 // The corner array 311 // The corner array 312 // 312 // 313 corners = new G4PolyconeSideRZ[numCorner]; 313 corners = new G4PolyconeSideRZ[numCorner]; 314 314 315 G4PolyconeSideRZ *corn = corners, 315 G4PolyconeSideRZ *corn = corners, 316 *sourceCorn = source.corners; 316 *sourceCorn = source.corners; 317 do // Loop checking, 13.08.2015, G.Cosmo 317 do // Loop checking, 13.08.2015, G.Cosmo 318 { 318 { 319 *corn = *sourceCorn; 319 *corn = *sourceCorn; 320 } while( ++sourceCorn, ++corn < corners+numC 320 } while( ++sourceCorn, ++corn < corners+numCorner ); 321 321 322 // 322 // 323 // Enclosing cylinder 323 // Enclosing cylinder 324 // 324 // 325 enclosingCylinder = new G4EnclosingCylinder( 325 enclosingCylinder = new G4EnclosingCylinder( *source.enclosingCylinder ); 326 326 327 // 327 // 328 // Surface elements 328 // Surface elements 329 // 329 // 330 delete fElements; 330 delete fElements; 331 fElements = nullptr; 331 fElements = nullptr; 332 332 333 // Polyhedron 333 // Polyhedron 334 // 334 // 335 fRebuildPolyhedron = false; 335 fRebuildPolyhedron = false; 336 delete fpPolyhedron; 336 delete fpPolyhedron; 337 fpPolyhedron = nullptr; 337 fpPolyhedron = nullptr; 338 } 338 } 339 339 340 // Reset 340 // Reset 341 // 341 // 342 G4bool G4GenericPolycone::Reset() 342 G4bool G4GenericPolycone::Reset() 343 { 343 { 344 std::ostringstream message; 344 std::ostringstream message; 345 message << "Solid " << GetName() << " built 345 message << "Solid " << GetName() << " built using generic construct." 346 << G4endl << "Not applicable to the 346 << G4endl << "Not applicable to the generic construct !"; 347 G4Exception("G4GenericPolycone::Reset()", "G 347 G4Exception("G4GenericPolycone::Reset()", "GeomSolids1001", 348 JustWarning, message, "Parameter 348 JustWarning, message, "Parameters NOT resetted."); 349 return true; 349 return true; 350 } 350 } 351 351 352 // Inside 352 // Inside 353 // 353 // 354 // This is an override of G4VCSGfaceted::Insid 354 // This is an override of G4VCSGfaceted::Inside, created in order 355 // to speed things up by first checking with G 355 // to speed things up by first checking with G4EnclosingCylinder. 356 // 356 // 357 EInside G4GenericPolycone::Inside( const G4Thr 357 EInside G4GenericPolycone::Inside( const G4ThreeVector& p ) const 358 { 358 { 359 // 359 // 360 // Quick test 360 // Quick test 361 // 361 // 362 if (enclosingCylinder->MustBeOutside(p)) ret 362 if (enclosingCylinder->MustBeOutside(p)) return kOutside; 363 363 364 // 364 // 365 // Long answer 365 // Long answer 366 // 366 // 367 return G4VCSGfaceted::Inside(p); 367 return G4VCSGfaceted::Inside(p); 368 } 368 } 369 369 370 // DistanceToIn 370 // DistanceToIn 371 // 371 // 372 // This is an override of G4VCSGfaceted::Insid 372 // This is an override of G4VCSGfaceted::Inside, created in order 373 // to speed things up by first checking with G 373 // to speed things up by first checking with G4EnclosingCylinder. 374 // 374 // 375 G4double G4GenericPolycone::DistanceToIn( cons 375 G4double G4GenericPolycone::DistanceToIn( const G4ThreeVector& p, 376 cons 376 const G4ThreeVector& v ) const 377 { 377 { 378 // 378 // 379 // Quick test 379 // Quick test 380 // 380 // 381 if (enclosingCylinder->ShouldMiss(p,v)) 381 if (enclosingCylinder->ShouldMiss(p,v)) 382 return kInfinity; 382 return kInfinity; 383 383 384 // 384 // 385 // Long answer 385 // Long answer 386 // 386 // 387 return G4VCSGfaceted::DistanceToIn( p, v ); 387 return G4VCSGfaceted::DistanceToIn( p, v ); 388 } 388 } 389 389 390 // DistanceToIn 390 // DistanceToIn 391 // 391 // 392 G4double G4GenericPolycone::DistanceToIn( cons 392 G4double G4GenericPolycone::DistanceToIn( const G4ThreeVector& p ) const 393 { 393 { 394 return G4VCSGfaceted::DistanceToIn(p); 394 return G4VCSGfaceted::DistanceToIn(p); 395 } 395 } 396 396 397 // BoundingLimits 397 // BoundingLimits 398 // 398 // 399 // Get bounding box 399 // Get bounding box 400 // 400 // 401 void 401 void 402 G4GenericPolycone::BoundingLimits(G4ThreeVecto 402 G4GenericPolycone::BoundingLimits(G4ThreeVector& pMin, 403 G4ThreeVecto 403 G4ThreeVector& pMax) const 404 { 404 { 405 G4double rmin = kInfinity, rmax = -kInfinity 405 G4double rmin = kInfinity, rmax = -kInfinity; 406 G4double zmin = kInfinity, zmax = -kInfinity 406 G4double zmin = kInfinity, zmax = -kInfinity; 407 407 408 for (G4int i=0; i<GetNumRZCorner(); ++i) 408 for (G4int i=0; i<GetNumRZCorner(); ++i) 409 { 409 { 410 G4PolyconeSideRZ corner = GetCorner(i); 410 G4PolyconeSideRZ corner = GetCorner(i); 411 if (corner.r < rmin) rmin = corner.r; 411 if (corner.r < rmin) rmin = corner.r; 412 if (corner.r > rmax) rmax = corner.r; 412 if (corner.r > rmax) rmax = corner.r; 413 if (corner.z < zmin) zmin = corner.z; 413 if (corner.z < zmin) zmin = corner.z; 414 if (corner.z > zmax) zmax = corner.z; 414 if (corner.z > zmax) zmax = corner.z; 415 } 415 } 416 416 417 if (IsOpen()) 417 if (IsOpen()) 418 { 418 { 419 G4TwoVector vmin,vmax; 419 G4TwoVector vmin,vmax; 420 G4GeomTools::DiskExtent(rmin,rmax, 420 G4GeomTools::DiskExtent(rmin,rmax, 421 GetSinStartPhi(),G 421 GetSinStartPhi(),GetCosStartPhi(), 422 GetSinEndPhi(),Get 422 GetSinEndPhi(),GetCosEndPhi(), 423 vmin,vmax); 423 vmin,vmax); 424 pMin.set(vmin.x(),vmin.y(),zmin); 424 pMin.set(vmin.x(),vmin.y(),zmin); 425 pMax.set(vmax.x(),vmax.y(),zmax); 425 pMax.set(vmax.x(),vmax.y(),zmax); 426 } 426 } 427 else 427 else 428 { 428 { 429 pMin.set(-rmax,-rmax, zmin); 429 pMin.set(-rmax,-rmax, zmin); 430 pMax.set( rmax, rmax, zmax); 430 pMax.set( rmax, rmax, zmax); 431 } 431 } 432 432 433 // Check correctness of the bounding box 433 // Check correctness of the bounding box 434 // 434 // 435 if (pMin.x() >= pMax.x() || pMin.y() >= pMax 435 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z()) 436 { 436 { 437 std::ostringstream message; 437 std::ostringstream message; 438 message << "Bad bounding box (min >= max) 438 message << "Bad bounding box (min >= max) for solid: " 439 << GetName() << " !" 439 << GetName() << " !" 440 << "\npMin = " << pMin 440 << "\npMin = " << pMin 441 << "\npMax = " << pMax; 441 << "\npMax = " << pMax; 442 G4Exception("GenericG4Polycone::BoundingLi 442 G4Exception("GenericG4Polycone::BoundingLimits()", "GeomMgt0001", 443 JustWarning, message); 443 JustWarning, message); 444 DumpInfo(); 444 DumpInfo(); 445 } 445 } 446 } 446 } 447 447 448 // CalculateExtent 448 // CalculateExtent 449 // 449 // 450 // Calculate extent under transform and specif 450 // Calculate extent under transform and specified limit 451 // 451 // 452 G4bool 452 G4bool 453 G4GenericPolycone::CalculateExtent(const EAxis 453 G4GenericPolycone::CalculateExtent(const EAxis pAxis, 454 const G4Vox 454 const G4VoxelLimits& pVoxelLimit, 455 const G4Aff 455 const G4AffineTransform& pTransform, 456 G4dou 456 G4double& pMin, G4double& pMax) const 457 { 457 { 458 G4ThreeVector bmin, bmax; 458 G4ThreeVector bmin, bmax; 459 G4bool exist; 459 G4bool exist; 460 460 461 // Check bounding box (bbox) 461 // Check bounding box (bbox) 462 // 462 // 463 BoundingLimits(bmin,bmax); 463 BoundingLimits(bmin,bmax); 464 G4BoundingEnvelope bbox(bmin,bmax); 464 G4BoundingEnvelope bbox(bmin,bmax); 465 #ifdef G4BBOX_EXTENT 465 #ifdef G4BBOX_EXTENT 466 return bbox.CalculateExtent(pAxis,pVoxelLimi 466 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax); 467 #endif 467 #endif 468 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox 468 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax)) 469 { 469 { 470 return exist = pMin < pMax; << 470 return exist = (pMin < pMax) ? true : false; 471 } 471 } 472 472 473 // To find the extent, RZ contour of the pol 473 // To find the extent, RZ contour of the polycone is subdivided 474 // in triangles. The extent is calculated as 474 // in triangles. The extent is calculated as cumulative extent of 475 // all sub-polycones formed by rotation of t 475 // all sub-polycones formed by rotation of triangles around Z 476 // 476 // 477 G4TwoVectorList contourRZ; 477 G4TwoVectorList contourRZ; 478 G4TwoVectorList triangles; 478 G4TwoVectorList triangles; 479 G4double eminlim = pVoxelLimit.GetMinExtent( 479 G4double eminlim = pVoxelLimit.GetMinExtent(pAxis); 480 G4double emaxlim = pVoxelLimit.GetMaxExtent( 480 G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis); 481 481 482 // get RZ contour, ensure anticlockwise orde 482 // get RZ contour, ensure anticlockwise order of corners 483 for (G4int i=0; i<GetNumRZCorner(); ++i) 483 for (G4int i=0; i<GetNumRZCorner(); ++i) 484 { 484 { 485 G4PolyconeSideRZ corner = GetCorner(i); 485 G4PolyconeSideRZ corner = GetCorner(i); 486 contourRZ.emplace_back(corner.r,corner.z); << 486 contourRZ.push_back(G4TwoVector(corner.r,corner.z)); 487 } 487 } 488 G4double area = G4GeomTools::PolygonArea(con 488 G4double area = G4GeomTools::PolygonArea(contourRZ); 489 if (area < 0.) std::reverse(contourRZ.begin( 489 if (area < 0.) std::reverse(contourRZ.begin(),contourRZ.end()); 490 490 491 // triangulate RZ countour 491 // triangulate RZ countour 492 if (!G4GeomTools::TriangulatePolygon(contour 492 if (!G4GeomTools::TriangulatePolygon(contourRZ,triangles)) 493 { 493 { 494 std::ostringstream message; 494 std::ostringstream message; 495 message << "Triangulation of RZ contour ha 495 message << "Triangulation of RZ contour has failed for solid: " 496 << GetName() << " !" 496 << GetName() << " !" 497 << "\nExtent has been calculated u 497 << "\nExtent has been calculated using boundary box"; 498 G4Exception("G4GenericPolycone::CalculateE 498 G4Exception("G4GenericPolycone::CalculateExtent()", 499 "GeomMgt1002", JustWarning, me 499 "GeomMgt1002", JustWarning, message); 500 return bbox.CalculateExtent(pAxis,pVoxelLi 500 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax); 501 } 501 } 502 502 503 // set trigonometric values 503 // set trigonometric values 504 const G4int NSTEPS = 24; // numbe 504 const G4int NSTEPS = 24; // number of steps for whole circle 505 G4double astep = twopi/NSTEPS; // max a 505 G4double astep = twopi/NSTEPS; // max angle for one step 506 506 507 G4double sphi = GetStartPhi(); 507 G4double sphi = GetStartPhi(); 508 G4double ephi = GetEndPhi(); 508 G4double ephi = GetEndPhi(); 509 G4double dphi = IsOpen() ? ephi-sphi : two 509 G4double dphi = IsOpen() ? ephi-sphi : twopi; 510 G4int ksteps = (dphi <= astep) ? 1 : (G4i 510 G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1; 511 G4double ang = dphi/ksteps; 511 G4double ang = dphi/ksteps; 512 512 513 G4double sinHalf = std::sin(0.5*ang); 513 G4double sinHalf = std::sin(0.5*ang); 514 G4double cosHalf = std::cos(0.5*ang); 514 G4double cosHalf = std::cos(0.5*ang); 515 G4double sinStep = 2.*sinHalf*cosHalf; 515 G4double sinStep = 2.*sinHalf*cosHalf; 516 G4double cosStep = 1. - 2.*sinHalf*sinHalf; 516 G4double cosStep = 1. - 2.*sinHalf*sinHalf; 517 517 518 G4double sinStart = GetSinStartPhi(); 518 G4double sinStart = GetSinStartPhi(); 519 G4double cosStart = GetCosStartPhi(); 519 G4double cosStart = GetCosStartPhi(); 520 G4double sinEnd = GetSinEndPhi(); 520 G4double sinEnd = GetSinEndPhi(); 521 G4double cosEnd = GetCosEndPhi(); 521 G4double cosEnd = GetCosEndPhi(); 522 522 523 // define vectors and arrays 523 // define vectors and arrays 524 std::vector<const G4ThreeVectorList *> polyg 524 std::vector<const G4ThreeVectorList *> polygons; 525 polygons.resize(ksteps+2); 525 polygons.resize(ksteps+2); 526 G4ThreeVectorList pols[NSTEPS+2]; 526 G4ThreeVectorList pols[NSTEPS+2]; 527 for (G4int k=0; k<ksteps+2; ++k) pols[k].res 527 for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(6); 528 for (G4int k=0; k<ksteps+2; ++k) polygons[k] 528 for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k]; 529 G4double r0[6],z0[6]; // contour with origin 529 G4double r0[6],z0[6]; // contour with original edges of triangle 530 G4double r1[6]; // shifted radii of ex 530 G4double r1[6]; // shifted radii of external edges of triangle 531 531 532 // main loop along triangles 532 // main loop along triangles 533 pMin = kInfinity; 533 pMin = kInfinity; 534 pMax =-kInfinity; 534 pMax =-kInfinity; 535 G4int ntria = (G4int)triangles.size()/3; 535 G4int ntria = (G4int)triangles.size()/3; 536 for (G4int i=0; i<ntria; ++i) 536 for (G4int i=0; i<ntria; ++i) 537 { 537 { 538 G4int i3 = i*3; 538 G4int i3 = i*3; 539 for (G4int k=0; k<3; ++k) 539 for (G4int k=0; k<3; ++k) 540 { 540 { 541 G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3; 541 G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3; 542 G4int k2 = k*2; 542 G4int k2 = k*2; 543 // set contour with original edges of tr 543 // set contour with original edges of triangle 544 r0[k2+0] = triangles[e0].x(); z0[k2+0] = 544 r0[k2+0] = triangles[e0].x(); z0[k2+0] = triangles[e0].y(); 545 r0[k2+1] = triangles[e1].x(); z0[k2+1] = 545 r0[k2+1] = triangles[e1].x(); z0[k2+1] = triangles[e1].y(); 546 // set shifted radii 546 // set shifted radii 547 r1[k2+0] = r0[k2+0]; 547 r1[k2+0] = r0[k2+0]; 548 r1[k2+1] = r0[k2+1]; 548 r1[k2+1] = r0[k2+1]; 549 if (z0[k2+1] - z0[k2+0] <= 0) continue; 549 if (z0[k2+1] - z0[k2+0] <= 0) continue; 550 r1[k2+0] /= cosHalf; 550 r1[k2+0] /= cosHalf; 551 r1[k2+1] /= cosHalf; 551 r1[k2+1] /= cosHalf; 552 } 552 } 553 553 554 // rotate countour, set sequence of 6-side 554 // rotate countour, set sequence of 6-sided polygons 555 G4double sinCur = sinStart*cosHalf + cosSt 555 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf; 556 G4double cosCur = cosStart*cosHalf - sinSt 556 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf; 557 for (G4int j=0; j<6; ++j) 557 for (G4int j=0; j<6; ++j) 558 { 558 { 559 pols[0][j].set(r0[j]*cosStart,r0[j]*sinS 559 pols[0][j].set(r0[j]*cosStart,r0[j]*sinStart,z0[j]); 560 } 560 } 561 for (G4int k=1; k<ksteps+1; ++k) 561 for (G4int k=1; k<ksteps+1; ++k) 562 { 562 { 563 for (G4int j=0; j<6; ++j) 563 for (G4int j=0; j<6; ++j) 564 { 564 { 565 pols[k][j].set(r1[j]*cosCur,r1[j]*sinC 565 pols[k][j].set(r1[j]*cosCur,r1[j]*sinCur,z0[j]); 566 } 566 } 567 G4double sinTmp = sinCur; 567 G4double sinTmp = sinCur; 568 sinCur = sinCur*cosStep + cosCur*sinStep 568 sinCur = sinCur*cosStep + cosCur*sinStep; 569 cosCur = cosCur*cosStep - sinTmp*sinStep 569 cosCur = cosCur*cosStep - sinTmp*sinStep; 570 } 570 } 571 for (G4int j=0; j<6; ++j) 571 for (G4int j=0; j<6; ++j) 572 { 572 { 573 pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j] 573 pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j]*sinEnd,z0[j]); 574 } 574 } 575 575 576 // set sub-envelope and adjust extent 576 // set sub-envelope and adjust extent 577 G4double emin,emax; 577 G4double emin,emax; 578 G4BoundingEnvelope benv(polygons); 578 G4BoundingEnvelope benv(polygons); 579 if (!benv.CalculateExtent(pAxis,pVoxelLimi 579 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue; 580 if (emin < pMin) pMin = emin; 580 if (emin < pMin) pMin = emin; 581 if (emax > pMax) pMax = emax; 581 if (emax > pMax) pMax = emax; 582 if (eminlim > pMin && emaxlim < pMax) retu 582 if (eminlim > pMin && emaxlim < pMax) return true; // max possible extent 583 } 583 } 584 return (pMin < pMax); 584 return (pMin < pMax); 585 } 585 } 586 586 587 // GetEntityType 587 // GetEntityType 588 // 588 // 589 G4GeometryType G4GenericPolycone::GetEntityTy 589 G4GeometryType G4GenericPolycone::GetEntityType() const 590 { 590 { 591 return {"G4GenericPolycone"}; << 591 return G4String("G4GenericPolycone"); 592 } 592 } 593 593 594 // Clone 594 // Clone 595 // 595 // 596 // Make a clone of the object 596 // Make a clone of the object 597 // 597 // 598 G4VSolid* G4GenericPolycone::Clone() const 598 G4VSolid* G4GenericPolycone::Clone() const 599 { 599 { 600 return new G4GenericPolycone(*this); 600 return new G4GenericPolycone(*this); 601 } 601 } 602 602 603 // StreamInfo 603 // StreamInfo 604 // 604 // 605 // Stream object contents to an output stream 605 // Stream object contents to an output stream 606 // 606 // 607 std::ostream& G4GenericPolycone::StreamInfo( s 607 std::ostream& G4GenericPolycone::StreamInfo( std::ostream& os ) const 608 { 608 { 609 G4long oldprc = os.precision(16); 609 G4long oldprc = os.precision(16); 610 os << "------------------------------------- 610 os << "-----------------------------------------------------------\n" 611 << " *** Dump for solid - " << GetName 611 << " *** Dump for solid - " << GetName() << " ***\n" 612 << " ================================= 612 << " ===================================================\n" 613 << " Solid type: G4GenericPolycone\n" 613 << " Solid type: G4GenericPolycone\n" 614 << " Parameters: \n" 614 << " Parameters: \n" 615 << " starting phi angle : " << startPh 615 << " starting phi angle : " << startPhi/degree << " degrees \n" 616 << " ending phi angle : " << endPhi/ 616 << " ending phi angle : " << endPhi/degree << " degrees \n"; 617 G4int i=0; 617 G4int i=0; 618 618 619 os << " number of RZ points: " << numCorn 619 os << " number of RZ points: " << numCorner << "\n" 620 << " RZ values (corners): \n 620 << " RZ values (corners): \n"; 621 for (i=0; i<numCorner; i++) 621 for (i=0; i<numCorner; i++) 622 { 622 { 623 os << " " 623 os << " " 624 << corners[i].r << ", " << corners[i 624 << corners[i].r << ", " << corners[i].z << "\n"; 625 } 625 } 626 os << "------------------------------------- 626 os << "-----------------------------------------------------------\n"; 627 os.precision(oldprc); 627 os.precision(oldprc); 628 628 629 return os; 629 return os; 630 } 630 } 631 631 632 ////////////////////////////////////////////// 632 ////////////////////////////////////////////////////////////////////////// 633 // 633 // 634 // Return volume 634 // Return volume 635 635 636 G4double G4GenericPolycone::GetCubicVolume() 636 G4double G4GenericPolycone::GetCubicVolume() 637 { 637 { 638 if (fCubicVolume == 0.) 638 if (fCubicVolume == 0.) 639 { 639 { 640 G4double total = 0.; 640 G4double total = 0.; 641 G4int nrz = GetNumRZCorner(); 641 G4int nrz = GetNumRZCorner(); 642 G4PolyconeSideRZ a = GetCorner(nrz - 1); 642 G4PolyconeSideRZ a = GetCorner(nrz - 1); 643 for (G4int i=0; i<nrz; ++i) 643 for (G4int i=0; i<nrz; ++i) 644 { 644 { 645 G4PolyconeSideRZ b = GetCorner(i); 645 G4PolyconeSideRZ b = GetCorner(i); 646 total += (b.r*b.r + b.r*a.r + a.r*a.r)*( 646 total += (b.r*b.r + b.r*a.r + a.r*a.r)*(b.z - a.z); 647 a = b; 647 a = b; 648 } 648 } 649 fCubicVolume = std::abs(total)*(GetEndPhi( 649 fCubicVolume = std::abs(total)*(GetEndPhi() - GetStartPhi())/6.; 650 } 650 } 651 return fCubicVolume; 651 return fCubicVolume; 652 } 652 } 653 653 654 ////////////////////////////////////////////// 654 ////////////////////////////////////////////////////////////////////////// 655 // 655 // 656 // Return surface area 656 // Return surface area 657 657 658 G4double G4GenericPolycone::GetSurfaceArea() 658 G4double G4GenericPolycone::GetSurfaceArea() 659 { 659 { 660 if (fSurfaceArea == 0.) 660 if (fSurfaceArea == 0.) 661 { 661 { 662 // phi cut area 662 // phi cut area 663 G4int nrz = GetNumRZCorner(); 663 G4int nrz = GetNumRZCorner(); 664 G4double scut = 0.; 664 G4double scut = 0.; 665 if (IsOpen()) 665 if (IsOpen()) 666 { 666 { 667 G4PolyconeSideRZ a = GetCorner(nrz - 1); 667 G4PolyconeSideRZ a = GetCorner(nrz - 1); 668 for (G4int i=0; i<nrz; ++i) 668 for (G4int i=0; i<nrz; ++i) 669 { 669 { 670 G4PolyconeSideRZ b = GetCorner(i); 670 G4PolyconeSideRZ b = GetCorner(i); 671 scut += a.r*b.z - a.z*b.r; 671 scut += a.r*b.z - a.z*b.r; 672 a = b; 672 a = b; 673 } 673 } 674 scut = std::abs(scut); 674 scut = std::abs(scut); 675 } 675 } 676 // lateral surface area 676 // lateral surface area 677 G4double slat = 0; 677 G4double slat = 0; 678 G4PolyconeSideRZ a = GetCorner(nrz - 1); 678 G4PolyconeSideRZ a = GetCorner(nrz - 1); 679 for (G4int i=0; i<nrz; ++i) 679 for (G4int i=0; i<nrz; ++i) 680 { 680 { 681 G4PolyconeSideRZ b = GetCorner(i); 681 G4PolyconeSideRZ b = GetCorner(i); 682 G4double h = std::sqrt((b.r - a.r)*(b.r 682 G4double h = std::sqrt((b.r - a.r)*(b.r - a.r) + (b.z - a.z)*(b.z - a.z)); 683 slat += (b.r + a.r)*h; 683 slat += (b.r + a.r)*h; 684 a = b; 684 a = b; 685 } 685 } 686 slat *= (GetEndPhi() - GetStartPhi())/2.; 686 slat *= (GetEndPhi() - GetStartPhi())/2.; 687 fSurfaceArea = scut + slat; 687 fSurfaceArea = scut + slat; 688 } 688 } 689 return fSurfaceArea; 689 return fSurfaceArea; 690 } 690 } 691 691 692 ////////////////////////////////////////////// 692 ////////////////////////////////////////////////////////////////////////// 693 // 693 // 694 // Set vector of surface elements, auxiliary m 694 // Set vector of surface elements, auxiliary method for sampling 695 // random points on surface 695 // random points on surface 696 696 697 void G4GenericPolycone::SetSurfaceElements() c 697 void G4GenericPolycone::SetSurfaceElements() const 698 { 698 { 699 fElements = new std::vector<G4GenericPolycon 699 fElements = new std::vector<G4GenericPolycone::surface_element>; 700 G4double sarea = 0.; 700 G4double sarea = 0.; 701 G4int nrz = GetNumRZCorner(); 701 G4int nrz = GetNumRZCorner(); 702 702 703 // set lateral surface elements 703 // set lateral surface elements 704 G4double dphi = GetEndPhi() - GetStartPhi(); 704 G4double dphi = GetEndPhi() - GetStartPhi(); 705 G4int ia = nrz - 1; 705 G4int ia = nrz - 1; 706 for (G4int ib=0; ib<nrz; ++ib) 706 for (G4int ib=0; ib<nrz; ++ib) 707 { 707 { 708 G4PolyconeSideRZ a = GetCorner(ia); 708 G4PolyconeSideRZ a = GetCorner(ia); 709 G4PolyconeSideRZ b = GetCorner(ib); 709 G4PolyconeSideRZ b = GetCorner(ib); 710 G4GenericPolycone::surface_element selem; 710 G4GenericPolycone::surface_element selem; 711 selem.i0 = ia; 711 selem.i0 = ia; 712 selem.i1 = ib; 712 selem.i1 = ib; 713 selem.i2 = -1; 713 selem.i2 = -1; 714 ia = ib; 714 ia = ib; 715 if (a.r == 0. && b.r == 0.) continue; 715 if (a.r == 0. && b.r == 0.) continue; 716 G4double h = std::sqrt((b.r - a.r)*(b.r - 716 G4double h = std::sqrt((b.r - a.r)*(b.r - a.r) + (b.z - a.z)*(b.z - a.z)); 717 sarea += 0.5*dphi*(b.r + a.r)*h; 717 sarea += 0.5*dphi*(b.r + a.r)*h; 718 selem.area = sarea; 718 selem.area = sarea; 719 fElements->push_back(selem); 719 fElements->push_back(selem); 720 } 720 } 721 721 722 // set elements for phi cuts 722 // set elements for phi cuts 723 if (IsOpen()) 723 if (IsOpen()) 724 { 724 { 725 G4TwoVectorList contourRZ; 725 G4TwoVectorList contourRZ; 726 std::vector<G4int> triangles; 726 std::vector<G4int> triangles; 727 for (G4int i=0; i<nrz; ++i) 727 for (G4int i=0; i<nrz; ++i) 728 { 728 { 729 G4PolyconeSideRZ corner = GetCorner(i); 729 G4PolyconeSideRZ corner = GetCorner(i); 730 contourRZ.emplace_back(corner.r, corner. << 730 contourRZ.push_back(G4TwoVector(corner.r, corner.z)); 731 } 731 } 732 G4GeomTools::TriangulatePolygon(contourRZ, 732 G4GeomTools::TriangulatePolygon(contourRZ, triangles); 733 auto ntria = (G4int)triangles.size(); << 733 G4int ntria = (G4int)triangles.size(); 734 for (G4int i=0; i<ntria; i+=3) 734 for (G4int i=0; i<ntria; i+=3) 735 { 735 { 736 G4GenericPolycone::surface_element selem 736 G4GenericPolycone::surface_element selem; 737 selem.i0 = triangles[i]; 737 selem.i0 = triangles[i]; 738 selem.i1 = triangles[i+1]; 738 selem.i1 = triangles[i+1]; 739 selem.i2 = triangles[i+2]; 739 selem.i2 = triangles[i+2]; 740 G4PolyconeSideRZ a = GetCorner(selem.i0) 740 G4PolyconeSideRZ a = GetCorner(selem.i0); 741 G4PolyconeSideRZ b = GetCorner(selem.i1) 741 G4PolyconeSideRZ b = GetCorner(selem.i1); 742 G4PolyconeSideRZ c = GetCorner(selem.i2) 742 G4PolyconeSideRZ c = GetCorner(selem.i2); 743 G4double stria = 743 G4double stria = 744 std::abs(G4GeomTools::TriangleArea(a.r 744 std::abs(G4GeomTools::TriangleArea(a.r, a.z, b.r, b.z, c.r, c.z)); 745 sarea += stria; 745 sarea += stria; 746 selem.area = sarea; 746 selem.area = sarea; 747 fElements->push_back(selem); // start ph 747 fElements->push_back(selem); // start phi 748 sarea += stria; 748 sarea += stria; 749 selem.area = sarea; 749 selem.area = sarea; 750 selem.i0 += nrz; 750 selem.i0 += nrz; 751 fElements->push_back(selem); // end phi 751 fElements->push_back(selem); // end phi 752 } 752 } 753 } 753 } 754 } 754 } 755 755 756 ////////////////////////////////////////////// 756 ////////////////////////////////////////////////////////////////////////// 757 // 757 // 758 // Generate random point on surface 758 // Generate random point on surface 759 759 760 G4ThreeVector G4GenericPolycone::GetPointOnSur 760 G4ThreeVector G4GenericPolycone::GetPointOnSurface() const 761 { 761 { 762 // Set surface elements 762 // Set surface elements 763 if (fElements == nullptr) << 763 if (!fElements) 764 { 764 { 765 G4AutoLock l(&surface_elementsMutex); 765 G4AutoLock l(&surface_elementsMutex); 766 SetSurfaceElements(); 766 SetSurfaceElements(); 767 l.unlock(); 767 l.unlock(); 768 } 768 } 769 769 770 // Select surface element 770 // Select surface element 771 G4GenericPolycone::surface_element selem; 771 G4GenericPolycone::surface_element selem; 772 selem = fElements->back(); 772 selem = fElements->back(); 773 G4double select = selem.area*G4QuickRand(); 773 G4double select = selem.area*G4QuickRand(); 774 auto it = std::lower_bound(fElements->begin( 774 auto it = std::lower_bound(fElements->begin(), fElements->end(), select, 775 [](const G4Generi 775 [](const G4GenericPolycone::surface_element& x, G4double val) 776 -> G4bool { retur 776 -> G4bool { return x.area < val; }); 777 777 778 // Generate random point 778 // Generate random point 779 G4double r = 0, z = 0, phi = 0; 779 G4double r = 0, z = 0, phi = 0; 780 G4double u = G4QuickRand(); 780 G4double u = G4QuickRand(); 781 G4double v = G4QuickRand(); 781 G4double v = G4QuickRand(); 782 G4int i0 = (*it).i0; 782 G4int i0 = (*it).i0; 783 G4int i1 = (*it).i1; 783 G4int i1 = (*it).i1; 784 G4int i2 = (*it).i2; 784 G4int i2 = (*it).i2; 785 if (i2 < 0) // lateral surface 785 if (i2 < 0) // lateral surface 786 { 786 { 787 G4PolyconeSideRZ p0 = GetCorner(i0); 787 G4PolyconeSideRZ p0 = GetCorner(i0); 788 G4PolyconeSideRZ p1 = GetCorner(i1); 788 G4PolyconeSideRZ p1 = GetCorner(i1); 789 if (p1.r < p0.r) 789 if (p1.r < p0.r) 790 { 790 { 791 p0 = GetCorner(i1); 791 p0 = GetCorner(i1); 792 p1 = GetCorner(i0); 792 p1 = GetCorner(i0); 793 } 793 } 794 if (p1.r - p0.r < kCarTolerance) // cylind 794 if (p1.r - p0.r < kCarTolerance) // cylindrical surface 795 { 795 { 796 r = (p1.r - p0.r)*u + p0.r; 796 r = (p1.r - p0.r)*u + p0.r; 797 z = (p1.z - p0.z)*u + p0.z; 797 z = (p1.z - p0.z)*u + p0.z; 798 } 798 } 799 else // conical surface 799 else // conical surface 800 { 800 { 801 r = std::sqrt(p1.r*p1.r*u + p0.r*p0.r*(1 801 r = std::sqrt(p1.r*p1.r*u + p0.r*p0.r*(1. - u)); 802 z = p0.z + (p1.z - p0.z)*(r - p0.r)/(p1. 802 z = p0.z + (p1.z - p0.z)*(r - p0.r)/(p1.r - p0.r); 803 } 803 } 804 phi = (GetEndPhi() - GetStartPhi())*v + Ge 804 phi = (GetEndPhi() - GetStartPhi())*v + GetStartPhi(); 805 } 805 } 806 else // phi cut 806 else // phi cut 807 { 807 { 808 G4int nrz = GetNumRZCorner(); 808 G4int nrz = GetNumRZCorner(); 809 phi = (i0 < nrz) ? GetStartPhi() : GetEndP 809 phi = (i0 < nrz) ? GetStartPhi() : GetEndPhi(); 810 if (i0 >= nrz) { i0 -= nrz; } 810 if (i0 >= nrz) { i0 -= nrz; } 811 G4PolyconeSideRZ p0 = GetCorner(i0); 811 G4PolyconeSideRZ p0 = GetCorner(i0); 812 G4PolyconeSideRZ p1 = GetCorner(i1); 812 G4PolyconeSideRZ p1 = GetCorner(i1); 813 G4PolyconeSideRZ p2 = GetCorner(i2); 813 G4PolyconeSideRZ p2 = GetCorner(i2); 814 if (u + v > 1.) { u = 1. - u; v = 1. - v; 814 if (u + v > 1.) { u = 1. - u; v = 1. - v; } 815 r = (p1.r - p0.r)*u + (p2.r - p0.r)*v + p 815 r = (p1.r - p0.r)*u + (p2.r - p0.r)*v + p0.r; 816 z = (p1.z - p0.z)*u + (p2.z - p0.z)*v + p 816 z = (p1.z - p0.z)*u + (p2.z - p0.z)*v + p0.z; 817 } 817 } 818 return {r*std::cos(phi), r*std::sin(phi), z} << 818 return G4ThreeVector(r*std::cos(phi), r*std::sin(phi), z); 819 } 819 } 820 820 821 ////////////////////////////////////////////// 821 ////////////////////////////////////////////////////////////////////////// 822 // 822 // 823 // CreatePolyhedron 823 // CreatePolyhedron 824 824 825 G4Polyhedron* G4GenericPolycone::CreatePolyhed 825 G4Polyhedron* G4GenericPolycone::CreatePolyhedron() const 826 { 826 { 827 std::vector<G4TwoVector> rz(numCorner); 827 std::vector<G4TwoVector> rz(numCorner); 828 for (G4int i = 0; i < numCorner; ++i) 828 for (G4int i = 0; i < numCorner; ++i) 829 rz[i].set(corners[i].r, corners[i].z); 829 rz[i].set(corners[i].r, corners[i].z); 830 return new G4PolyhedronPcon(startPhi, endPhi 830 return new G4PolyhedronPcon(startPhi, endPhi - startPhi, rz); 831 } 831 } 832 832 833 #endif 833 #endif 834 834