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

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

before tag

File size: 28.8 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// $Id: G4PhysicalVolumeModel.cc,v 1.68 2010/11/05 15:19:29 allison Exp $
28// GEANT4 tag $Name: $
29//
30//
31// John Allison 31st December 1997.
32// Model for physical volumes.
33
34#include "G4PhysicalVolumeModel.hh"
35
36#include "G4ModelingParameters.hh"
37#include "G4VGraphicsScene.hh"
38#include "G4VPhysicalVolume.hh"
39#include "G4VPVParameterisation.hh"
40#include "G4LogicalVolume.hh"
41#include "G4VSolid.hh"
42#include "G4SubtractionSolid.hh"
43#include "G4IntersectionSolid.hh"
44#include "G4Material.hh"
45#include "G4VisAttributes.hh"
46#include "G4BoundingSphereScene.hh"
47#include "G4PhysicalVolumeSearchScene.hh"
48#include "G4TransportationManager.hh"
49#include "G4Polyhedron.hh"
50#include "HepPolyhedronProcessor.h"
51#include "G4AttDefStore.hh"
52#include "G4AttDef.hh"
53#include "G4AttValue.hh"
54#include "G4UnitsTable.hh"
55#include "G4Vector3D.hh"
56
57#include <sstream>
58
59G4PhysicalVolumeModel::G4PhysicalVolumeModel
60(G4VPhysicalVolume* pVPV,
61 G4int requestedDepth,
62 const G4Transform3D& modelTransformation,
63 const G4ModelingParameters* pMP,
64 G4bool useFullExtent):
65 G4VModel (modelTransformation, pMP),
66 fpTopPV (pVPV),
67 fTopPVName (pVPV -> GetName ()),
68 fTopPVCopyNo (pVPV -> GetCopyNo ()),
69 fRequestedDepth (requestedDepth),
70 fUseFullExtent (useFullExtent),
71 fCurrentDepth (0),
72 fpCurrentPV (0),
73 fpCurrentLV (0),
74 fpCurrentMaterial (0),
75 fpCurrentTransform (0),
76 fCurtailDescent (false),
77 fpClippingSolid (0),
78 fClippingMode (subtraction)
79{
80 std::ostringstream o;
81 o << fpTopPV -> GetCopyNo ();
82 fGlobalTag = fpTopPV -> GetName () + "." + o.str();
83 fGlobalDescription = "G4PhysicalVolumeModel " + fGlobalTag;
84
85 CalculateExtent ();
86}
87
88G4PhysicalVolumeModel::~G4PhysicalVolumeModel ()
89{
90 delete fpClippingSolid;
91}
92
93void G4PhysicalVolumeModel::CalculateExtent ()
94{
95 if (fUseFullExtent) {
96 fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
97 }
98 else {
99 G4BoundingSphereScene bsScene(this);
100 const G4int tempRequestedDepth = fRequestedDepth;
101 fRequestedDepth = -1; // Always search to all depths to define extent.
102 const G4ModelingParameters* tempMP = fpMP;
103 G4ModelingParameters mParams
104 (0, // No default vis attributes needed.
105 G4ModelingParameters::wf, // wireframe (not relevant for this).
106 true, // Global culling.
107 true, // Cull invisible volumes.
108 false, // Density culling.
109 0., // Density (not relevant if density culling false).
110 true, // Cull daughters of opaque mothers.
111 24); // No of sides (not relevant for this operation).
112 fpMP = &mParams;
113 DescribeYourselfTo (bsScene);
114 G4double radius = bsScene.GetRadius();
115 if (radius < 0.) { // Nothing in the scene.
116 fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
117 } else {
118 // Transform back to coordinates relative to the top
119 // transformation, which is in G4VModel::fTransform. This makes
120 // it conform to all models, which are defined by a
121 // transformation and an extent relative to that
122 // transformation...
123 G4Point3D centre = bsScene.GetCentre();
124 centre.transform(fTransform.inverse());
125 fExtent = G4VisExtent(centre, radius);
126 }
127 fpMP = tempMP;
128 fRequestedDepth = tempRequestedDepth;
129 }
130}
131
132void G4PhysicalVolumeModel::DescribeYourselfTo
133(G4VGraphicsScene& sceneHandler)
134{
135 if (!fpMP) G4Exception
136 ("G4PhysicalVolumeModel::DescribeYourselfTo: No modeling parameters.");
137
138 // For safety...
139 fCurrentDepth = 0;
140
141 G4Transform3D startingTransformation = fTransform;
142
143 VisitGeometryAndGetVisReps
144 (fpTopPV,
145 fRequestedDepth,
146 startingTransformation,
147 sceneHandler);
148
149 // Clear data...
150 fCurrentDepth = 0;
151 fpCurrentPV = 0;
152 fpCurrentLV = 0;
153 fpCurrentMaterial = 0;
154 fFullPVPath.clear();
155 fDrawnPVPath.clear();
156}
157
158G4String G4PhysicalVolumeModel::GetCurrentTag () const
159{
160 if (fpCurrentPV) {
161 std::ostringstream o;
162 o << fpCurrentPV -> GetCopyNo ();
163 return fpCurrentPV -> GetName () + "." + o.str();
164 }
165 else {
166 return "WARNING: NO CURRENT VOLUME - global tag is " + fGlobalTag;
167 }
168}
169
170G4String G4PhysicalVolumeModel::GetCurrentDescription () const
171{
172 return "G4PhysicalVolumeModel " + GetCurrentTag ();
173}
174
175void G4PhysicalVolumeModel::VisitGeometryAndGetVisReps
176(G4VPhysicalVolume* pVPV,
177 G4int requestedDepth,
178 const G4Transform3D& theAT,
179 G4VGraphicsScene& sceneHandler)
180{
181 // Visits geometry structure to a given depth (requestedDepth), starting
182 // at given physical volume with given starting transformation and
183 // describes volumes to the scene handler.
184 // requestedDepth < 0 (default) implies full visit.
185 // theAT is the Accumulated Transformation.
186
187 // Find corresponding logical volume and (later) solid, storing in
188 // local variables to preserve re-entrancy.
189 G4LogicalVolume* pLV = pVPV -> GetLogicalVolume ();
190
191 G4VSolid* pSol;
192 G4Material* pMaterial;
193
194 if (!(pVPV -> IsReplicated ())) {
195 // Non-replicated physical volume.
196 pSol = pLV -> GetSolid ();
197 pMaterial = pLV -> GetMaterial ();
198 DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
199 theAT, sceneHandler);
200 }
201 else {
202 // Replicated or parametrised physical volume.
203 EAxis axis;
204 G4int nReplicas;
205 G4double width;
206 G4double offset;
207 G4bool consuming;
208 pVPV -> GetReplicationData (axis, nReplicas, width, offset, consuming);
209 G4VPVParameterisation* pP = pVPV -> GetParameterisation ();
210 if (pP) { // Parametrised volume.
211 if (fCurrentDepth == 0) nReplicas = 1; // Just draw first
212 for (int n = 0; n < nReplicas; n++) {
213 pSol = pP -> ComputeSolid (n, pVPV);
214 pP -> ComputeTransformation (n, pVPV);
215 pSol -> ComputeDimensions (pP, n, pVPV);
216 pVPV -> SetCopyNo (n);
217 // Create a touchable of current parent for ComputeMaterial.
218 // fFullPVPath has not been updated yet so at this point it
219 // corresponds to the parent.
220 G4PhysicalVolumeModelTouchable parentTouchable(fFullPVPath);
221 pMaterial = pP -> ComputeMaterial (n, pVPV, &parentTouchable);
222 DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
223 theAT, sceneHandler);
224 }
225 }
226 else { // Plain replicated volume. From geometry_guide.txt...
227 // The replica's positions are claculated by means of a linear formula.
228 // Replication may occur along:
229 //
230 // o Cartesian axes (kXAxis,kYAxis,kZAxis)
231 //
232 // The replications, of specified width have coordinates of
233 // form (-width*(nReplicas-1)*0.5+n*width,0,0) where n=0.. nReplicas-1
234 // for the case of kXAxis, and are unrotated.
235 //
236 // o Radial axis (cylindrical polar) (kRho)
237 //
238 // The replications are cons/tubs sections, centred on the origin
239 // and are unrotated.
240 // They have radii of width*n+offset to width*(n+1)+offset
241 // where n=0..nReplicas-1
242 //
243 // o Phi axis (cylindrical polar) (kPhi)
244 // The replications are `phi sections' or wedges, and of cons/tubs form
245 // They have phi of offset+n*width to offset+(n+1)*width where
246 // n=0..nReplicas-1
247 //
248 pSol = pLV -> GetSolid ();
249 pMaterial = pLV -> GetMaterial ();
250 G4ThreeVector originalTranslation = pVPV -> GetTranslation ();
251 G4RotationMatrix* pOriginalRotation = pVPV -> GetRotation ();
252 G4double originalRMin = 0., originalRMax = 0.;
253 if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
254 originalRMin = ((G4Tubs*)pSol)->GetInnerRadius();
255 originalRMax = ((G4Tubs*)pSol)->GetOuterRadius();
256 }
257 G4bool visualisable = true;
258 for (int n = 0; n < nReplicas; n++) {
259 G4ThreeVector translation; // Null.
260 G4RotationMatrix rotation; // Null - life long enough for visualizing.
261 G4RotationMatrix* pRotation = 0;
262 switch (axis) {
263 default:
264 case kXAxis:
265 translation = G4ThreeVector (-width*(nReplicas-1)*0.5+n*width,0,0);
266 break;
267 case kYAxis:
268 translation = G4ThreeVector (0,-width*(nReplicas-1)*0.5+n*width,0);
269 break;
270 case kZAxis:
271 translation = G4ThreeVector (0,0,-width*(nReplicas-1)*0.5+n*width);
272 break;
273 case kRho:
274 if (pSol->GetEntityType() == "G4Tubs") {
275 ((G4Tubs*)pSol)->SetInnerRadius(width*n+offset);
276 ((G4Tubs*)pSol)->SetOuterRadius(width*(n+1)+offset);
277 } else {
278 if (fpMP->IsWarning())
279 G4cout <<
280 "G4PhysicalVolumeModel::VisitGeometryAndGetVisReps: WARNING:"
281 "\n built-in replicated volumes replicated in radius for "
282 << pSol->GetEntityType() <<
283 "-type\n solids (your solid \""
284 << pSol->GetName() <<
285 "\") are not visualisable."
286 << G4endl;
287 visualisable = false;
288 }
289 break;
290 case kPhi:
291 rotation.rotateZ (-(offset+(n+0.5)*width));
292 // Minus Sign because for the physical volume we need the
293 // coordinate system rotation.
294 pRotation = &rotation;
295 break;
296 }
297 pVPV -> SetTranslation (translation);
298 pVPV -> SetRotation (pRotation);
299 pVPV -> SetCopyNo (n);
300 if (visualisable) {
301 DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
302 theAT, sceneHandler);
303 }
304 }
305 // Restore originals...
306 pVPV -> SetTranslation (originalTranslation);
307 pVPV -> SetRotation (pOriginalRotation);
308 if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
309 ((G4Tubs*)pSol)->SetInnerRadius(originalRMin);
310 ((G4Tubs*)pSol)->SetOuterRadius(originalRMax);
311 }
312 }
313 }
314
315 return;
316}
317
318void G4PhysicalVolumeModel::DescribeAndDescend
319(G4VPhysicalVolume* pVPV,
320 G4int requestedDepth,
321 G4LogicalVolume* pLV,
322 G4VSolid* pSol,
323 G4Material* pMaterial,
324 const G4Transform3D& theAT,
325 G4VGraphicsScene& sceneHandler)
326{
327 // Maintain useful data members...
328 fpCurrentPV = pVPV;
329 fpCurrentLV = pLV;
330 fpCurrentMaterial = pMaterial;
331
332 const G4RotationMatrix objectRotation = pVPV -> GetObjectRotationValue ();
333 const G4ThreeVector& translation = pVPV -> GetTranslation ();
334 G4Transform3D theLT (G4Transform3D (objectRotation, translation));
335
336 // Compute the accumulated transformation...
337 // Note that top volume's transformation relative to the world
338 // coordinate system is specified in theAT == startingTransformation
339 // = fTransform (see DescribeYourselfTo), so first time through the
340 // volume's own transformation, which is only relative to its
341 // mother, i.e., not relative to the world coordinate system, should
342 // not be accumulated.
343 G4Transform3D theNewAT (theAT);
344 if (fCurrentDepth != 0) theNewAT = theAT * theLT;
345 fpCurrentTransform = &theNewAT;
346
347 // Make decision to draw...
348 const G4VisAttributes* pVisAttribs = pLV->GetVisAttributes();
349 if (!pVisAttribs) pVisAttribs = fpMP->GetDefaultVisAttributes();
350 // Beware - pVisAttribs might still be zero - create a temporary default one...
351 G4bool visAttsCreated = false;
352 if (!pVisAttribs) {
353 pVisAttribs = new G4VisAttributes;
354 visAttsCreated = true;
355 }
356
357 // From here, can assume pVisAttribs is a valid pointer.
358
359 G4bool thisToBeDrawn = true;
360
361 // There are various reasons why this volume
362 // might not be drawn...
363 G4bool culling = fpMP->IsCulling();
364 G4bool cullingInvisible = fpMP->IsCullingInvisible();
365 G4bool markedVisible = pVisAttribs->IsVisible();
366 G4bool cullingLowDensity = fpMP->IsDensityCulling();
367 G4double density = pMaterial? pMaterial->GetDensity(): 0;
368 G4double densityCut = fpMP -> GetVisibleDensity ();
369
370 // 1) Global culling is on....
371 if (culling) {
372 // 2) Culling of invisible volumes is on...
373 if (cullingInvisible) {
374 // 3) ...and the volume is marked not visible...
375 if (!markedVisible) thisToBeDrawn = false;
376 }
377 // 4) Or culling of low density volumes is on...
378 if (cullingLowDensity) {
379 // 5) ...and density is less than cut value...
380 if (density < densityCut) thisToBeDrawn = false;
381 }
382 }
383
384 // Update full path of physical volumes...
385 G4int copyNo = fpCurrentPV->GetCopyNo();
386 fFullPVPath.push_back
387 (G4PhysicalVolumeNodeID
388 (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform));
389
390 if (thisToBeDrawn) {
391
392 // Update path of drawn physical volumes...
393 G4int copyNo = fpCurrentPV->GetCopyNo();
394 fDrawnPVPath.push_back
395 (G4PhysicalVolumeNodeID
396 (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform));
397
398 if (fpMP->IsExplode() && fDrawnPVPath.size() == 1) {
399 // For top-level drawn volumes, explode along radius...
400 G4Transform3D centering = G4Translate3D(fpMP->GetExplodeCentre());
401 G4Transform3D centred = centering.inverse() * theNewAT;
402 G4Scale3D scale;
403 G4Rotate3D rotation;
404 G4Translate3D translation;
405 centred.getDecomposition(scale, rotation, translation);
406 G4double explodeFactor = fpMP->GetExplodeFactor();
407 G4Translate3D newTranslation =
408 G4Translate3D(explodeFactor * translation.dx(),
409 explodeFactor * translation.dy(),
410 explodeFactor * translation.dz());
411 theNewAT = centering * newTranslation * rotation * scale;
412 }
413
414 DescribeSolid (theNewAT, pSol, pVisAttribs, sceneHandler);
415
416 }
417
418 // Make decision to draw daughters, if any. There are various
419 // reasons why daughters might not be drawn...
420
421 // First, reasons that do not depend on culling policy...
422 G4int nDaughters = pLV->GetNoDaughters();
423 G4bool daughtersToBeDrawn = true;
424 // 1) There are no daughters...
425 if (!nDaughters) daughtersToBeDrawn = false;
426 // 2) We are at the limit if requested depth...
427 else if (requestedDepth == 0) daughtersToBeDrawn = false;
428 // 3) The user has asked that the descent be curtailed...
429 else if (fCurtailDescent) daughtersToBeDrawn = false;
430
431 // Now, reasons that depend on culling policy...
432 else {
433 G4bool culling = fpMP->IsCulling();
434 G4bool cullingInvisible = fpMP->IsCullingInvisible();
435 G4bool daughtersInvisible = pVisAttribs->IsDaughtersInvisible();
436 // Culling of covered daughters request. This is computed in
437 // G4VSceneHandler::CreateModelingParameters() depending on view
438 // parameters...
439 G4bool cullingCovered = fpMP->IsCullingCovered();
440 G4bool surfaceDrawing =
441 fpMP->GetDrawingStyle() == G4ModelingParameters::hsr ||
442 fpMP->GetDrawingStyle() == G4ModelingParameters::hlhsr;
443 if (pVisAttribs->IsForceDrawingStyle()) {
444 switch (pVisAttribs->GetForcedDrawingStyle()) {
445 default:
446 case G4VisAttributes::wireframe: surfaceDrawing = false; break;
447 case G4VisAttributes::solid: surfaceDrawing = true; break;
448 }
449 }
450 G4bool opaque = pVisAttribs->GetColour().GetAlpha() >= 1.;
451 // 4) Global culling is on....
452 if (culling) {
453 // 5) ..and culling of invisible volumes is on...
454 if (cullingInvisible) {
455 // 6) ...and the mother requests daughters invisible
456 if (daughtersInvisible) daughtersToBeDrawn = false;
457 }
458 // 7) Or culling of covered daughters is requested...
459 if (cullingCovered) {
460 // 8) ...and surface drawing is operating...
461 if (surfaceDrawing) {
462 // 9) ...but only if mother is visible...
463 if (thisToBeDrawn) {
464 // 10) ...and opaque...
465 if (opaque) daughtersToBeDrawn = false;
466 }
467 }
468 }
469 }
470 }
471
472 // Vis atts for this volume no longer needed if created...
473 if (visAttsCreated) delete pVisAttribs;
474
475 if (daughtersToBeDrawn) {
476 for (G4int iDaughter = 0; iDaughter < nDaughters; iDaughter++) {
477 // Store daughter pVPV in local variable ready for recursion...
478 G4VPhysicalVolume* pDaughterVPV = pLV -> GetDaughter (iDaughter);
479 // Descend the geometry structure recursively...
480 fCurrentDepth++;
481 VisitGeometryAndGetVisReps
482 (pDaughterVPV, requestedDepth - 1, theNewAT, sceneHandler);
483 fCurrentDepth--;
484 }
485 }
486
487 // Reset for normal descending of next volume at this level...
488 fCurtailDescent = false;
489
490 // Pop item from paths physical volumes...
491 fFullPVPath.pop_back();
492 if (thisToBeDrawn) {
493 fDrawnPVPath.pop_back();
494 }
495}
496
497void G4PhysicalVolumeModel::DescribeSolid
498(const G4Transform3D& theAT,
499 G4VSolid* pSol,
500 const G4VisAttributes* pVisAttribs,
501 G4VGraphicsScene& sceneHandler)
502{
503 sceneHandler.PreAddSolid (theAT, *pVisAttribs);
504
505 G4VSolid* pSectionSolid = fpMP->GetSectionSolid();
506 G4VSolid* pCutawaySolid = fpMP->GetCutawaySolid();
507
508 if (!fpClippingSolid && !pSectionSolid && !pCutawaySolid) {
509
510 pSol -> DescribeYourselfTo (sceneHandler); // Standard treatment.
511
512 } else {
513
514 // Clipping, etc., performed by Boolean operations.
515
516 // First, get polyhedron for current solid...
517 if (pVisAttribs->IsForceLineSegmentsPerCircle())
518 G4Polyhedron::SetNumberOfRotationSteps
519 (pVisAttribs->GetForcedLineSegmentsPerCircle());
520 else
521 G4Polyhedron::SetNumberOfRotationSteps(fpMP->GetNoOfSides());
522 const G4Polyhedron* pOriginal = pSol->GetPolyhedron();
523 G4Polyhedron::ResetNumberOfRotationSteps();
524
525 if (!pOriginal) {
526
527 if (fpMP->IsWarning())
528 G4cout <<
529 "WARNING: G4PhysicalVolumeModel::DescribeSolid: solid\n \""
530 << pSol->GetName() <<
531 "\" has no polyhedron. Cannot by clipped."
532 << G4endl;
533 pSol -> DescribeYourselfTo (sceneHandler); // Standard treatment.
534
535 } else {
536
537 G4Polyhedron resultant(*pOriginal);
538 G4VisAttributes resultantVisAttribs(*pVisAttribs);
539 G4VSolid* resultantSolid = 0;
540
541 if (fpClippingSolid) {
542 switch (fClippingMode) {
543 default:
544 case subtraction:
545 resultantSolid = new G4SubtractionSolid
546 ("resultant_solid", pSol, fpClippingSolid, theAT.inverse());
547 break;
548 case intersection:
549 resultantSolid = new G4IntersectionSolid
550 ("resultant_solid", pSol, fpClippingSolid, theAT.inverse());
551 break;
552 }
553 }
554
555 if (pSectionSolid) {
556 resultantSolid = new G4IntersectionSolid
557 ("sectioned_solid", pSol, pSectionSolid, theAT.inverse());
558 }
559
560 if (pCutawaySolid) {
561 resultantSolid = new G4SubtractionSolid
562 ("cutaway_solid", pSol, pCutawaySolid, theAT.inverse());
563 }
564
565 G4Polyhedron* tmpResultant = resultantSolid->GetPolyhedron();
566 if (tmpResultant) resultant = *tmpResultant;
567 else {
568 if (fpMP->IsWarning())
569 G4cout <<
570 "WARNING: G4PhysicalVolumeModel::DescribeSolid: resultant polyhedron for"
571 "\n solid \"" << pSol->GetName() <<
572 "\" not defined due to error during Boolean processing."
573 "\n Original will be drawn in red."
574 << G4endl;
575 resultantVisAttribs.SetColour(G4Colour::Red());
576 }
577
578 delete resultantSolid;
579
580 // Finally, force polyhedron drawing...
581 resultant.SetVisAttributes(resultantVisAttribs);
582 sceneHandler.BeginPrimitives(theAT);
583 sceneHandler.AddPrimitive(resultant);
584 sceneHandler.EndPrimitives();
585 }
586 }
587 sceneHandler.PostAddSolid ();
588}
589
590G4bool G4PhysicalVolumeModel::Validate (G4bool warn)
591{
592 G4VPhysicalVolume* world =
593 G4TransportationManager::GetTransportationManager ()
594 -> GetNavigatorForTracking () -> GetWorldVolume ();
595 // The idea now is to seek a PV with the same name and copy no
596 // in the hope it's the same one!!
597 if (warn) {
598 G4cout << "G4PhysicalVolumeModel::Validate() called." << G4endl;
599 }
600 G4PhysicalVolumeModel searchModel (world);
601 G4PhysicalVolumeSearchScene searchScene
602 (&searchModel, fTopPVName, fTopPVCopyNo);
603 G4ModelingParameters mp; // Default modeling parameters for this search.
604 mp.SetDefaultVisAttributes(fpMP? fpMP->GetDefaultVisAttributes(): 0);
605 searchModel.SetModelingParameters (&mp);
606 searchModel.DescribeYourselfTo (searchScene);
607 G4VPhysicalVolume* foundVolume = searchScene.GetFoundVolume ();
608 if (foundVolume) {
609 if (warn) {
610 G4cout << " Volume of the same name and copy number (\""
611 << fTopPVName << "\", copy " << fTopPVCopyNo
612 << ") still exists and is being used."
613 "\n WARNING: This does not necessarily guarantee it's the same"
614 "\n volume you originally specified in /vis/scene/add/."
615 << G4endl;
616 }
617 fpTopPV = foundVolume;
618 CalculateExtent ();
619 return true;
620 }
621 else {
622 if (warn) {
623 G4cout << " A volume of the same name and copy number (\""
624 << fTopPVName << "\", copy " << fTopPVCopyNo
625 << ") no longer exists."
626 << G4endl;
627 }
628 return false;
629 }
630}
631
632const std::map<G4String,G4AttDef>* G4PhysicalVolumeModel::GetAttDefs() const
633{
634 G4bool isNew;
635 std::map<G4String,G4AttDef>* store
636 = G4AttDefStore::GetInstance("G4PhysicalVolumeModel", isNew);
637 if (isNew) {
638 (*store)["PVPath"] =
639 G4AttDef("PVPath","Physical Volume Path","Physics","","G4String");
640 (*store)["LVol"] =
641 G4AttDef("LVol","Logical Volume","Physics","","G4String");
642 (*store)["Solid"] =
643 G4AttDef("Solid","Solid Name","Physics","","G4String");
644 (*store)["EType"] =
645 G4AttDef("EType","Entity Type","Physics","","G4String");
646 (*store)["DmpSol"] =
647 G4AttDef("DmpSol","Dump of Solid properties","Physics","","G4String");
648 (*store)["Trans"] =
649 G4AttDef("Trans","Transformation of volume","Physics","","G4String");
650 (*store)["Material"] =
651 G4AttDef("Material","Material Name","Physics","","G4String");
652 (*store)["Density"] =
653 G4AttDef("Density","Material Density","Physics","G4BestUnit","G4double");
654 (*store)["State"] =
655 G4AttDef("State","Material State (enum undefined,solid,liquid,gas)","Physics","","G4String");
656 (*store)["Radlen"] =
657 G4AttDef("Radlen","Material Radiation Length","Physics","G4BestUnit","G4double");
658 }
659 (*store)["Region"] =
660 G4AttDef("Region","Cuts Region","Physics","","G4String");
661 (*store)["RootRegion"] =
662 G4AttDef("RootRegion","Root Region (0/1 = false/true)","Physics","","G4bool");
663 return store;
664}
665
666#include <iomanip>
667
668static std::ostream& operator<< (std::ostream& o, const G4Transform3D t)
669{
670 using namespace std;
671
672 G4Scale3D s;
673 G4Rotate3D r;
674 G4Translate3D tl;
675 t.getDecomposition(s, r, tl);
676
677 const int w = 10;
678
679 // Transformation itself
680 o << setw(w) << t.xx() << setw(w) << t.xy() << setw(w) << t.xz() << setw(w) << t.dx() << endl;
681 o << setw(w) << t.yx() << setw(w) << t.yy() << setw(w) << t.yz() << setw(w) << t.dy() << endl;
682 o << setw(w) << t.zx() << setw(w) << t.zy() << setw(w) << t.zz() << setw(w) << t.dz() << endl;
683
684 // Translation
685 o << "= translation:" << endl;
686 o << setw(w) << tl.dx() << setw(w) << tl.dy() << setw(w) << tl.dz() << endl;
687
688 // Rotation
689 o << "* rotation:" << endl;
690 o << setw(w) << r.xx() << setw(w) << r.xy() << setw(w) << r.xz() << endl;
691 o << setw(w) << r.yx() << setw(w) << r.yy() << setw(w) << r.yz() << endl;
692 o << setw(w) << r.zx() << setw(w) << r.zy() << setw(w) << r.zz() << endl;
693
694 // Scale
695 o << "* scale:" << endl;
696 o << setw(w) << s.xx() << setw(w) << s.yy() << setw(w) << s.zz() << endl;
697
698 // Transformed axes
699 o << "Transformed axes:" << endl;
700 o << "x': " << r * G4Vector3D(1., 0., 0.) << endl;
701 o << "y': " << r * G4Vector3D(0., 1., 0.) << endl;
702 o << "z': " << r * G4Vector3D(0., 0., 1.) << endl;
703
704 return o;
705}
706
707std::vector<G4AttValue>* G4PhysicalVolumeModel::CreateCurrentAttValues() const
708{
709 std::vector<G4AttValue>* values = new std::vector<G4AttValue>;
710 std::ostringstream oss;
711 for (size_t i = 0; i < fFullPVPath.size(); ++i) {
712 oss << fFullPVPath[i].GetPhysicalVolume()->GetName()
713 << ':' << fFullPVPath[i].GetCopyNo();
714 if (i != fFullPVPath.size() - 1) oss << '/';
715 }
716
717 if (!fpCurrentLV) {
718 G4Exception
719 ("G4PhysicalVolumeModel::CreateCurrentAttValues",
720 "",
721 JustWarning,
722 "Current logical volume not defined.");
723 return values;
724 }
725
726 values->push_back(G4AttValue("PVPath", oss.str(),""));
727 values->push_back(G4AttValue("LVol", fpCurrentLV->GetName(),""));
728 G4VSolid* pSol = fpCurrentLV->GetSolid();
729 values->push_back(G4AttValue("Solid", pSol->GetName(),""));
730 values->push_back(G4AttValue("EType", pSol->GetEntityType(),""));
731 oss.str(""); oss << '\n' << *pSol;
732 values->push_back(G4AttValue("DmpSol", oss.str(),""));
733 oss.str(""); oss << '\n' << *fpCurrentTransform;
734 values->push_back(G4AttValue("Trans", oss.str(),""));
735 G4String matName = fpCurrentMaterial? fpCurrentMaterial->GetName(): G4String("No material");
736 values->push_back(G4AttValue("Material", matName,""));
737 G4double matDensity = fpCurrentMaterial? fpCurrentMaterial->GetDensity(): 0.;
738 values->push_back(G4AttValue("Density", G4BestUnit(matDensity,"Volumic Mass"),""));
739 G4State matState = fpCurrentMaterial? fpCurrentMaterial->GetState(): kStateUndefined;
740 oss.str(""); oss << matState;
741 values->push_back(G4AttValue("State", oss.str(),""));
742 G4double matRadlen = fpCurrentMaterial? fpCurrentMaterial->GetRadlen(): 0.;
743 values->push_back(G4AttValue("Radlen", G4BestUnit(matRadlen,"Length"),""));
744 G4Region* region = fpCurrentLV->GetRegion();
745 G4String regionName = region? region->GetName(): G4String("No region");
746 values->push_back(G4AttValue("Region", regionName,""));
747 oss.str(""); oss << fpCurrentLV->IsRootRegion();
748 values->push_back(G4AttValue("RootRegion", oss.str(),""));
749 return values;
750}
751
752G4bool G4PhysicalVolumeModel::G4PhysicalVolumeNodeID::operator<
753 (const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID& right) const
754{
755 if (fpPV < right.fpPV) return true;
756 if (fpPV == right.fpPV) {
757 if (fCopyNo < right.fCopyNo) return true;
758 if (fCopyNo == right.fCopyNo)
759 return fNonCulledDepth < right.fNonCulledDepth;
760 }
761 return false;
762}
763
764std::ostream& operator<<
765 (std::ostream& os, const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID node)
766{
767 G4VPhysicalVolume* pPV = node.GetPhysicalVolume();
768 if (pPV) {
769 os << pPV->GetName()
770 << ':' << node.GetCopyNo()
771 << '[' << node.GetNonCulledDepth() << ']'
772 << ':' << node.GetTransform();
773 } else {
774 os << "Null node";
775 }
776 return os;
777}
778
779G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::G4PhysicalVolumeModelTouchable
780(const std::vector<G4PhysicalVolumeNodeID>& fullPVPath):
781 fFullPVPath(fullPVPath) {}
782
783const G4ThreeVector& G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetTranslation(G4int depth) const
784{
785 size_t i = fFullPVPath.size() - depth - 1;
786 if (i >= fFullPVPath.size()) {
787 G4Exception("G4PhysicalVolumeModelTouchable::GetTranslation",
788 "Index out of range",
789 FatalErrorInArgument,
790 "Asking for non-existent depth");
791 }
792 static G4ThreeVector tempTranslation;
793 tempTranslation = fFullPVPath[i].GetTransform().getTranslation();
794 return tempTranslation;
795}
796
797const G4RotationMatrix* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetRotation(G4int depth) const
798{
799 size_t i = fFullPVPath.size() - depth - 1;
800 if (i >= fFullPVPath.size()) {
801 G4Exception("G4PhysicalVolumeModelTouchable::GetRotation",
802 "Index out of range",
803 FatalErrorInArgument,
804 "Asking for non-existent depth");
805 }
806 static G4RotationMatrix tempRotation;
807 tempRotation = fFullPVPath[i].GetTransform().getRotation();
808 return &tempRotation;
809}
810
811G4VPhysicalVolume* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetVolume(G4int depth) const
812{
813 size_t i = fFullPVPath.size() - depth - 1;
814 if (i >= fFullPVPath.size()) {
815 G4Exception("G4PhysicalVolumeModelTouchable::GetVolume",
816 "Index out of range",
817 FatalErrorInArgument,
818 "Asking for non-existent depth");
819 }
820 return fFullPVPath[i].GetPhysicalVolume();
821}
822
823G4VSolid* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetSolid(G4int depth) const
824{
825 size_t i = fFullPVPath.size() - depth - 1;
826 if (i >= fFullPVPath.size()) {
827 G4Exception("G4PhysicalVolumeModelTouchable::GetSolid",
828 "Index out of range",
829 FatalErrorInArgument,
830 "Asking for non-existent depth");
831 }
832 return fFullPVPath[i].GetPhysicalVolume()->GetLogicalVolume()->GetSolid();
833}
834
835G4int G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetReplicaNumber(G4int depth) const
836{
837 size_t i = fFullPVPath.size() - depth - 1;
838 if (i >= fFullPVPath.size()) {
839 G4Exception("G4PhysicalVolumeModelTouchable::GetReplicaNumber",
840 "Index out of range",
841 FatalErrorInArgument,
842 "Asking for non-existent depth");
843 }
844 return fFullPVPath[i].GetCopyNo();
845}
Note: See TracBrowser for help on using the repository browser.