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); |
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); |
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 |
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 |
177 | (fpTopPV, |
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 (); |
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 | G4bool visAttsCreated = false; |
392 | if (!pVisAttribs) { |
393 | pVisAttribs = new G4VisAttributes; |
394 | visAttsCreated = true; |
395 | } |
396 | |
397 | |
398 | |
399 | G4bool thisToBeDrawn = true; |
400 | |
401 | |
402 | G4int copyNo = fpCurrentPV->GetCopyNo(); |
403 | fFullPVPath.push_back |
404 | (G4PhysicalVolumeNodeID |
405 | (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform)); |
406 | |
407 | |
408 | G4bool copyForVAM = false; |
409 | const G4VisAttributes* pUnmodifiedVisAtts = pVisAttribs; |
410 | G4VisAttributes* pModifiedVisAtts = 0; |
411 | |
412 | |
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 | |
424 | |
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 | |
431 | |
432 | |
433 | |
434 | |
435 | |
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 | |
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 | |
498 | |
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 | |
507 | if (culling) { |
508 | |
509 | if (cullingInvisible) { |
510 | |
511 | if (!markedVisible) thisToBeDrawn = false; |
512 | } |
513 | |
514 | if (cullingLowDensity) { |
515 | |
516 | if (density < densityCut) thisToBeDrawn = false; |
517 | } |
518 | } |
519 | |
520 | if (fAbort) thisToBeDrawn = false; |
521 | |
522 | #ifdef BYPASS_DRAWING_CLIPPED_VOLUMES1 |
523 | |
524 | |
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 | |
582 | fFullPVPath.back().SetDrawn(thisToBeDrawn); |
583 | |
584 | if (thisToBeDrawn) { |
585 | |
586 | |
587 | fDrawnPVPath.push_back |
588 | (G4PhysicalVolumeNodeID |
589 | (fpCurrentPV,copyNo,fCurrentDepth,*fpCurrentTransform,thisToBeDrawn)); |
590 | |
591 | if (fpMP->IsExplode() && fDrawnPVPath.size() == 1) { |
592 | |
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 | |
612 | |
613 | |
614 | |
615 | G4int nDaughters = pLV->GetNoDaughters(); |
616 | #ifdef BYPASS_DRAWING_CLIPPED_VOLUMES1 |
617 | G4bool daughtersToBeDrawn = ! thisToBeBypassed; |
618 | #else |
619 | G4bool daughtersToBeDrawn = true; |
620 | #endif |
621 | |
622 | if (!nDaughters) daughtersToBeDrawn = false; |
623 | |
624 | else if (requestedDepth == 0) daughtersToBeDrawn = false; |
625 | |
626 | else if (fAbort) daughtersToBeDrawn = false; |
627 | |
628 | else if (fCurtailDescent) daughtersToBeDrawn = false; |
629 | |
630 | |
631 | else { |
632 | G4bool daughtersInvisible = pVisAttribs->IsDaughtersInvisible(); |
633 | |
634 | |
635 | |
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 | |
649 | if (culling) { |
650 | |
651 | if (cullingInvisible) { |
652 | |
653 | if (daughtersInvisible) daughtersToBeDrawn = false; |
654 | } |
655 | |
656 | if (cullingCovered) { |
657 | |
658 | if (surfaceDrawing) { |
659 | |
660 | if (thisToBeDrawn) { |
661 | |
662 | if (opaque) daughtersToBeDrawn = false; |
663 | } |
664 | } |
665 | } |
666 | } |
667 | } |
668 | |
669 | |
670 | if (copyForVAM) { |
671 | delete pModifiedVisAtts; |
672 | pVisAttribs = pUnmodifiedVisAtts; |
673 | copyForVAM = false; |
| Value stored to 'copyForVAM' is never read |
674 | } |
675 | |
676 | |
677 | if (visAttsCreated) delete pVisAttribs; |
678 | |
679 | if (daughtersToBeDrawn) { |
680 | for (G4int iDaughter = 0; iDaughter < nDaughters; iDaughter++) { |
681 | |
682 | G4VPhysicalVolume* pDaughterVPV = pLV -> GetDaughter (iDaughter); |
683 | |
684 | fCurrentDepth++; |
685 | VisitGeometryAndGetVisReps |
686 | (pDaughterVPV, requestedDepth - 1, theNewAT, sceneHandler); |
687 | fCurrentDepth--; |
688 | } |
689 | } |
690 | |
691 | |
692 | fCurtailDescent = false; |
693 | |
694 | |
695 | fFullPVPath.pop_back(); |
696 | if (thisToBeDrawn) { |
697 | fDrawnPVPath.pop_back(); |
698 | } |
699 | } |
700 | |
701 | void 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); |
715 | |
716 | } else { |
717 | |
718 | |
719 | |
720 | |
721 | if (pVisAttribs->IsForceLineSegmentsPerCircle()) |
722 | G4Polyhedron::SetNumberOfRotationSteps |
723 | (pVisAttribs->GetForcedLineSegmentsPerCircle()); |
724 | else |
725 | G4Polyhedron::SetNumberOfRotationSteps(fpMP->GetNoOfSides()); |
726 | |
727 | |
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 | |
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); |
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 | |
820 | resultant.SetVisAttributes(resultantVisAttribs); |
821 | sceneHandler.BeginPrimitives(theAT); |
822 | sceneHandler.AddPrimitive(resultant); |
823 | sceneHandler.EndPrimitives(); |
824 | } |
825 | } |
826 | sceneHandler.PostAddSolid (); |
827 | } |
828 | |
829 | G4bool 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) { |
841 | G4VPhysicalVolume* world = (*iterWorld); |
842 | |
843 | |
844 | G4PhysicalVolumeModel searchModel (world); |
845 | G4int verbosity = 0; |
846 | G4PhysicalVolumeSearchScene searchScene |
847 | (&searchModel, fTopPVName, fTopPVCopyNo, verbosity); |
848 | G4ModelingParameters mp; |
849 | mp.SetDefaultVisAttributes(fpMP? fpMP->GetDefaultVisAttributes(): 0); |
850 | searchModel.SetModelingParameters (&mp); |
851 | searchModel.DescribeYourselfTo (searchScene); |
852 | G4VPhysicalVolume* foundVolume = searchScene.GetFoundVolume (); |
853 | if (foundVolume) { |
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 (); |
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 | |
883 | const 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 | |
921 | static 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 | |
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 | |
938 | o << "= translation:" << endl; |
939 | o << setw(w) << tl.dx() << setw(w) << tl.dy() << setw(w) << tl.dz() << endl; |
940 | |
941 | |
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 | |
948 | o << "* scale:" << endl; |
949 | o << setw(w) << sc.xx() << setw(w) << sc.yy() << setw(w) << sc.zz() << endl; |
950 | |
951 | |
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 | |
960 | std::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 | |
1009 | G4bool 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 | |
1021 | std::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 | |
1038 | G4PhysicalVolumeModel::G4PhysicalVolumeModelTouchable::G4PhysicalVolumeModelTouchable |
1039 | (const std::vector<G4PhysicalVolumeNodeID>& fullPVPath): |
1040 | fFullPVPath(fullPVPath) {} |
1041 | |
1042 | const 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 | |
1056 | const 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 | |
1070 | G4VPhysicalVolume* 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 | |
1082 | G4VSolid* 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 | |
1094 | G4int 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 | } |