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

Last change on this file since 1237 was 1171, checked in by garnier, 16 years ago

update contre CVS

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