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 97704 2016-06-07 10:43:40Z 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) {
7
Taking false branch
124 fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent ();
125 }
126 else {
127 G4BoundingSphereScene bsScene(this);
8
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);
9
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
10
Assuming pointer value is null
11
Taking true branch
164 ("G4PhysicalVolumeModel::DescribeYourselfTo",
165 "modeling0012", FatalException, "No model.");
166
167 if (!fpMP) G4Exception
12
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
14
Calling 'G4PhysicalVolumeModel::VisitGeometryAndGetVisReps'
177 (fpTopPV,
13
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 ();
15
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 - create a temporary default one...
391 G4bool visAttsCreated = false;
392 if (!pVisAttribs) {
393 pVisAttribs = new G4VisAttributes;
394 visAttsCreated = true;
395 }
396 // From here, can assume pVisAttribs is a valid pointer.
397
398 // Make decision to draw...
399 G4bool thisToBeDrawn = true;
400
401 // Update full path of physical volumes...
402 G4int copyNo = fpCurrentPV->GetCopyNo();
403 fFullPVPath.push_back
404 (G4PhysicalVolumeNodeID
405 (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform));
406
407 // In case we need to copy the vis atts for modification...
408 G4bool copyForVAM = false;
409 const G4VisAttributes* pUnmodifiedVisAtts = pVisAttribs;
410 G4VisAttributes* pModifiedVisAtts = 0;
411
412 // Check if vis attributes are to be modified by a /vis/touchable/set/ command.
413 const std::vector<G4ModelingParameters::VisAttributesModifier>& vams =
414 fpMP->GetVisAttributesModifiers();
415 std::vector<G4ModelingParameters::VisAttributesModifier>::const_iterator
416 iModifier;
417 for (iModifier = vams.begin();
418 iModifier != vams.end();
419 ++iModifier) {
420 const G4ModelingParameters::PVNameCopyNoPath& vamPath =
421 iModifier->GetPVNameCopyNoPath();
422 if (vamPath.size() == fFullPVPath.size()) {
423 // OK - there's a size match. Check it out.
424// G4cout << "Size match" << G4endl;
425 G4ModelingParameters::PVNameCopyNoPathConstIterator iVAMNameCopyNo;
426 std::vector<G4PhysicalVolumeNodeID>::const_iterator iPVNodeId;
427 for (iVAMNameCopyNo = vamPath.begin(), iPVNodeId = fFullPVPath.begin();
428 iVAMNameCopyNo != vamPath.end();
429 ++iVAMNameCopyNo, ++iPVNodeId) {
430// G4cout
431// << iVAMNameCopyNo->fName
432// << ',' << iVAMNameCopyNo->fCopyNo
433// << "; " << iPVNodeId->GetPhysicalVolume()->GetName()
434// << ',' << iPVNodeId->GetPhysicalVolume()->GetCopyNo()
435// << G4endl;
436 if (!(
437 iVAMNameCopyNo->GetName() ==
438 iPVNodeId->GetPhysicalVolume()->GetName() &&
439 iVAMNameCopyNo->GetCopyNo() ==
440 iPVNodeId->GetPhysicalVolume()->GetCopyNo()
441 )) {
442 break;
443 }
444 }
445 if (iVAMNameCopyNo == vamPath.end()) {
446// G4cout << "Match found" << G4endl;
447 if (!copyForVAM) {
448 pModifiedVisAtts = new G4VisAttributes(*pUnmodifiedVisAtts);
449 pVisAttribs = pModifiedVisAtts;
450 copyForVAM = true;
451 }
452 const G4VisAttributes& transVisAtts = iModifier->GetVisAttributes();
453 switch (iModifier->GetVisAttributesSignifier()) {
454 case G4ModelingParameters::VASVisibility:
455 pModifiedVisAtts->SetVisibility(transVisAtts.IsVisible());
456 break;
457 case G4ModelingParameters::VASDaughtersInvisible:
458 pModifiedVisAtts->SetDaughtersInvisible
459 (transVisAtts.IsDaughtersInvisible());
460 break;
461 case G4ModelingParameters::VASColour:
462 pModifiedVisAtts->SetColour(transVisAtts.GetColour());
463 break;
464 case G4ModelingParameters::VASLineStyle:
465 pModifiedVisAtts->SetLineStyle(transVisAtts.GetLineStyle());
466 break;
467 case G4ModelingParameters::VASLineWidth:
468 pModifiedVisAtts->SetLineWidth(transVisAtts.GetLineWidth());
469 break;
470 case G4ModelingParameters::VASForceWireframe:
471 if (transVisAtts.GetForcedDrawingStyle() ==
472 G4VisAttributes::wireframe) {
473 pModifiedVisAtts->SetForceWireframe
474 (transVisAtts.IsForceDrawingStyle());
475 }
476 break;
477 case G4ModelingParameters::VASForceSolid:
478 if (transVisAtts.GetForcedDrawingStyle() ==
479 G4VisAttributes::solid) {
480 pModifiedVisAtts->SetForceSolid
481 (transVisAtts.IsForceDrawingStyle());
482 }
483 break;
484 case G4ModelingParameters::VASForceAuxEdgeVisible:
485 pModifiedVisAtts->SetForceAuxEdgeVisible
486 (transVisAtts.IsForceAuxEdgeVisible());
487 break;
488 case G4ModelingParameters::VASForceLineSegmentsPerCircle:
489 pModifiedVisAtts->SetForceLineSegmentsPerCircle
490 (transVisAtts.GetForcedLineSegmentsPerCircle());
491 break;
492 }
493 }
494 }
495 }
496
497 // There are various reasons why this volume
498 // might not be drawn...
499 G4bool culling = fpMP->IsCulling();
500 G4bool cullingInvisible = fpMP->IsCullingInvisible();
501 G4bool markedVisible = pVisAttribs->IsVisible();
502 G4bool cullingLowDensity = fpMP->IsDensityCulling();
503 G4double density = pMaterial? pMaterial->GetDensity(): 0;
504 G4double densityCut = fpMP -> GetVisibleDensity ();
505
506 // 1) Global culling is on....
507 if (culling) {
508 // 2) Culling of invisible volumes is on...
509 if (cullingInvisible) {
510 // 3) ...and the volume is marked not visible...
511 if (!markedVisible) thisToBeDrawn = false;
512 }
513 // 4) Or culling of low density volumes is on...
514 if (cullingLowDensity) {
515 // 5) ...and density is less than cut value...
516 if (density < densityCut) thisToBeDrawn = false;
517 }
518 }
519 // 6) The user has asked for all further traversing to be aborted...
520 if (fAbort) thisToBeDrawn = false;
521
522#ifdef BYPASS_DRAWING_CLIPPED_VOLUMES1
523
524 // Check if a view clipping operation cuts this volume from the scene
525
526 bool thisToBeBypassed = false;
527 G4VSolid* pIntersector = fpMP->GetSectionSolid();
528 G4VSolid* pSubtractor = fpMP->GetCutawaySolid();
529 if (fpClippingSolid) {
530 switch (fClippingMode) {
531 case subtraction:
532 pSubtractor = fpClippingSolid;
533 break;
534 case intersection:
535 pIntersector = fpClippingSolid;
536 break;
537 }
538 }
539
540 G4DisplacedSolid *pClipper;
541 if ((pClipper = dynamic_cast<G4DisplacedSolid*>(pIntersector)))
542 {
543 G4AffineTransform clipAT(pClipper->GetTransform());
544 G4AffineTransform currAT(fpCurrentTransform->getRotation().inverse(),
545 fpCurrentTransform->getTranslation());
546 G4AffineTransform combAT;
547 combAT.Product(currAT,clipAT);
548 G4DisplacedSolid pClipped("temporary_to_clip",pSol,combAT);
549 G4VisExtent clipper(pClipper->GetConstituentMovedSolid()->GetExtent());
550 G4VisExtent clipped(pClipped.GetExtent());
551 thisToBeBypassed = (clipper.GetXmax() < clipped.GetXmin())
552 || (clipper.GetXmin() > clipped.GetXmax())
553 || (clipper.GetYmax() < clipped.GetYmin())
554 || (clipper.GetYmin() > clipped.GetYmax())
555 || (clipper.GetZmax() < clipped.GetZmin())
556 || (clipper.GetZmin() > clipped.GetZmax());
557 }
558
559 if ((pClipper = dynamic_cast<G4DisplacedSolid*>(pSubtractor)))
560 {
561 G4AffineTransform clipAT(pClipper->GetTransform());
562 G4AffineTransform currAT(fpCurrentTransform->getRotation().inverse(),
563 fpCurrentTransform->getTranslation());
564 G4AffineTransform combAT;
565 combAT.Product(currAT,clipAT);
566 G4DisplacedSolid pClipped("temporary_to_clip",pSol,combAT);
567 G4VisExtent clipper(pClipper->GetConstituentMovedSolid()->GetExtent());
568 G4VisExtent clipped(pClipped.GetExtent());
569 thisToBeBypassed = (clipper.GetXmax() > clipped.GetXmax())
570 && (clipper.GetXmin() < clipped.GetXmin())
571 && (clipper.GetYmax() > clipped.GetYmax())
572 && (clipper.GetYmin() < clipped.GetYmin())
573 && (clipper.GetZmax() > clipped.GetZmax())
574 && (clipper.GetZmin() < clipped.GetZmin());
575 }
576
577 thisToBeDrawn = thisToBeDrawn && (! thisToBeBypassed);
578
579#endif
580
581 // Record thisToBeDrawn in path...
582 fFullPVPath.back().SetDrawn(thisToBeDrawn);
583
584 if (thisToBeDrawn) {
585
586 // Update path of drawn physical volumes...
587 fDrawnPVPath.push_back
588 (G4PhysicalVolumeNodeID
589 (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform,thisToBeDrawn));
590
591 if (fpMP->IsExplode() && fDrawnPVPath.size() == 1) {
592 // For top-level drawn volumes, explode along radius...
593 G4Transform3D centering = G4Translate3D(fpMP->GetExplodeCentre());
594 G4Transform3D centred = centering.inverse() * theNewAT;
595 G4Scale3D oldScale;
596 G4Rotate3D oldRotation;
597 G4Translate3D oldTranslation;
598 centred.getDecomposition(oldScale, oldRotation, oldTranslation);
599 G4double explodeFactor = fpMP->GetExplodeFactor();
600 G4Translate3D newTranslation =
601 G4Translate3D(explodeFactor * oldTranslation.dx(),
602 explodeFactor * oldTranslation.dy(),
603 explodeFactor * oldTranslation.dz());
604 theNewAT = centering * newTranslation * oldRotation * oldScale;
605 }
606
607 DescribeSolid (theNewAT, pSol, pVisAttribs, sceneHandler);
608
609 }
610
611 // Make decision to draw daughters, if any. There are various
612 // reasons why daughters might not be drawn...
613
614 // First, reasons that do not depend on culling policy...
615 G4int nDaughters = pLV->GetNoDaughters();
616#ifdef BYPASS_DRAWING_CLIPPED_VOLUMES1
617 G4bool daughtersToBeDrawn = ! thisToBeBypassed;
618#else
619 G4bool daughtersToBeDrawn = true;
620#endif
621 // 1) There are no daughters...
622 if (!nDaughters) daughtersToBeDrawn = false;
623 // 2) We are at the limit if requested depth...
624 else if (requestedDepth == 0) daughtersToBeDrawn = false;
625 // 3) The user has asked for all further traversing to be aborted...
626 else if (fAbort) daughtersToBeDrawn = false;
627 // 4) The user has asked that the descent be curtailed...
628 else if (fCurtailDescent) daughtersToBeDrawn = false;
629
630 // Now, reasons that depend on culling policy...
631 else {
632 G4bool daughtersInvisible = pVisAttribs->IsDaughtersInvisible();
633 // Culling of covered daughters request. This is computed in
634 // G4VSceneHandler::CreateModelingParameters() depending on view
635 // parameters...
636 G4bool cullingCovered = fpMP->IsCullingCovered();
637 G4bool surfaceDrawing =
638 fpMP->GetDrawingStyle() == G4ModelingParameters::hsr ||
639 fpMP->GetDrawingStyle() == G4ModelingParameters::hlhsr;
640 if (pVisAttribs->IsForceDrawingStyle()) {
641 switch (pVisAttribs->GetForcedDrawingStyle()) {
642 default:
643 case G4VisAttributes::wireframe: surfaceDrawing = false; break;
644 case G4VisAttributes::solid: surfaceDrawing = true; break;
645 }
646 }
647 G4bool opaque = pVisAttribs->GetColour().GetAlpha() >= 1.;
648 // 5) Global culling is on....
649 if (culling) {
650 // 6) ..and culling of invisible volumes is on...
651 if (cullingInvisible) {
652 // 7) ...and the mother requests daughters invisible
653 if (daughtersInvisible) daughtersToBeDrawn = false;
654 }
655 // 8) Or culling of covered daughters is requested...
656 if (cullingCovered) {
657 // 9) ...and surface drawing is operating...
658 if (surfaceDrawing) {
659 // 10) ...but only if mother is visible...
660 if (thisToBeDrawn) {
661 // 11) ...and opaque...
662 if (opaque) daughtersToBeDrawn = false;
663 }
664 }
665 }
666 }
667 }
668
669 // Delete modified vis atts if created...
670 if (copyForVAM) {
671 delete pModifiedVisAtts;
672 pVisAttribs = pUnmodifiedVisAtts;
673 copyForVAM = false;
674 }
675
676 // Vis atts for this volume no longer needed if created...
677 if (visAttsCreated) delete pVisAttribs;
678
679 if (daughtersToBeDrawn) {
680 for (G4int iDaughter = 0; iDaughter < nDaughters; iDaughter++) {
681 // Store daughter pVPV in local variable ready for recursion...
682 G4VPhysicalVolume* pDaughterVPV = pLV -> GetDaughter (iDaughter);
683 // Descend the geometry structure recursively...
684 fCurrentDepth++;
685 VisitGeometryAndGetVisReps
686 (pDaughterVPV, requestedDepth - 1, theNewAT, sceneHandler);
687 fCurrentDepth--;
688 }
689 }
690
691 // Reset for normal descending of next volume at this level...
692 fCurtailDescent = false;
693
694 // Pop item from paths physical volumes...
695 fFullPVPath.pop_back();
696 if (thisToBeDrawn) {
697 fDrawnPVPath.pop_back();
698 }
699}
700
701void G4PhysicalVolumeModel::DescribeSolid
702(const G4Transform3D& theAT,
703 G4VSolid* pSol,
704 const G4VisAttributes* pVisAttribs,
705 G4VGraphicsScene& sceneHandler)
706{
707 sceneHandler.PreAddSolid (theAT, *pVisAttribs);
708
709 G4VSolid* pSectionSolid = fpMP->GetSectionSolid();
710 G4VSolid* pCutawaySolid = fpMP->GetCutawaySolid();
711
712 if (!fpClippingSolid && !pSectionSolid && !pCutawaySolid) {
713
714 pSol -> DescribeYourselfTo (sceneHandler); // Standard treatment.
715
716 } else {
717
718 // Clipping, etc., performed by Boolean operations.
719
720 // First, get polyhedron for current solid...
721 if (pVisAttribs->IsForceLineSegmentsPerCircle())
722 G4Polyhedron::SetNumberOfRotationSteps
723 (pVisAttribs->GetForcedLineSegmentsPerCircle());
724 else
725 G4Polyhedron::SetNumberOfRotationSteps(fpMP->GetNoOfSides());
726
727 // Special treatment for G4PolyHedra and G4Polycone
728
729 G4Polyhedra *polyhedr = dynamic_cast<G4Polyhedra*>(pSol);
730 G4Polycone *polycone = dynamic_cast<G4Polycone*>(pSol);
731 if (polyhedr) {
732 G4PolyhedraHistorical pars(*polyhedr->GetOriginalParameters());
733 for (int p=1; p < pars.Num_z_planes; ++p) {
734 if (pars.Z_values[p] <= pars.Z_values[p-1])
735 pars.Z_values[p] = pars.Z_values[p] + 1e-3;
736 }
737 G4String visname(pSol->GetName() + "_visual");
738 pSol = new G4Polyhedra(visname, pars.Start_angle,
739 pars.Opening_angle,
740 pars.numSide,
741 pars.Num_z_planes,
742 pars.Z_values,
743 pars.Rmin,
744 pars.Rmax);
745 }
746 else if (polycone) {
747 G4PolyconeHistorical pars(*polycone->GetOriginalParameters());
748 for (int p=1; p < pars.Num_z_planes; ++p) {
749 if (pars.Z_values[p] <= pars.Z_values[p-1])
750 pars.Z_values[p] = pars.Z_values[p] + 1e-3;
751 }
752 G4String visname(pSol->GetName() + "_visual");
753 pSol = new G4Polycone(visname, pars.Start_angle,
754 pars.Opening_angle,
755 pars.Num_z_planes,
756 pars.Z_values,
757 pars.Rmin,
758 pars.Rmax);
759 }
760
761 const G4Polyhedron* pOriginal = pSol->GetPolyhedron();
762 //G4Polyhedron::ResetNumberOfRotationSteps();
763
764 if (!pOriginal) {
765
766 if (fpMP->IsWarning())
767 G4cout(*G4cout_p) <<
768 "WARNING: G4PhysicalVolumeModel::DescribeSolid: solid\n \""
769 << pSol->GetName() <<
770 "\" has no polyhedron. Cannot by clipped."
771 << G4endlstd::endl;
772 pSol -> DescribeYourselfTo (sceneHandler); // Standard treatment.
773
774 } else {
775
776 G4Polyhedron resultant(*pOriginal);
777 G4VisAttributes resultantVisAttribs(*pVisAttribs);
778 G4VSolid* resultantSolid = 0;
779
780 if (fpClippingSolid) {
781 switch (fClippingMode) {
782 default:
783 case subtraction:
784 resultantSolid = new G4SubtractionSolid
785 ("resultant_solid", pSol, fpClippingSolid, theAT.inverse());
786 break;
787 case intersection:
788 resultantSolid = new G4IntersectionSolid
789 ("resultant_solid", pSol, fpClippingSolid, theAT.inverse());
790 break;
791 }
792 }
793
794 if (pSectionSolid) {
795 resultantSolid = new G4IntersectionSolid
796 ("sectioned_solid", pSol, pSectionSolid, theAT.inverse());
797 }
798
799 if (pCutawaySolid) {
800 resultantSolid = new G4SubtractionSolid
801 ("cutaway_solid", pSol, pCutawaySolid, theAT.inverse());
802 }
803
804 G4Polyhedron* tmpResultant = resultantSolid->GetPolyhedron();
805 if (tmpResultant) resultant = *tmpResultant;
806 else {
807 if (fpMP->IsWarning())
808 G4cout(*G4cout_p) <<
809 "WARNING: G4PhysicalVolumeModel::DescribeSolid: resultant polyhedron for"
810 "\n solid \"" << pSol->GetName() <<
811 "\" not defined due to error during Boolean processing."
812 "\n Original will be drawn in red."
813 << G4endlstd::endl;
814 resultantVisAttribs.SetColour(G4Colour::Red());
815 }
816
817 delete resultantSolid;
818
819 // Finally, force polyhedron drawing...
820 resultant.SetVisAttributes(resultantVisAttribs);
821 sceneHandler.BeginPrimitives(theAT);
822 sceneHandler.AddPrimitive(resultant);
823 sceneHandler.EndPrimitives();
824 }
825 }
826 sceneHandler.PostAddSolid ();
827}
828
829G4bool G4PhysicalVolumeModel::Validate (G4bool warn)
830{
831 G4TransportationManager* transportationManager =
832 G4TransportationManager::GetTransportationManager ();
833
834 size_t nWorlds = transportationManager->GetNoWorlds();
835
836 G4bool found = false;
837
838 std::vector<G4VPhysicalVolume*>::iterator iterWorld =
839 transportationManager->GetWorldsIterator();
840 for (size_t i = 0; i < nWorlds; ++i, ++iterWorld) {
1
Assuming 'i' is < 'nWorlds'
2
Loop condition is true. Entering loop body
841 G4VPhysicalVolume* world = (*iterWorld);
842 // The idea now is to seek a PV with the same name and copy no
843 // in the hope it's the same one!!
844 G4PhysicalVolumeModel searchModel (world);
845 G4int verbosity = 0; // Suppress messages from G4PhysicalVolumeSearchScene.
846 G4PhysicalVolumeSearchScene searchScene
847 (&searchModel, fTopPVName, fTopPVCopyNo, verbosity);
848 G4ModelingParameters mp; // Default modeling parameters for this search.
849 mp.SetDefaultVisAttributes(fpMP? fpMP->GetDefaultVisAttributes(): 0);
3
'?' condition is false
850 searchModel.SetModelingParameters (&mp);
851 searchModel.DescribeYourselfTo (searchScene);
852 G4VPhysicalVolume* foundVolume = searchScene.GetFoundVolume ();
853 if (foundVolume) {
4
Assuming 'foundVolume' is non-null
5
Taking true branch
854 if (foundVolume != fpTopPV && warn) {
855 G4cout(*G4cout_p) <<
856 "G4PhysicalVolumeModel::Validate(): A volume of the same name and"
857 "\n copy number (\""
858 << fTopPVName << "\", copy " << fTopPVCopyNo
859 << ") still exists and is being used."
860 "\n But it is not the same volume you originally specified"
861 "\n in /vis/scene/add/."
862 << G4endlstd::endl;
863 }
864 fpTopPV = foundVolume;
865 CalculateExtent ();
6
Calling 'G4PhysicalVolumeModel::CalculateExtent'
866 found = true;
867 }
868 }
869 if (found) return true;
870 else {
871 if (warn) {
872 G4cout(*G4cout_p) <<
873 "G4PhysicalVolumeModel::Validate(): No volume of name and"
874 "\n copy number (\""
875 << fTopPVName << "\", copy " << fTopPVCopyNo
876 << ") exists."
877 << G4endlstd::endl;
878 }
879 return false;
880 }
881}
882
883const std::map<G4String,G4AttDef>* G4PhysicalVolumeModel::GetAttDefs() const
884{
885 G4bool isNew;
886 std::map<G4String,G4AttDef>* store
887 = G4AttDefStore::GetInstance("G4PhysicalVolumeModel", isNew);
888 if (isNew) {
889 (*store)["PVPath"] =
890 G4AttDef("PVPath","Physical Volume Path","Physics","","G4String");
891 (*store)["LVol"] =
892 G4AttDef("LVol","Logical Volume","Physics","","G4String");
893 (*store)["Solid"] =
894 G4AttDef("Solid","Solid Name","Physics","","G4String");
895 (*store)["EType"] =
896 G4AttDef("EType","Entity Type","Physics","","G4String");
897 (*store)["DmpSol"] =
898 G4AttDef("DmpSol","Dump of Solid properties","Physics","","G4String");
899 (*store)["LocalTrans"] =
900 G4AttDef("LocalTrans","Local transformation of volume","Physics","","G4String");
901 (*store)["GlobalTrans"] =
902 G4AttDef("GlobalTrans","Global transformation of volume","Physics","","G4String");
903 (*store)["Material"] =
904 G4AttDef("Material","Material Name","Physics","","G4String");
905 (*store)["Density"] =
906 G4AttDef("Density","Material Density","Physics","G4BestUnit","G4double");
907 (*store)["State"] =
908 G4AttDef("State","Material State (enum undefined,solid,liquid,gas)","Physics","","G4String");
909 (*store)["Radlen"] =
910 G4AttDef("Radlen","Material Radiation Length","Physics","G4BestUnit","G4double");
911 (*store)["Region"] =
912 G4AttDef("Region","Cuts Region","Physics","","G4String");
913 (*store)["RootRegion"] =
914 G4AttDef("RootRegion","Root Region (0/1 = false/true)","Physics","","G4bool");
915 }
916 return store;
917}
918
919#include <iomanip>
920
921static std::ostream& operator<< (std::ostream& o, const G4Transform3D t)
922{
923 using namespace std;
924
925 G4Scale3D sc;
926 G4Rotate3D r;
927 G4Translate3D tl;
928 t.getDecomposition(sc, r, tl);
929
930 const int w = 10;
931
932 // Transformation itself
933 o << setw(w) << t.xx() << setw(w) << t.xy() << setw(w) << t.xz() << setw(w) << t.dx() << endl;
934 o << setw(w) << t.yx() << setw(w) << t.yy() << setw(w) << t.yz() << setw(w) << t.dy() << endl;
935 o << setw(w) << t.zx() << setw(w) << t.zy() << setw(w) << t.zz() << setw(w) << t.dz() << endl;
936
937 // Translation
938 o << "= translation:" << endl;
939 o << setw(w) << tl.dx() << setw(w) << tl.dy() << setw(w) << tl.dz() << endl;
940
941 // Rotation
942 o << "* rotation:" << endl;
943 o << setw(w) << r.xx() << setw(w) << r.xy() << setw(w) << r.xz() << endl;
944 o << setw(w) << r.yx() << setw(w) << r.yy() << setw(w) << r.yz() << endl;
945 o << setw(w) << r.zx() << setw(w) << r.zy() << setw(w) << r.zz() << endl;
946
947 // Scale
948 o << "* scale:" << endl;
949 o << setw(w) << sc.xx() << setw(w) << sc.yy() << setw(w) << sc.zz() << endl;
950
951 // Transformed axes
952 o << "Transformed axes:" << endl;
953 o << "x': " << r * G4Vector3D(1., 0., 0.) << endl;
954 o << "y': " << r * G4Vector3D(0., 1., 0.) << endl;
955 o << "z': " << r * G4Vector3D(0., 0., 1.) << endl;
956
957 return o;
958}
959
960std::vector<G4AttValue>* G4PhysicalVolumeModel::CreateCurrentAttValues() const
961{
962 std::vector<G4AttValue>* values = new std::vector<G4AttValue>;
963 std::ostringstream oss;
964 for (size_t i = 0; i < fFullPVPath.size(); ++i) {
965 oss << fFullPVPath[i].GetPhysicalVolume()->GetName()
966 << ':' << fFullPVPath[i].GetCopyNo();
967 if (i != fFullPVPath.size() - 1) oss << '/';
968 }
969
970 if (!fpCurrentLV) {
971 G4Exception
972 ("G4PhysicalVolumeModel::CreateCurrentAttValues",
973 "modeling0004",
974 JustWarning,
975 "Current logical volume not defined.");
976 return values;
977 }
978
979 values->push_back(G4AttValue("PVPath", oss.str(),""));
980 values->push_back(G4AttValue("LVol", fpCurrentLV->GetName(),""));
981 G4VSolid* pSol = fpCurrentLV->GetSolid();
982 values->push_back(G4AttValue("Solid", pSol->GetName(),""));
983 values->push_back(G4AttValue("EType", pSol->GetEntityType(),""));
984 oss.str(""); oss << '\n' << *pSol;
985 values->push_back(G4AttValue("DmpSol", oss.str(),""));
986 const G4RotationMatrix localRotation = fpCurrentPV->GetObjectRotationValue();
987 const G4ThreeVector& localTranslation = fpCurrentPV->GetTranslation();
988 oss.str(""); oss << '\n' << G4Transform3D(localRotation,localTranslation);
989 values->push_back(G4AttValue("LocalTrans", oss.str(),""));
990 oss.str(""); oss << '\n' << *fpCurrentTransform;
991 values->push_back(G4AttValue("GlobalTrans", oss.str(),""));
992 G4String matName = fpCurrentMaterial? fpCurrentMaterial->GetName(): G4String("No material");
993 values->push_back(G4AttValue("Material", matName,""));
994 G4double matDensity = fpCurrentMaterial? fpCurrentMaterial->GetDensity(): 0.;
995 values->push_back(G4AttValue("Density", G4BestUnit(matDensity,"Volumic Mass"),""));
996 G4State matState = fpCurrentMaterial? fpCurrentMaterial->GetState(): kStateUndefined;
997 oss.str(""); oss << matState;
998 values->push_back(G4AttValue("State", oss.str(),""));
999 G4double matRadlen = fpCurrentMaterial? fpCurrentMaterial->GetRadlen(): 0.;
1000 values->push_back(G4AttValue("Radlen", G4BestUnit(matRadlen,"Length"),""));
1001 G4Region* region = fpCurrentLV->GetRegion();
1002 G4String regionName = region? region->GetName(): G4String("No region");
1003 values->push_back(G4AttValue("Region", regionName,""));
1004 oss.str(""); oss << fpCurrentLV->IsRootRegion();
1005 values->push_back(G4AttValue("RootRegion", oss.str(),""));
1006 return values;
1007}
1008
1009G4bool G4PhysicalVolumeModel::G4PhysicalVolumeNodeID::operator<
1010 (const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID& right) const
1011{
1012 if (fpPV < right.fpPV) return true;
1013 if (fpPV == right.fpPV) {
1014 if (fCopyNo < right.fCopyNo) return true;
1015 if (fCopyNo == right.fCopyNo)
1016 return fNonCulledDepth < right.fNonCulledDepth;
1017 }
1018 return false;
1019}
1020
1021std::ostream& operator<<
1022 (std::ostream& os, const G4PhysicalVolumeModel::G4PhysicalVolumeNodeID node)
1023{
1024 G4VPhysicalVolume* pPV = node.GetPhysicalVolume();
1025 if (pPV) {
1026 os << pPV->GetName()
1027 << ':' << node.GetCopyNo()
1028 << '[' << node.GetNonCulledDepth() << ']'
1029 << ':' << node.GetTransform();
1030 if (!node.GetDrawn()) os << " Not ";
1031 os << "drawn";
1032 } else {
1033 os << "Null node";
1034 }
1035 return os;
1036}
1037
1038G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::G4PhysicalVolumeModelTouchable
1039(const std::vector<G4PhysicalVolumeNodeID>& fullPVPath):
1040 fFullPVPath(fullPVPath) {}
1041
1042const G4ThreeVector& G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetTranslation(G4int depth) const
1043{
1044 size_t i = fFullPVPath.size() - depth - 1;
1045 if (i >= fFullPVPath.size()) {
1046 G4Exception("G4PhysicalVolumeModelTouchable::GetTranslation",
1047 "modeling0005",
1048 FatalErrorInArgument,
1049 "Index out of range. Asking for non-existent depth");
1050 }
1051 static G4ThreeVector tempTranslation;
1052 tempTranslation = fFullPVPath[i].GetTransform().getTranslation();
1053 return tempTranslation;
1054}
1055
1056const G4RotationMatrix* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetRotation(G4int depth) const
1057{
1058 size_t i = fFullPVPath.size() - depth - 1;
1059 if (i >= fFullPVPath.size()) {
1060 G4Exception("G4PhysicalVolumeModelTouchable::GetRotation",
1061 "modeling0006",
1062 FatalErrorInArgument,
1063 "Index out of range. Asking for non-existent depth");
1064 }
1065 static G4RotationMatrix tempRotation;
1066 tempRotation = fFullPVPath[i].GetTransform().getRotation();
1067 return &tempRotation;
1068}
1069
1070G4VPhysicalVolume* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetVolume(G4int depth) const
1071{
1072 size_t i = fFullPVPath.size() - depth - 1;
1073 if (i >= fFullPVPath.size()) {
1074 G4Exception("G4PhysicalVolumeModelTouchable::GetVolume",
1075 "modeling0007",
1076 FatalErrorInArgument,
1077 "Index out of range. Asking for non-existent depth");
1078 }
1079 return fFullPVPath[i].GetPhysicalVolume();
1080}
1081
1082G4VSolid* G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetSolid(G4int depth) const
1083{
1084 size_t i = fFullPVPath.size() - depth - 1;
1085 if (i >= fFullPVPath.size()) {
1086 G4Exception("G4PhysicalVolumeModelTouchable::GetSolid",
1087 "modeling0008",
1088 FatalErrorInArgument,
1089 "Index out of range. Asking for non-existent depth");
1090 }
1091 return fFullPVPath[i].GetPhysicalVolume()->GetLogicalVolume()->GetSolid();
1092}
1093
1094G4int G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::GetReplicaNumber(G4int depth) const
1095{
1096 size_t i = fFullPVPath.size() - depth - 1;
1097 if (i >= fFullPVPath.size()) {
1098 G4Exception("G4PhysicalVolumeModelTouchable::GetReplicaNumber",
1099 "modeling0009",
1100 FatalErrorInArgument,
1101 "Index out of range. Asking for non-existent depth");
1102 }
1103 return fFullPVPath[i].GetCopyNo();
1104}