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

Last change on this file since 1259 was 1258, checked in by garnier, 14 years ago

cvs update

File size: 28.7 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//
[1258]27// $Id: G4PhysicalVolumeModel.cc,v 1.67 2010/05/11 11:16:51 allison Exp $
[954]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++) {
477      G4VPhysicalVolume* pVPV = pLV -> GetDaughter (iDaughter);
478      // Descend the geometry structure recursively...
479      fCurrentDepth++;
480      VisitGeometryAndGetVisReps
481        (pVPV, requestedDepth - 1, theNewAT, sceneHandler);
482      fCurrentDepth--;
483    }
484  }
485
486  // Reset for normal descending of next volume at this level...
487  fCurtailDescent = false;
488
489  // Pop item from paths physical volumes...
490  fFullPVPath.pop_back();
491  if (thisToBeDrawn) {
492    fDrawnPVPath.pop_back();
493  }
494}
495
496void G4PhysicalVolumeModel::DescribeSolid
497(const G4Transform3D& theAT,
498 G4VSolid* pSol,
499 const G4VisAttributes* pVisAttribs,
500 G4VGraphicsScene& sceneHandler)
501{
502  sceneHandler.PreAddSolid (theAT, *pVisAttribs);
503
[1258]504  G4VSolid* pSectionSolid = fpMP->GetSectionSolid();
505  G4VSolid* pCutawaySolid = fpMP->GetCutawaySolid();
[834]506
[1258]507  if (!fpClippingSolid && !pSectionSolid && !pCutawaySolid) {
[834]508
509    pSol -> DescribeYourselfTo (sceneHandler);  // Standard treatment.
510
511  } else {
512
[1258]513    // Clipping, etc., performed by Boolean operations.
[834]514
515    // First, get polyhedron for current solid...
516    if (pVisAttribs->IsForceLineSegmentsPerCircle())
517      G4Polyhedron::SetNumberOfRotationSteps
518        (pVisAttribs->GetForcedLineSegmentsPerCircle());
519    else
520      G4Polyhedron::SetNumberOfRotationSteps(fpMP->GetNoOfSides());
[1258]521    const G4Polyhedron* pOriginal = pSol->GetPolyhedron();
[834]522    G4Polyhedron::ResetNumberOfRotationSteps();
[1140]523
[834]524    if (!pOriginal) {
[1140]525
526      if (fpMP->IsWarning())
527        G4cout <<
528          "WARNING: G4PhysicalVolumeModel::DescribeSolid: solid\n  \""
529               << pSol->GetName() <<
530          "\" has no polyhedron.  Cannot by clipped."
531               << G4endl;
532      pSol -> DescribeYourselfTo (sceneHandler);  // Standard treatment.
533
[834]534    } else {
535
[1258]536      G4Polyhedron resultant(*pOriginal);
[1140]537      G4VisAttributes resultantVisAttribs(*pVisAttribs);
[1258]538      G4VSolid* resultantSolid = 0;
[834]539
[1258]540      if (fpClippingSolid) {
[834]541        switch (fClippingMode) {
542        default:
[1258]543        case subtraction:
544          resultantSolid = new G4SubtractionSolid
545            ("resultant_solid", pSol, fpClippingSolid, theAT.inverse());
546          break;
547        case intersection:
548          resultantSolid = new G4IntersectionSolid
549            ("resultant_solid", pSol, fpClippingSolid, theAT.inverse());
550          break;
[834]551        }
552      }
553
[1258]554      if (pSectionSolid) {
555        resultantSolid = new G4IntersectionSolid
556          ("sectioned_solid", pSol, pSectionSolid, theAT.inverse());
[834]557      }
558
[1258]559      if (pCutawaySolid) {
560        resultantSolid = new G4SubtractionSolid
561          ("cutaway_solid", pSol, pCutawaySolid, theAT.inverse());
[834]562      }
563
[1258]564      G4Polyhedron* tmpResultant = resultantSolid->GetPolyhedron();
565      if (tmpResultant) resultant = *tmpResultant;
566      else {
567        if (fpMP->IsWarning())
568          G4cout <<
569            "WARNING: G4PhysicalVolumeModel::DescribeSolid: resultant polyhedron for"
570            "\n  solid \"" << pSol->GetName() <<
571            "\" not defined due to error during Boolean processing."
572            "\n  Original will be drawn in red."
573                 << G4endl;
574        resultantVisAttribs.SetColour(G4Colour::Red());
575      }
576
577      delete resultantSolid;
578
[834]579      // Finally, force polyhedron drawing...
[1140]580      resultant.SetVisAttributes(resultantVisAttribs);
[834]581      sceneHandler.BeginPrimitives(theAT);
582      sceneHandler.AddPrimitive(resultant);
583      sceneHandler.EndPrimitives();
584    }
585  }
586  sceneHandler.PostAddSolid ();
587}
588
589G4bool G4PhysicalVolumeModel::Validate (G4bool warn)
590{
591  G4VPhysicalVolume* world =
592    G4TransportationManager::GetTransportationManager ()
593    -> GetNavigatorForTracking () -> GetWorldVolume ();
594  // The idea now is to seek a PV with the same name and copy no
595  // in the hope it's the same one!!
596  if (warn) {
597    G4cout << "G4PhysicalVolumeModel::Validate() called." << G4endl;
598  }
599  G4PhysicalVolumeModel searchModel (world);
600  G4PhysicalVolumeSearchScene searchScene
601    (&searchModel, fTopPVName, fTopPVCopyNo);
602  G4ModelingParameters mp;  // Default modeling parameters for this search.
603  mp.SetDefaultVisAttributes(fpMP? fpMP->GetDefaultVisAttributes(): 0);
604  searchModel.SetModelingParameters (&mp);
605  searchModel.DescribeYourselfTo (searchScene);
606  G4VPhysicalVolume* foundVolume = searchScene.GetFoundVolume ();
607  if (foundVolume) {
608    if (warn) {
609      G4cout << "  Volume of the same name and copy number (\""
610             << fTopPVName << "\", copy " << fTopPVCopyNo
611             << ") still exists and is being used."
612        "\n  WARNING: This does not necessarily guarantee it's the same"
613        "\n  volume you originally specified in /vis/scene/add/."
614             << G4endl;
615    }
616    fpTopPV = foundVolume;
617    CalculateExtent ();
618    return true;
619  }
620  else {
621    if (warn) {
622      G4cout << "  A volume of the same name and copy number (\""
623             << fTopPVName << "\", copy " << fTopPVCopyNo
624             << ") no longer exists."
625             << G4endl;
626    }
627    return false;
628  }
629}
630
631const std::map<G4String,G4AttDef>* G4PhysicalVolumeModel::GetAttDefs() const
632{
633    G4bool isNew;
634    std::map<G4String,G4AttDef>* store
635      = G4AttDefStore::GetInstance("G4PhysicalVolumeModel", isNew);
636    if (isNew) {
637      (*store)["PVPath"] =
638        G4AttDef("PVPath","Physical Volume Path","Physics","","G4String");
639      (*store)["LVol"] =
640        G4AttDef("LVol","Logical Volume","Physics","","G4String");
641      (*store)["Solid"] =
642        G4AttDef("Solid","Solid Name","Physics","","G4String");
643      (*store)["EType"] =
644        G4AttDef("EType","Entity Type","Physics","","G4String");
645      (*store)["DmpSol"] =
646        G4AttDef("DmpSol","Dump of Solid properties","Physics","","G4String");
647      (*store)["Trans"] =
648        G4AttDef("Trans","Transformation of volume","Physics","","G4String");
649      (*store)["Material"] =
650        G4AttDef("Material","Material Name","Physics","","G4String");
651      (*store)["Density"] =
652        G4AttDef("Density","Material Density","Physics","G4BestUnit","G4double");
653      (*store)["State"] =
654        G4AttDef("State","Material State (enum undefined,solid,liquid,gas)","Physics","","G4String");
655      (*store)["Radlen"] =
656        G4AttDef("Radlen","Material Radiation Length","Physics","G4BestUnit","G4double");
657    }
658      (*store)["Region"] =
659        G4AttDef("Region","Cuts Region","Physics","","G4String");
660      (*store)["RootRegion"] =
661        G4AttDef("RootRegion","Root Region (0/1 = false/true)","Physics","","G4bool");
662    return store;
663}
664
665#include <iomanip>
666
667static std::ostream& operator<< (std::ostream& o, const G4Transform3D t)
668{
669  using namespace std;
670
671  G4Scale3D s;
672  G4Rotate3D r;
673  G4Translate3D tl;
674  t.getDecomposition(s, r, tl);
675
676  const int w = 10;
677
678  // Transformation itself
679  o << setw(w) << t.xx() << setw(w) << t.xy() << setw(w) << t.xz() << setw(w) << t.dx() << endl;
680  o << setw(w) << t.yx() << setw(w) << t.yy() << setw(w) << t.yz() << setw(w) << t.dy() << endl;
681  o << setw(w) << t.zx() << setw(w) << t.zy() << setw(w) << t.zz() << setw(w) << t.dz() << endl;
682
683  // Translation
684  o << "= translation:" << endl;
685  o << setw(w) << tl.dx() << setw(w) << tl.dy() << setw(w) << tl.dz() << endl;
686
687  // Rotation
688  o << "* rotation:" << endl;
689  o << setw(w) << r.xx() << setw(w) << r.xy() << setw(w) << r.xz() << endl;
690  o << setw(w) << r.yx() << setw(w) << r.yy() << setw(w) << r.yz() << endl;
691  o << setw(w) << r.zx() << setw(w) << r.zy() << setw(w) << r.zz() << endl;
692
693  // Scale
694  o << "* scale:" << endl;
695  o << setw(w) << s.xx() << setw(w) << s.yy() << setw(w) << s.zz() << endl;
696
697  // Transformed axes
698  o << "Transformed axes:" << endl;
699  o << "x': " << r * G4Vector3D(1., 0., 0.) << endl;
700  o << "y': " << r * G4Vector3D(0., 1., 0.) << endl;
701  o << "z': " << r * G4Vector3D(0., 0., 1.) << endl;
702
703  return o;
704}
705
706std::vector<G4AttValue>* G4PhysicalVolumeModel::CreateCurrentAttValues() const
707{
708  std::vector<G4AttValue>* values = new std::vector<G4AttValue>;
709  std::ostringstream oss;
710  for (size_t i = 0; i < fFullPVPath.size(); ++i) {
711    oss << fFullPVPath[i].GetPhysicalVolume()->GetName()
712        << ':' << fFullPVPath[i].GetCopyNo();
713    if (i != fFullPVPath.size() - 1) oss << '/';
714  }
[1140]715
716  if (!fpCurrentLV) {
717     G4Exception
718        ("G4PhysicalVolumeModel::CreateCurrentAttValues",
719         "",
720         JustWarning,
721         "Current logical volume not defined.");
722     return values;
723  }
724
[834]725  values->push_back(G4AttValue("PVPath", oss.str(),""));
[1171]726  values->push_back(G4AttValue("LVol", fpCurrentLV->GetName(),""));
727  G4VSolid* pSol = fpCurrentLV->GetSolid();
728  values->push_back(G4AttValue("Solid", pSol->GetName(),""));
729  values->push_back(G4AttValue("EType", pSol->GetEntityType(),""));
730  oss.str(""); oss << '\n' << *pSol;
731  values->push_back(G4AttValue("DmpSol", oss.str(),""));
732  oss.str(""); oss << '\n' << *fpCurrentTransform;
733  values->push_back(G4AttValue("Trans", oss.str(),""));
734  G4String matName = fpCurrentMaterial? fpCurrentMaterial->GetName(): G4String("No material");
735  values->push_back(G4AttValue("Material", matName,""));
736  G4double matDensity = fpCurrentMaterial? fpCurrentMaterial->GetDensity(): 0.;
737  values->push_back(G4AttValue("Density", G4BestUnit(matDensity,"Volumic Mass"),""));
738  G4State matState = fpCurrentMaterial? fpCurrentMaterial->GetState(): kStateUndefined;
739  oss.str(""); oss << matState;
740  values->push_back(G4AttValue("State", oss.str(),""));
741  G4double matRadlen = fpCurrentMaterial? fpCurrentMaterial->GetRadlen(): 0.;
742  values->push_back(G4AttValue("Radlen", G4BestUnit(matRadlen,"Length"),""));
743  G4Region* region = fpCurrentLV->GetRegion();
744  G4String regionName = region? region->GetName(): G4String("No region");
745  values->push_back(G4AttValue("Region", regionName,""));
746  oss.str(""); oss << fpCurrentLV->IsRootRegion();
747  values->push_back(G4AttValue("RootRegion", oss.str(),""));
[834]748  return values;
749}
[1140]750
751G4bool G4PhysicalVolumeModel::G4PhysicalVolumeNodeID::operator<
752  (const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID& right) const
753{
754  if (fpPV < right.fpPV) return true;
755  if (fpPV == right.fpPV) {
756    if (fCopyNo < right.fCopyNo) return true;
757    if (fCopyNo == right.fCopyNo)
758      return fNonCulledDepth < right.fNonCulledDepth;
759  }
760  return false;
761}
762
763std::ostream& operator<<
764  (std::ostream& os, const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID node)
765{
766  G4VPhysicalVolume* pPV = node.GetPhysicalVolume();
767  if (pPV) {
768    os << pPV->GetName()
769       << ':' << node.GetCopyNo()
770       << '[' << node.GetNonCulledDepth() << ']'
771       << ':' << node.GetTransform();
772  } else {
773    os << "Null node";
774  }
775  return os;
776}
777
778G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::G4PhysicalVolumeModelTouchable
779(const std::vector<G4PhysicalVolumeNodeID>& fullPVPath):
780  fFullPVPath(fullPVPath) {}
781
782const G4ThreeVector& G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetTranslation(G4int depth) const
783{
784  size_t i = fFullPVPath.size() - depth - 1;
785  if (i >= fFullPVPath.size()) {
786    G4Exception("G4PhysicalVolumeModelTouchable::GetTranslation",
787                "Index out of range",
788                FatalErrorInArgument,
789                "Asking for non-existent depth");
790  }
791  static G4ThreeVector tempTranslation;
792  tempTranslation = fFullPVPath[i].GetTransform().getTranslation();
793  return tempTranslation;
794}
795
796const G4RotationMatrix* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetRotation(G4int depth) const
797{
798  size_t i = fFullPVPath.size() - depth - 1;
799  if (i >= fFullPVPath.size()) {
800    G4Exception("G4PhysicalVolumeModelTouchable::GetRotation",
801                "Index out of range",
802                FatalErrorInArgument,
803                "Asking for non-existent depth");
804  }
805  static G4RotationMatrix tempRotation;
806  tempRotation = fFullPVPath[i].GetTransform().getRotation();
807  return &tempRotation;
808}
809
810G4VPhysicalVolume* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetVolume(G4int depth) const
811{
812  size_t i = fFullPVPath.size() - depth - 1;
813  if (i >= fFullPVPath.size()) {
814    G4Exception("G4PhysicalVolumeModelTouchable::GetVolume",
815                "Index out of range",
816                FatalErrorInArgument,
817                "Asking for non-existent depth");
818  }
819  return fFullPVPath[i].GetPhysicalVolume();
820}
821
822G4VSolid* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetSolid(G4int depth) const
823{
824  size_t i = fFullPVPath.size() - depth - 1;
825  if (i >= fFullPVPath.size()) {
826    G4Exception("G4PhysicalVolumeModelTouchable::GetSolid",
827                "Index out of range",
828                FatalErrorInArgument,
829                "Asking for non-existent depth");
830  }
831  return fFullPVPath[i].GetPhysicalVolume()->GetLogicalVolume()->GetSolid();
832}
833
834G4int G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetReplicaNumber(G4int depth) const
835{
836  size_t i = fFullPVPath.size() - depth - 1;
837  if (i >= fFullPVPath.size()) {
838    G4Exception("G4PhysicalVolumeModelTouchable::GetReplicaNumber",
839                "Index out of range",
840                FatalErrorInArgument,
841                "Asking for non-existent depth");
842  }
843  return fFullPVPath[i].GetCopyNo();
844}
Note: See TracBrowser for help on using the repository browser.