1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
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 | |
60 | G4PhysicalVolumeModel::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 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
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 | |
116 | G4PhysicalVolumeModel::~G4PhysicalVolumeModel () |
117 | { |
118 | delete fpClippingSolid; |
119 | } |
120 | |
121 | void G4PhysicalVolumeModel::CalculateExtent () |
122 | { |
123 | if (fUseFullExtent) { |
| |
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; |
130 | const G4ModelingParameters* tempMP = fpMP; |
131 | G4ModelingParameters mParams |
132 | (0, |
133 | G4ModelingParameters::wf, |
134 | true, |
135 | true, |
136 | false, |
137 | 0., |
138 | true, |
139 | 24); |
140 | fpMP = &mParams; |
141 | DescribeYourselfTo (bsScene); |
| 11 | | Calling 'G4PhysicalVolumeModel::DescribeYourselfTo' | |
|
142 | G4double radius = bsScene.GetRadius(); |
143 | if (radius < 0.) { |
144 | fExtent = fpTopPV -> GetLogicalVolume () -> GetSolid () -> GetExtent (); |
145 | } else { |
146 | |
147 | |
148 | |
149 | |
150 | |
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 | |
160 | void G4PhysicalVolumeModel::DescribeYourselfTo |
161 | (G4VGraphicsScene& sceneHandler) |
162 | { |
163 | if (!fpTopPV) G4Exception |
| 12 | | Assuming pointer value is null | |
|
| |
164 | ("G4PhysicalVolumeModel::DescribeYourselfTo", |
165 | "modeling0012", FatalException, "No model."); |
166 | |
167 | if (!fpMP) G4Exception |
| |
168 | ("G4PhysicalVolumeModel::DescribeYourselfTo", |
169 | "modeling0003", FatalException, "No modeling parameters."); |
170 | |
171 | |
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 | |
183 | fCurrentDepth = 0; |
184 | fpCurrentPV = 0; |
185 | fpCurrentLV = 0; |
186 | fpCurrentMaterial = 0; |
187 | if (fFullPVPath.size() != fBaseFullPVPath.size()) { |
188 | |
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 | |
201 | G4String 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 | |
213 | G4String G4PhysicalVolumeModel::GetCurrentDescription () const |
214 | { |
215 | return "G4PhysicalVolumeModel " + GetCurrentTag (); |
216 | } |
217 | |
218 | void G4PhysicalVolumeModel::VisitGeometryAndGetVisReps |
219 | (G4VPhysicalVolume* pVPV, |
220 | G4int requestedDepth, |
221 | const G4Transform3D& theAT, |
222 | G4VGraphicsScene& sceneHandler) |
223 | { |
224 | |
225 | |
226 | |
227 | |
228 | |
229 | |
230 | |
231 | |
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 | |
239 | pSol = pLV -> GetSolid (); |
240 | pMaterial = pLV -> GetMaterial (); |
241 | DescribeAndDescend (pVPV, requestedDepth, pLV, pSol, pMaterial, |
242 | theAT, sceneHandler); |
243 | } |
244 | else { |
245 | |
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; |
253 | G4VPVParameterisation* pP = pVPV -> GetParameterisation (); |
254 | if (pP) { |
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 | |
261 | |
262 | |
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 { |
270 | |
271 | |
272 | |
273 | |
274 | |
275 | |
276 | |
277 | |
278 | |
279 | |
280 | |
281 | |
282 | |
283 | |
284 | |
285 | |
286 | |
287 | |
288 | |
289 | |
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; |
303 | G4RotationMatrix rotation; |
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 | |
336 | |
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 | |
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 | |
359 | void 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 | |
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 | |
378 | |
379 | |
380 | |
381 | |
382 | |
383 | |
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 | |
391 | |
392 | if (!pVisAttribs) { |
393 | static G4VisAttributes defaultVisAttribs; |
394 | pVisAttribs = &defaultVisAttribs; |
395 | } |
396 | |
397 | |
398 | |
399 | |
400 | G4bool thisToBeDrawn = true; |
401 | |
402 | |
403 | G4int copyNo = fpCurrentPV->GetCopyNo(); |
404 | fFullPVPath.push_back |
405 | (G4PhysicalVolumeNodeID |
406 | (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform)); |
407 | |
408 | |
409 | const auto& vams = fpMP->GetVisAttributesModifiers(); |
410 | if (vams.size()) { |
411 | |
412 | for (const auto& vam: vams) { |
413 | const auto& vamPath = vam.GetPVNameCopyNoPath(); |
414 | if (vamPath.size() == fFullPVPath.size()) { |
415 | |
416 | |
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 | |
427 | break; |
428 | } |
429 | } |
430 | if (iVAMNameCopyNo == vamPath.end()) { |
431 | |
432 | |
433 | |
434 | static G4VisAttributes modifiedVisAtts; |
435 | |
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 | |
489 | |
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 | |
498 | if (culling) { |
499 | |
500 | if (cullingInvisible) { |
501 | |
502 | if (!markedVisible) thisToBeDrawn = false; |
503 | } |
504 | |
505 | if (cullingLowDensity) { |
506 | |
507 | if (density < densityCut) thisToBeDrawn = false; |
508 | } |
509 | } |
510 | |
511 | if (fAbort) thisToBeDrawn = false; |
512 | |
513 | #ifdef BYPASS_DRAWING_CLIPPED_VOLUMES1 |
514 | |
515 | |
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 | |
573 | fFullPVPath.back().SetDrawn(thisToBeDrawn); |
574 | |
575 | if (thisToBeDrawn) { |
576 | |
577 | |
578 | fDrawnPVPath.push_back |
579 | (G4PhysicalVolumeNodeID |
580 | (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform,thisToBeDrawn)); |
581 | |
582 | if (fpMP->IsExplode() && fDrawnPVPath.size() == 1) { |
583 | |
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 | |
603 | |
604 | |
605 | |
606 | G4int nDaughters = pLV->GetNoDaughters(); |
607 | #ifdef BYPASS_DRAWING_CLIPPED_VOLUMES1 |
608 | G4bool daughtersToBeDrawn = ! thisToBeBypassed; |
609 | #else |
610 | G4bool daughtersToBeDrawn = true; |
611 | #endif |
612 | |
613 | if (!nDaughters) daughtersToBeDrawn = false; |
614 | |
615 | else if (requestedDepth == 0) daughtersToBeDrawn = false; |
616 | |
617 | else if (fAbort) daughtersToBeDrawn = false; |
618 | |
619 | else if (fCurtailDescent) daughtersToBeDrawn = false; |
620 | |
621 | |
622 | else { |
623 | G4bool daughtersInvisible = pVisAttribs->IsDaughtersInvisible(); |
624 | |
625 | |
626 | |
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 | |
640 | if (culling) { |
641 | |
642 | if (cullingInvisible) { |
643 | |
644 | if (daughtersInvisible) daughtersToBeDrawn = false; |
645 | } |
646 | |
647 | if (cullingCovered) { |
648 | |
649 | if (surfaceDrawing) { |
650 | |
651 | if (thisToBeDrawn) { |
652 | |
653 | if (opaque) daughtersToBeDrawn = false; |
654 | } |
655 | } |
656 | } |
657 | } |
658 | } |
659 | |
660 | if (daughtersToBeDrawn) { |
661 | for (G4int iDaughter = 0; iDaughter < nDaughters; iDaughter++) { |
662 | |
663 | G4VPhysicalVolume* pDaughterVPV = pLV -> GetDaughter (iDaughter); |
664 | |
665 | fCurrentDepth++; |
666 | VisitGeometryAndGetVisReps |
667 | (pDaughterVPV, requestedDepth - 1, theNewAT, sceneHandler); |
668 | fCurrentDepth--; |
669 | } |
670 | } |
671 | |
672 | |
673 | fCurtailDescent = false; |
674 | |
675 | |
676 | fFullPVPath.pop_back(); |
677 | if (thisToBeDrawn) { |
678 | fDrawnPVPath.pop_back(); |
679 | } |
680 | } |
681 | |
682 | void 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); |
696 | |
697 | } else { |
698 | |
699 | |
700 | |
701 | |
702 | if (pVisAttribs->IsForceLineSegmentsPerCircle()) |
703 | G4Polyhedron::SetNumberOfRotationSteps |
704 | (pVisAttribs->GetForcedLineSegmentsPerCircle()); |
705 | else |
706 | G4Polyhedron::SetNumberOfRotationSteps(fpMP->GetNoOfSides()); |
707 | |
708 | |
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 | |
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); |
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 | |
801 | resultant.SetVisAttributes(resultantVisAttribs); |
802 | sceneHandler.BeginPrimitives(theAT); |
803 | sceneHandler.AddPrimitive(resultant); |
804 | sceneHandler.EndPrimitives(); |
805 | } |
806 | } |
807 | sceneHandler.PostAddSolid (); |
808 | } |
809 | |
810 | G4bool 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; |
| 3 | | Assuming 'world' is non-null | |
|
| |
824 | |
825 | |
826 | G4PhysicalVolumeModel searchModel (world); |
827 | G4int verbosity = 0; |
828 | G4PhysicalVolumeSearchScene searchScene |
829 | (&searchModel, fTopPVName, fTopPVCopyNo, verbosity); |
830 | G4ModelingParameters mp; |
831 | mp.SetDefaultVisAttributes(fpMP? fpMP->GetDefaultVisAttributes(): 0); |
| |
832 | searchModel.SetModelingParameters (&mp); |
833 | searchModel.DescribeYourselfTo (searchScene); |
834 | G4VPhysicalVolume* foundVolume = searchScene.GetFoundVolume (); |
835 | if (foundVolume) { |
| 6 | | Assuming 'foundVolume' is non-null | |
|
| |
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 | |
865 | const 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 | |
903 | static 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 | |
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 | |
920 | o << "= translation:" << endl; |
921 | o << setw(w) << tl.dx() << setw(w) << tl.dy() << setw(w) << tl.dz() << endl; |
922 | |
923 | |
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 | |
930 | o << "* scale:" << endl; |
931 | o << setw(w) << sc.xx() << setw(w) << sc.yy() << setw(w) << sc.zz() << endl; |
932 | |
933 | |
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 | |
942 | std::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 | |
991 | G4bool 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 | |
1003 | std::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 | |
1011 | |
1012 | ; |
1013 | |
1014 | |
1015 | |
1016 | } else { |
1017 | os << " (Null node)"; |
1018 | } |
1019 | return os; |
1020 | } |
1021 | |
1022 | std::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 | |
1031 | G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::G4PhysicalVolumeModelTouchable |
1032 | (const std::vector<G4PhysicalVolumeNodeID>& fullPVPath): |
1033 | fFullPVPath(fullPVPath) {} |
1034 | |
1035 | const 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 | |
1049 | const 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 | |
1063 | G4VPhysicalVolume* 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 | |
1075 | G4VSolid* 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 | |
1087 | G4int 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 | } |