Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // Implementation for G4ReflectedSolid class 27 // 28 // Author: Vladimir Grichine, 23.07.01 (Vladimir.Grichine@cern.ch) 29 // -------------------------------------------------------------------- 30 31 #include "G4ReflectedSolid.hh" 32 33 #include <sstream> 34 35 #include "G4Point3D.hh" 36 #include "G4Vector3D.hh" 37 38 #include "G4AffineTransform.hh" 39 #include "G4Transform3D.hh" 40 #include "G4VoxelLimits.hh" 41 42 #include "G4VPVParameterisation.hh" 43 44 #include "G4VGraphicsScene.hh" 45 #include "G4Polyhedron.hh" 46 47 ///////////////////////////////////////////////////////////////// 48 // 49 // Constructor using HepTransform3D, in fact HepReflect3D 50 51 G4ReflectedSolid::G4ReflectedSolid( const G4String& pName, 52 G4VSolid* pSolid , 53 const G4Transform3D& transform ) 54 : G4VSolid(pName) 55 { 56 fPtrSolid = pSolid; 57 fDirectTransform3D = new G4Transform3D(transform); 58 } 59 60 /////////////////////////////////////////////////////////////////// 61 // 62 63 G4ReflectedSolid::~G4ReflectedSolid() 64 { 65 delete fDirectTransform3D; fDirectTransform3D = nullptr; 66 delete fpPolyhedron; fpPolyhedron = nullptr; 67 } 68 69 /////////////////////////////////////////////////////////////////// 70 // 71 72 G4ReflectedSolid::G4ReflectedSolid(const G4ReflectedSolid& rhs) 73 : G4VSolid(rhs), fPtrSolid(rhs.fPtrSolid) 74 { 75 fDirectTransform3D = new G4Transform3D(*rhs.fDirectTransform3D); 76 } 77 78 /////////////////////////////////////////////////////////////////// 79 // 80 81 G4ReflectedSolid& G4ReflectedSolid::operator=(const G4ReflectedSolid& rhs) 82 { 83 // Check assignment to self 84 // 85 if (this == &rhs) { return *this; } 86 87 // Copy base class data 88 // 89 G4VSolid::operator=(rhs); 90 91 // Copy data 92 // 93 fPtrSolid = rhs.fPtrSolid; 94 delete fDirectTransform3D; 95 fDirectTransform3D = new G4Transform3D(*rhs.fDirectTransform3D); 96 fRebuildPolyhedron = false; 97 delete fpPolyhedron; fpPolyhedron = nullptr; 98 99 return *this; 100 } 101 102 /////////////////////////////////////////////////////////////////// 103 // 104 105 G4GeometryType G4ReflectedSolid::GetEntityType() const 106 { 107 return {"G4ReflectedSolid"}; 108 } 109 110 const G4ReflectedSolid* G4ReflectedSolid::GetReflectedSolidPtr() const 111 { 112 return this; 113 } 114 115 G4ReflectedSolid* G4ReflectedSolid::GetReflectedSolidPtr() 116 { 117 return this; 118 } 119 120 G4VSolid* G4ReflectedSolid::GetConstituentMovedSolid() const 121 { 122 return fPtrSolid; 123 } 124 125 ///////////////////////////////////////////////////////////////////////////// 126 // 127 128 G4Transform3D G4ReflectedSolid::GetTransform3D() const 129 { 130 return fDirectTransform3D->inverse(); 131 } 132 133 G4Transform3D G4ReflectedSolid::GetDirectTransform3D() const 134 { 135 G4Transform3D aTransform = *fDirectTransform3D; 136 return aTransform; 137 } 138 139 void G4ReflectedSolid::SetDirectTransform3D(G4Transform3D& transform) 140 { 141 fDirectTransform3D = &transform; 142 fRebuildPolyhedron = true; 143 } 144 145 ////////////////////////////////////////////////////////////////////////// 146 // 147 // Get bounding box 148 149 void G4ReflectedSolid::BoundingLimits(G4ThreeVector& pMin, 150 G4ThreeVector& pMax) const 151 { 152 fPtrSolid->BoundingLimits(pMin,pMax); 153 G4double xmin = pMin.x(), ymin = pMin.y(), zmin = pMin.z(); 154 G4double xmax = pMax.x(), ymax = pMax.y(), zmax = pMax.z(); 155 G4double xx = fDirectTransform3D->xx(); 156 G4double yy = fDirectTransform3D->yy(); 157 G4double zz = fDirectTransform3D->zz(); 158 159 if (std::abs(xx) == 1 && std::abs(yy) == 1 && std::abs(zz) == 1) 160 { 161 // Special case of reflection in axis and pure translation 162 // 163 if (xx == -1) { G4double tmp = -xmin; xmin = -xmax; xmax = tmp; } 164 if (yy == -1) { G4double tmp = -ymin; ymin = -ymax; ymax = tmp; } 165 if (zz == -1) { G4double tmp = -zmin; zmin = -zmax; zmax = tmp; } 166 xmin += fDirectTransform3D->dx(); 167 xmax += fDirectTransform3D->dx(); 168 ymin += fDirectTransform3D->dy(); 169 ymax += fDirectTransform3D->dy(); 170 zmin += fDirectTransform3D->dz(); 171 zmax += fDirectTransform3D->dz(); 172 } 173 else 174 { 175 // Use additional reflection in Z to set up affine transformation 176 // 177 G4Transform3D transform3D = G4ReflectZ3D()*(*fDirectTransform3D); 178 G4AffineTransform transform(transform3D.getRotation().inverse(), 179 transform3D.getTranslation()); 180 181 // Find bounding box 182 // 183 G4VoxelLimits unLimit; 184 fPtrSolid->CalculateExtent(kXAxis,unLimit,transform,xmin,xmax); 185 fPtrSolid->CalculateExtent(kYAxis,unLimit,transform,ymin,ymax); 186 fPtrSolid->CalculateExtent(kZAxis,unLimit,transform,zmin,zmax); 187 } 188 189 pMin.set(xmin,ymin,-zmax); 190 pMax.set(xmax,ymax,-zmin); 191 192 // Check correctness of the bounding box 193 // 194 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z()) 195 { 196 std::ostringstream message; 197 message << "Bad bounding box (min >= max) for solid: " 198 << GetName() << " !" 199 << "\npMin = " << pMin 200 << "\npMax = " << pMax; 201 G4Exception("G4ReflectedSolid::BoundingLimits()", "GeomMgt0001", 202 JustWarning, message); 203 DumpInfo(); 204 } 205 } 206 207 ////////////////////////////////////////////////////////////////////////// 208 // 209 // Calculate extent under transform and specified limit 210 211 G4bool 212 G4ReflectedSolid::CalculateExtent( const EAxis pAxis, 213 const G4VoxelLimits& pVoxelLimits, 214 const G4AffineTransform& pTransform, 215 G4double& pMin, 216 G4double& pMax ) const 217 { 218 // Separation of transformations. Calculation of the extent is done 219 // in a reflection of the global space. In such way, the voxel is 220 // reflected, but the solid is transformed just by G4AffineTransform. 221 // It allows one to use CalculateExtent() of the solid. 222 223 // Reflect voxel limits in Z 224 // 225 G4VoxelLimits limits; 226 limits.AddLimit(kXAxis, pVoxelLimits.GetMinXExtent(), 227 pVoxelLimits.GetMaxXExtent()); 228 limits.AddLimit(kYAxis, pVoxelLimits.GetMinYExtent(), 229 pVoxelLimits.GetMaxYExtent()); 230 limits.AddLimit(kZAxis,-pVoxelLimits.GetMaxZExtent(), 231 -pVoxelLimits.GetMinZExtent()); 232 233 // Set affine transformation 234 // 235 G4Transform3D transform3D = G4ReflectZ3D()*pTransform*(*fDirectTransform3D); 236 G4AffineTransform transform(transform3D.getRotation().inverse(), 237 transform3D.getTranslation()); 238 239 // Find extent 240 // 241 if (!fPtrSolid->CalculateExtent(pAxis, limits, transform, pMin, pMax)) 242 { 243 return false; 244 } 245 if (pAxis == kZAxis) 246 { 247 G4double tmp= -pMin; pMin= -pMax; pMax= tmp; 248 } 249 250 return true; 251 } 252 253 ////////////////////////////////////////////////////////////// 254 // 255 // 256 257 EInside G4ReflectedSolid::Inside(const G4ThreeVector& p ) const 258 { 259 G4ThreeVector newPoint = (*fDirectTransform3D)*G4Point3D(p); 260 return fPtrSolid->Inside(newPoint); 261 } 262 263 ////////////////////////////////////////////////////////////// 264 // 265 // 266 267 G4ThreeVector 268 G4ReflectedSolid::SurfaceNormal( const G4ThreeVector& p ) const 269 { 270 G4ThreeVector newPoint = (*fDirectTransform3D)*G4Point3D(p); 271 G4Vector3D normal = fPtrSolid->SurfaceNormal(newPoint); 272 return (*fDirectTransform3D)*normal; 273 } 274 275 ///////////////////////////////////////////////////////////// 276 // 277 // The same algorithm as in DistanceToIn(p) 278 279 G4double 280 G4ReflectedSolid::DistanceToIn( const G4ThreeVector& p, 281 const G4ThreeVector& v ) const 282 { 283 G4ThreeVector newPoint = (*fDirectTransform3D)*G4Point3D(p); 284 G4ThreeVector newDirection = (*fDirectTransform3D)*G4Vector3D(v); 285 return fPtrSolid->DistanceToIn(newPoint,newDirection); 286 } 287 288 //////////////////////////////////////////////////////// 289 // 290 // Approximate nearest distance from the point p to the intersection of 291 // two solids 292 293 G4double 294 G4ReflectedSolid::DistanceToIn( const G4ThreeVector& p ) const 295 { 296 G4ThreeVector newPoint = (*fDirectTransform3D)*G4Point3D(p); 297 return fPtrSolid->DistanceToIn(newPoint); 298 } 299 300 ////////////////////////////////////////////////////////// 301 // 302 // The same algorithm as DistanceToOut(p) 303 304 G4double 305 G4ReflectedSolid::DistanceToOut( const G4ThreeVector& p, 306 const G4ThreeVector& v, 307 const G4bool calcNorm, 308 G4bool* validNorm, 309 G4ThreeVector* n ) const 310 { 311 G4ThreeVector solNorm; 312 313 G4ThreeVector newPoint = (*fDirectTransform3D)*G4Point3D(p); 314 G4ThreeVector newDirection = (*fDirectTransform3D)*G4Vector3D(v); 315 316 G4double dist = fPtrSolid->DistanceToOut(newPoint, newDirection, 317 calcNorm, validNorm, &solNorm); 318 if(calcNorm) 319 { 320 *n = (*fDirectTransform3D)*G4Vector3D(solNorm); 321 } 322 return dist; 323 } 324 325 ////////////////////////////////////////////////////////////// 326 // 327 // Inverted algorithm of DistanceToIn(p) 328 329 G4double 330 G4ReflectedSolid::DistanceToOut( const G4ThreeVector& p ) const 331 { 332 G4ThreeVector newPoint = (*fDirectTransform3D)*G4Point3D(p); 333 return fPtrSolid->DistanceToOut(newPoint); 334 } 335 336 ////////////////////////////////////////////////////////////// 337 // 338 // 339 340 void 341 G4ReflectedSolid::ComputeDimensions( G4VPVParameterisation*, 342 const G4int, 343 const G4VPhysicalVolume* ) 344 { 345 DumpInfo(); 346 G4Exception("G4ReflectedSolid::ComputeDimensions()", 347 "GeomMgt0001", FatalException, 348 "Method not applicable in this context!"); 349 } 350 351 ////////////////////////////////////////////////////////////// 352 // 353 // Return volume 354 355 G4double G4ReflectedSolid::GetCubicVolume() 356 { 357 return fPtrSolid->GetCubicVolume(); 358 } 359 360 ////////////////////////////////////////////////////////////// 361 // 362 // Return surface area 363 364 G4double G4ReflectedSolid::GetSurfaceArea() 365 { 366 return fPtrSolid->GetSurfaceArea(); 367 } 368 369 ////////////////////////////////////////////////////////////// 370 // 371 // Return a point (G4ThreeVector) randomly and uniformly selected 372 // on the solid surface 373 374 G4ThreeVector G4ReflectedSolid::GetPointOnSurface() const 375 { 376 G4ThreeVector p = fPtrSolid->GetPointOnSurface(); 377 return (*fDirectTransform3D)*G4Point3D(p); 378 } 379 380 ////////////////////////////////////////////////////////////// 381 // 382 // Return the number of constituents used for construction 383 // of the solid 384 385 G4int G4ReflectedSolid::GetNumOfConstituents() const 386 { 387 return fPtrSolid->GetNumOfConstituents(); 388 } 389 390 ////////////////////////////////////////////////////////////// 391 // 392 // Return true if the reflected solid has only planar faces 393 394 G4bool G4ReflectedSolid::IsFaceted() const 395 { 396 return fPtrSolid->IsFaceted(); 397 } 398 399 ////////////////////////////////////////////////////////////////////////// 400 // 401 // Make a clone of this object 402 403 G4VSolid* G4ReflectedSolid::Clone() const 404 { 405 return new G4ReflectedSolid(*this); 406 } 407 408 ////////////////////////////////////////////////////////////////////////// 409 // 410 // Stream object contents to an output stream 411 412 std::ostream& G4ReflectedSolid::StreamInfo(std::ostream& os) const 413 { 414 os << "-----------------------------------------------------------\n" 415 << " *** Dump for Reflected solid - " << GetName() << " ***\n" 416 << " ===================================================\n" 417 << " Solid type: " << GetEntityType() << "\n" 418 << " Parameters of constituent solid: \n" 419 << "===========================================================\n"; 420 fPtrSolid->StreamInfo(os); 421 os << "===========================================================\n" 422 << " Transformations: \n" 423 << " Direct transformation - translation : \n" 424 << " " << fDirectTransform3D->getTranslation() << "\n" 425 << " - rotation : \n" 426 << " "; 427 fDirectTransform3D->getRotation().print(os); 428 os << "\n" 429 << "===========================================================\n"; 430 431 return os; 432 } 433 434 ///////////////////////////////////////////////// 435 // 436 // 437 438 void 439 G4ReflectedSolid::DescribeYourselfTo ( G4VGraphicsScene& scene ) const 440 { 441 scene.AddSolid (*this); 442 } 443 444 //////////////////////////////////////////////////// 445 // 446 // 447 448 G4Polyhedron* 449 G4ReflectedSolid::CreatePolyhedron () const 450 { 451 G4Polyhedron* polyhedron = fPtrSolid->CreatePolyhedron(); 452 if (polyhedron != nullptr) 453 { 454 polyhedron->Transform(*fDirectTransform3D); 455 return polyhedron; 456 } 457 else 458 { 459 std::ostringstream message; 460 message << "Solid - " << GetName() 461 << " - original solid has no" << G4endl 462 << "corresponding polyhedron. Returning NULL!"; 463 G4Exception("G4ReflectedSolid::CreatePolyhedron()", 464 "GeomMgt1001", JustWarning, message); 465 return nullptr; 466 } 467 } 468 469 ///////////////////////////////////////////////////////// 470 // 471 // 472 473 G4Polyhedron* 474 G4ReflectedSolid::GetPolyhedron () const 475 { 476 if ((fpPolyhedron == nullptr) || fRebuildPolyhedron || 477 (fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() != 478 fpPolyhedron->GetNumberOfRotationSteps())) 479 { 480 fpPolyhedron = CreatePolyhedron(); 481 fRebuildPolyhedron = false; 482 } 483 return fpPolyhedron; 484 } 485