source: trunk/source/visualization/modeling/src/G4PhysicalVolumeModel.cc @ 1355

Last change on this file since 1355 was 1346, checked in by garnier, 14 years ago

before tag

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