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

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

cvs update

File size: 28.7 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.67 2010/05/11 11:16:51 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      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
504  G4VSolid* pSectionSolid = fpMP->GetSectionSolid();
505  G4VSolid* pCutawaySolid = fpMP->GetCutawaySolid();
506
507  if (!fpClippingSolid && !pSectionSolid && !pCutawaySolid) {
508
509    pSol -> DescribeYourselfTo (sceneHandler);  // Standard treatment.
510
511  } else {
512
513    // Clipping, etc., performed by Boolean operations.
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());
521    const G4Polyhedron* pOriginal = pSol->GetPolyhedron();
522    G4Polyhedron::ResetNumberOfRotationSteps();
523
524    if (!pOriginal) {
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
534    } else {
535
536      G4Polyhedron resultant(*pOriginal);
537      G4VisAttributes resultantVisAttribs(*pVisAttribs);
538      G4VSolid* resultantSolid = 0;
539
540      if (fpClippingSolid) {
541        switch (fClippingMode) {
542        default:
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;
551        }
552      }
553
554      if (pSectionSolid) {
555        resultantSolid = new G4IntersectionSolid
556          ("sectioned_solid", pSol, pSectionSolid, theAT.inverse());
557      }
558
559      if (pCutawaySolid) {
560        resultantSolid = new G4SubtractionSolid
561          ("cutaway_solid", pSol, pCutawaySolid, theAT.inverse());
562      }
563
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
579      // Finally, force polyhedron drawing...
580      resultant.SetVisAttributes(resultantVisAttribs);
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  }
715
716  if (!fpCurrentLV) {
717     G4Exception
718        ("G4PhysicalVolumeModel::CreateCurrentAttValues",
719         "",
720         JustWarning,
721         "Current logical volume not defined.");
722     return values;
723  }
724
725  values->push_back(G4AttValue("PVPath", oss.str(),""));
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(),""));
748  return values;
749}
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.