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 for G4ScaledSolid class 27 // 28 // 27.10.15 G.Cosmo: created, based on impleme 29 // ------------------------------------------- 30 31 #include "G4ScaledSolid.hh" 32 #include "G4BoundingEnvelope.hh" 33 34 #include "G4VPVParameterisation.hh" 35 36 #include "G4ScaleTransform.hh" 37 38 #include "G4VGraphicsScene.hh" 39 #include "G4Polyhedron.hh" 40 41 ////////////////////////////////////////////// 42 // 43 // Constructor 44 // 45 G4ScaledSolid::G4ScaledSolid( const G4String& 46 G4VSolid* 47 const G4Scale3D& 48 : G4VSolid(pName), fPtrSolid(pSolid) 49 { 50 fScale = new G4ScaleTransform(pScale); 51 } 52 53 ////////////////////////////////////////////// 54 // 55 // Fake default constructor - sets only member 56 // for usage restri 57 // 58 G4ScaledSolid::G4ScaledSolid( __void__& a ) 59 : G4VSolid(a) 60 { 61 } 62 63 ////////////////////////////////////////////// 64 // 65 // Destructor 66 // 67 G4ScaledSolid::~G4ScaledSolid() 68 { 69 delete fpPolyhedron; fpPolyhedron = nullptr; 70 delete fScale; fScale = nullptr; 71 } 72 73 ////////////////////////////////////////////// 74 // 75 // Copy constructor 76 // 77 G4ScaledSolid::G4ScaledSolid(const G4ScaledSol 78 : G4VSolid (rhs), fPtrSolid(rhs.fPtrSolid), 79 fCubicVolume(rhs.fCubicVolume), fSurfaceAr 80 { 81 fScale = new G4ScaleTransform(*(rhs.fScale)) 82 } 83 84 ////////////////////////////////////////////// 85 // 86 // Assignment operator 87 // 88 G4ScaledSolid& G4ScaledSolid::operator = (cons 89 { 90 // Check assignment to self 91 // 92 if (this == &rhs) { return *this; } 93 94 // Copy base class data 95 // 96 G4VSolid::operator=(rhs); 97 98 // Copy data 99 // 100 fPtrSolid = rhs.fPtrSolid; 101 delete fScale; 102 fScale = new G4ScaleTransform(*(rhs.fScale)) 103 fCubicVolume = rhs.fCubicVolume; 104 fSurfaceArea = rhs.fSurfaceArea; 105 fRebuildPolyhedron = false; 106 delete fpPolyhedron; fpPolyhedron = nullptr; 107 108 return *this; 109 } 110 111 ////////////////////////////////////////////// 112 // 113 // Return original solid not scaled 114 // 115 G4VSolid* G4ScaledSolid::GetUnscaledSolid() co 116 { 117 return fPtrSolid; 118 } 119 120 ////////////////////////////////////////////// 121 // 122 // Get bounding box 123 // 124 void G4ScaledSolid::BoundingLimits(G4ThreeVect 125 G4ThreeVect 126 { 127 G4ThreeVector bmin,bmax; 128 G4ThreeVector scale = fScale->GetScale(); 129 130 fPtrSolid->BoundingLimits(bmin,bmax); 131 pMin.set(bmin.x()*scale.x(),bmin.y()*scale.y 132 pMax.set(bmax.x()*scale.x(),bmax.y()*scale.y 133 134 // Check correctness of the bounding box 135 // 136 if (pMin.x() >= pMax.x() || pMin.y() >= pMax 137 { 138 std::ostringstream message; 139 message << "Bad bounding box (min >= max) 140 << GetName() << " !" 141 << "\npMin = " << pMin 142 << "\npMax = " << pMax; 143 G4Exception("G4ScaledSolid::BoundingLimits 144 JustWarning, message); 145 DumpInfo(); 146 } 147 } 148 149 ////////////////////////////////////////////// 150 // 151 // Calculate extent under transform and specif 152 // 153 G4bool 154 G4ScaledSolid::CalculateExtent( const EAxis pA 155 const G4VoxelL 156 const G4Affine 157 G4double 158 G4double 159 { 160 // Find bounding box of unscaled solid 161 G4ThreeVector bmin,bmax; 162 fPtrSolid->BoundingLimits(bmin,bmax); 163 164 // Set combined transformation 165 G4Transform3D transform3D = 166 G4Transform3D(pTransform.NetRotation().inv 167 pTransform.NetTranslation()) 168 169 // Find extent 170 G4BoundingEnvelope bbox(bmin,bmax); 171 return bbox.CalculateExtent(pAxis,pVoxelLimi 172 } 173 174 ////////////////////////////////////////////// 175 // 176 // Inside 177 // 178 EInside G4ScaledSolid::Inside(const G4ThreeVec 179 { 180 return fPtrSolid->Inside(fScale->Transform(p 181 } 182 183 ////////////////////////////////////////////// 184 // 185 // SurfaceNormal 186 // 187 G4ThreeVector 188 G4ScaledSolid::SurfaceNormal( const G4ThreeVec 189 { 190 // Transform point to unscaled shape frame 191 G4ThreeVector newPoint; 192 fScale->Transform(p, newPoint); 193 194 // Compute normal in unscaled frame 195 G4ThreeVector newNormal = fPtrSolid->Surface 196 G4ThreeVector normal; 197 198 // Convert normal to scaled frame 199 fScale->InverseTransformNormal(newNormal, no 200 return normal/normal.mag(); 201 } 202 203 ////////////////////////////////////////////// 204 // 205 // The same algorithm as in DistanceToIn(p) 206 // 207 G4double 208 G4ScaledSolid::DistanceToIn( const G4ThreeVect 209 const G4ThreeVect 210 { 211 // Transform point and direction to unscaled 212 G4ThreeVector newPoint; 213 fScale->Transform(p, newPoint); 214 215 // Direction is un-normalized after scale tr 216 G4ThreeVector newDirection; 217 fScale->Transform(v, newDirection); 218 newDirection = newDirection/newDirection.mag 219 220 // Compute distance in unscaled system 221 G4double dist = fPtrSolid->DistanceToIn(newP 222 223 // Return converted distance to global 224 return fScale->InverseTransformDistance(dist 225 } 226 227 ////////////////////////////////////////////// 228 // 229 // Approximate nearest distance from the point 230 // 231 G4double 232 G4ScaledSolid::DistanceToIn( const G4ThreeVect 233 { 234 // Transform point to unscaled shape frame 235 G4ThreeVector newPoint; 236 fScale->Transform(p, newPoint); 237 238 // Compute unscaled safety, then scale it 239 G4double dist = fPtrSolid->DistanceToIn(newP 240 return fScale->InverseTransformDistance(dist 241 } 242 243 ////////////////////////////////////////////// 244 // 245 // The same algorithm as DistanceToOut(p) 246 // 247 G4double 248 G4ScaledSolid::DistanceToOut( const G4ThreeVec 249 const G4ThreeVec 250 const G4bool cal 251 G4bool *va 252 G4ThreeVec 253 { 254 // Transform point and direction to unscaled 255 G4ThreeVector newPoint; 256 fScale->Transform(p, newPoint); 257 258 // Direction is un-normalized after scale tr 259 G4ThreeVector newDirection; 260 fScale->Transform(v, newDirection); 261 newDirection = newDirection/newDirection.mag 262 263 // Compute distance in unscaled system 264 G4ThreeVector solNorm; 265 G4double dist = fPtrSolid->DistanceToOut(new 266 cal 267 if(calcNorm) 268 { 269 G4ThreeVector normal; 270 fScale->TransformNormal(solNorm, normal); 271 *n = normal.unit(); 272 } 273 274 // Return distance converted to global 275 return fScale->InverseTransformDistance(dist 276 } 277 278 ////////////////////////////////////////////// 279 // 280 // Approximate nearest distance from the poin 281 // 282 G4double 283 G4ScaledSolid::DistanceToOut( const G4ThreeVec 284 { 285 // Transform point to unscaled shape frame 286 G4ThreeVector newPoint; 287 fScale->Transform(p, newPoint); 288 289 // Compute unscaled safety, then scale it 290 G4double dist = fPtrSolid->DistanceToOut(new 291 return fScale->InverseTransformDistance(dist 292 } 293 294 ////////////////////////////////////////////// 295 // 296 // ComputeDimensions 297 // 298 void 299 G4ScaledSolid::ComputeDimensions( G4VPVParamet 300 const G4int, 301 const G4VPhy 302 { 303 DumpInfo(); 304 G4Exception("G4ScaledSolid::ComputeDimension 305 "GeomSolids0001", FatalException 306 "Method not applicable in this c 307 } 308 309 ////////////////////////////////////////////// 310 // 311 // Returns a point (G4ThreeVector) randomly an 312 // on the solid surface 313 // 314 G4ThreeVector G4ScaledSolid::GetPointOnSurface 315 { 316 return fScale->InverseTransform(fPtrSolid->G 317 } 318 ////////////////////////////////////////////// 319 // 320 // Return the number of constituents used for 321 // 322 G4int G4ScaledSolid::GetNumOfConstituents() co 323 { 324 return fPtrSolid->GetNumOfConstituents(); 325 } 326 327 ////////////////////////////////////////////// 328 // 329 // Return true if the solid has only planar fa 330 // 331 G4bool G4ScaledSolid::IsFaceted() const 332 { 333 return fPtrSolid->IsFaceted(); 334 } 335 336 ////////////////////////////////////////////// 337 // 338 // Return object type name 339 // 340 G4GeometryType G4ScaledSolid::GetEntityType() 341 { 342 return {"G4ScaledSolid"}; 343 } 344 345 ////////////////////////////////////////////// 346 // 347 // Make a clone of the object 348 // 349 G4VSolid* G4ScaledSolid::Clone() const 350 { 351 return new G4ScaledSolid(*this); 352 } 353 354 ////////////////////////////////////////////// 355 // 356 // Returning the scaling transformation 357 // 358 G4Scale3D G4ScaledSolid::GetScaleTransform() c 359 { 360 return { fScale->GetScale().x(), 361 fScale->GetScale().y(), 362 fScale->GetScale().z() }; 363 } 364 365 ////////////////////////////////////////////// 366 // 367 // Setting the scaling transformation 368 // 369 void G4ScaledSolid::SetScaleTransform(const G4 370 { 371 delete fScale; 372 fScale = new G4ScaleTransform(scale); 373 fRebuildPolyhedron = true; 374 } 375 376 ////////////////////////////////////////////// 377 // 378 // Get volume of the scaled solid 379 // 380 G4double G4ScaledSolid::GetCubicVolume() 381 { 382 if(fCubicVolume < 0.) 383 { 384 fCubicVolume = fPtrSolid->GetCubicVolume() 385 fScale->GetScale().x() * 386 fScale->GetScale().y() * 387 fScale->GetScale().z(); 388 } 389 return fCubicVolume; 390 } 391 392 ////////////////////////////////////////////// 393 // 394 // Get estimated surface area of the scaled so 395 // 396 G4double G4ScaledSolid::GetSurfaceArea() 397 { 398 if(fSurfaceArea < 0.) 399 { 400 fSurfaceArea = G4VSolid::GetSurfaceArea(); 401 } 402 return fSurfaceArea; 403 } 404 405 ////////////////////////////////////////////// 406 // 407 // Stream object contents to an output stream 408 // 409 std::ostream& G4ScaledSolid::StreamInfo(std::o 410 { 411 os << "------------------------------------- 412 << " *** Dump for Scaled solid - " << 413 << " ================================= 414 << " Solid type: " << GetEntityType() << 415 << " Parameters of constituent solid: \n" 416 << "===================================== 417 fPtrSolid->StreamInfo(os); 418 os << "===================================== 419 << " Scaling: \n" 420 << " Scale transformation : \n" 421 << " " << fScale->GetScale().x( 422 << fScale->GetScale().y( 423 << fScale->GetScale().z( 424 << "===================================== 425 426 return os; 427 } 428 429 ////////////////////////////////////////////// 430 // 431 // DescribeYourselfTo 432 // 433 void 434 G4ScaledSolid::DescribeYourselfTo ( G4VGraphic 435 { 436 scene.AddSolid (*this); 437 } 438 439 ////////////////////////////////////////////// 440 // 441 // CreatePolyhedron 442 // 443 G4Polyhedron* 444 G4ScaledSolid::CreatePolyhedron () const 445 { 446 G4Polyhedron* polyhedron = fPtrSolid->Create 447 if (polyhedron != nullptr) 448 { 449 polyhedron->Transform(GetScaleTransform()) 450 } 451 else 452 { 453 DumpInfo(); 454 G4Exception("G4ScaledSolid::CreatePolyhedr 455 "GeomSolids2003", JustWarning, 456 "No G4Polyhedron for scaled so 457 } 458 return polyhedron; 459 } 460 461 ////////////////////////////////////////////// 462 // 463 // GetPolyhedron 464 // 465 G4Polyhedron* G4ScaledSolid::GetPolyhedron () 466 { 467 if (fpPolyhedron == nullptr || 468 fRebuildPolyhedron || 469 fpPolyhedron->GetNumberOfRotationStepsAt 470 fpPolyhedron->GetNumberOfRotationSteps() 471 { 472 fpPolyhedron = CreatePolyhedron(); 473 fRebuildPolyhedron = false; 474 } 475 return fpPolyhedron; 476 } 477