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

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

before tag

File size: 28.8 KB
Line 
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: G4PhysicalVolumeModel.cc,v 1.68 2010/11/05 15:19:29 allison Exp $
28// GEANT4 tag $Name:  $
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"
42#include "G4SubtractionSolid.hh"
43#include "G4IntersectionSolid.hh"
44#include "G4Material.hh"
45#include "G4VisAttributes.hh"
46#include "G4BoundingSphereScene.hh"
47#include "G4PhysicalVolumeSearchScene.hh"
48#include "G4TransportationManager.hh"
49#include "G4Polyhedron.hh"
50#include "HepPolyhedronProcessor.h"
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),
77  fpClippingSolid (0),
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{
90  delete fpClippingSolid;
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.
211      if (fCurrentDepth == 0) nReplicas = 1;  // Just draw first
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);
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);
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
387    (G4PhysicalVolumeNodeID
388     (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform));
389
390  if (thisToBeDrawn) {
391
392    // Update path of drawn physical volumes...
393    G4int copyNo = fpCurrentPV->GetCopyNo();
394    fDrawnPVPath.push_back
395      (G4PhysicalVolumeNodeID
396       (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform));
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      // Store daughter pVPV in local variable ready for recursion...
478      G4VPhysicalVolume* pDaughterVPV = pLV -> GetDaughter (iDaughter);
479      // Descend the geometry structure recursively...
480      fCurrentDepth++;
481      VisitGeometryAndGetVisReps
482        (pDaughterVPV, requestedDepth - 1, theNewAT, sceneHandler);
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
505  G4VSolid* pSectionSolid = fpMP->GetSectionSolid();
506  G4VSolid* pCutawaySolid = fpMP->GetCutawaySolid();
507
508  if (!fpClippingSolid && !pSectionSolid && !pCutawaySolid) {
509
510    pSol -> DescribeYourselfTo (sceneHandler);  // Standard treatment.
511
512  } else {
513
514    // Clipping, etc., performed by Boolean operations.
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());
522    const G4Polyhedron* pOriginal = pSol->GetPolyhedron();
523    G4Polyhedron::ResetNumberOfRotationSteps();
524
525    if (!pOriginal) {
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
535    } else {
536
537      G4Polyhedron resultant(*pOriginal);
538      G4VisAttributes resultantVisAttribs(*pVisAttribs);
539      G4VSolid* resultantSolid = 0;
540
541      if (fpClippingSolid) {
542        switch (fClippingMode) {
543        default:
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;
552        }
553      }
554
555      if (pSectionSolid) {
556        resultantSolid = new G4IntersectionSolid
557          ("sectioned_solid", pSol, pSectionSolid, theAT.inverse());
558      }
559
560      if (pCutawaySolid) {
561        resultantSolid = new G4SubtractionSolid
562          ("cutaway_solid", pSol, pCutawaySolid, theAT.inverse());
563      }
564
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
580      // Finally, force polyhedron drawing...
581      resultant.SetVisAttributes(resultantVisAttribs);
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  }
716
717  if (!fpCurrentLV) {
718     G4Exception
719        ("G4PhysicalVolumeModel::CreateCurrentAttValues",
720         "",
721         JustWarning,
722         "Current logical volume not defined.");
723     return values;
724  }
725
726  values->push_back(G4AttValue("PVPath", oss.str(),""));
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(),""));
749  return values;
750}
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.