Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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 // $Id$
28 //
29 //
30 // John Allison 31st December 1997.
31 // Model for physical volumes.
32 
33 #include "G4PhysicalVolumeModel.hh"
34 
35 #include "G4ModelingParameters.hh"
36 #include "G4VGraphicsScene.hh"
37 #include "G4VPhysicalVolume.hh"
38 #include "G4VPVParameterisation.hh"
39 #include "G4LogicalVolume.hh"
40 #include "G4VSolid.hh"
41 #include "G4SubtractionSolid.hh"
42 #include "G4IntersectionSolid.hh"
43 #include "G4Material.hh"
44 #include "G4VisAttributes.hh"
45 #include "G4BoundingSphereScene.hh"
48 #include "G4Polyhedron.hh"
49 #include "HepPolyhedronProcessor.h"
50 #include "G4AttDefStore.hh"
51 #include "G4AttDef.hh"
52 #include "G4AttValue.hh"
53 #include "G4UnitsTable.hh"
54 #include "G4Vector3D.hh"
55 
56 #include <sstream>
57 
60  G4int requestedDepth,
61  const G4Transform3D& modelTransformation,
62  const G4ModelingParameters* pMP,
63  G4bool useFullExtent):
64  G4VModel (modelTransformation, pMP),
65  fpTopPV (pVPV),
66  fRequestedDepth (requestedDepth),
67  fUseFullExtent (useFullExtent),
68  fCurrentDepth (0),
69  fpCurrentPV (0),
70  fpCurrentLV (0),
71  fpCurrentMaterial (0),
72  fpCurrentTransform (0),
73  fCurtailDescent (false),
74  fpClippingSolid (0),
75  fClippingMode (subtraction)
76 {
77  if (fpTopPV) {
78 
79  fType = "G4PhysicalVolumeModel";
80  fTopPVName = fpTopPV -> GetName ();
81  fTopPVCopyNo = fpTopPV -> GetCopyNo ();
82  std::ostringstream o;
83  o << fpTopPV -> GetCopyNo ();
84  fGlobalTag = fpTopPV -> GetName () + "." + o.str();
85  fGlobalDescription = "G4PhysicalVolumeModel " + fGlobalTag;
86 
87  CalculateExtent ();
88  }
89 }
90 
92 {
93  delete fpClippingSolid;
94 }
95 
97 {
98  if (fUseFullExtent) {
99  fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
100  }
101  else {
102  G4BoundingSphereScene bsScene(this);
103  const G4int tempRequestedDepth = fRequestedDepth;
104  fRequestedDepth = -1; // Always search to all depths to define extent.
105  const G4ModelingParameters* tempMP = fpMP;
106  G4ModelingParameters mParams
107  (0, // No default vis attributes needed.
108  G4ModelingParameters::wf, // wireframe (not relevant for this).
109  true, // Global culling.
110  true, // Cull invisible volumes.
111  false, // Density culling.
112  0., // Density (not relevant if density culling false).
113  true, // Cull daughters of opaque mothers.
114  24); // No of sides (not relevant for this operation).
115  fpMP = &mParams;
116  DescribeYourselfTo (bsScene);
117  G4double radius = bsScene.GetRadius();
118  if (radius < 0.) { // Nothing in the scene.
119  fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
120  } else {
121  // Transform back to coordinates relative to the top
122  // transformation, which is in G4VModel::fTransform. This makes
123  // it conform to all models, which are defined by a
124  // transformation and an extent relative to that
125  // transformation...
126  G4Point3D centre = bsScene.GetCentre();
127  centre.transform(fTransform.inverse());
128  fExtent = G4VisExtent(centre, radius);
129  }
130  fpMP = tempMP;
131  fRequestedDepth = tempRequestedDepth;
132  }
133 }
134 
136 (G4VGraphicsScene& sceneHandler)
137 {
138  if (!fpTopPV) G4Exception
139  ("G4PhysicalVolumeModel::DescribeYourselfTo",
140  "modeling0012", FatalException, "No model.");
141 
142  if (!fpMP) G4Exception
143  ("G4PhysicalVolumeModel::DescribeYourselfTo",
144  "modeling0003", FatalException, "No modeling parameters.");
145 
146  // For safety...
147  fCurrentDepth = 0;
148 
149  G4Transform3D startingTransformation = fTransform;
150 
151  VisitGeometryAndGetVisReps
152  (fpTopPV,
153  fRequestedDepth,
154  startingTransformation,
155  sceneHandler);
156 
157  // Clear data...
158  fCurrentDepth = 0;
159  fpCurrentPV = 0;
160  fpCurrentLV = 0;
161  fpCurrentMaterial = 0;
162  if (fFullPVPath.size() != fBaseFullPVPath.size()) {
163  // They should be equal if pushing and popping is happening properly.
165  ("G4PhysicalVolumeModel::DescribeYourselfTo",
166  "modeling0013",
168  "Path at start of modeling not equal to base path. Something badly"
169  "\nwrong. Please contact visualisation coordinator.");
170  }
171  fDrawnPVPath.clear();
172 }
173 
175 {
176  if (fpCurrentPV) {
177  std::ostringstream o;
178  o << fpCurrentPV -> GetCopyNo ();
179  return fpCurrentPV -> GetName () + "." + o.str();
180  }
181  else {
182  return "WARNING: NO CURRENT VOLUME - global tag is " + fGlobalTag;
183  }
184 }
185 
187 {
188  return "G4PhysicalVolumeModel " + GetCurrentTag ();
189 }
190 
193  G4int requestedDepth,
194  const G4Transform3D& theAT,
195  G4VGraphicsScene& sceneHandler)
196 {
197  // Visits geometry structure to a given depth (requestedDepth), starting
198  // at given physical volume with given starting transformation and
199  // describes volumes to the scene handler.
200  // requestedDepth < 0 (default) implies full visit.
201  // theAT is the Accumulated Transformation.
202 
203  // Find corresponding logical volume and (later) solid, storing in
204  // local variables to preserve re-entrancy.
205  G4LogicalVolume* pLV = pVPV -> GetLogicalVolume ();
206 
207  G4VSolid* pSol;
208  G4Material* pMaterial;
209 
210  if (!(pVPV -> IsReplicated ())) {
211  // Non-replicated physical volume.
212  pSol = pLV -> GetSolid ();
213  pMaterial = pLV -> GetMaterial ();
214  DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
215  theAT, sceneHandler);
216  }
217  else {
218  // Replicated or parametrised physical volume.
219  EAxis axis;
220  G4int nReplicas;
221  G4double width;
222  G4double offset;
223  G4bool consuming;
224  pVPV -> GetReplicationData (axis, nReplicas, width, offset, consuming);
225  if (fCurrentDepth == 0) nReplicas = 1; // Just draw first
226  G4VPVParameterisation* pP = pVPV -> GetParameterisation ();
227  if (pP) { // Parametrised volume.
228  for (int n = 0; n < nReplicas; n++) {
229  pSol = pP -> ComputeSolid (n, pVPV);
230  pP -> ComputeTransformation (n, pVPV);
231  pSol -> ComputeDimensions (pP, n, pVPV);
232  pVPV -> SetCopyNo (n);
233  // Create a touchable of current parent for ComputeMaterial.
234  // fFullPVPath has not been updated yet so at this point it
235  // corresponds to the parent.
236  G4PhysicalVolumeModelTouchable parentTouchable(fFullPVPath);
237  pMaterial = pP -> ComputeMaterial (n, pVPV, &parentTouchable);
238  DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
239  theAT, sceneHandler);
240  }
241  }
242  else { // Plain replicated volume. From geometry_guide.txt...
243  // The replica's positions are claculated by means of a linear formula.
244  // Replication may occur along:
245  //
246  // o Cartesian axes (kXAxis,kYAxis,kZAxis)
247  //
248  // The replications, of specified width have coordinates of
249  // form (-width*(nReplicas-1)*0.5+n*width,0,0) where n=0.. nReplicas-1
250  // for the case of kXAxis, and are unrotated.
251  //
252  // o Radial axis (cylindrical polar) (kRho)
253  //
254  // The replications are cons/tubs sections, centred on the origin
255  // and are unrotated.
256  // They have radii of width*n+offset to width*(n+1)+offset
257  // where n=0..nReplicas-1
258  //
259  // o Phi axis (cylindrical polar) (kPhi)
260  // The replications are `phi sections' or wedges, and of cons/tubs form
261  // They have phi of offset+n*width to offset+(n+1)*width where
262  // n=0..nReplicas-1
263  //
264  pSol = pLV -> GetSolid ();
265  pMaterial = pLV -> GetMaterial ();
266  G4ThreeVector originalTranslation = pVPV -> GetTranslation ();
267  G4RotationMatrix* pOriginalRotation = pVPV -> GetRotation ();
268  G4double originalRMin = 0., originalRMax = 0.;
269  if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
270  originalRMin = ((G4Tubs*)pSol)->GetInnerRadius();
271  originalRMax = ((G4Tubs*)pSol)->GetOuterRadius();
272  }
273  G4bool visualisable = true;
274  for (int n = 0; n < nReplicas; n++) {
275  G4ThreeVector translation; // Null.
276  G4RotationMatrix rotation; // Null - life long enough for visualizing.
277  G4RotationMatrix* pRotation = 0;
278  switch (axis) {
279  default:
280  case kXAxis:
281  translation = G4ThreeVector (-width*(nReplicas-1)*0.5+n*width,0,0);
282  break;
283  case kYAxis:
284  translation = G4ThreeVector (0,-width*(nReplicas-1)*0.5+n*width,0);
285  break;
286  case kZAxis:
287  translation = G4ThreeVector (0,0,-width*(nReplicas-1)*0.5+n*width);
288  break;
289  case kRho:
290  if (pSol->GetEntityType() == "G4Tubs") {
291  ((G4Tubs*)pSol)->SetInnerRadius(width*n+offset);
292  ((G4Tubs*)pSol)->SetOuterRadius(width*(n+1)+offset);
293  } else {
294  if (fpMP->IsWarning())
295  G4cout <<
296  "G4PhysicalVolumeModel::VisitGeometryAndGetVisReps: WARNING:"
297  "\n built-in replicated volumes replicated in radius for "
298  << pSol->GetEntityType() <<
299  "-type\n solids (your solid \""
300  << pSol->GetName() <<
301  "\") are not visualisable."
302  << G4endl;
303  visualisable = false;
304  }
305  break;
306  case kPhi:
307  rotation.rotateZ (-(offset+(n+0.5)*width));
308  // Minus Sign because for the physical volume we need the
309  // coordinate system rotation.
310  pRotation = &rotation;
311  break;
312  }
313  pVPV -> SetTranslation (translation);
314  pVPV -> SetRotation (pRotation);
315  pVPV -> SetCopyNo (n);
316  if (visualisable) {
317  DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
318  theAT, sceneHandler);
319  }
320  }
321  // Restore originals...
322  pVPV -> SetTranslation (originalTranslation);
323  pVPV -> SetRotation (pOriginalRotation);
324  if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
325  ((G4Tubs*)pSol)->SetInnerRadius(originalRMin);
326  ((G4Tubs*)pSol)->SetOuterRadius(originalRMax);
327  }
328  }
329  }
330 
331  return;
332 }
333 
336  G4int requestedDepth,
337  G4LogicalVolume* pLV,
338  G4VSolid* pSol,
339  G4Material* pMaterial,
340  const G4Transform3D& theAT,
341  G4VGraphicsScene& sceneHandler)
342 {
343  // Maintain useful data members...
344  fpCurrentPV = pVPV;
345  fpCurrentLV = pLV;
346  fpCurrentMaterial = pMaterial;
347 
348  const G4RotationMatrix objectRotation = pVPV -> GetObjectRotationValue ();
349  const G4ThreeVector& translation = pVPV -> GetTranslation ();
350  G4Transform3D theLT (G4Transform3D (objectRotation, translation));
351 
352  // Compute the accumulated transformation...
353  // Note that top volume's transformation relative to the world
354  // coordinate system is specified in theAT == startingTransformation
355  // = fTransform (see DescribeYourselfTo), so first time through the
356  // volume's own transformation, which is only relative to its
357  // mother, i.e., not relative to the world coordinate system, should
358  // not be accumulated.
359  G4Transform3D theNewAT (theAT);
360  if (fCurrentDepth != 0) theNewAT = theAT * theLT;
361  fpCurrentTransform = &theNewAT;
362 
363  const G4VisAttributes* pVisAttribs = pLV->GetVisAttributes();
364  if (!pVisAttribs) pVisAttribs = fpMP->GetDefaultVisAttributes();
365  // Beware - pVisAttribs might still be zero - create a temporary default one...
366  G4bool visAttsCreated = false;
367  if (!pVisAttribs) {
368  pVisAttribs = new G4VisAttributes;
369  visAttsCreated = true;
370  }
371  // From here, can assume pVisAttribs is a valid pointer.
372 
373  // Make decision to draw...
374  G4bool thisToBeDrawn = true;
375 
376  // Update full path of physical volumes...
377  G4int copyNo = fpCurrentPV->GetCopyNo();
378  fFullPVPath.push_back
380  (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform));
381 
382  // In case we need to copy the vis atts for modification...
383  G4bool copyForVAM = false;
384  const G4VisAttributes* pUnmodifiedVisAtts = pVisAttribs;
385  G4VisAttributes* pModifiedVisAtts = 0;
386 
387  // Check if vis attributes are to be modified by a /vis/touchable/set/ command.
388  const std::vector<G4ModelingParameters::VisAttributesModifier>& vams =
389  fpMP->GetVisAttributesModifiers();
390  std::vector<G4ModelingParameters::VisAttributesModifier>::const_iterator
391  iModifier;
392  for (iModifier = vams.begin();
393  iModifier != vams.end();
394  ++iModifier) {
396  iModifier->GetPVNameCopyNoPath();
397  if (vamPath.size() == fFullPVPath.size()) {
398  // OK - there's a size match. Check it out.
399 // G4cout << "Size match" << G4endl;
401  std::vector<G4PhysicalVolumeNodeID>::const_iterator iPVNodeId;
402  for (iVAMNameCopyNo = vamPath.begin(), iPVNodeId = fFullPVPath.begin();
403  iVAMNameCopyNo != vamPath.end();
404  ++iVAMNameCopyNo, ++iPVNodeId) {
405 // G4cout
406 // << iVAMNameCopyNo->fName
407 // << ',' << iVAMNameCopyNo->fCopyNo
408 // << "; " << iPVNodeId->GetPhysicalVolume()->GetName()
409 // << ',' << iPVNodeId->GetPhysicalVolume()->GetCopyNo()
410 // << G4endl;
411  if (!(
412  iVAMNameCopyNo->GetName() ==
413  iPVNodeId->GetPhysicalVolume()->GetName() &&
414  iVAMNameCopyNo->GetCopyNo() ==
415  iPVNodeId->GetPhysicalVolume()->GetCopyNo()
416  )) {
417  break;
418  }
419  }
420  if (iVAMNameCopyNo == vamPath.end()) {
421 // G4cout << "Match found" << G4endl;
422  if (!copyForVAM) {
423  pModifiedVisAtts = new G4VisAttributes(*pUnmodifiedVisAtts);
424  pVisAttribs = pModifiedVisAtts;
425  copyForVAM = true;
426  }
427  const G4VisAttributes& transVisAtts = iModifier->GetVisAttributes();
428  switch (iModifier->GetVisAttributesSignifier()) {
430  pModifiedVisAtts->SetVisibility(transVisAtts.IsVisible());
431  break;
433  pModifiedVisAtts->SetDaughtersInvisible
434  (transVisAtts.IsDaughtersInvisible());
435  break;
437  pModifiedVisAtts->SetColour(transVisAtts.GetColour());
438  break;
440  pModifiedVisAtts->SetLineStyle(transVisAtts.GetLineStyle());
441  break;
443  pModifiedVisAtts->SetLineWidth(transVisAtts.GetLineWidth());
444  break;
446  if (transVisAtts.GetForcedDrawingStyle() ==
448  pModifiedVisAtts->SetForceWireframe
449  (transVisAtts.IsForceDrawingStyle());
450  }
451  break;
453  if (transVisAtts.GetForcedDrawingStyle() ==
455  pModifiedVisAtts->SetForceSolid
456  (transVisAtts.IsForceDrawingStyle());
457  }
458  break;
460  pModifiedVisAtts->SetForceAuxEdgeVisible
461  (transVisAtts.IsForceAuxEdgeVisible());
462  break;
464  pModifiedVisAtts->SetForceLineSegmentsPerCircle
465  (transVisAtts.GetForcedLineSegmentsPerCircle());
466  break;
467  }
468  }
469  }
470  }
471 
472  // There are various reasons why this volume
473  // might not be drawn...
474  G4bool culling = fpMP->IsCulling();
475  G4bool cullingInvisible = fpMP->IsCullingInvisible();
476  G4bool markedVisible = pVisAttribs->IsVisible();
477  G4bool cullingLowDensity = fpMP->IsDensityCulling();
478  G4double density = pMaterial? pMaterial->GetDensity(): 0;
479  G4double densityCut = fpMP -> GetVisibleDensity ();
480 
481  // 1) Global culling is on....
482  if (culling) {
483  // 2) Culling of invisible volumes is on...
484  if (cullingInvisible) {
485  // 3) ...and the volume is marked not visible...
486  if (!markedVisible) thisToBeDrawn = false;
487  }
488  // 4) Or culling of low density volumes is on...
489  if (cullingLowDensity) {
490  // 5) ...and density is less than cut value...
491  if (density < densityCut) thisToBeDrawn = false;
492  }
493  }
494 
495  // Record thisToBeDrawn in path...
496  fFullPVPath.back().SetDrawn(thisToBeDrawn);
497 
498  if (thisToBeDrawn) {
499 
500  // Update path of drawn physical volumes...
501  fDrawnPVPath.push_back
503  (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform,thisToBeDrawn));
504 
505  if (fpMP->IsExplode() && fDrawnPVPath.size() == 1) {
506  // For top-level drawn volumes, explode along radius...
507  G4Transform3D centering = G4Translate3D(fpMP->GetExplodeCentre());
508  G4Transform3D centred = centering.inverse() * theNewAT;
509  G4Scale3D oldScale;
510  G4Rotate3D oldRotation;
511  G4Translate3D oldTranslation;
512  centred.getDecomposition(oldScale, oldRotation, oldTranslation);
513  G4double explodeFactor = fpMP->GetExplodeFactor();
514  G4Translate3D newTranslation =
515  G4Translate3D(explodeFactor * oldTranslation.dx(),
516  explodeFactor * oldTranslation.dy(),
517  explodeFactor * oldTranslation.dz());
518  theNewAT = centering * newTranslation * oldRotation * oldScale;
519  }
520 
521  DescribeSolid (theNewAT, pSol, pVisAttribs, sceneHandler);
522 
523  }
524 
525  // Make decision to draw daughters, if any. There are various
526  // reasons why daughters might not be drawn...
527 
528  // First, reasons that do not depend on culling policy...
529  G4int nDaughters = pLV->GetNoDaughters();
530  G4bool daughtersToBeDrawn = true;
531  // 1) There are no daughters...
532  if (!nDaughters) daughtersToBeDrawn = false;
533  // 2) We are at the limit if requested depth...
534  else if (requestedDepth == 0) daughtersToBeDrawn = false;
535  // 3) The user has asked that the descent be curtailed...
536  else if (fCurtailDescent) daughtersToBeDrawn = false;
537 
538  // Now, reasons that depend on culling policy...
539  else {
540  G4bool daughtersInvisible = pVisAttribs->IsDaughtersInvisible();
541  // Culling of covered daughters request. This is computed in
542  // G4VSceneHandler::CreateModelingParameters() depending on view
543  // parameters...
544  G4bool cullingCovered = fpMP->IsCullingCovered();
545  G4bool surfaceDrawing =
546  fpMP->GetDrawingStyle() == G4ModelingParameters::hsr ||
547  fpMP->GetDrawingStyle() == G4ModelingParameters::hlhsr;
548  if (pVisAttribs->IsForceDrawingStyle()) {
549  switch (pVisAttribs->GetForcedDrawingStyle()) {
550  default:
551  case G4VisAttributes::wireframe: surfaceDrawing = false; break;
552  case G4VisAttributes::solid: surfaceDrawing = true; break;
553  }
554  }
555  G4bool opaque = pVisAttribs->GetColour().GetAlpha() >= 1.;
556  // 4) Global culling is on....
557  if (culling) {
558  // 5) ..and culling of invisible volumes is on...
559  if (cullingInvisible) {
560  // 6) ...and the mother requests daughters invisible
561  if (daughtersInvisible) daughtersToBeDrawn = false;
562  }
563  // 7) Or culling of covered daughters is requested...
564  if (cullingCovered) {
565  // 8) ...and surface drawing is operating...
566  if (surfaceDrawing) {
567  // 9) ...but only if mother is visible...
568  if (thisToBeDrawn) {
569  // 10) ...and opaque...
570  if (opaque) daughtersToBeDrawn = false;
571  }
572  }
573  }
574  }
575  }
576 
577  // Delete modified vis atts if created...
578  if (copyForVAM) {
579  delete pModifiedVisAtts;
580  pVisAttribs = pUnmodifiedVisAtts;
581  }
582 
583  // Vis atts for this volume no longer needed if created...
584  if (visAttsCreated) delete pVisAttribs;
585 
586  if (daughtersToBeDrawn) {
587  for (G4int iDaughter = 0; iDaughter < nDaughters; iDaughter++) {
588  // Store daughter pVPV in local variable ready for recursion...
589  G4VPhysicalVolume* pDaughterVPV = pLV -> GetDaughter (iDaughter);
590  // Descend the geometry structure recursively...
591  fCurrentDepth++;
592  VisitGeometryAndGetVisReps
593  (pDaughterVPV, requestedDepth - 1, theNewAT, sceneHandler);
594  fCurrentDepth--;
595  }
596  }
597 
598  // Reset for normal descending of next volume at this level...
599  fCurtailDescent = false;
600 
601  // Pop item from paths physical volumes...
602  fFullPVPath.pop_back();
603  if (thisToBeDrawn) {
604  fDrawnPVPath.pop_back();
605  }
606 }
607 
609 (const G4Transform3D& theAT,
610  G4VSolid* pSol,
611  const G4VisAttributes* pVisAttribs,
612  G4VGraphicsScene& sceneHandler)
613 {
614  sceneHandler.PreAddSolid (theAT, *pVisAttribs);
615 
616  G4VSolid* pSectionSolid = fpMP->GetSectionSolid();
617  G4VSolid* pCutawaySolid = fpMP->GetCutawaySolid();
618 
619  if (!fpClippingSolid && !pSectionSolid && !pCutawaySolid) {
620 
621  pSol -> DescribeYourselfTo (sceneHandler); // Standard treatment.
622 
623  } else {
624 
625  // Clipping, etc., performed by Boolean operations.
626 
627  // First, get polyhedron for current solid...
628  if (pVisAttribs->IsForceLineSegmentsPerCircle())
630  (pVisAttribs->GetForcedLineSegmentsPerCircle());
631  else
632  G4Polyhedron::SetNumberOfRotationSteps(fpMP->GetNoOfSides());
633  const G4Polyhedron* pOriginal = pSol->GetPolyhedron();
635 
636  if (!pOriginal) {
637 
638  if (fpMP->IsWarning())
639  G4cout <<
640  "WARNING: G4PhysicalVolumeModel::DescribeSolid: solid\n \""
641  << pSol->GetName() <<
642  "\" has no polyhedron. Cannot by clipped."
643  << G4endl;
644  pSol -> DescribeYourselfTo (sceneHandler); // Standard treatment.
645 
646  } else {
647 
648  G4Polyhedron resultant(*pOriginal);
649  G4VisAttributes resultantVisAttribs(*pVisAttribs);
650  G4VSolid* resultantSolid = 0;
651 
652  if (fpClippingSolid) {
653  switch (fClippingMode) {
654  default:
655  case subtraction:
656  resultantSolid = new G4SubtractionSolid
657  ("resultant_solid", pSol, fpClippingSolid, theAT.inverse());
658  break;
659  case intersection:
660  resultantSolid = new G4IntersectionSolid
661  ("resultant_solid", pSol, fpClippingSolid, theAT.inverse());
662  break;
663  }
664  }
665 
666  if (pSectionSolid) {
667  resultantSolid = new G4IntersectionSolid
668  ("sectioned_solid", pSol, pSectionSolid, theAT.inverse());
669  }
670 
671  if (pCutawaySolid) {
672  resultantSolid = new G4SubtractionSolid
673  ("cutaway_solid", pSol, pCutawaySolid, theAT.inverse());
674  }
675 
676  G4Polyhedron* tmpResultant = resultantSolid->GetPolyhedron();
677  if (tmpResultant) resultant = *tmpResultant;
678  else {
679  if (fpMP->IsWarning())
680  G4cout <<
681  "WARNING: G4PhysicalVolumeModel::DescribeSolid: resultant polyhedron for"
682  "\n solid \"" << pSol->GetName() <<
683  "\" not defined due to error during Boolean processing."
684  "\n Original will be drawn in red."
685  << G4endl;
686  resultantVisAttribs.SetColour(G4Colour::Red());
687  }
688 
689  delete resultantSolid;
690 
691  // Finally, force polyhedron drawing...
692  resultant.SetVisAttributes(resultantVisAttribs);
693  sceneHandler.BeginPrimitives(theAT);
694  sceneHandler.AddPrimitive(resultant);
695  sceneHandler.EndPrimitives();
696  }
697  }
698  sceneHandler.PostAddSolid ();
699 }
700 
702 {
703  G4TransportationManager* transportationManager =
705 
706  size_t nWorlds = transportationManager->GetNoWorlds();
707 
708  G4bool found = false;
709 
710  std::vector<G4VPhysicalVolume*>::iterator iterWorld =
711  transportationManager->GetWorldsIterator();
712  for (size_t i = 0; i < nWorlds; ++i, ++iterWorld) {
713  G4VPhysicalVolume* world = (*iterWorld);
714  // The idea now is to seek a PV with the same name and copy no
715  // in the hope it's the same one!!
716  G4PhysicalVolumeModel searchModel (world);
717  G4PhysicalVolumeSearchScene searchScene
718  (&searchModel, fTopPVName, fTopPVCopyNo);
719  G4ModelingParameters mp; // Default modeling parameters for this search.
721  searchModel.SetModelingParameters (&mp);
722  searchModel.DescribeYourselfTo (searchScene);
723  G4VPhysicalVolume* foundVolume = searchScene.GetFoundVolume ();
724  if (foundVolume) {
725  if (foundVolume != fpTopPV && warn) {
726  G4cout <<
727  "G4PhysicalVolumeModel::Validate(): A volume of the same name and"
728  "\n copy number (\""
729  << fTopPVName << "\", copy " << fTopPVCopyNo
730  << ") still exists and is being used."
731  "\n But it is not the same volume you originally specified"
732  "\n in /vis/scene/add/."
733  << G4endl;
734  }
735  fpTopPV = foundVolume;
736  CalculateExtent ();
737  found = true;
738  }
739  }
740  if (found) return true;
741  else {
742  if (warn) {
743  G4cout <<
744  "G4PhysicalVolumeModel::Validate(): No volume of name and"
745  "\n copy number (\""
746  << fTopPVName << "\", copy " << fTopPVCopyNo
747  << ") exists."
748  << G4endl;
749  }
750  return false;
751  }
752 }
753 
754 const std::map<G4String,G4AttDef>* G4PhysicalVolumeModel::GetAttDefs() const
755 {
756  G4bool isNew;
757  std::map<G4String,G4AttDef>* store
758  = G4AttDefStore::GetInstance("G4PhysicalVolumeModel", isNew);
759  if (isNew) {
760  (*store)["PVPath"] =
761  G4AttDef("PVPath","Physical Volume Path","Physics","","G4String");
762  (*store)["LVol"] =
763  G4AttDef("LVol","Logical Volume","Physics","","G4String");
764  (*store)["Solid"] =
765  G4AttDef("Solid","Solid Name","Physics","","G4String");
766  (*store)["EType"] =
767  G4AttDef("EType","Entity Type","Physics","","G4String");
768  (*store)["DmpSol"] =
769  G4AttDef("DmpSol","Dump of Solid properties","Physics","","G4String");
770  (*store)["Trans"] =
771  G4AttDef("Trans","Transformation of volume","Physics","","G4String");
772  (*store)["Material"] =
773  G4AttDef("Material","Material Name","Physics","","G4String");
774  (*store)["Density"] =
775  G4AttDef("Density","Material Density","Physics","G4BestUnit","G4double");
776  (*store)["State"] =
777  G4AttDef("State","Material State (enum undefined,solid,liquid,gas)","Physics","","G4String");
778  (*store)["Radlen"] =
779  G4AttDef("Radlen","Material Radiation Length","Physics","G4BestUnit","G4double");
780  (*store)["Region"] =
781  G4AttDef("Region","Cuts Region","Physics","","G4String");
782  (*store)["RootRegion"] =
783  G4AttDef("RootRegion","Root Region (0/1 = false/true)","Physics","","G4bool");
784  }
785  return store;
786 }
787 
788 #include <iomanip>
789 
790 static std::ostream& operator<< (std::ostream& o, const G4Transform3D t)
791 {
792  using namespace std;
793 
794  G4Scale3D sc;
795  G4Rotate3D r;
796  G4Translate3D tl;
797  t.getDecomposition(sc, r, tl);
798 
799  const int w = 10;
800 
801  // Transformation itself
802  o << setw(w) << t.xx() << setw(w) << t.xy() << setw(w) << t.xz() << setw(w) << t.dx() << endl;
803  o << setw(w) << t.yx() << setw(w) << t.yy() << setw(w) << t.yz() << setw(w) << t.dy() << endl;
804  o << setw(w) << t.zx() << setw(w) << t.zy() << setw(w) << t.zz() << setw(w) << t.dz() << endl;
805 
806  // Translation
807  o << "= translation:" << endl;
808  o << setw(w) << tl.dx() << setw(w) << tl.dy() << setw(w) << tl.dz() << endl;
809 
810  // Rotation
811  o << "* rotation:" << endl;
812  o << setw(w) << r.xx() << setw(w) << r.xy() << setw(w) << r.xz() << endl;
813  o << setw(w) << r.yx() << setw(w) << r.yy() << setw(w) << r.yz() << endl;
814  o << setw(w) << r.zx() << setw(w) << r.zy() << setw(w) << r.zz() << endl;
815 
816  // Scale
817  o << "* scale:" << endl;
818  o << setw(w) << sc.xx() << setw(w) << sc.yy() << setw(w) << sc.zz() << endl;
819 
820  // Transformed axes
821  o << "Transformed axes:" << endl;
822  o << "x': " << r * G4Vector3D(1., 0., 0.) << endl;
823  o << "y': " << r * G4Vector3D(0., 1., 0.) << endl;
824  o << "z': " << r * G4Vector3D(0., 0., 1.) << endl;
825 
826  return o;
827 }
828 
829 std::vector<G4AttValue>* G4PhysicalVolumeModel::CreateCurrentAttValues() const
830 {
831  std::vector<G4AttValue>* values = new std::vector<G4AttValue>;
832  std::ostringstream oss;
833  for (size_t i = 0; i < fFullPVPath.size(); ++i) {
834  oss << fFullPVPath[i].GetPhysicalVolume()->GetName()
835  << ':' << fFullPVPath[i].GetCopyNo();
836  if (i != fFullPVPath.size() - 1) oss << '/';
837  }
838 
839  if (!fpCurrentLV) {
841  ("G4PhysicalVolumeModel::CreateCurrentAttValues",
842  "modeling0004",
843  JustWarning,
844  "Current logical volume not defined.");
845  return values;
846  }
847 
848  values->push_back(G4AttValue("PVPath", oss.str(),""));
849  values->push_back(G4AttValue("LVol", fpCurrentLV->GetName(),""));
850  G4VSolid* pSol = fpCurrentLV->GetSolid();
851  values->push_back(G4AttValue("Solid", pSol->GetName(),""));
852  values->push_back(G4AttValue("EType", pSol->GetEntityType(),""));
853  oss.str(""); oss << '\n' << *pSol;
854  values->push_back(G4AttValue("DmpSol", oss.str(),""));
855  oss.str(""); oss << '\n' << *fpCurrentTransform;
856  values->push_back(G4AttValue("Trans", oss.str(),""));
857  G4String matName = fpCurrentMaterial? fpCurrentMaterial->GetName(): G4String("No material");
858  values->push_back(G4AttValue("Material", matName,""));
860  values->push_back(G4AttValue("Density", G4BestUnit(matDensity,"Volumic Mass"),""));
862  oss.str(""); oss << matState;
863  values->push_back(G4AttValue("State", oss.str(),""));
865  values->push_back(G4AttValue("Radlen", G4BestUnit(matRadlen,"Length"),""));
866  G4Region* region = fpCurrentLV->GetRegion();
867  G4String regionName = region? region->GetName(): G4String("No region");
868  values->push_back(G4AttValue("Region", regionName,""));
869  oss.str(""); oss << fpCurrentLV->IsRootRegion();
870  values->push_back(G4AttValue("RootRegion", oss.str(),""));
871  return values;
872 }
873 
874 G4bool G4PhysicalVolumeModel::G4PhysicalVolumeNodeID::operator<
876 {
877  if (fpPV < right.fpPV) return true;
878  if (fpPV == right.fpPV) {
879  if (fCopyNo < right.fCopyNo) return true;
880  if (fCopyNo == right.fCopyNo)
881  return fNonCulledDepth < right.fNonCulledDepth;
882  }
883  return false;
884 }
885 
886 std::ostream& operator<<
887  (std::ostream& os, const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID node)
888 {
889  G4VPhysicalVolume* pPV = node.GetPhysicalVolume();
890  if (pPV) {
891  os << pPV->GetName()
892  << ':' << node.GetCopyNo()
893  << '[' << node.GetNonCulledDepth() << ']'
894  << ':' << node.GetTransform();
895  if (!node.GetDrawn()) os << " Not "; os << "drawn";
896  } else {
897  os << "Null node";
898  }
899  return os;
900 }
901 
903 (const std::vector<G4PhysicalVolumeNodeID>& fullPVPath):
904  fFullPVPath(fullPVPath) {}
905 
907 {
908  size_t i = fFullPVPath.size() - depth - 1;
909  if (i >= fFullPVPath.size()) {
910  G4Exception("G4PhysicalVolumeModelTouchable::GetTranslation",
911  "modeling0005",
913  "Index out of range. Asking for non-existent depth");
914  }
915  static G4ThreeVector tempTranslation;
916  tempTranslation = fFullPVPath[i].GetTransform().getTranslation();
917  return tempTranslation;
918 }
919 
921 {
922  size_t i = fFullPVPath.size() - depth - 1;
923  if (i >= fFullPVPath.size()) {
924  G4Exception("G4PhysicalVolumeModelTouchable::GetRotation",
925  "modeling0006",
927  "Index out of range. Asking for non-existent depth");
928  }
929  static G4RotationMatrix tempRotation;
930  tempRotation = fFullPVPath[i].GetTransform().getRotation();
931  return &tempRotation;
932 }
933 
935 {
936  size_t i = fFullPVPath.size() - depth - 1;
937  if (i >= fFullPVPath.size()) {
938  G4Exception("G4PhysicalVolumeModelTouchable::GetVolume",
939  "modeling0007",
941  "Index out of range. Asking for non-existent depth");
942  }
943  return fFullPVPath[i].GetPhysicalVolume();
944 }
945 
947 {
948  size_t i = fFullPVPath.size() - depth - 1;
949  if (i >= fFullPVPath.size()) {
950  G4Exception("G4PhysicalVolumeModelTouchable::GetSolid",
951  "modeling0008",
953  "Index out of range. Asking for non-existent depth");
954  }
955  return fFullPVPath[i].GetPhysicalVolume()->GetLogicalVolume()->GetSolid();
956 }
957 
959 {
960  size_t i = fFullPVPath.size() - depth - 1;
961  if (i >= fFullPVPath.size()) {
962  G4Exception("G4PhysicalVolumeModelTouchable::GetReplicaNumber",
963  "modeling0009",
965  "Index out of range. Asking for non-existent depth");
966  }
967  return fFullPVPath[i].GetCopyNo();
968 }