Bug Summary

File:scratch/gluex/scan-build-work/hdgeant4/src/G4fixes/G4PhysicalVolumeModel.cc
Location:line 232, column 27
Description:Called C++ object pointer is null

Annotated Source Code

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 106122 2017-09-13 12:51:53Z gcosmo $
28//
29//
30// John Allison 31st December 1997.
31// Model for physical volumes.
32
33#include "G4PhysicalVolumeModel.hh"
34
35#include "G4ModelingParameters.hh"
36#include "G4VGraphicsScene.hh"
37#include "G4VPhysicalVolume.hh"
38#include "G4VPVParameterisation.hh"
39#include "G4LogicalVolume.hh"
40#include "G4VSolid.hh"
41#include "G4SubtractionSolid.hh"
42#include "G4IntersectionSolid.hh"
43#include "G4Material.hh"
44#include "G4VisAttributes.hh"
45#include "G4BoundingSphereScene.hh"
46#include "G4PhysicalVolumeSearchScene.hh"
47#include "G4TransportationManager.hh"
48#include "G4Polycone.hh"
49#include "G4Polyhedra.hh"
50#include "G4Polyhedron.hh"
51#include "HepPolyhedronProcessor.h"
52#include "G4AttDefStore.hh"
53#include "G4AttDef.hh"
54#include "G4AttValue.hh"
55#include "G4UnitsTable.hh"
56#include "G4Vector3D.hh"
57
58#include <sstream>
59
60G4PhysicalVolumeModel::G4PhysicalVolumeModel
61(G4VPhysicalVolume* pVPV
62 , G4int requestedDepth
63 , const G4Transform3D& modelTransformation
64 , const G4ModelingParameters* pMP
65 , G4bool useFullExtent)
66: G4VModel (modelTransformation, pMP)
67, fpTopPV (pVPV)
68, fTopPVCopyNo (0)
69, fRequestedDepth (requestedDepth)
70, fUseFullExtent (useFullExtent)
71, fCurrentDepth (0)
72, fpCurrentPV (0)
73, fpCurrentLV (0)
74, fpCurrentMaterial (0)
75, fpCurrentTransform (0)
76, fAbort (false)
77, fCurtailDescent (false)
78, fpClippingSolid (0)
79, fClippingMode (subtraction)
80{
81 fType = "G4PhysicalVolumeModel";
82
83 if (!fpTopPV) {
84
85 // In some circumstances creating an "empty" G4PhysicalVolumeModel is
86 // allowed, so I have supressed the G4Exception below. If it proves to
87 // be a problem we might have to re-instate it, but it is unlikley to
88 // be used except by visualisation experts. See, for example, /vis/list,
89 // where it is used simply to get a list of G4AttDefs.
90 // G4Exception
91 // ("G4PhysicalVolumeModel::G4PhysicalVolumeModel",
92 // "modeling0010", FatalException, "Null G4PhysicalVolumeModel pointer.");
93
94 fTopPVName = "NULL";
95 fGlobalTag = "Empty";
96 fGlobalDescription = "G4PhysicalVolumeModel " + fGlobalTag;
97
98 } else {
99
100 fTopPVName = fpTopPV -> GetName ();
101 fTopPVCopyNo = fpTopPV -> GetCopyNo ();
102 std::ostringstream o;
103 o << fpTopPV -> GetCopyNo ();
104 fGlobalTag = fpTopPV -> GetName () + "." + o.str();
105 fGlobalDescription = "G4PhysicalVolumeModel " + fGlobalTag;
106
107 fpCurrentPV = fpTopPV;
108 if (fpCurrentPV) fpCurrentLV = fpCurrentPV->GetLogicalVolume();
109 if (fpCurrentLV) fpCurrentMaterial = fpCurrentLV->GetMaterial();
110 fpCurrentTransform = const_cast<G4Transform3D*>(&modelTransformation);
111
112 CalculateExtent ();
113 }
114}
115
116G4PhysicalVolumeModel::~G4PhysicalVolumeModel ()
117{
118 delete fpClippingSolid;
119}
120
121void G4PhysicalVolumeModel::CalculateExtent ()
122{
123 if (fUseFullExtent) {
9
Taking false branch
124 fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
125 }
126 else {
127 G4BoundingSphereScene bsScene(this);
10
Value assigned to field 'fpTopPV'
128 const G4int tempRequestedDepth = fRequestedDepth;
129 fRequestedDepth = -1; // Always search to all depths to define extent.
130 const G4ModelingParameters* tempMP = fpMP;
131 G4ModelingParameters mParams
132 (0, // No default vis attributes needed.
133 G4ModelingParameters::wf, // wireframe (not relevant for this).
134 true, // Global culling.
135 true, // Cull invisible volumes.
136 false, // Density culling.
137 0., // Density (not relevant if density culling false).
138 true, // Cull daughters of opaque mothers.
139 24); // No of sides (not relevant for this operation).
140 fpMP = &mParams;
141 DescribeYourselfTo (bsScene);
11
Calling 'G4PhysicalVolumeModel::DescribeYourselfTo'
142 G4double radius = bsScene.GetRadius();
143 if (radius < 0.) { // Nothing in the scene.
144 fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
145 } else {
146 // Transform back to coordinates relative to the top
147 // transformation, which is in G4VModel::fTransform. This makes
148 // it conform to all models, which are defined by a
149 // transformation and an extent relative to that
150 // transformation...
151 G4Point3D centre = bsScene.GetCentre();
152 centre.transform(fTransform.inverse());
153 fExtent = G4VisExtent(centre, radius);
154 }
155 fpMP = tempMP;
156 fRequestedDepth = tempRequestedDepth;
157 }
158}
159
160void G4PhysicalVolumeModel::DescribeYourselfTo
161(G4VGraphicsScene& sceneHandler)
162{
163 if (!fpTopPV) G4Exception
12
Assuming pointer value is null
13
Taking true branch
164 ("G4PhysicalVolumeModel::DescribeYourselfTo",
165 "modeling0012", FatalException, "No model.");
166
167 if (!fpMP) G4Exception
14
Taking false branch
168 ("G4PhysicalVolumeModel::DescribeYourselfTo",
169 "modeling0003", FatalException, "No modeling parameters.");
170
171 // For safety...
172 fCurrentDepth = 0;
173
174 G4Transform3D startingTransformation = fTransform;
175
176 VisitGeometryAndGetVisReps
16
Calling 'G4PhysicalVolumeModel::VisitGeometryAndGetVisReps'
177 (fpTopPV,
15
Passing null pointer value via 1st parameter 'pVPV'
178 fRequestedDepth,
179 startingTransformation,
180 sceneHandler);
181
182 // Clear data...
183 fCurrentDepth = 0;
184 fpCurrentPV = 0;
185 fpCurrentLV = 0;
186 fpCurrentMaterial = 0;
187 if (fFullPVPath.size() != fBaseFullPVPath.size()) {
188 // They should be equal if pushing and popping is happening properly.
189 G4Exception
190 ("G4PhysicalVolumeModel::DescribeYourselfTo",
191 "modeling0013",
192 FatalException,
193 "Path at start of modeling not equal to base path. Something badly"
194 "\nwrong. Please contact visualisation coordinator.");
195 }
196 fDrawnPVPath.clear();
197 fAbort = false;
198 fCurtailDescent = false;
199}
200
201G4String G4PhysicalVolumeModel::GetCurrentTag () const
202{
203 if (fpCurrentPV) {
204 std::ostringstream o;
205 o << fpCurrentPV -> GetCopyNo ();
206 return fpCurrentPV -> GetName () + "." + o.str();
207 }
208 else {
209 return "WARNING: NO CURRENT VOLUME - global tag is " + fGlobalTag;
210 }
211}
212
213G4String G4PhysicalVolumeModel::GetCurrentDescription () const
214{
215 return "G4PhysicalVolumeModel " + GetCurrentTag ();
216}
217
218void G4PhysicalVolumeModel::VisitGeometryAndGetVisReps
219(G4VPhysicalVolume* pVPV,
220 G4int requestedDepth,
221 const G4Transform3D& theAT,
222 G4VGraphicsScene& sceneHandler)
223{
224 // Visits geometry structure to a given depth (requestedDepth), starting
225 // at given physical volume with given starting transformation and
226 // describes volumes to the scene handler.
227 // requestedDepth < 0 (default) implies full visit.
228 // theAT is the Accumulated Transformation.
229
230 // Find corresponding logical volume and (later) solid, storing in
231 // local variables to preserve re-entrancy.
232 G4LogicalVolume* pLV = pVPV -> GetLogicalVolume ();
17
Called C++ object pointer is null
233
234 G4VSolid* pSol;
235 G4Material* pMaterial;
236
237 if (!(pVPV -> IsReplicated ())) {
238 // Non-replicated physical volume.
239 pSol = pLV -> GetSolid ();
240 pMaterial = pLV -> GetMaterial ();
241 DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
242 theAT, sceneHandler);
243 }
244 else {
245 // Replicated or parametrised physical volume.
246 EAxis axis;
247 G4int nReplicas;
248 G4double width;
249 G4double offset;
250 G4bool consuming;
251 pVPV -> GetReplicationData (axis, nReplicas, width, offset, consuming);
252 if (fCurrentDepth == 0) nReplicas = 1; // Just draw first
253 G4VPVParameterisation* pP = pVPV -> GetParameterisation ();
254 if (pP) { // Parametrised volume.
255 for (int n = 0; n < nReplicas; n++) {
256 pSol = pP -> ComputeSolid (n, pVPV);
257 pP -> ComputeTransformation (n, pVPV);
258 pSol -> ComputeDimensions (pP, n, pVPV);
259 pVPV -> SetCopyNo (n);
260 // Create a touchable of current parent for ComputeMaterial.
261 // fFullPVPath has not been updated yet so at this point it
262 // corresponds to the parent.
263 G4PhysicalVolumeModelTouchable parentTouchable(fFullPVPath);
264 pMaterial = pP -> ComputeMaterial (n, pVPV, &parentTouchable);
265 DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
266 theAT, sceneHandler);
267 }
268 }
269 else { // Plain replicated volume. From geometry_guide.txt...
270 // The replica's positions are claculated by means of a linear formula.
271 // Replication may occur along:
272 //
273 // o Cartesian axes (kXAxis,kYAxis,kZAxis)
274 //
275 // The replications, of specified width have coordinates of
276 // form (-width*(nReplicas-1)*0.5+n*width,0,0) where n=0.. nReplicas-1
277 // for the case of kXAxis, and are unrotated.
278 //
279 // o Radial axis (cylindrical polar) (kRho)
280 //
281 // The replications are cons/tubs sections, centred on the origin
282 // and are unrotated.
283 // They have radii of width*n+offset to width*(n+1)+offset
284 // where n=0..nReplicas-1
285 //
286 // o Phi axis (cylindrical polar) (kPhi)
287 // The replications are `phi sections' or wedges, and of cons/tubs form
288 // They have phi of offset+n*width to offset+(n+1)*width where
289 // n=0..nReplicas-1
290 //
291 pSol = pLV -> GetSolid ();
292 pMaterial = pLV -> GetMaterial ();
293 G4ThreeVector originalTranslation = pVPV -> GetTranslation ();
294 G4RotationMatrix* pOriginalRotation = pVPV -> GetRotation ();
295 G4double originalRMin = 0., originalRMax = 0.;
296 if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
297 originalRMin = ((G4Tubs*)pSol)->GetInnerRadius();
298 originalRMax = ((G4Tubs*)pSol)->GetOuterRadius();
299 }
300 G4bool visualisable = true;
301 for (int n = 0; n < nReplicas; n++) {
302 G4ThreeVector translation; // Identity.
303 G4RotationMatrix rotation; // Identity - life enough for visualizing.
304 G4RotationMatrix* pRotation = 0;
305 switch (axis) {
306 default:
307 case kXAxis:
308 translation = G4ThreeVector (-width*(nReplicas-1)*0.5+n*width,0,0);
309 break;
310 case kYAxis:
311 translation = G4ThreeVector (0,-width*(nReplicas-1)*0.5+n*width,0);
312 break;
313 case kZAxis:
314 translation = G4ThreeVector (0,0,-width*(nReplicas-1)*0.5+n*width);
315 break;
316 case kRho:
317 if (pSol->GetEntityType() == "G4Tubs") {
318 ((G4Tubs*)pSol)->SetInnerRadius(width*n+offset);
319 ((G4Tubs*)pSol)->SetOuterRadius(width*(n+1)+offset);
320 } else {
321 if (fpMP->IsWarning())
322 G4cout(*G4cout_p) <<
323 "G4PhysicalVolumeModel::VisitGeometryAndGetVisReps: WARNING:"
324 "\n built-in replicated volumes replicated in radius for "
325 << pSol->GetEntityType() <<
326 "-type\n solids (your solid \""
327 << pSol->GetName() <<
328 "\") are not visualisable."
329 << G4endlstd::endl;
330 visualisable = false;
331 }
332 break;
333 case kPhi:
334 rotation.rotateZ (-(offset+(n+0.5)*width));
335 // Minus Sign because for the physical volume we need the
336 // coordinate system rotation.
337 pRotation = &rotation;
338 break;
339 }
340 pVPV -> SetTranslation (translation);
341 pVPV -> SetRotation (pRotation);
342 pVPV -> SetCopyNo (n);
343 if (visualisable) {
344 DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial,
345 theAT, sceneHandler);
346 }
347 }
348 // Restore originals...
349 pVPV -> SetTranslation (originalTranslation);
350 pVPV -> SetRotation (pOriginalRotation);
351 if (axis == kRho && pSol->GetEntityType() == "G4Tubs") {
352 ((G4Tubs*)pSol)->SetInnerRadius(originalRMin);
353 ((G4Tubs*)pSol)->SetOuterRadius(originalRMax);
354 }
355 }
356 }
357}
358
359void G4PhysicalVolumeModel::DescribeAndDescend
360(G4VPhysicalVolume* pVPV,
361 G4int requestedDepth,
362 G4LogicalVolume* pLV,
363 G4VSolid* pSol,
364 G4Material* pMaterial,
365 const G4Transform3D& theAT,
366 G4VGraphicsScene& sceneHandler)
367{
368 // Maintain useful data members...
369 fpCurrentPV = pVPV;
370 fpCurrentLV = pLV;
371 fpCurrentMaterial = pMaterial;
372
373 const G4RotationMatrix objectRotation = pVPV -> GetObjectRotationValue ();
374 const G4ThreeVector& translation = pVPV -> GetTranslation ();
375 G4Transform3D theLT (G4Transform3D (objectRotation, translation));
376
377 // Compute the accumulated transformation...
378 // Note that top volume's transformation relative to the world
379 // coordinate system is specified in theAT == startingTransformation
380 // = fTransform (see DescribeYourselfTo), so first time through the
381 // volume's own transformation, which is only relative to its
382 // mother, i.e., not relative to the world coordinate system, should
383 // not be accumulated.
384 G4Transform3D theNewAT (theAT);
385 if (fCurrentDepth != 0) theNewAT = theAT * theLT;
386 fpCurrentTransform = &theNewAT;
387
388 const G4VisAttributes* pVisAttribs = pLV->GetVisAttributes();
389 if (!pVisAttribs) pVisAttribs = fpMP->GetDefaultVisAttributes();
390 // Beware - pVisAttribs might still be zero - probably will, since that's
391 // the default for G4ModelingParameters. So create one if necessary...
392 if (!pVisAttribs) {
393 static G4VisAttributes defaultVisAttribs;
394 pVisAttribs = &defaultVisAttribs;
395 }
396 // From here, can assume pVisAttribs is a valid pointer. This is necessary
397 // because PreAddSolid needs a vis attributes object.
398
399 // Make decision to draw...
400 G4bool thisToBeDrawn = true;
401
402 // Update full path of physical volumes...
403 G4int copyNo = fpCurrentPV->GetCopyNo();
404 fFullPVPath.push_back
405 (G4PhysicalVolumeNodeID
406 (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform));
407
408 // Check if vis attributes are to be modified by a /vis/touchable/set/ command.
409 const auto& vams = fpMP->GetVisAttributesModifiers();
410 if (vams.size()) {
411 // OK, we have some VAMs (Vis Attributes Modifiers).
412 for (const auto& vam: vams) {
413 const auto& vamPath = vam.GetPVNameCopyNoPath();
414 if (vamPath.size() == fFullPVPath.size()) {
415 // OK, we have a size match.
416 // Check the volume name/copy number path.
417 auto iVAMNameCopyNo = vamPath.begin();
418 auto iPVNodeId = fFullPVPath.begin();
419 for (; iVAMNameCopyNo != vamPath.end(); ++iVAMNameCopyNo, ++iPVNodeId) {
420 if (!(
421 iVAMNameCopyNo->GetName() ==
422 iPVNodeId->GetPhysicalVolume()->GetName() &&
423 iVAMNameCopyNo->GetCopyNo() ==
424 iPVNodeId->GetPhysicalVolume()->GetCopyNo()
425 )) {
426 // This path element does NOT match.
427 break;
428 }
429 }
430 if (iVAMNameCopyNo == vamPath.end()) {
431 // OK, the paths match (the above loop terminated normally).
432 // Create a vis atts object for the modified vis atts.
433 // It is static so that we may return a reliable pointer to it.
434 static G4VisAttributes modifiedVisAtts;
435 // Initialise it with the current vis atts and reset the pointer.
436 modifiedVisAtts = *pVisAttribs;
437 pVisAttribs = &modifiedVisAtts;
438 const G4VisAttributes& transVisAtts = vam.GetVisAttributes();
439 switch (vam.GetVisAttributesSignifier()) {
440 case G4ModelingParameters::VASVisibility:
441 modifiedVisAtts.SetVisibility(transVisAtts.IsVisible());
442 break;
443 case G4ModelingParameters::VASDaughtersInvisible:
444 modifiedVisAtts.SetDaughtersInvisible
445 (transVisAtts.IsDaughtersInvisible());
446 break;
447 case G4ModelingParameters::VASColour:
448 modifiedVisAtts.SetColour(transVisAtts.GetColour());
449 break;
450 case G4ModelingParameters::VASLineStyle:
451 modifiedVisAtts.SetLineStyle(transVisAtts.GetLineStyle());
452 break;
453 case G4ModelingParameters::VASLineWidth:
454 modifiedVisAtts.SetLineWidth(transVisAtts.GetLineWidth());
455 break;
456 case G4ModelingParameters::VASForceWireframe:
457 if (transVisAtts.IsForceDrawingStyle()) {
458 if (transVisAtts.GetForcedDrawingStyle() ==
459 G4VisAttributes::wireframe) {
460 modifiedVisAtts.SetForceWireframe(true);
461 }
462 }
463 break;
464 case G4ModelingParameters::VASForceSolid:
465 if (transVisAtts.IsForceDrawingStyle()) {
466 if (transVisAtts.GetForcedDrawingStyle() ==
467 G4VisAttributes::solid) {
468 modifiedVisAtts.SetForceSolid(true);
469 }
470 }
471 break;
472 case G4ModelingParameters::VASForceAuxEdgeVisible:
473 if (transVisAtts.IsForceAuxEdgeVisible()) {
474 modifiedVisAtts.SetForceAuxEdgeVisible
475 (transVisAtts.IsForcedAuxEdgeVisible());
476 }
477 break;
478 case G4ModelingParameters::VASForceLineSegmentsPerCircle:
479 modifiedVisAtts.SetForceLineSegmentsPerCircle
480 (transVisAtts.GetForcedLineSegmentsPerCircle());
481 break;
482 }
483 }
484 }
485 }
486 }
487
488 // There are various reasons why this volume
489 // might not be drawn...
490 G4bool culling = fpMP->IsCulling();
491 G4bool cullingInvisible = fpMP->IsCullingInvisible();
492 G4bool markedVisible = pVisAttribs->IsVisible();
493 G4bool cullingLowDensity = fpMP->IsDensityCulling();
494 G4double density = pMaterial? pMaterial->GetDensity(): 0;
495 G4double densityCut = fpMP -> GetVisibleDensity ();
496
497 // 1) Global culling is on....
498 if (culling) {
499 // 2) Culling of invisible volumes is on...
500 if (cullingInvisible) {
501 // 3) ...and the volume is marked not visible...
502 if (!markedVisible) thisToBeDrawn = false;
503 }
504 // 4) Or culling of low density volumes is on...
505 if (cullingLowDensity) {
506 // 5) ...and density is less than cut value...
507 if (density < densityCut) thisToBeDrawn = false;
508 }
509 }
510 // 6) The user has asked for all further traversing to be aborted...
511 if (fAbort) thisToBeDrawn = false;
512
513#ifdef BYPASS_DRAWING_CLIPPED_VOLUMES1
514
515 // Check if a view clipping operation cuts this volume from the scene
516
517 bool thisToBeBypassed = false;
518 G4VSolid* pIntersector = fpMP->GetSectionSolid();
519 G4VSolid* pSubtractor = fpMP->GetCutawaySolid();
520 if (fpClippingSolid) {
521 switch (fClippingMode) {
522 case subtraction:
523 pSubtractor = fpClippingSolid;
524 break;
525 case intersection:
526 pIntersector = fpClippingSolid;
527 break;
528 }
529 }
530
531 G4DisplacedSolid *pClipper;
532 if ((pClipper = dynamic_cast<G4DisplacedSolid*>(pIntersector)))
533 {
534 G4AffineTransform clipAT(pClipper->GetTransform());
535 G4AffineTransform currAT(fpCurrentTransform->getRotation().inverse(),
536 fpCurrentTransform->getTranslation());
537 G4AffineTransform combAT;
538 combAT.Product(currAT,clipAT);
539 G4DisplacedSolid pClipped("temporary_to_clip",pSol,combAT);
540 G4VisExtent clipper(pClipper->GetConstituentMovedSolid()->GetExtent());
541 G4VisExtent clipped(pClipped.GetExtent());
542 thisToBeBypassed = (clipper.GetXmax() < clipped.GetXmin())
543 || (clipper.GetXmin() > clipped.GetXmax())
544 || (clipper.GetYmax() < clipped.GetYmin())
545 || (clipper.GetYmin() > clipped.GetYmax())
546 || (clipper.GetZmax() < clipped.GetZmin())
547 || (clipper.GetZmin() > clipped.GetZmax());
548 }
549
550 if ((pClipper = dynamic_cast<G4DisplacedSolid*>(pSubtractor)))
551 {
552 G4AffineTransform clipAT(pClipper->GetTransform());
553 G4AffineTransform currAT(fpCurrentTransform->getRotation().inverse(),
554 fpCurrentTransform->getTranslation());
555 G4AffineTransform combAT;
556 combAT.Product(currAT,clipAT);
557 G4DisplacedSolid pClipped("temporary_to_clip",pSol,combAT);
558 G4VisExtent clipper(pClipper->GetConstituentMovedSolid()->GetExtent());
559 G4VisExtent clipped(pClipped.GetExtent());
560 thisToBeBypassed = (clipper.GetXmax() > clipped.GetXmax())
561 && (clipper.GetXmin() < clipped.GetXmin())
562 && (clipper.GetYmax() > clipped.GetYmax())
563 && (clipper.GetYmin() < clipped.GetYmin())
564 && (clipper.GetZmax() > clipped.GetZmax())
565 && (clipper.GetZmin() < clipped.GetZmin());
566 }
567
568 thisToBeDrawn = thisToBeDrawn && (! thisToBeBypassed);
569
570#endif
571
572 // Record thisToBeDrawn in path...
573 fFullPVPath.back().SetDrawn(thisToBeDrawn);
574
575 if (thisToBeDrawn) {
576
577 // Update path of drawn physical volumes...
578 fDrawnPVPath.push_back
579 (G4PhysicalVolumeNodeID
580 (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform,thisToBeDrawn));
581
582 if (fpMP->IsExplode() && fDrawnPVPath.size() == 1) {
583 // For top-level drawn volumes, explode along radius...
584 G4Transform3D centering = G4Translate3D(fpMP->GetExplodeCentre());
585 G4Transform3D centred = centering.inverse() * theNewAT;
586 G4Scale3D oldScale;
587 G4Rotate3D oldRotation;
588 G4Translate3D oldTranslation;
589 centred.getDecomposition(oldScale, oldRotation, oldTranslation);
590 G4double explodeFactor = fpMP->GetExplodeFactor();
591 G4Translate3D newTranslation =
592 G4Translate3D(explodeFactor * oldTranslation.dx(),
593 explodeFactor * oldTranslation.dy(),
594 explodeFactor * oldTranslation.dz());
595 theNewAT = centering * newTranslation * oldRotation * oldScale;
596 }
597
598 DescribeSolid (theNewAT, pSol, pVisAttribs, sceneHandler);
599
600 }
601
602 // Make decision to draw daughters, if any. There are various
603 // reasons why daughters might not be drawn...
604
605 // First, reasons that do not depend on culling policy...
606 G4int nDaughters = pLV->GetNoDaughters();
607#ifdef BYPASS_DRAWING_CLIPPED_VOLUMES1
608 G4bool daughtersToBeDrawn = ! thisToBeBypassed;
609#else
610 G4bool daughtersToBeDrawn = true;
611#endif
612 // 1) There are no daughters...
613 if (!nDaughters) daughtersToBeDrawn = false;
614 // 2) We are at the limit if requested depth...
615 else if (requestedDepth == 0) daughtersToBeDrawn = false;
616 // 3) The user has asked for all further traversing to be aborted...
617 else if (fAbort) daughtersToBeDrawn = false;
618 // 4) The user has asked that the descent be curtailed...
619 else if (fCurtailDescent) daughtersToBeDrawn = false;
620
621 // Now, reasons that depend on culling policy...
622 else {
623 G4bool daughtersInvisible = pVisAttribs->IsDaughtersInvisible();
624 // Culling of covered daughters request. This is computed in
625 // G4VSceneHandler::CreateModelingParameters() depending on view
626 // parameters...
627 G4bool cullingCovered = fpMP->IsCullingCovered();
628 G4bool surfaceDrawing =
629 fpMP->GetDrawingStyle() == G4ModelingParameters::hsr ||
630 fpMP->GetDrawingStyle() == G4ModelingParameters::hlhsr;
631 if (pVisAttribs->IsForceDrawingStyle()) {
632 switch (pVisAttribs->GetForcedDrawingStyle()) {
633 default:
634 case G4VisAttributes::wireframe: surfaceDrawing = false; break;
635 case G4VisAttributes::solid: surfaceDrawing = true; break;
636 }
637 }
638 G4bool opaque = pVisAttribs->GetColour().GetAlpha() >= 1.;
639 // 5) Global culling is on....
640 if (culling) {
641 // 6) ..and culling of invisible volumes is on...
642 if (cullingInvisible) {
643 // 7) ...and the mother requests daughters invisible
644 if (daughtersInvisible) daughtersToBeDrawn = false;
645 }
646 // 8) Or culling of covered daughters is requested...
647 if (cullingCovered) {
648 // 9) ...and surface drawing is operating...
649 if (surfaceDrawing) {
650 // 10) ...but only if mother is visible...
651 if (thisToBeDrawn) {
652 // 11) ...and opaque...
653 if (opaque) daughtersToBeDrawn = false;
654 }
655 }
656 }
657 }
658 }
659
660 if (daughtersToBeDrawn) {
661 for (G4int iDaughter = 0; iDaughter < nDaughters; iDaughter++) {
662 // Store daughter pVPV in local variable ready for recursion...
663 G4VPhysicalVolume* pDaughterVPV = pLV -> GetDaughter (iDaughter);
664 // Descend the geometry structure recursively...
665 fCurrentDepth++;
666 VisitGeometryAndGetVisReps
667 (pDaughterVPV, requestedDepth - 1, theNewAT, sceneHandler);
668 fCurrentDepth--;
669 }
670 }
671
672 // Reset for normal descending of next volume at this level...
673 fCurtailDescent = false;
674
675 // Pop item from paths physical volumes...
676 fFullPVPath.pop_back();
677 if (thisToBeDrawn) {
678 fDrawnPVPath.pop_back();
679 }
680}
681
682void G4PhysicalVolumeModel::DescribeSolid
683(const G4Transform3D& theAT,
684 G4VSolid* pSol,
685 const G4VisAttributes* pVisAttribs,
686 G4VGraphicsScene& sceneHandler)
687{
688 sceneHandler.PreAddSolid (theAT, *pVisAttribs);
689
690 G4VSolid* pSectionSolid = fpMP->GetSectionSolid();
691 G4VSolid* pCutawaySolid = fpMP->GetCutawaySolid();
692
693 if (!fpClippingSolid && !pSectionSolid && !pCutawaySolid) {
694
695 pSol -> DescribeYourselfTo (sceneHandler); // Standard treatment.
696
697 } else {
698
699 // Clipping, etc., performed by Boolean operations.
700
701 // First, get polyhedron for current solid...
702 if (pVisAttribs->IsForceLineSegmentsPerCircle())
703 G4Polyhedron::SetNumberOfRotationSteps
704 (pVisAttribs->GetForcedLineSegmentsPerCircle());
705 else
706 G4Polyhedron::SetNumberOfRotationSteps(fpMP->GetNoOfSides());
707
708 // Special treatment for G4PolyHedra and G4Polycone
709
710 G4Polyhedra *polyhedr = dynamic_cast<G4Polyhedra*>(pSol);
711 G4Polycone *polycone = dynamic_cast<G4Polycone*>(pSol);
712 if (polyhedr) {
713 G4PolyhedraHistorical pars(*polyhedr->GetOriginalParameters());
714 for (int p=1; p < pars.Num_z_planes; ++p) {
715 if (pars.Z_values[p] <= pars.Z_values[p-1])
716 pars.Z_values[p] = pars.Z_values[p] + 1e-3;
717 }
718 G4String visname(pSol->GetName() + "_visual");
719 pSol = new G4Polyhedra(visname, pars.Start_angle,
720 pars.Opening_angle,
721 pars.numSide,
722 pars.Num_z_planes,
723 pars.Z_values,
724 pars.Rmin,
725 pars.Rmax);
726 }
727 else if (polycone) {
728 G4PolyconeHistorical pars(*polycone->GetOriginalParameters());
729 for (int p=1; p < pars.Num_z_planes; ++p) {
730 if (pars.Z_values[p] <= pars.Z_values[p-1])
731 pars.Z_values[p] = pars.Z_values[p] + 1e-3;
732 }
733 G4String visname(pSol->GetName() + "_visual");
734 pSol = new G4Polycone(visname, pars.Start_angle,
735 pars.Opening_angle,
736 pars.Num_z_planes,
737 pars.Z_values,
738 pars.Rmin,
739 pars.Rmax);
740 }
741
742 const G4Polyhedron* pOriginal = pSol->GetPolyhedron();
743 //G4Polyhedron::ResetNumberOfRotationSteps();
744
745 if (!pOriginal) {
746
747 if (fpMP->IsWarning())
748 G4cout(*G4cout_p) <<
749 "WARNING: G4PhysicalVolumeModel::DescribeSolid: solid\n \""
750 << pSol->GetName() <<
751 "\" has no polyhedron. Cannot by clipped."
752 << G4endlstd::endl;
753 pSol -> DescribeYourselfTo (sceneHandler); // Standard treatment.
754
755 } else {
756
757 G4Polyhedron resultant(*pOriginal);
758 G4VisAttributes resultantVisAttribs(*pVisAttribs);
759 G4VSolid* resultantSolid = 0;
760
761 if (fpClippingSolid) {
762 switch (fClippingMode) {
763 default:
764 case subtraction:
765 resultantSolid = new G4SubtractionSolid
766 ("resultant_solid", pSol, fpClippingSolid, theAT.inverse());
767 break;
768 case intersection:
769 resultantSolid = new G4IntersectionSolid
770 ("resultant_solid", pSol, fpClippingSolid, theAT.inverse());
771 break;
772 }
773 }
774
775 if (pSectionSolid) {
776 resultantSolid = new G4IntersectionSolid
777 ("sectioned_solid", pSol, pSectionSolid, theAT.inverse());
778 }
779
780 if (pCutawaySolid) {
781 resultantSolid = new G4SubtractionSolid
782 ("cutaway_solid", pSol, pCutawaySolid, theAT.inverse());
783 }
784
785 G4Polyhedron* tmpResultant = resultantSolid->GetPolyhedron();
786 if (tmpResultant) resultant = *tmpResultant;
787 else {
788 if (fpMP->IsWarning())
789 G4cout(*G4cout_p) <<
790 "WARNING: G4PhysicalVolumeModel::DescribeSolid: resultant polyhedron for"
791 "\n solid \"" << pSol->GetName() <<
792 "\" not defined due to error during Boolean processing."
793 "\n Original will be drawn in red."
794 << G4endlstd::endl;
795 resultantVisAttribs.SetColour(G4Colour::Red());
796 }
797
798 delete resultantSolid;
799
800 // Finally, force polyhedron drawing...
801 resultant.SetVisAttributes(resultantVisAttribs);
802 sceneHandler.BeginPrimitives(theAT);
803 sceneHandler.AddPrimitive(resultant);
804 sceneHandler.EndPrimitives();
805 }
806 }
807 sceneHandler.PostAddSolid ();
808}
809
810G4bool G4PhysicalVolumeModel::Validate (G4bool warn)
811{
812 G4TransportationManager* transportationManager =
813 G4TransportationManager::GetTransportationManager ();
814
815 size_t nWorlds = transportationManager->GetNoWorlds();
816
817 G4bool found = false;
818
819 std::vector<G4VPhysicalVolume*>::iterator iterWorld =
820 transportationManager->GetWorldsIterator();
821 for (size_t i = 0; i < nWorlds; ++i, ++iterWorld) {
1
Assuming 'i' is < 'nWorlds'
2
Loop condition is true. Entering loop body
822 G4VPhysicalVolume* world = (*iterWorld);
823 if (!world) break; // This can happen if geometry has been cleared/destroyed.
3
Assuming 'world' is non-null
4
Taking false branch
824 // The idea now is to seek a PV with the same name and copy no
825 // in the hope it's the same one!!
826 G4PhysicalVolumeModel searchModel (world);
827 G4int verbosity = 0; // Suppress messages from G4PhysicalVolumeSearchScene.
828 G4PhysicalVolumeSearchScene searchScene
829 (&searchModel, fTopPVName, fTopPVCopyNo, verbosity);
830 G4ModelingParameters mp; // Default modeling parameters for this search.
831 mp.SetDefaultVisAttributes(fpMP? fpMP->GetDefaultVisAttributes(): 0);
5
'?' condition is false
832 searchModel.SetModelingParameters (&mp);
833 searchModel.DescribeYourselfTo (searchScene);
834 G4VPhysicalVolume* foundVolume = searchScene.GetFoundVolume ();
835 if (foundVolume) {
6
Assuming 'foundVolume' is non-null
7
Taking true branch
836 if (foundVolume != fpTopPV && warn) {
837 G4cout(*G4cout_p) <<
838 "G4PhysicalVolumeModel::Validate(): A volume of the same name and"
839 "\n copy number (\""
840 << fTopPVName << "\", copy " << fTopPVCopyNo
841 << ") still exists and is being used."
842 "\n But it is not the same volume you originally specified"
843 "\n in /vis/scene/add/."
844 << G4endlstd::endl;
845 }
846 fpTopPV = foundVolume;
847 CalculateExtent ();
8
Calling 'G4PhysicalVolumeModel::CalculateExtent'
848 found = true;
849 }
850 }
851 if (found) return true;
852 else {
853 if (warn) {
854 G4cout(*G4cout_p) <<
855 "G4PhysicalVolumeModel::Validate(): No volume of name and"
856 "\n copy number (\""
857 << fTopPVName << "\", copy " << fTopPVCopyNo
858 << ") exists."
859 << G4endlstd::endl;
860 }
861 return false;
862 }
863}
864
865const std::map<G4String,G4AttDef>* G4PhysicalVolumeModel::GetAttDefs() const
866{
867 G4bool isNew;
868 std::map<G4String,G4AttDef>* store
869 = G4AttDefStore::GetInstance("G4PhysicalVolumeModel", isNew);
870 if (isNew) {
871 (*store)["PVPath"] =
872 G4AttDef("PVPath","Physical Volume Path","Physics","","G4String");
873 (*store)["LVol"] =
874 G4AttDef("LVol","Logical Volume","Physics","","G4String");
875 (*store)["Solid"] =
876 G4AttDef("Solid","Solid Name","Physics","","G4String");
877 (*store)["EType"] =
878 G4AttDef("EType","Entity Type","Physics","","G4String");
879 (*store)["DmpSol"] =
880 G4AttDef("DmpSol","Dump of Solid properties","Physics","","G4String");
881 (*store)["LocalTrans"] =
882 G4AttDef("LocalTrans","Local transformation of volume","Physics","","G4String");
883 (*store)["GlobalTrans"] =
884 G4AttDef("GlobalTrans","Global transformation of volume","Physics","","G4String");
885 (*store)["Material"] =
886 G4AttDef("Material","Material Name","Physics","","G4String");
887 (*store)["Density"] =
888 G4AttDef("Density","Material Density","Physics","G4BestUnit","G4double");
889 (*store)["State"] =
890 G4AttDef("State","Material State (enum undefined,solid,liquid,gas)","Physics","","G4String");
891 (*store)["Radlen"] =
892 G4AttDef("Radlen","Material Radiation Length","Physics","G4BestUnit","G4double");
893 (*store)["Region"] =
894 G4AttDef("Region","Cuts Region","Physics","","G4String");
895 (*store)["RootRegion"] =
896 G4AttDef("RootRegion","Root Region (0/1 = false/true)","Physics","","G4bool");
897 }
898 return store;
899}
900
901#include <iomanip>
902
903static std::ostream& operator<< (std::ostream& o, const G4Transform3D t)
904{
905 using namespace std;
906
907 G4Scale3D sc;
908 G4Rotate3D r;
909 G4Translate3D tl;
910 t.getDecomposition(sc, r, tl);
911
912 const int w = 10;
913
914 // Transformation itself
915 o << setw(w) << t.xx() << setw(w) << t.xy() << setw(w) << t.xz() << setw(w) << t.dx() << endl;
916 o << setw(w) << t.yx() << setw(w) << t.yy() << setw(w) << t.yz() << setw(w) << t.dy() << endl;
917 o << setw(w) << t.zx() << setw(w) << t.zy() << setw(w) << t.zz() << setw(w) << t.dz() << endl;
918
919 // Translation
920 o << "= translation:" << endl;
921 o << setw(w) << tl.dx() << setw(w) << tl.dy() << setw(w) << tl.dz() << endl;
922
923 // Rotation
924 o << "* rotation:" << endl;
925 o << setw(w) << r.xx() << setw(w) << r.xy() << setw(w) << r.xz() << endl;
926 o << setw(w) << r.yx() << setw(w) << r.yy() << setw(w) << r.yz() << endl;
927 o << setw(w) << r.zx() << setw(w) << r.zy() << setw(w) << r.zz() << endl;
928
929 // Scale
930 o << "* scale:" << endl;
931 o << setw(w) << sc.xx() << setw(w) << sc.yy() << setw(w) << sc.zz() << endl;
932
933 // Transformed axes
934 o << "Transformed axes:" << endl;
935 o << "x': " << r * G4Vector3D(1., 0., 0.) << endl;
936 o << "y': " << r * G4Vector3D(0., 1., 0.) << endl;
937 o << "z': " << r * G4Vector3D(0., 0., 1.) << endl;
938
939 return o;
940}
941
942std::vector<G4AttValue>* G4PhysicalVolumeModel::CreateCurrentAttValues() const
943{
944 std::vector<G4AttValue>* values = new std::vector<G4AttValue>;
945 std::ostringstream oss;
946 for (size_t i = 0; i < fFullPVPath.size(); ++i) {
947 oss << fFullPVPath[i].GetPhysicalVolume()->GetName()
948 << ':' << fFullPVPath[i].GetCopyNo();
949 if (i != fFullPVPath.size() - 1) oss << '/';
950 }
951
952 if (!fpCurrentLV) {
953 G4Exception
954 ("G4PhysicalVolumeModel::CreateCurrentAttValues",
955 "modeling0004",
956 JustWarning,
957 "Current logical volume not defined.");
958 return values;
959 }
960
961 values->push_back(G4AttValue("PVPath", oss.str(),""));
962 values->push_back(G4AttValue("LVol", fpCurrentLV->GetName(),""));
963 G4VSolid* pSol = fpCurrentLV->GetSolid();
964 values->push_back(G4AttValue("Solid", pSol->GetName(),""));
965 values->push_back(G4AttValue("EType", pSol->GetEntityType(),""));
966 oss.str(""); oss << '\n' << *pSol;
967 values->push_back(G4AttValue("DmpSol", oss.str(),""));
968 const G4RotationMatrix localRotation = fpCurrentPV->GetObjectRotationValue();
969 const G4ThreeVector& localTranslation = fpCurrentPV->GetTranslation();
970 oss.str(""); oss << '\n' << G4Transform3D(localRotation,localTranslation);
971 values->push_back(G4AttValue("LocalTrans", oss.str(),""));
972 oss.str(""); oss << '\n' << *fpCurrentTransform;
973 values->push_back(G4AttValue("GlobalTrans", oss.str(),""));
974 G4String matName = fpCurrentMaterial? fpCurrentMaterial->GetName(): G4String("No material");
975 values->push_back(G4AttValue("Material", matName,""));
976 G4double matDensity = fpCurrentMaterial? fpCurrentMaterial->GetDensity(): 0.;
977 values->push_back(G4AttValue("Density", G4BestUnit(matDensity,"Volumic Mass"),""));
978 G4State matState = fpCurrentMaterial? fpCurrentMaterial->GetState(): kStateUndefined;
979 oss.str(""); oss << matState;
980 values->push_back(G4AttValue("State", oss.str(),""));
981 G4double matRadlen = fpCurrentMaterial? fpCurrentMaterial->GetRadlen(): 0.;
982 values->push_back(G4AttValue("Radlen", G4BestUnit(matRadlen,"Length"),""));
983 G4Region* region = fpCurrentLV->GetRegion();
984 G4String regionName = region? region->GetName(): G4String("No region");
985 values->push_back(G4AttValue("Region", regionName,""));
986 oss.str(""); oss << fpCurrentLV->IsRootRegion();
987 values->push_back(G4AttValue("RootRegion", oss.str(),""));
988 return values;
989}
990
991G4bool G4PhysicalVolumeModel::G4PhysicalVolumeNodeID::operator<
992 (const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID& right) const
993{
994 if (fpPV < right.fpPV) return true;
995 if (fpPV == right.fpPV) {
996 if (fCopyNo < right.fCopyNo) return true;
997 if (fCopyNo == right.fCopyNo)
998 return fNonCulledDepth < right.fNonCulledDepth;
999 }
1000 return false;
1001}
1002
1003std::ostream& operator<<
1004 (std::ostream& os, const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID& node)
1005{
1006 G4VPhysicalVolume* pPV = node.GetPhysicalVolume();
1007 if (pPV) {
1008 os << pPV->GetName()
1009 << ' ' << node.GetCopyNo()
1010// << '[' << node.GetNonCulledDepth() << ']'
1011// << ':' << node.GetTransform()
1012 ;
1013// os << " (";
1014// if (!node.GetDrawn()) os << "not ";
1015// os << "drawn)";
1016 } else {
1017 os << " (Null node)";
1018 }
1019 return os;
1020}
1021
1022std::ostream& operator<<
1023(std::ostream& os, const std::vector<G4PhysicalVolumeModel::G4PhysicalVolumeNodeID>& path)
1024{
1025 for (const auto& nodeID: path) {
1026 os << nodeID << ' ';
1027 }
1028 return os;
1029}
1030
1031G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::G4PhysicalVolumeModelTouchable
1032(const std::vector<G4PhysicalVolumeNodeID>& fullPVPath):
1033 fFullPVPath(fullPVPath) {}
1034
1035const G4ThreeVector& G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetTranslation(G4int depth) const
1036{
1037 size_t i = fFullPVPath.size() - depth - 1;
1038 if (i >= fFullPVPath.size()) {
1039 G4Exception("G4PhysicalVolumeModelTouchable::GetTranslation",
1040 "modeling0005",
1041 FatalErrorInArgument,
1042 "Index out of range. Asking for non-existent depth");
1043 }
1044 static G4ThreeVector tempTranslation;
1045 tempTranslation = fFullPVPath[i].GetTransform().getTranslation();
1046 return tempTranslation;
1047}
1048
1049const G4RotationMatrix* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetRotation(G4int depth) const
1050{
1051 size_t i = fFullPVPath.size() - depth - 1;
1052 if (i >= fFullPVPath.size()) {
1053 G4Exception("G4PhysicalVolumeModelTouchable::GetRotation",
1054 "modeling0006",
1055 FatalErrorInArgument,
1056 "Index out of range. Asking for non-existent depth");
1057 }
1058 static G4RotationMatrix tempRotation;
1059 tempRotation = fFullPVPath[i].GetTransform().getRotation();
1060 return &tempRotation;
1061}
1062
1063G4VPhysicalVolume* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetVolume(G4int depth) const
1064{
1065 size_t i = fFullPVPath.size() - depth - 1;
1066 if (i >= fFullPVPath.size()) {
1067 G4Exception("G4PhysicalVolumeModelTouchable::GetVolume",
1068 "modeling0007",
1069 FatalErrorInArgument,
1070 "Index out of range. Asking for non-existent depth");
1071 }
1072 return fFullPVPath[i].GetPhysicalVolume();
1073}
1074
1075G4VSolid* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetSolid(G4int depth) const
1076{
1077 size_t i = fFullPVPath.size() - depth - 1;
1078 if (i >= fFullPVPath.size()) {
1079 G4Exception("G4PhysicalVolumeModelTouchable::GetSolid",
1080 "modeling0008",
1081 FatalErrorInArgument,
1082 "Index out of range. Asking for non-existent depth");
1083 }
1084 return fFullPVPath[i].GetPhysicalVolume()->GetLogicalVolume()->GetSolid();
1085}
1086
1087G4int G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetReplicaNumber(G4int depth) const
1088{
1089 size_t i = fFullPVPath.size() - depth - 1;
1090 if (i >= fFullPVPath.size()) {
1091 G4Exception("G4PhysicalVolumeModelTouchable::GetReplicaNumber",
1092 "modeling0009",
1093 FatalErrorInArgument,
1094 "Index out of range. Asking for non-existent depth");
1095 }
1096 return fFullPVPath[i].GetCopyNo();
1097}