Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4PhysicalVolumeModel.cc
Go to the documentation of this file.
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//
27//
28//
29// John Allison 31st December 1997.
30// Model for physical volumes.
31
33
34#include "G4VGraphicsScene.hh"
35#include "G4VPhysicalVolume.hh"
38#include "G4LogicalVolume.hh"
39#include "G4VSolid.hh"
40#include "G4SubtractionSolid.hh"
42#include "G4Material.hh"
43#include "G4VisAttributes.hh"
46#include "G4Polyhedron.hh"
48#include "G4AttDefStore.hh"
49#include "G4AttDef.hh"
50#include "G4AttValue.hh"
51#include "G4UnitsTable.hh"
52#include "G4Vector3D.hh"
53#include "G4Mesh.hh"
54
55#include <sstream>
56#include <iomanip>
57
58#define G4warn G4cout
59
60namespace {
61 G4int volumeCount = 0;
62}
63
66 , G4int requestedDepth
67 , const G4Transform3D& modelTransform
68 , const G4ModelingParameters* pMP
69 , G4bool useFullExtent
70 , const std::vector<G4PhysicalVolumeNodeID>& baseFullPVPath)
71: G4VModel (pMP)
72, fpTopPV (pVPV)
73, fTopPVCopyNo (pVPV? pVPV->GetCopyNo(): 0)
74, fRequestedDepth (requestedDepth)
75, fUseFullExtent (useFullExtent)
76, fTransform (modelTransform)
77, fCurrentDepth (0)
78, fpCurrentPV (fpTopPV)
79, fCurrentPVCopyNo (fpTopPV? fpTopPV->GetCopyNo(): 0)
80, fpCurrentLV (fpTopPV? fpTopPV->GetLogicalVolume(): 0)
81, fpCurrentMaterial (fpCurrentLV? fpCurrentLV->GetMaterial(): 0)
82, fCurrentTransform (modelTransform)
83, fBaseFullPVPath (baseFullPVPath)
84, fAbort (false)
85, fCurtailDescent (false)
86, fpClippingSolid (0)
87, fClippingMode (subtraction)
88{
89 fType = "G4PhysicalVolumeModel";
90
91 if (!fpTopPV) {
92
93 // In some circumstances creating an "empty" G4PhysicalVolumeModel is
94 // allowed, so I have supressed the G4Exception below. If it proves to
95 // be a problem we might have to re-instate it, but it is unlikley to
96 // be used except by visualisation experts. See, for example, /vis/list,
97 // where it is used simply to get a list of G4AttDefs.
98 // G4Exception
99 // ("G4PhysicalVolumeModel::G4PhysicalVolumeModel",
100 // "modeling0010", FatalException, "Null G4PhysicalVolumeModel pointer.");
101
102 fTopPVName = "NULL";
103 fGlobalTag = "Empty";
104 fGlobalDescription = "G4PhysicalVolumeModel " + fGlobalTag;
105
106 } else {
107
108 fTopPVName = fpTopPV -> GetName ();
109 std::ostringstream oss;
110 oss << fpTopPV->GetName() << ':' << fpTopPV->GetCopyNo()
111 << " BasePath:" << fBaseFullPVPath;
112 fGlobalTag = oss.str();
113 fGlobalDescription = "G4PhysicalVolumeModel " + fGlobalTag;
115 }
116}
117
119{
120 delete fpClippingSolid;
121}
122
124(const std::vector<G4PhysicalVolumeNodeID>& path)
125{
127 for (const auto& node: path) {
128 PVNameCopyNoPath.push_back
130 (node.GetPhysicalVolume()->GetName(),node.GetCopyNo()));
131 }
132 return PVNameCopyNoPath;
133}
134
136{
137 // To handle paramaterisations, set copy number and compute dimensions
138 // to get extent right
139 G4VPVParameterisation* pP = fpTopPV -> GetParameterisation ();
140 if (pP) {
141 fpTopPV -> SetCopyNo (fTopPVCopyNo);
142 G4VSolid* solid = pP -> ComputeSolid (fTopPVCopyNo, fpTopPV);
143 solid -> ComputeDimensions (pP, fTopPVCopyNo, fpTopPV);
144 }
145 if (fUseFullExtent) {
146 fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
147 } else {
148 // Calculate extent of *drawn* volumes, i.e., ignoring culled, e.g.,
149 // invisible volumes, by traversing the whole geometry hierarchy below
150 // this physical volume.
151 G4BoundingExtentScene beScene(this);
152 const G4int tempRequestedDepth = fRequestedDepth;
153 const G4Transform3D tempTransform = fTransform;
154 const G4ModelingParameters* tempMP = fpMP;
155 fRequestedDepth = -1; // Always search to all depths to define extent.
156 fTransform = G4Transform3D(); // Extent is in local cooridinates
158 (0, // No default vis attributes needed.
159 G4ModelingParameters::wf, // wireframe (not relevant for this).
160 true, // Global culling.
161 true, // Cull invisible volumes.
162 false, // Density culling.
163 0., // Density (not relevant if density culling false).
164 true, // Cull daughters of opaque mothers.
165 24); // No of sides (not relevant for this operation).
166 mParams.SetSpecialMeshRendering(true); // Avoids traversing parameterisations
167 fpMP = &mParams;
168 DescribeYourselfTo (beScene);
169 fExtent = beScene.GetBoundingExtent();
170 fpMP = tempMP;
171 fTransform = tempTransform;
172 fRequestedDepth = tempRequestedDepth;
173 }
175 if (radius < 0.) { // Nothing in the scene - revert to top extent
176 fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
177 }
179}
180
182(G4VGraphicsScene& sceneHandler)
183{
184 if (!fpTopPV) G4Exception
185 ("G4PhysicalVolumeModel::DescribeYourselfTo",
186 "modeling0012", FatalException, "No model.");
187
188 if (!fpMP) G4Exception
189 ("G4PhysicalVolumeModel::DescribeYourselfTo",
190 "modeling0003", FatalException, "No modeling parameters.");
191
192 G4Transform3D startingTransformation = fTransform;
193
194 volumeCount = 0;
195
197 (fpTopPV,
199 startingTransformation,
200 sceneHandler);
201
202// G4cout
203// << "G4PhysicalVolumeModel::DescribeYourselfTo: volume count: "
204// << volumeCount
205// << G4endl;
206
207 // Reset or clear data...
208 fCurrentDepth = 0;
214 fDrawnPVPath.clear();
215 fAbort = false;
216 fCurtailDescent = false;
217}
218
220{
221 if (fpCurrentPV) {
222 std::ostringstream o;
223 o << fpCurrentPV -> GetCopyNo ();
224 return fpCurrentPV -> GetName () + ":" + o.str();
225 }
226 else {
227 return "WARNING: NO CURRENT VOLUME - global tag is " + fGlobalTag;
228 }
229}
230
232{
233 return "G4PhysicalVolumeModel " + GetCurrentTag ();
234}
235
237(G4VPhysicalVolume* pVPV,
238 G4int requestedDepth,
239 const G4Transform3D& theAT,
240 G4VGraphicsScene& sceneHandler)
241{
242 // Visits geometry structure to a given depth (requestedDepth), starting
243 // at given physical volume with given starting transformation and
244 // describes volumes to the scene handler.
245 // requestedDepth < 0 (default) implies full visit.
246 // theAT is the Accumulated Transformation.
247
248 // Find corresponding logical volume and (later) solid, storing in
249 // local variables to preserve re-entrancy.
250 G4LogicalVolume* pLV = pVPV -> GetLogicalVolume ();
251 G4VSolid* pSol = nullptr;
252 G4Material* pMaterial = nullptr;
253
254 if (!(pVPV -> IsReplicated ())) {
255 // Non-replicated physical volume.
256 pSol = pLV -> GetSolid ();
257 pMaterial = pLV -> GetMaterial ();
258 DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
259 theAT, sceneHandler);
260 }
261 else {
262 // Replicated or parametrised physical volume.
263 EAxis axis;
264 G4int nReplicas;
265 G4double width;
266 G4double offset;
267 G4bool consuming;
268 pVPV -> GetReplicationData (axis, nReplicas, width, offset, consuming);
269 G4int nBegin = 0;
270 G4int nEnd = nReplicas;
271 if (fCurrentDepth == 0) { // i.e., top volume
272 nBegin = fTopPVCopyNo; // Describe only one volume, namely the one
273 nEnd = nBegin + 1; // specified by the given copy number.
274 }
275 G4VPVParameterisation* pP = pVPV -> GetParameterisation ();
276 if (pP) { // Parametrised volume.
277 for (int n = nBegin; n < nEnd; n++) {
278 pSol = pP -> ComputeSolid (n, pVPV);
279 pP -> ComputeTransformation (n, pVPV);
280 pSol -> ComputeDimensions (pP, n, pVPV);
281 pVPV -> SetCopyNo (n);
283 // Create a touchable of current parent for ComputeMaterial.
284 // fFullPVPath has not been updated yet so at this point it
285 // corresponds to the parent.
287 pMaterial = pP -> ComputeMaterial (n, pVPV, &parentTouchable);
288 DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
289 theAT, sceneHandler);
290 }
291 }
292 else { // Plain replicated volume. From geometry_guide.txt...
293 // The replica's positions are claculated by means of a linear formula.
294 // Replication may occur along:
295 //
296 // o Cartesian axes (kXAxis,kYAxis,kZAxis)
297 //
298 // The replications, of specified width have coordinates of
299 // form (-width*(nReplicas-1)*0.5+n*width,0,0) where n=0.. nReplicas-1
300 // for the case of kXAxis, and are unrotated.
301 //
302 // o Radial axis (cylindrical polar) (kRho)
303 //
304 // The replications are cons/tubs sections, centred on the origin
305 // and are unrotated.
306 // They have radii of width*n+offset to width*(n+1)+offset
307 // where n=0..nReplicas-1
308 //
309 // o Phi axis (cylindrical polar) (kPhi)
310 // The replications are `phi sections' or wedges, and of cons/tubs form
311 // They have phi of offset+n*width to offset+(n+1)*width where
312 // n=0..nReplicas-1
313 //
314 pSol = pLV -> GetSolid ();
315 pMaterial = pLV -> GetMaterial ();
316 G4ThreeVector originalTranslation = pVPV -> GetTranslation ();
317 G4RotationMatrix* pOriginalRotation = pVPV -> GetRotation ();
318 G4double originalRMin = 0., originalRMax = 0.;
319 if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
320 originalRMin = ((G4Tubs*)pSol)->GetInnerRadius();
321 originalRMax = ((G4Tubs*)pSol)->GetOuterRadius();
322 }
323 G4bool visualisable = true;
324 for (int n = nBegin; n < nEnd; n++) {
325 G4ThreeVector translation; // Identity.
326 G4RotationMatrix rotation; // Identity - life enough for visualizing.
327 G4RotationMatrix* pRotation = 0;
328 switch (axis) {
329 default:
330 case kXAxis:
331 translation = G4ThreeVector (-width*(nReplicas-1)*0.5+n*width,0,0);
332 break;
333 case kYAxis:
334 translation = G4ThreeVector (0,-width*(nReplicas-1)*0.5+n*width,0);
335 break;
336 case kZAxis:
337 translation = G4ThreeVector (0,0,-width*(nReplicas-1)*0.5+n*width);
338 break;
339 case kRho:
340 if (pSol->GetEntityType() == "G4Tubs") {
341 ((G4Tubs*)pSol)->SetInnerRadius(width*n+offset);
342 ((G4Tubs*)pSol)->SetOuterRadius(width*(n+1)+offset);
343 } else {
344 if (fpMP->IsWarning())
345 G4warn <<
346 "G4PhysicalVolumeModel::VisitGeometryAndGetVisReps: WARNING:"
347 "\n built-in replicated volumes replicated in radius for "
348 << pSol->GetEntityType() <<
349 "-type\n solids (your solid \""
350 << pSol->GetName() <<
351 "\") are not visualisable."
352 << G4endl;
353 visualisable = false;
354 }
355 break;
356 case kPhi:
357 rotation.rotateZ (-(offset+(n+0.5)*width));
358 // Minus Sign because for the physical volume we need the
359 // coordinate system rotation.
360 pRotation = &rotation;
361 break;
362 }
363 pVPV -> SetTranslation (translation);
364 pVPV -> SetRotation (pRotation);
365 pVPV -> SetCopyNo (n);
367 if (visualisable) {
368 DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
369 theAT, sceneHandler);
370 }
371 }
372 // Restore originals...
373 pVPV -> SetTranslation (originalTranslation);
374 pVPV -> SetRotation (pOriginalRotation);
375 if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
376 ((G4Tubs*)pSol)->SetInnerRadius(originalRMin);
377 ((G4Tubs*)pSol)->SetOuterRadius(originalRMax);
378 }
379 }
380 }
381}
382
384(G4VPhysicalVolume* pVPV,
385 G4int requestedDepth,
386 G4LogicalVolume* pLV,
387 G4VSolid* pSol,
388 G4Material* pMaterial,
389 const G4Transform3D& theAT,
390 G4VGraphicsScene& sceneHandler)
391{
392 // Maintain useful data members...
393 fpCurrentPV = pVPV;
394 fCurrentPVCopyNo = pVPV->GetCopyNo();
395 fpCurrentLV = pLV;
396 fpCurrentMaterial = pMaterial;
397
398 // Create a nodeID for use below - note the "drawn" flag is true
399 G4int copyNo = fpCurrentPV->GetCopyNo();
400 auto nodeID = G4PhysicalVolumeNodeID
402
403 // Update full path of physical volumes...
404 fFullPVPath.push_back(nodeID);
405
406 const G4RotationMatrix objectRotation = pVPV -> GetObjectRotationValue ();
407 const G4ThreeVector& translation = pVPV -> GetTranslation ();
408 G4Transform3D theLT (G4Transform3D (objectRotation, translation));
409
410 // Compute the accumulated transformation...
411 // Note that top volume's transformation relative to the world
412 // coordinate system is specified in theAT == startingTransformation
413 // = fTransform (see DescribeYourselfTo), so first time through the
414 // volume's own transformation, which is only relative to its
415 // mother, i.e., not relative to the world coordinate system, should
416 // not be accumulated.
417 G4Transform3D theNewAT (theAT);
418 if (fCurrentDepth != 0) theNewAT = theAT * theLT;
419 fCurrentTransform = theNewAT;
420
421 const G4VisAttributes* pVisAttribs = pLV->GetVisAttributes();
422 // If the volume does not have any vis attributes, create it.
423 G4VisAttributes* tempVisAtts = nullptr;
424 if (!pVisAttribs) {
426 tempVisAtts = new G4VisAttributes(*fpMP->GetDefaultVisAttributes());
427 } else {
428 tempVisAtts = new G4VisAttributes;
429 }
430 // The user may request /vis/viewer/set/colourByDensity.
431 if (fpMP->GetCBDAlgorithmNumber() == 1) {
432 // Algorithm 1: 3 parameters: Simple rainbow mapping.
433 if (fpMP->GetCBDParameters().size() != 3) {
434 G4Exception("G4PhysicalVolumeModelTouchable::DescribeAndDescend",
435 "modeling0014",
437 "Algorithm-parameter mismatch for Colour By Density");
438 } else {
439 const G4double d = pMaterial? pMaterial->GetDensity(): 0.;
440 const G4double d0 = fpMP->GetCBDParameters()[0]; // Invisible d < d0.
441 const G4double d1 = fpMP->GetCBDParameters()[1]; // Rainbow d0->d1->d2.
442 const G4double d2 = fpMP->GetCBDParameters()[2]; // Blue d > d2.
443 if (d < d0) { // Density < d0 is invisible.
444 tempVisAtts->SetVisibility(false);
445 } else { // Intermediate densities are on a spectrum.
446 G4double red, green, blue;
447 if (d < d1) {
448 red = (d1-d)/(d1-d0); green = (d-d0)/(d1-d0); blue = 0.;
449 } else if (d < d2) {
450 red = 0.; green = (d2-d)/(d2-d1); blue = (d-d1)/(d2-d1);
451 } else { // Density >= d2 is blue.
452 red = 0.; green = 0.; blue = 1.;
453 }
454 tempVisAtts->SetColour(G4Colour(red,green,blue));
455 }
456 }
457 } else if (fpMP->GetCBDAlgorithmNumber() == 2) {
458 // Algorithm 2
459 // ...etc.
460 }
461 pVisAttribs = tempVisAtts;
462 }
463 // From here, can assume pVisAttribs is a valid pointer. This is necessary
464 // because PreAddSolid needs a vis attributes object.
465
466 // Check if vis attributes are to be modified by a /vis/touchable/set/ command.
467 const auto& vams = fpMP->GetVisAttributesModifiers();
468 if (vams.size()) {
469 // OK, we have some VAMs (Vis Attributes Modifiers).
470 for (const auto& vam: vams) {
471 const auto& vamPath = vam.GetPVNameCopyNoPath();
472 if (vamPath.size() == fFullPVPath.size()) {
473 // OK, we have a size match.
474 // Check the volume name/copy number path.
475 auto iVAMNameCopyNo = vamPath.begin();
476 auto iPVNodeId = fFullPVPath.begin();
477 for (; iVAMNameCopyNo != vamPath.end(); ++iVAMNameCopyNo, ++iPVNodeId) {
478 if (!(
479 iVAMNameCopyNo->GetName() ==
480 iPVNodeId->GetPhysicalVolume()->GetName() &&
481 iVAMNameCopyNo->GetCopyNo() ==
482 iPVNodeId->GetPhysicalVolume()->GetCopyNo()
483 )) {
484 // This path element does NOT match.
485 break;
486 }
487 }
488 if (iVAMNameCopyNo == vamPath.end()) {
489 // OK, the paths match (the above loop terminated normally).
490 // Create a vis atts object for the modified vis atts.
491 // It is static so that we may return a reliable pointer to it.
492 static G4VisAttributes modifiedVisAtts;
493 // Initialise it with the current vis atts and reset the pointer.
494 modifiedVisAtts = *pVisAttribs;
495 pVisAttribs = &modifiedVisAtts;
496 const G4VisAttributes& transVisAtts = vam.GetVisAttributes();
497 switch (vam.GetVisAttributesSignifier()) {
499 modifiedVisAtts.SetVisibility(transVisAtts.IsVisible());
500 break;
502 modifiedVisAtts.SetDaughtersInvisible
503 (transVisAtts.IsDaughtersInvisible());
504 break;
506 modifiedVisAtts.SetColour(transVisAtts.GetColour());
507 break;
509 modifiedVisAtts.SetLineStyle(transVisAtts.GetLineStyle());
510 break;
512 modifiedVisAtts.SetLineWidth(transVisAtts.GetLineWidth());
513 break;
515 if (transVisAtts.IsForceDrawingStyle()) {
516 if (transVisAtts.GetForcedDrawingStyle() ==
518 modifiedVisAtts.SetForceWireframe(true);
519 }
520 }
521 break;
523 if (transVisAtts.IsForceDrawingStyle()) {
524 if (transVisAtts.GetForcedDrawingStyle() ==
526 modifiedVisAtts.SetForceSolid(true);
527 }
528 }
529 break;
531 if (transVisAtts.IsForceDrawingStyle()) {
532 if (transVisAtts.GetForcedDrawingStyle() ==
534 modifiedVisAtts.SetForceCloud(true);
535 }
536 }
537 break;
539 modifiedVisAtts.SetForceNumberOfCloudPoints
540 (transVisAtts.GetForcedNumberOfCloudPoints());
541 break;
543 if (transVisAtts.IsForceAuxEdgeVisible()) {
544 modifiedVisAtts.SetForceAuxEdgeVisible
545 (transVisAtts.IsForcedAuxEdgeVisible());
546 }
547 break;
549 modifiedVisAtts.SetForceLineSegmentsPerCircle
550 (transVisAtts.GetForcedLineSegmentsPerCircle());
551 break;
552 }
553 }
554 }
555 }
556 }
557
558 // Check for special mesh rendering
560 G4bool potentialG4Mesh = false;
561 if (fpMP->GetSpecialMeshVolumes().empty()) {
562 // No volumes specified - all are potentially possible
563 potentialG4Mesh = true;
564 } else {
565 // Name and (optionally) copy number of container volume is specified
566 for (const auto& pvNameCopyNo: fpMP->GetSpecialMeshVolumes()) {
567 if (pVPV->GetName() == pvNameCopyNo.GetName()) {
568 // We have a name match
569 if (pvNameCopyNo.GetCopyNo() < 0) {
570 // Any copy number is OK
571 potentialG4Mesh = true;
572 } else {
573 if (pVPV->GetCopyNo() == pvNameCopyNo.GetCopyNo()) {
574 // We have a name and copy number match
575 potentialG4Mesh = true;
576 }
577 }
578 }
579 }
580 }
581 if (potentialG4Mesh) {
582 // Create - or at least attempt to create - a mesh. If it cannot be created
583 // out of this pVPV the type will be "invalid".
584 G4Mesh mesh(pVPV,theNewAT);
585 if (mesh.GetMeshType() != G4Mesh::invalid) {
586 // Create "artificial" nodeID to represent the replaced volumes
587 G4int artCopyNo = 0;
588 auto artPV = mesh.GetParameterisedVolume();
589 auto artDepth = fCurrentDepth + 1;
590 auto artNodeID = G4PhysicalVolumeNodeID(artPV,artCopyNo,artDepth);
591 fFullPVPath.push_back(artNodeID);
592 fDrawnPVPath.push_back(artNodeID);
593 sceneHandler.AddCompound(mesh);
594 fFullPVPath.pop_back();
595 fDrawnPVPath.pop_back();
596 delete tempVisAtts; // Needs cleaning up (Coverity warning!!)
597 return; // Mesh found and processed - nothing more to do.
598 } // else continue processing
599 }
600 }
601
602 // Make decision to draw...
603 G4bool thisToBeDrawn = true;
604
605 // There are various reasons why this volume
606 // might not be drawn...
607 G4bool culling = fpMP->IsCulling();
608 G4bool cullingInvisible = fpMP->IsCullingInvisible();
609 G4bool markedVisible
610 = pVisAttribs->IsVisible() && pVisAttribs->GetColour().GetAlpha() > 0;
611 G4bool cullingLowDensity = fpMP->IsDensityCulling();
612 G4double density = pMaterial? pMaterial->GetDensity(): 0;
613 G4double densityCut = fpMP -> GetVisibleDensity ();
614
615 // 1) Global culling is on....
616 if (culling) {
617 // 2) Culling of invisible volumes is on...
618 if (cullingInvisible) {
619 // 3) ...and the volume is marked not visible...
620 if (!markedVisible) thisToBeDrawn = false;
621 }
622 // 4) Or culling of low density volumes is on...
623 if (cullingLowDensity) {
624 // 5) ...and density is less than cut value...
625 if (density < densityCut) thisToBeDrawn = false;
626 }
627 }
628 // 6) The user has asked for all further traversing to be aborted...
629 if (fAbort) thisToBeDrawn = false;
630
631 // Set "drawn" flag (it was true by default) - thisToBeDrawn may be false
632 nodeID.SetDrawn(thisToBeDrawn);
633
634 if (thisToBeDrawn) {
635
636 // Update path of drawn physical volumes...
637 fDrawnPVPath.push_back(nodeID);
638
639 if (fpMP->IsExplode() && fDrawnPVPath.size() == 1) {
640 // For top-level drawn volumes, explode along radius...
642 G4Transform3D centred = centering.inverse() * theNewAT;
643 G4Scale3D oldScale;
644 G4Rotate3D oldRotation;
645 G4Translate3D oldTranslation;
646 centred.getDecomposition(oldScale, oldRotation, oldTranslation);
647 G4double explodeFactor = fpMP->GetExplodeFactor();
648 G4Translate3D newTranslation =
649 G4Translate3D(explodeFactor * oldTranslation.dx(),
650 explodeFactor * oldTranslation.dy(),
651 explodeFactor * oldTranslation.dz());
652 theNewAT = centering * newTranslation * oldRotation * oldScale;
653 }
654
655 volumeCount++;
656 DescribeSolid (theNewAT, pSol, pVisAttribs, sceneHandler);
657
658 }
659
660 // Make decision to draw daughters, if any. There are various
661 // reasons why daughters might not be drawn...
662
663 // First, reasons that do not depend on culling policy...
664 G4int nDaughters = (G4int)pLV->GetNoDaughters();
665 G4bool daughtersToBeDrawn = true;
666 // 1) There are no daughters...
667 if (!nDaughters) daughtersToBeDrawn = false;
668 // 2) We are at the limit if requested depth...
669 else if (requestedDepth == 0) daughtersToBeDrawn = false;
670 // 3) The user has asked for all further traversing to be aborted...
671 else if (fAbort) daughtersToBeDrawn = false;
672 // 4) The user has asked that the descent be curtailed...
673 else if (fCurtailDescent) daughtersToBeDrawn = false;
674
675 // Now, reasons that depend on culling policy...
676 else {
677 G4bool daughtersInvisible = pVisAttribs->IsDaughtersInvisible();
678 // Culling of covered daughters request. This is computed in
679 // G4VSceneHandler::CreateModelingParameters() depending on view
680 // parameters...
681 G4bool cullingCovered = fpMP->IsCullingCovered();
682 G4bool surfaceDrawing =
685 if (pVisAttribs->IsForceDrawingStyle()) {
686 switch (pVisAttribs->GetForcedDrawingStyle()) {
687 default:
688 case G4VisAttributes::wireframe: surfaceDrawing = false; break;
689 case G4VisAttributes::solid: surfaceDrawing = true; break;
690 }
691 }
692 G4bool opaque = pVisAttribs->GetColour().GetAlpha() >= 1.;
693 // 5) Global culling is on....
694 if (culling) {
695 // 6) ..and culling of invisible volumes is on...
696 if (cullingInvisible) {
697 // 7) ...and the mother requests daughters invisible
698 if (daughtersInvisible) daughtersToBeDrawn = false;
699 }
700 // 8) Or culling of covered daughters is requested...
701 if (cullingCovered) {
702 // 9) ...and surface drawing is operating...
703 if (surfaceDrawing) {
704 // 10) ...but only if mother is visible...
705 if (thisToBeDrawn) {
706 // 11) ...and opaque...
707 if (opaque) daughtersToBeDrawn = false;
708 }
709 }
710 }
711 }
712 }
713
714 if (daughtersToBeDrawn) {
715 for (G4int iDaughter = 0; iDaughter < nDaughters; iDaughter++) {
716 // Store daughter pVPV in local variable ready for recursion...
717 G4VPhysicalVolume* pDaughterVPV = pLV -> GetDaughter (iDaughter);
718 // Descend the geometry structure recursively...
721 (pDaughterVPV, requestedDepth - 1, theNewAT, sceneHandler);
723 }
724 }
725
726 // Clean up
727 delete tempVisAtts;
728
729 // Reset for normal descending of next volume at this level...
730 fCurtailDescent = false;
731
732 // Pop item from paths physical volumes...
733 fFullPVPath.pop_back();
734 if (thisToBeDrawn) {
735 fDrawnPVPath.pop_back();
736 }
737}
738
740(const G4Transform3D& theAT,
741 G4VSolid* pSol,
742 const G4VisAttributes* pVisAttribs,
743 G4VGraphicsScene& sceneHandler)
744{
745 G4DisplacedSolid* pSectionSolid = fpMP->GetSectionSolid();
746 G4DisplacedSolid* pCutawaySolid = fpMP->GetCutawaySolid();
747
748 if (!fpClippingSolid && !pSectionSolid && !pCutawaySolid) {
749
750 sceneHandler.PreAddSolid (theAT, *pVisAttribs);
751 pSol -> DescribeYourselfTo (sceneHandler); // Standard treatment.
752 sceneHandler.PostAddSolid ();
753
754 } else {
755
756 G4VSolid* pResultantSolid = nullptr;
757
758 if (fpClippingSolid) {
759 switch (fClippingMode) {
760 default:
761 case subtraction:
762 pResultantSolid = new G4SubtractionSolid
763 ("subtracted_clipped_solid", pSol, fpClippingSolid, theAT.inverse());
764 break;
765 case intersection:
766 pResultantSolid = new G4IntersectionSolid
767 ("intersected_clipped_solid", pSol, fpClippingSolid, theAT.inverse());
768 break;
769 }
770 }
771
772 if (pSectionSolid) {
773 pResultantSolid = new G4IntersectionSolid
774 ("sectioned_solid", pSol, pSectionSolid, theAT.inverse());
775 }
776
777 if (pCutawaySolid) {
778 pResultantSolid = new G4SubtractionSolid
779 ("cutaway_solid", pSol, pCutawaySolid, theAT.inverse());
780 }
781
782 sceneHandler.PreAddSolid (theAT, *pVisAttribs);
783 pResultantSolid -> DescribeYourselfTo (sceneHandler);
784 sceneHandler.PostAddSolid ();
785
786 delete pResultantSolid;
787 }
788}
789
791{
792// Not easy to see how to validate this sort of model. Previously there was
793// a check that a volume of the same name (fTopPVName) existed somewhere in
794// the geometry tree but under some circumstances this consumed lots of CPU
795// time. Instead, let us simply check that the volume (fpTopPV) exists in the
796// physical volume store.
797 const auto& pvStore = G4PhysicalVolumeStore::GetInstance();
798 auto iterator = find(pvStore->begin(),pvStore->end(),fpTopPV);
799 if (iterator == pvStore->end()) {
800 if (warn) {
802 ed << "Attempt to validate a volume that is no longer in the physical volume store.";
803 G4Exception("G4PhysicalVolumeModel::Validate", "modeling0015", JustWarning, ed);
804 }
805 return false;
806 } else {
807 return true;
808 }
809}
810
811const std::map<G4String,G4AttDef>* G4PhysicalVolumeModel::GetAttDefs() const
812{
813 G4bool isNew;
814 std::map<G4String,G4AttDef>* store
815 = G4AttDefStore::GetInstance("G4PhysicalVolumeModel", isNew);
816 if (isNew) {
817 (*store)["PVPath"] =
818 G4AttDef("PVPath","Physical Volume Path","Physics","","G4String");
819 (*store)["BasePVPath"] =
820 G4AttDef("BasePVPath","Base Physical Volume Path","Physics","","G4String");
821 (*store)["LVol"] =
822 G4AttDef("LVol","Logical Volume","Physics","","G4String");
823 (*store)["Solid"] =
824 G4AttDef("Solid","Solid Name","Physics","","G4String");
825 (*store)["EType"] =
826 G4AttDef("EType","Entity Type","Physics","","G4String");
827 (*store)["DmpSol"] =
828 G4AttDef("DmpSol","Dump of Solid properties","Physics","","G4String");
829 (*store)["LocalTrans"] =
830 G4AttDef("LocalTrans","Local transformation of volume","Physics","","G4String");
831 (*store)["LocalExtent"] =
832 G4AttDef("LocalExtent","Local extent of volume","Physics","","G4String");
833 (*store)["GlobalTrans"] =
834 G4AttDef("GlobalTrans","Global transformation of volume","Physics","","G4String");
835 (*store)["GlobalExtent"] =
836 G4AttDef("GlobalExtent","Global extent of volume","Physics","","G4String");
837 (*store)["Material"] =
838 G4AttDef("Material","Material Name","Physics","","G4String");
839 (*store)["Density"] =
840 G4AttDef("Density","Material Density","Physics","G4BestUnit","G4double");
841 (*store)["State"] =
842 G4AttDef("State","Material State (enum undefined,solid,liquid,gas)","Physics","","G4String");
843 (*store)["Radlen"] =
844 G4AttDef("Radlen","Material Radiation Length","Physics","G4BestUnit","G4double");
845 (*store)["Region"] =
846 G4AttDef("Region","Cuts Region","Physics","","G4String");
847 (*store)["RootRegion"] =
848 G4AttDef("RootRegion","Root Region (0/1 = false/true)","Physics","","G4bool");
849 }
850 return store;
851}
852
853static std::ostream& operator<< (std::ostream& o, const G4Transform3D t)
854{
855 using namespace std;
856
857 G4Scale3D sc;
858 G4Rotate3D r;
859 G4Translate3D tl;
860 t.getDecomposition(sc, r, tl);
861
862 const int w = 10;
863
864 // Transformation itself
865 o << setw(w) << t.xx() << setw(w) << t.xy() << setw(w) << t.xz() << setw(w) << t.dx() << endl;
866 o << setw(w) << t.yx() << setw(w) << t.yy() << setw(w) << t.yz() << setw(w) << t.dy() << endl;
867 o << setw(w) << t.zx() << setw(w) << t.zy() << setw(w) << t.zz() << setw(w) << t.dz() << endl;
868
869 // Translation
870 o << "= translation:" << endl;
871 o << setw(w) << tl.dx() << setw(w) << tl.dy() << setw(w) << tl.dz() << endl;
872
873 // Rotation
874 o << "* rotation:" << endl;
875 o << setw(w) << r.xx() << setw(w) << r.xy() << setw(w) << r.xz() << endl;
876 o << setw(w) << r.yx() << setw(w) << r.yy() << setw(w) << r.yz() << endl;
877 o << setw(w) << r.zx() << setw(w) << r.zy() << setw(w) << r.zz() << endl;
878
879 // Scale
880 o << "* scale:" << endl;
881 o << setw(w) << sc.xx() << setw(w) << sc.yy() << setw(w) << sc.zz() << endl;
882
883 // Transformed axes
884 o << "Transformed axes:" << endl;
885 o << "x': " << r * G4Vector3D(1., 0., 0.) << endl;
886 o << "y': " << r * G4Vector3D(0., 1., 0.) << endl;
887 o << "z': " << r * G4Vector3D(0., 0., 1.) << endl;
888
889 return o;
890}
891
892std::vector<G4AttValue>* G4PhysicalVolumeModel::CreateCurrentAttValues() const
893{
894 std::vector<G4AttValue>* values = new std::vector<G4AttValue>;
895
896 if (!fpCurrentLV) {
898 ("G4PhysicalVolumeModel::CreateCurrentAttValues",
899 "modeling0004",
901 "Current logical volume not defined.");
902 return values;
903 }
904
905 std::ostringstream oss; oss << fFullPVPath;
906 values->push_back(G4AttValue("PVPath", oss.str(),""));
907
908 oss.str(""); oss << fBaseFullPVPath;
909 values->push_back(G4AttValue("BasePVPath", oss.str(),""));
910
911 values->push_back(G4AttValue("LVol", fpCurrentLV->GetName(),""));
912 G4VSolid* pSol = fpCurrentLV->GetSolid();
913
914 values->push_back(G4AttValue("Solid", pSol->GetName(),""));
915
916 values->push_back(G4AttValue("EType", pSol->GetEntityType(),""));
917
918 oss.str(""); oss << '\n' << *pSol;
919 values->push_back(G4AttValue("DmpSol", oss.str(),""));
920
921 const G4RotationMatrix localRotation = fpCurrentPV->GetObjectRotationValue();
922 const G4ThreeVector& localTranslation = fpCurrentPV->GetTranslation();
923 oss.str(""); oss << '\n' << G4Transform3D(localRotation,localTranslation);
924 values->push_back(G4AttValue("LocalTrans", oss.str(),""));
925
926 oss.str(""); oss << '\n' << pSol->GetExtent() << std::endl;
927 values->push_back(G4AttValue("LocalExtent", oss.str(),""));
928
929 oss.str(""); oss << '\n' << fCurrentTransform;
930 values->push_back(G4AttValue("GlobalTrans", oss.str(),""));
931
932 oss.str(""); oss << '\n' << (pSol->GetExtent()).Transform(fCurrentTransform) << std::endl;
933 values->push_back(G4AttValue("GlobalExtent", oss.str(),""));
934
935 G4String matName = fpCurrentMaterial? fpCurrentMaterial->GetName(): G4String("No material");
936 values->push_back(G4AttValue("Material", matName,""));
937
939 values->push_back(G4AttValue("Density", G4BestUnit(matDensity,"Volumic Mass"),""));
940
942 oss.str(""); oss << matState;
943 values->push_back(G4AttValue("State", oss.str(),""));
944
946 values->push_back(G4AttValue("Radlen", G4BestUnit(matRadlen,"Length"),""));
947
948 G4Region* region = fpCurrentLV->GetRegion();
949 G4String regionName = region? region->GetName(): G4String("No region");
950 values->push_back(G4AttValue("Region", regionName,""));
951
952 oss.str(""); oss << fpCurrentLV->IsRootRegion();
953 values->push_back(G4AttValue("RootRegion", oss.str(),""));
954
955 return values;
956}
957
958G4bool G4PhysicalVolumeModel::G4PhysicalVolumeNodeID::operator<
960{
961 if (fpPV < right.fpPV) return true;
962 if (fpPV == right.fpPV) {
963 if (fCopyNo < right.fCopyNo) return true;
964 if (fCopyNo == right.fCopyNo)
965 return fNonCulledDepth < right.fNonCulledDepth;
966 }
967 return false;
968}
969
970G4bool G4PhysicalVolumeModel::G4PhysicalVolumeNodeID::operator!=
972{
973 if (fpPV != right.fpPV ||
974 fCopyNo != right.fCopyNo ||
975 fNonCulledDepth != right.fNonCulledDepth ||
976 fTransform != right.fTransform ||
977 fDrawn != right.fDrawn) return true;
978 return false;
979}
980
981std::ostream& operator<<
982 (std::ostream& os, const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID& node)
983{
984 G4VPhysicalVolume* pPV = node.GetPhysicalVolume();
985 if (pPV) {
986 os << pPV->GetName()
987 << ' ' << node.GetCopyNo()
988// << '[' << node.GetNonCulledDepth() << ']'
989// << ':' << node.GetTransform()
990 ;
991// os << " (";
992// if (!node.GetDrawn()) os << "not ";
993// os << "drawn)";
994 } else {
995 os << " (Null PV node)";
996 }
997 return os;
998}
999
1000std::ostream& operator<<
1001(std::ostream& os, const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>& path)
1002{
1003 if (path.empty()) {
1004 os << " TOP";
1005 } else {
1006 for (const auto& nodeID: path) {
1007 os << ' ' << nodeID;
1008 }
1009 }
1010 return os;
1011}
1012
1014(const std::vector<G4PhysicalVolumeNodeID>& fullPVPath):
1015 fFullPVPath(fullPVPath) {}
1016
1018{
1019 size_t i = fFullPVPath.size() - depth - 1;
1020 if (i >= fFullPVPath.size()) {
1021 G4Exception("G4PhysicalVolumeModelTouchable::GetTranslation",
1022 "modeling0005",
1024 "Index out of range. Asking for non-existent depth");
1025 }
1026 static G4ThreeVector tempTranslation;
1027 tempTranslation = fFullPVPath[i].GetTransform().getTranslation();
1028 return tempTranslation;
1029}
1030
1032{
1033 size_t i = fFullPVPath.size() - depth - 1;
1034 if (i >= fFullPVPath.size()) {
1035 G4Exception("G4PhysicalVolumeModelTouchable::GetRotation",
1036 "modeling0006",
1038 "Index out of range. Asking for non-existent depth");
1039 }
1040 static G4RotationMatrix tempRotation;
1041 tempRotation = fFullPVPath[i].GetTransform().getRotation();
1042 return &tempRotation;
1043}
1044
1046{
1047 size_t i = fFullPVPath.size() - depth - 1;
1048 if (i >= fFullPVPath.size()) {
1049 G4Exception("G4PhysicalVolumeModelTouchable::GetVolume",
1050 "modeling0007",
1052 "Index out of range. Asking for non-existent depth");
1053 }
1054 return fFullPVPath[i].GetPhysicalVolume();
1055}
1056
1058{
1059 size_t i = fFullPVPath.size() - depth - 1;
1060 if (i >= fFullPVPath.size()) {
1061 G4Exception("G4PhysicalVolumeModelTouchable::GetSolid",
1062 "modeling0008",
1064 "Index out of range. Asking for non-existent depth");
1065 }
1066 return fFullPVPath[i].GetPhysicalVolume()->GetLogicalVolume()->GetSolid();
1067}
1068
1070{
1071 size_t i = fFullPVPath.size() - depth - 1;
1072 if (i >= fFullPVPath.size()) {
1073 G4Exception("G4PhysicalVolumeModelTouchable::GetReplicaNumber",
1074 "modeling0009",
1076 "Index out of range. Asking for non-existent depth");
1077 }
1078 return fFullPVPath[i].GetCopyNo();
1079}
@ JustWarning
@ FatalException
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
G4State
Definition: G4Material.hh:110
@ kStateUndefined
Definition: G4Material.hh:110
#define G4warn
Definition: G4Scene.cc:41
#define G4BestUnit(a, b)
CLHEP::Hep3Vector G4ThreeVector
HepGeom::Transform3D G4Transform3D
HepGeom::Translate3D G4Translate3D
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
HepGeom::Vector3D< G4double > G4Vector3D
Definition: G4Vector3D.hh:34
#define G4endl
Definition: G4ios.hh:57
HepRotation & rotateZ(double delta)
Definition: Rotation.cc:87
const G4VisExtent & GetBoundingExtent() const
G4double GetAlpha() const
Definition: G4Colour.hh:155
G4VSolid * GetSolid() const
const G4VisAttributes * GetVisAttributes() const
std::size_t GetNoDaughters() const
G4bool IsRootRegion() const
G4Region * GetRegion() const
G4Material * GetMaterial() const
const G4String & GetName() const
G4double GetDensity() const
Definition: G4Material.hh:175
G4State GetState() const
Definition: G4Material.hh:176
G4double GetRadlen() const
Definition: G4Material.hh:215
const G4String & GetName() const
Definition: G4Material.hh:172
Definition: G4Mesh.hh:48
G4VPhysicalVolume * GetParameterisedVolume() const
Definition: G4Mesh.hh:74
MeshType GetMeshType() const
Definition: G4Mesh.hh:75
@ invalid
Definition: G4Mesh.hh:52
G4bool IsWarning() const
const G4VisAttributes * GetDefaultVisAttributes() const
const std::vector< VisAttributesModifier > & GetVisAttributesModifiers() const
const G4Point3D & GetExplodeCentre() const
std::vector< PVNameCopyNo > PVNameCopyNoPath
G4bool IsCullingInvisible() const
const std::vector< PVNameCopyNo > & GetSpecialMeshVolumes() const
G4bool IsExplode() const
G4bool IsCulling() const
const std::vector< G4double > & GetCBDParameters() const
G4bool IsDensityCulling() const
G4bool IsSpecialMeshRendering() const
DrawingStyle GetDrawingStyle() const
G4DisplacedSolid * GetSectionSolid() const
G4double GetExplodeFactor() const
G4DisplacedSolid * GetCutawaySolid() const
G4bool IsCullingCovered() const
G4int GetCBDAlgorithmNumber() const
void SetSpecialMeshRendering(G4bool)
const G4RotationMatrix * GetRotation(G4int depth) const
G4PhysicalVolumeModelTouchable(const std::vector< G4PhysicalVolumeNodeID > &fullPVPath)
const G4ThreeVector & GetTranslation(G4int depth) const
void DescribeAndDescend(G4VPhysicalVolume *, G4int requestedDepth, G4LogicalVolume *, G4VSolid *, G4Material *, const G4Transform3D &, G4VGraphicsScene &)
std::vector< G4PhysicalVolumeNodeID > fFullPVPath
G4VPhysicalVolume * fpTopPV
void VisitGeometryAndGetVisReps(G4VPhysicalVolume *, G4int requestedDepth, const G4Transform3D &, G4VGraphicsScene &)
std::vector< G4AttValue > * CreateCurrentAttValues() const
G4PhysicalVolumeModel(G4VPhysicalVolume *=0, G4int requestedDepth=UNLIMITED, const G4Transform3D &modelTransformation=G4Transform3D(), const G4ModelingParameters *=0, G4bool useFullExtent=false, const std::vector< G4PhysicalVolumeNodeID > &baseFullPVPath=std::vector< G4PhysicalVolumeNodeID >())
std::vector< G4PhysicalVolumeNodeID > fDrawnPVPath
G4bool Validate(G4bool warn)
virtual void DescribeSolid(const G4Transform3D &theAT, G4VSolid *pSol, const G4VisAttributes *pVisAttribs, G4VGraphicsScene &sceneHandler)
G4String GetCurrentDescription() const
void DescribeYourselfTo(G4VGraphicsScene &)
std::vector< G4PhysicalVolumeNodeID > fBaseFullPVPath
G4VPhysicalVolume * fpCurrentPV
const std::map< G4String, G4AttDef > * GetAttDefs() const
static G4ModelingParameters::PVNameCopyNoPath GetPVNameCopyNoPath(const std::vector< G4PhysicalVolumeNodeID > &)
static G4PhysicalVolumeStore * GetInstance()
const G4String & GetName() const
Definition: G4Tubs.hh:75
virtual void AddCompound(const G4VTrajectory &)=0
virtual void PostAddSolid()=0
virtual void PreAddSolid(const G4Transform3D &objectTransformation, const G4VisAttributes &visAttribs)=0
G4VisExtent fExtent
Definition: G4VModel.hh:101
G4String fGlobalDescription
Definition: G4VModel.hh:100
const G4VisExtent & GetExtent() const
G4String fType
Definition: G4VModel.hh:98
const G4ModelingParameters * fpMP
Definition: G4VModel.hh:102
G4String fGlobalTag
Definition: G4VModel.hh:99
const G4ThreeVector GetTranslation() const
G4LogicalVolume * GetLogicalVolume() const
G4RotationMatrix GetObjectRotationValue() const
virtual G4int GetCopyNo() const =0
const G4String & GetName() const
G4String GetName() const
virtual G4VisExtent GetExtent() const
Definition: G4VSolid.cc:682
virtual G4GeometryType GetEntityType() const =0
G4int GetForcedNumberOfCloudPoints() const
G4double GetLineWidth() const
G4bool IsDaughtersInvisible() const
void SetColour(const G4Colour &)
void SetVisibility(G4bool=true)
void SetForceAuxEdgeVisible(G4bool=true)
void SetForceCloud(G4bool=true)
G4int GetForcedLineSegmentsPerCircle() const
void SetForceWireframe(G4bool=true)
void SetLineWidth(G4double)
LineStyle GetLineStyle() const
const G4Colour & GetColour() const
G4bool IsVisible() const
G4bool IsForceAuxEdgeVisible() const
G4bool IsForcedAuxEdgeVisible() const
ForcedDrawingStyle GetForcedDrawingStyle() const
void SetForceSolid(G4bool=true)
void SetLineStyle(LineStyle)
void SetForceLineSegmentsPerCircle(G4int nSegments)
void SetDaughtersInvisible(G4bool=true)
void SetForceNumberOfCloudPoints(G4int nPoints)
G4bool IsForceDrawingStyle() const
G4double GetExtentRadius() const
Definition: G4VisExtent.cc:75
G4VisExtent & Transform(const G4Transform3D &)
Definition: G4VisExtent.cc:102
double dy() const
Definition: Transform3D.h:287
double zz() const
Definition: Transform3D.h:281
double yz() const
Definition: Transform3D.h:272
double dz() const
Definition: Transform3D.h:290
double dx() const
Definition: Transform3D.h:284
void getDecomposition(Scale3D &scale, Rotate3D &rotation, Translate3D &translation) const
Definition: Transform3D.cc:173
double xy() const
Definition: Transform3D.h:260
double zx() const
Definition: Transform3D.h:275
double yx() const
Definition: Transform3D.h:266
Transform3D inverse() const
Definition: Transform3D.cc:141
double zy() const
Definition: Transform3D.h:278
double xx() const
Definition: Transform3D.h:257
double yy() const
Definition: Transform3D.h:269
double xz() const
Definition: Transform3D.h:263
EAxis
Definition: geomdefs.hh:54
@ kPhi
Definition: geomdefs.hh:60
@ kYAxis
Definition: geomdefs.hh:56
@ kXAxis
Definition: geomdefs.hh:55
@ kZAxis
Definition: geomdefs.hh:57
@ kRho
Definition: geomdefs.hh:58
std::map< G4String, G4AttDef > * GetInstance(const G4String &storeKey, G4bool &isNew)