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

Last change on this file since 1288 was 1258, checked in by garnier, 16 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.