Geant4 Cross Reference |
1 // 1 2 // ******************************************* 3 // * License and Disclaimer 4 // * 5 // * The Geant4 software is copyright of th 6 // * the Geant4 Collaboration. It is provided 7 // * conditions of the Geant4 Software License 8 // * LICENSE and available at http://cern.ch/ 9 // * include a list of copyright holders. 10 // * 11 // * Neither the authors of this software syst 12 // * institutes,nor the agencies providing fin 13 // * work make any representation or warran 14 // * regarding this software system or assum 15 // * use. Please see the license in the file 16 // * for the full disclaimer and the limitatio 17 // * 18 // * This code implementation is the result 19 // * technical work of the GEANT4 collaboratio 20 // * By using, copying, modifying or distri 21 // * any work based on the software) you ag 22 // * use in resulting scientific publicati 23 // * acceptance of all terms of the Geant4 Sof 24 // ******************************************* 25 // 26 // Implementation of G4UPolycone wrapper class 27 // 28 // 31.10.13 G.Cosmo, CERN 29 // ------------------------------------------- 30 31 #include "G4Polycone.hh" 32 #include "G4UPolycone.hh" 33 34 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G 35 36 #include "G4GeomTools.hh" 37 #include "G4AffineTransform.hh" 38 #include "G4VPVParameterisation.hh" 39 #include "G4BoundingEnvelope.hh" 40 41 using namespace CLHEP; 42 43 ////////////////////////////////////////////// 44 // 45 // Constructor (GEANT3 style parameters) 46 // 47 G4UPolycone::G4UPolycone( const G4String& name 48 G4double phiStar 49 G4double phiTota 50 G4int numZPlanes 51 const G4double zPlane[ 52 const G4double rInner[ 53 const G4double rOuter[ 54 : Base_t(name, phiStart, phiTotal, numZPlane 55 { 56 fGenericPcon = false; 57 SetOriginalParameters(); 58 wrStart = phiStart; 59 while (wrStart < 0) 60 { 61 wrStart += twopi; 62 } 63 wrDelta = phiTotal; 64 if (wrDelta <= 0 || wrDelta >= twopi*(1-DBL_ 65 { 66 wrStart = 0; 67 wrDelta = twopi; 68 } 69 rzcorners.resize(0); 70 for (G4int i=0; i<numZPlanes; ++i) 71 { 72 G4double z = zPlane[i]; 73 G4double r = rOuter[i]; 74 rzcorners.emplace_back(r,z); 75 } 76 for (G4int i=numZPlanes-1; i>=0; --i) 77 { 78 G4double z = zPlane[i]; 79 G4double r = rInner[i]; 80 rzcorners.emplace_back(r,z); 81 } 82 std::vector<G4int> iout; 83 G4GeomTools::RemoveRedundantVertices(rzcorne 84 } 85 86 87 ////////////////////////////////////////////// 88 // 89 // Constructor (generic parameters) 90 // 91 G4UPolycone::G4UPolycone(const G4String& name, 92 G4double phiSta 93 G4double phiTot 94 G4int numRZ, 95 const G4double r[], 96 const G4double z[] 97 : Base_t(name, phiStart, phiTotal, numRZ, r, 98 { 99 fGenericPcon = true; 100 SetOriginalParameters(); 101 wrStart = phiStart; while (wrStart < 0) wrSt 102 wrDelta = phiTotal; 103 if (wrDelta <= 0 || wrDelta >= twopi*(1-DBL_ 104 { 105 wrStart = 0; 106 wrDelta = twopi; 107 } 108 rzcorners.resize(0); 109 for (G4int i=0; i<numRZ; ++i) 110 { 111 rzcorners.emplace_back(r[i],z[i]); 112 } 113 std::vector<G4int> iout; 114 G4GeomTools::RemoveRedundantVertices(rzcorne 115 } 116 117 118 ////////////////////////////////////////////// 119 // 120 // Fake default constructor - sets only member 121 // for usage restri 122 // 123 G4UPolycone::G4UPolycone( __void__& a ) 124 : Base_t(a) 125 { 126 } 127 128 129 ////////////////////////////////////////////// 130 // 131 // Destructor 132 // 133 G4UPolycone::~G4UPolycone() = default; 134 135 136 ////////////////////////////////////////////// 137 // 138 // Copy constructor 139 // 140 G4UPolycone::G4UPolycone( const G4UPolycone& s 141 : Base_t( source ) 142 { 143 fGenericPcon = source.fGenericPcon; 144 fOriginalParameters = source.fOriginalParame 145 wrStart = source.wrStart; 146 wrDelta = source.wrDelta; 147 rzcorners = source.rzcorners; 148 } 149 150 151 ////////////////////////////////////////////// 152 // 153 // Assignment operator 154 // 155 G4UPolycone& G4UPolycone::operator=( const G4U 156 { 157 if (this == &source) return *this; 158 159 Base_t::operator=( source ); 160 fGenericPcon = source.fGenericPcon; 161 fOriginalParameters = source.fOriginalParame 162 wrStart = source.wrStart; 163 wrDelta = source.wrDelta; 164 rzcorners = source.rzcorners; 165 166 return *this; 167 } 168 169 170 ////////////////////////////////////////////// 171 // 172 // Accessors & modifiers 173 // 174 G4double G4UPolycone::GetStartPhi() const 175 { 176 return wrStart; 177 } 178 G4double G4UPolycone::GetDeltaPhi() const 179 { 180 return wrDelta; 181 } 182 G4double G4UPolycone::GetEndPhi() const 183 { 184 return (wrStart + wrDelta); 185 } 186 G4double G4UPolycone::GetSinStartPhi() const 187 { 188 if (!IsOpen()) return 0.; 189 G4double phi = GetStartPhi(); 190 return std::sin(phi); 191 } 192 G4double G4UPolycone::GetCosStartPhi() const 193 { 194 if (!IsOpen()) return 1.; 195 G4double phi = GetStartPhi(); 196 return std::cos(phi); 197 } 198 G4double G4UPolycone::GetSinEndPhi() const 199 { 200 if (!IsOpen()) return 0.; 201 G4double phi = GetEndPhi(); 202 return std::sin(phi); 203 } 204 G4double G4UPolycone::GetCosEndPhi() const 205 { 206 if (!IsOpen()) return 1.; 207 G4double phi = GetEndPhi(); 208 return std::cos(phi); 209 } 210 G4bool G4UPolycone::IsOpen() const 211 { 212 return (wrDelta < twopi); 213 } 214 G4int G4UPolycone::GetNumRZCorner() const 215 { 216 return rzcorners.size(); 217 } 218 G4PolyconeSideRZ G4UPolycone::GetCorner(G4int 219 { 220 G4TwoVector rz = rzcorners.at(index); 221 G4PolyconeSideRZ psiderz = { rz.x(), rz.y() 222 223 return psiderz; 224 } 225 G4PolyconeHistorical* G4UPolycone::GetOriginal 226 { 227 return new G4PolyconeHistorical(fOriginalPar 228 } 229 void G4UPolycone::SetOriginalParameters() 230 { 231 vecgeom::PolyconeHistorical* original_parame 232 233 fOriginalParameters.Start_angle = original 234 fOriginalParameters.Opening_angle = original 235 fOriginalParameters.Num_z_planes = original 236 237 delete [] fOriginalParameters.Z_values; 238 delete [] fOriginalParameters.Rmin; 239 delete [] fOriginalParameters.Rmax; 240 241 G4int numPlanes = fOriginalParameters.Num_z_ 242 fOriginalParameters.Z_values = new G4double[ 243 fOriginalParameters.Rmin = new G4double[numP 244 fOriginalParameters.Rmax = new G4double[numP 245 for (G4int i=0; i<numPlanes; ++i) 246 { 247 fOriginalParameters.Z_values[i] = original 248 fOriginalParameters.Rmin[i] = original 249 fOriginalParameters.Rmax[i] = original 250 } 251 } 252 void G4UPolycone::SetOriginalParameters(G4Poly 253 { 254 fOriginalParameters = *pars; 255 fRebuildPolyhedron = true; 256 Reset(); 257 } 258 259 G4bool G4UPolycone::Reset() 260 { 261 if (fGenericPcon) 262 { 263 std::ostringstream message; 264 message << "Solid " << GetName() << " buil 265 << G4endl << "Not applicable to th 266 G4Exception("G4UPolycone::Reset()", "GeomS 267 JustWarning, message, "Paramet 268 return true; // error code set 269 } 270 271 // 272 // Rebuild polycone based on original parame 273 // 274 wrStart = fOriginalParameters.Start_angle; 275 while (wrStart < 0.) 276 { 277 wrStart += twopi; 278 } 279 wrDelta = fOriginalParameters.Opening_angle; 280 if (wrDelta <= 0. || wrDelta >= twopi*(1-DBL 281 { 282 wrStart = 0.; 283 wrDelta = twopi; 284 } 285 rzcorners.resize(0); 286 for (G4int i=0; i<fOriginalParameters.Num_z_ 287 { 288 G4double z = fOriginalParameters.Z_value 289 G4double r = fOriginalParameters.Rmax[i] 290 rzcorners.emplace_back(r,z); 291 } 292 for (G4int i=fOriginalParameters.Num_z_plane 293 { 294 G4double z = fOriginalParameters.Z_value 295 G4double r = fOriginalParameters.Rmin[i] 296 rzcorners.emplace_back(r,z); 297 } 298 std::vector<G4int> iout; 299 G4GeomTools::RemoveRedundantVertices(rzcorne 300 301 return false; // error code unset 302 } 303 304 ////////////////////////////////////////////// 305 // 306 // Dispatch to parameterisation for replicatio 307 // computation & modification. 308 // 309 void G4UPolycone::ComputeDimensions(G4VPVParam 310 const G4in 311 const G4VP 312 { 313 p->ComputeDimensions(*(G4Polycone*)this,n,pR 314 } 315 316 317 ////////////////////////////////////////////// 318 // 319 // Make a clone of the object 320 321 G4VSolid* G4UPolycone::Clone() const 322 { 323 return new G4UPolycone(*this); 324 } 325 326 ////////////////////////////////////////////// 327 // 328 // Get bounding box 329 330 void G4UPolycone::BoundingLimits(G4ThreeVector 331 G4ThreeVector 332 { 333 static G4bool checkBBox = true; 334 static G4bool checkPhi = true; 335 336 G4double rmin = kInfinity, rmax = -kInfinity 337 G4double zmin = kInfinity, zmax = -kInfinity 338 339 for (G4int i=0; i<GetNumRZCorner(); ++i) 340 { 341 G4PolyconeSideRZ corner = GetCorner(i); 342 if (corner.r < rmin) rmin = corner.r; 343 if (corner.r > rmax) rmax = corner.r; 344 if (corner.z < zmin) zmin = corner.z; 345 if (corner.z > zmax) zmax = corner.z; 346 } 347 348 if (IsOpen()) 349 { 350 G4TwoVector vmin,vmax; 351 G4GeomTools::DiskExtent(rmin,rmax, 352 GetSinStartPhi(),G 353 GetSinEndPhi(),Get 354 vmin,vmax); 355 pMin.set(vmin.x(),vmin.y(),zmin); 356 pMax.set(vmax.x(),vmax.y(),zmax); 357 } 358 else 359 { 360 pMin.set(-rmax,-rmax, zmin); 361 pMax.set( rmax, rmax, zmax); 362 } 363 364 // Check correctness of the bounding box 365 // 366 if (pMin.x() >= pMax.x() || pMin.y() >= pMax 367 { 368 std::ostringstream message; 369 message << "Bad bounding box (min >= max) 370 << GetName() << " !" 371 << "\npMin = " << pMin 372 << "\npMax = " << pMax; 373 G4Exception("G4UPolycone::BoundingLimits() 374 JustWarning, message); 375 StreamInfo(G4cout); 376 } 377 378 // Check consistency of bounding boxes 379 // 380 if (checkBBox) 381 { 382 U3Vector vmin, vmax; 383 Extent(vmin,vmax); 384 if (std::abs(pMin.x()-vmin.x()) > kCarTole 385 std::abs(pMin.y()-vmin.y()) > kCarTole 386 std::abs(pMin.z()-vmin.z()) > kCarTole 387 std::abs(pMax.x()-vmax.x()) > kCarTole 388 std::abs(pMax.y()-vmax.y()) > kCarTole 389 std::abs(pMax.z()-vmax.z()) > kCarTole 390 { 391 std::ostringstream message; 392 message << "Inconsistency in bounding bo 393 << GetName() << " !" 394 << "\nBBox min: wrapper = " << p 395 << "\nBBox max: wrapper = " << p 396 G4Exception("G4UPolycone::BoundingLimits 397 JustWarning, message); 398 checkBBox = false; 399 } 400 } 401 402 // Check consistency of angles 403 // 404 if (checkPhi) 405 { 406 if (GetStartPhi() != Base_t::GetStartPhi() 407 GetEndPhi() != Base_t::GetEndPhi() 408 IsOpen() != (Base_t::GetDeltaPhi( 409 { 410 std::ostringstream message; 411 message << "Inconsistency in Phi angles 412 << GetName() << " !" 413 << "\nPhi start : wrapper = " < 414 << " solid = " << Base_t::Ge 415 << "\nPhi end : wrapper = " < 416 << " solid = " << Base_t::Ge 417 << "\nPhi is open: wrapper = " < 418 << " solid = " 419 << ((Base_t::GetDeltaPhi() < two 420 G4Exception("G4UPolycone::BoundingLimits 421 JustWarning, message); 422 checkPhi = false; 423 } 424 } 425 } 426 427 ////////////////////////////////////////////// 428 // 429 // Calculate extent under transform and specif 430 431 G4bool G4UPolycone::CalculateExtent(const EAxi 432 const G4Vo 433 const G4Af 434 G4do 435 { 436 G4ThreeVector bmin, bmax; 437 G4bool exist; 438 439 // Check bounding box (bbox) 440 // 441 BoundingLimits(bmin,bmax); 442 G4BoundingEnvelope bbox(bmin,bmax); 443 #ifdef G4BBOX_EXTENT 444 return bbox.CalculateExtent(pAxis,pVoxelLimi 445 #endif 446 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox 447 { 448 return exist = pMin < pMax; 449 } 450 451 // To find the extent, RZ contour of the pol 452 // in triangles. The extent is calculated as 453 // all sub-polycones formed by rotation of t 454 // 455 G4TwoVectorList contourRZ; 456 G4TwoVectorList triangles; 457 std::vector<G4int> iout; 458 G4double eminlim = pVoxelLimit.GetMinExtent( 459 G4double emaxlim = pVoxelLimit.GetMaxExtent( 460 461 // get RZ contour, ensure anticlockwise orde 462 for (G4int i=0; i<GetNumRZCorner(); ++i) 463 { 464 G4PolyconeSideRZ corner = GetCorner(i); 465 contourRZ.emplace_back(corner.r,corner.z); 466 } 467 G4GeomTools::RemoveRedundantVertices(contour 468 G4double area = G4GeomTools::PolygonArea(con 469 if (area < 0.) std::reverse(contourRZ.begin( 470 471 // triangulate RZ countour 472 if (!G4GeomTools::TriangulatePolygon(contour 473 { 474 std::ostringstream message; 475 message << "Triangulation of RZ contour ha 476 << GetName() << " !" 477 << "\nExtent has been calculated u 478 G4Exception("G4UPolycone::CalculateExtent( 479 "GeomMgt1002", JustWarning, me 480 return bbox.CalculateExtent(pAxis,pVoxelLi 481 } 482 483 // set trigonometric values 484 const G4int NSTEPS = 24; // numbe 485 G4double astep = twopi/NSTEPS; // max a 486 487 G4double sphi = GetStartPhi(); 488 G4double ephi = GetEndPhi(); 489 G4double dphi = IsOpen() ? ephi-sphi : two 490 G4int ksteps = (dphi <= astep) ? 1 : (G4i 491 G4double ang = dphi/ksteps; 492 493 G4double sinHalf = std::sin(0.5*ang); 494 G4double cosHalf = std::cos(0.5*ang); 495 G4double sinStep = 2.*sinHalf*cosHalf; 496 G4double cosStep = 1. - 2.*sinHalf*sinHalf; 497 498 G4double sinStart = GetSinStartPhi(); 499 G4double cosStart = GetCosStartPhi(); 500 G4double sinEnd = GetSinEndPhi(); 501 G4double cosEnd = GetCosEndPhi(); 502 503 // define vectors and arrays 504 std::vector<const G4ThreeVectorList *> polyg 505 polygons.resize(ksteps+2); 506 G4ThreeVectorList pols[NSTEPS+2]; 507 for (G4int k=0; k<ksteps+2; ++k) pols[k].res 508 for (G4int k=0; k<ksteps+2; ++k) polygons[k] 509 G4double r0[6],z0[6]; // contour with origin 510 G4double r1[6]; // shifted radii of ex 511 512 // main loop along triangles 513 pMin = kInfinity; 514 pMax =-kInfinity; 515 G4int ntria = triangles.size()/3; 516 for (G4int i=0; i<ntria; ++i) 517 { 518 G4int i3 = i*3; 519 for (G4int k=0; k<3; ++k) 520 { 521 G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3; 522 G4int k2 = k*2; 523 // set contour with original edges of tr 524 r0[k2+0] = triangles[e0].x(); z0[k2+0] = 525 r0[k2+1] = triangles[e1].x(); z0[k2+1] = 526 // set shifted radii 527 r1[k2+0] = r0[k2+0]; 528 r1[k2+1] = r0[k2+1]; 529 if (z0[k2+1] - z0[k2+0] <= 0) continue; 530 r1[k2+0] /= cosHalf; 531 r1[k2+1] /= cosHalf; 532 } 533 534 // rotate countour, set sequence of 6-side 535 G4double sinCur = sinStart*cosHalf + cosSt 536 G4double cosCur = cosStart*cosHalf - sinSt 537 for (G4int j=0; j<6; ++j) pols[0][j].set(r 538 for (G4int k=1; k<ksteps+1; ++k) 539 { 540 for (G4int j=0; j<6; ++j) pols[k][j].set 541 G4double sinTmp = sinCur; 542 sinCur = sinCur*cosStep + cosCur*sinStep 543 cosCur = cosCur*cosStep - sinTmp*sinStep 544 } 545 for (G4int j=0; j<6; ++j) pols[ksteps+1][j 546 547 // set sub-envelope and adjust extent 548 G4double emin,emax; 549 G4BoundingEnvelope benv(polygons); 550 if (!benv.CalculateExtent(pAxis,pVoxelLimi 551 if (emin < pMin) pMin = emin; 552 if (emax > pMax) pMax = emax; 553 if (eminlim > pMin && emaxlim < pMax) retu 554 } 555 return (pMin < pMax); 556 } 557 558 ////////////////////////////////////////////// 559 // 560 // CreatePolyhedron 561 // 562 G4Polyhedron* G4UPolycone::CreatePolyhedron() 563 { 564 return new G4PolyhedronPcon(wrStart, wrDelta 565 } 566 567 #endif // G4GEOM_USE_USOLIDS 568