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

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