Geant4 Cross Reference |
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 // 28 // 29 // John Allison 26th July 1999. 30 // Model for logical volumes. 31 32 #include "G4LogicalVolumeModel.hh" 33 34 #include "G4VSolid.hh" 35 #include "G4LogicalVolume.hh" 36 #include "G4PVPlacement.hh" 37 #include "G4PVParameterised.hh" 38 #include "G4VPVParameterisation.hh" 39 #include "G4ModelingParameters.hh" 40 #include "G4VGraphicsScene.hh" 41 #include "G4DrawVoxels.hh" 42 #include "G4VSensitiveDetector.hh" 43 #include "G4VReadOutGeometry.hh" 44 #include "G4Circle.hh" 45 46 #include <vector> 47 #include <utility> 48 49 G4LogicalVolumeModel::G4LogicalVolumeModel 50 (G4LogicalVolume* pLV, 51 G4int soughtDepth, 52 G4bool booleans, 53 G4bool voxels, 54 G4bool readout, 55 G4bool checkOverlaps, 56 const G4Transform3D& modelTransformation, 57 const G4ModelingParameters* pMP): 58 // Instantiate a G4PhysicalVolumeModel with a G4PVPlacement to 59 // represent this logical volume. It has no rotation and a null 60 // translation so that the logical volume will be seen in its own 61 // reference system. It will be added to the physical volume store 62 // but it will not be part of the normal geometry heirarchy so it 63 // has no mother. 64 G4PhysicalVolumeModel 65 (new G4PVPlacement (0, // No rotation. 66 G4ThreeVector(), // Null traslation. 67 "PhysVol representation of LogVol " + pLV -> GetName (), 68 pLV, 69 0, // No mother. 70 false, // Not "MANY". 71 0), // Copy number. 72 soughtDepth, 73 modelTransformation, 74 pMP, 75 true), // Use full extent. 76 fpLV (pLV), 77 fBooleans (booleans), 78 fVoxels (voxels), 79 fReadout (readout), 80 fCheckOverlaps(checkOverlaps), 81 fOverlapsPrinted(false) 82 { 83 fType = "G4LogicalVolumeModel"; 84 fGlobalTag = fpLV -> GetName (); 85 fGlobalDescription = "G4LogicalVolumeModel " + fGlobalTag; 86 } 87 88 G4LogicalVolumeModel::~G4LogicalVolumeModel () {} 89 90 namespace { 91 // Vis attributes 92 const G4Colour highlightSolidColour(1.0,0.8,0.8); 93 const G4double highlightSolidLineWidth(10./*pixels*/); 94 const G4Colour highlightPointColour(0.5,0.5,1.0); 95 const G4double highlightPointDiameter(20./*pixels*/); 96 // Keep a vector of solid-copy number pairs to avoid duplication. 97 typedef std::pair<G4VSolid*,G4int> solidCopyNoPair; 98 std::vector<solidCopyNoPair> solidCopyNoVector; 99 void DrawSolid 100 (G4VGraphicsScene& sceneHandler, 101 G4VSolid* sol, G4int copyNo, const G4Transform3D& t) { 102 // Avoid duplication. 103 std::pair<G4VSolid*,G4int> pair(sol,copyNo); 104 auto iter = solidCopyNoVector.begin(); 105 for ( ; iter != solidCopyNoVector.end(); ++iter) { 106 if (*iter == pair) break; 107 } 108 if (iter == solidCopyNoVector.end()) { 109 solidCopyNoVector.push_back(pair); 110 G4VisAttributes highlightSolidVisAtts(highlightSolidColour); 111 highlightSolidVisAtts.SetLineWidth(highlightSolidLineWidth); 112 sceneHandler.PreAddSolid(t,highlightSolidVisAtts); 113 sceneHandler.AddSolid(*sol); 114 sceneHandler.PostAddSolid(); 115 } 116 } 117 void DrawPoint 118 (G4VGraphicsScene& sceneHandler, 119 const G4ThreeVector& point) { 120 G4VisAttributes highlightPointVisAtts(highlightPointColour); 121 G4Circle overlapPoint; 122 overlapPoint.SetVisAttributes(highlightPointVisAtts); 123 overlapPoint.SetPosition(point); 124 overlapPoint.SetDiameter(G4VMarker::SizeType::screen,highlightPointDiameter); 125 overlapPoint.SetFillStyle(G4VMarker::FillStyle::filled); 126 sceneHandler.BeginPrimitives(); 127 sceneHandler.AddPrimitive(overlapPoint); 128 sceneHandler.EndPrimitives(); 129 } 130 } 131 132 void G4LogicalVolumeModel::DescribeYourselfTo 133 (G4VGraphicsScene& sceneHandler) { 134 135 // Store current modeling parameters and ensure nothing is culled. 136 const G4ModelingParameters* tmpMP = fpMP; 137 G4ModelingParameters nonCulledMP; 138 if (fpMP) nonCulledMP = *fpMP; 139 nonCulledMP.SetCulling (false); 140 fpMP = &nonCulledMP; 141 G4PhysicalVolumeModel::DescribeYourselfTo (sceneHandler); 142 fpMP = tmpMP; 143 144 if (fVoxels) { 145 if (fpTopPV->GetLogicalVolume()->GetVoxelHeader()) { 146 // Add Voxels. 147 G4DrawVoxels dv; 148 G4PlacedPolyhedronList* pPPL = 149 dv.CreatePlacedPolyhedra (fpTopPV -> GetLogicalVolume ()); 150 for (size_t i = 0; i < pPPL -> size (); i++) { 151 const G4Transform3D& transform = (*pPPL)[i].GetTransform (); 152 const G4Polyhedron& polyhedron = (*pPPL)[i].GetPolyhedron (); 153 sceneHandler.BeginPrimitives (transform); 154 sceneHandler.AddPrimitive (polyhedron); 155 sceneHandler.EndPrimitives (); 156 } 157 delete pPPL; 158 } 159 } 160 161 if (fReadout) { 162 // Draw readout geometry... 163 G4VSensitiveDetector* sd = fpLV->GetSensitiveDetector(); 164 if (sd) { 165 G4VReadOutGeometry* roGeom = sd->GetROgeometry(); 166 if (roGeom) { 167 G4VPhysicalVolume* roWorld = roGeom->GetROWorld(); 168 // G4cout << "Readout geometry \"" << roGeom->GetName() 169 // << "\" with top physical volume \"" 170 // << roWorld->GetName() 171 // << "\"" << G4endl; 172 G4PhysicalVolumeModel pvModel(roWorld); 173 pvModel.SetModelingParameters(fpMP); 174 pvModel.DescribeYourselfTo(sceneHandler); 175 } 176 } 177 } 178 179 if (fCheckOverlaps) { 180 G4LogicalVolume* motherLog = fpTopPV->GetLogicalVolume(); 181 G4VSolid* motherSolid = motherLog->GetSolid(); 182 G4int nDaughters = (G4int)motherLog->GetNoDaughters(); 183 184 // Models are called repeatedly by the scene handler so be careful... 185 // Print overlaps - but only the first time for a given instantiation of G4LogicalVolume 186 if (!fOverlapsPrinted) { 187 for (G4int iDaughter = 0; iDaughter < nDaughters; ++iDaughter) { 188 G4VPhysicalVolume* daughterPhys = motherLog->GetDaughter(iDaughter); 189 daughterPhys->CheckOverlaps(); 190 } 191 fOverlapsPrinted = true; 192 } 193 194 // Draw overlaps 195 solidCopyNoVector.clear(); 196 for (G4int iDaughter = 0; iDaughter < nDaughters; ++iDaughter) { 197 G4VPhysicalVolume* daughterPhys = motherLog->GetDaughter(iDaughter); 198 G4PVPlacement* daughterPVPlace = dynamic_cast<G4PVPlacement*>(daughterPhys); 199 G4PVParameterised* daughterPVParam = dynamic_cast<G4PVParameterised*>(daughterPhys); 200 const G4int nPoints = 1000; 201 202 if (daughterPVPlace) { 203 204 // This algorithm is based on G4PVPlacement::CheckOverlaps. 205 G4AffineTransform tDaughter(daughterPhys->GetRotation(),daughterPhys->GetTranslation()); 206 G4VSolid* daughterSolid = daughterPhys->GetLogicalVolume()->GetSolid(); 207 for (G4int i = 0; i < nPoints; ++i) { 208 G4ThreeVector point = daughterSolid->GetPointOnSurface(); 209 // Transform to mother's coordinate system 210 G4ThreeVector motherPoint = tDaughter.TransformPoint(point); 211 // Check overlaps with the mother volume 212 if (motherSolid->Inside(motherPoint)==kOutside) { 213 // Draw mother and daughter and point 214 DrawSolid(sceneHandler,motherSolid,0,G4Transform3D()); 215 DrawSolid(sceneHandler,daughterSolid,daughterPhys->GetCopyNo(),tDaughter); 216 DrawPoint(sceneHandler,motherPoint); 217 } 218 // Check other daughters 219 for (G4int iSister = 0; iSister < nDaughters; ++iSister) { 220 if (iSister == iDaughter) continue; 221 G4VPhysicalVolume* sisterPhys = motherLog->GetDaughter(iSister); 222 G4AffineTransform tSister(sisterPhys->GetRotation(),sisterPhys->GetTranslation()); 223 // Transform to sister's coordinate system 224 G4ThreeVector sisterPoint = tSister.InverseTransformPoint(motherPoint); 225 G4LogicalVolume* sisterLog = sisterPhys->GetLogicalVolume(); 226 G4VSolid* sisterSolid = sisterLog->GetSolid(); 227 if (sisterSolid->Inside(sisterPoint)==kInside) { 228 // Draw daughter and sister and point 229 DrawSolid(sceneHandler,daughterSolid,daughterPhys->GetCopyNo(),tDaughter); 230 DrawSolid(sceneHandler,sisterSolid,sisterPhys->GetCopyNo(),tSister); 231 DrawPoint(sceneHandler,motherPoint); 232 } 233 } 234 } 235 236 } else if (daughterPVParam) { 237 238 // This algorithm is based on G4PVParameterised::CheckOverlaps 239 const G4int multiplicity = daughterPVParam->GetMultiplicity(); 240 auto* param = daughterPVParam->GetParameterisation(); 241 // Cache points for later checking against other parameterisations 242 std::vector<G4ThreeVector> motherPoints; 243 for (G4int iP = 0; iP < multiplicity; iP++) { 244 G4VSolid* daughterSolid = param->ComputeSolid(iP, daughterPhys); 245 daughterSolid->ComputeDimensions(param, iP, daughterPhys); 246 param->ComputeTransformation(iP, daughterPhys); 247 G4AffineTransform tDaughter(daughterPVParam->GetRotation(),daughterPVParam->GetTranslation()); 248 for (G4int i = 0; i < nPoints; ++i) { 249 G4ThreeVector point = daughterSolid->GetPointOnSurface(); 250 // Transform to mother's coordinate system 251 G4ThreeVector motherPoint = tDaughter.TransformPoint(point); 252 // Check overlaps with the mother volume 253 if (motherSolid->Inside(motherPoint)==kOutside) { 254 // Draw mother and daughter and point 255 DrawSolid(sceneHandler,motherSolid,0,G4Transform3D()); 256 DrawSolid(sceneHandler,daughterSolid,iP,tDaughter); 257 DrawPoint(sceneHandler,motherPoint); 258 } 259 motherPoints.push_back(motherPoint); 260 } 261 // Check sister parameterisations 262 for (G4int iPP = iP + 1; iPP < multiplicity; iPP++) { 263 G4VSolid* sisterSolid = param->ComputeSolid(iPP, daughterPhys); 264 sisterSolid->ComputeDimensions(param, iPP, daughterPhys); 265 param->ComputeTransformation(iPP, daughterPhys); 266 G4AffineTransform tSister 267 (daughterPVParam->GetRotation(),daughterPVParam->GetTranslation()); 268 for (const auto& motherPoint: motherPoints) { 269 // Transform each point into daughter's frame 270 G4ThreeVector sisterPoint = tSister.InverseTransformPoint(motherPoint); 271 if (sisterSolid->Inside(sisterPoint)==kInside) { 272 // Draw sister 273 DrawSolid(sceneHandler,sisterSolid,iPP,tSister); 274 // Recompute daughter parameterisation before drawing 275 daughterSolid->ComputeDimensions(param, iP, daughterPhys); 276 param->ComputeTransformation(iP, daughterPhys); 277 tDaughter = G4AffineTransform 278 (daughterPVParam->GetRotation(),daughterPVParam->GetTranslation()); 279 DrawSolid(sceneHandler,daughterSolid,iP,tDaughter); 280 DrawPoint(sceneHandler,motherPoint); 281 } 282 } 283 } 284 } 285 } 286 } 287 } 288 } 289 290 // This called from G4PhysicalVolumeModel::DescribeAndDescend by the 291 // virtual function mechanism. 292 void G4LogicalVolumeModel::DescribeSolid 293 (const G4Transform3D& theAT, 294 G4VSolid* pSol, 295 const G4VisAttributes* pVisAttribs, 296 G4VGraphicsScene& sceneHandler) { 297 298 if (fBooleans) { 299 // Look for "constituents". Could be a Boolean solid. 300 G4VSolid* pSol0 = pSol -> GetConstituentSolid (0); 301 if (pSol0) { // Composite solid... 302 G4VSolid* pSol1 = pSol -> GetConstituentSolid (1); 303 if (!pSol1) { 304 G4Exception 305 ("G4PhysicalVolumeModel::DescribeSolid", 306 "modeling0001", FatalException, 307 "2nd component solid in Boolean is missing."); 308 } 309 // Draw these constituents white and "forced wireframe"... 310 G4VisAttributes constituentAttributes; 311 constituentAttributes.SetForceWireframe(true); 312 DescribeSolid (theAT, pSol0, &constituentAttributes, sceneHandler); 313 DescribeSolid (theAT, pSol1, &constituentAttributes, sceneHandler); 314 } 315 } 316 317 // In any case draw the original/resultant solid... 318 sceneHandler.PreAddSolid (theAT, *pVisAttribs); 319 pSol -> DescribeYourselfTo (sceneHandler); 320 sceneHandler.PostAddSolid (); 321 } 322