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 #include <vtkPoints.h> 27 #include <vtkCellArray.h> 28 #include <vtkCharArray.h> 29 #include <vtkUnstructuredGrid.h> 30 #include <vtkDataSetMapper.h> 31 #include <vtkUnstructuredGridVolumeMapper.h> 32 #include <vtkUnstructuredGridVolumeRayCastMapper.h> 33 #include <vtkUnstructuredGridVolumeZSweepMapper.h> 34 #include <vtkOpenGLProjectedTetrahedraMapper.h> 35 #include <vtkActor.h> 36 #include <vtkColorTransferFunction.h> 37 #include <vtkPiecewiseFunction.h> 38 #include <vtkLookupTable.h> 39 #include <vtkVolumeProperty.h> 40 #include <vtkVolume.h> 41 #include <vtkNew.h> 42 #include <vtkTetra.h> 43 #include <vtkVoxel.h> 44 // #include <vtkCleanUnstructuredGrid.h> 45 #include <vtkDataSetTriangleFilter.h> 46 #include <vtkClipDataSet.h> 47 48 #include "G4VtkUnstructuredGridPipeline.hh" 49 #include "G4VtkVisContext.hh" 50 #include "G4VtkViewer.hh" 51 52 #include "G4Mesh.hh" 53 #include "G4LogicalVolume.hh" 54 #include "G4VNestedParameterisation.hh" 55 #include "G4ModelingParameters.hh" 56 #include "G4PhysicalVolumeModel.hh" 57 #include "G4PseudoScene.hh" 58 #include "G4Transform3D.hh" 59 #include "G4VSolid.hh" 60 #include "G4Tet.hh" 61 #include "G4Material.hh" 62 63 G4VtkUnstructuredGridPipeline::G4VtkUnstructuredGridPipeline(G4String nameIn, const G4VtkVisContext& vcIn) : 64 G4VVtkPipeline(nameIn, "G4VtkUnstructuredPipeline", vcIn, false, vcIn.fViewer->renderer) { 65 66 points = vtkSmartPointer<vtkPoints>::New(); 67 68 pointColourValues = vtkSmartPointer<vtkDoubleArray>::New(); 69 cellColourValues = vtkSmartPointer<vtkDoubleArray>::New(); 70 pointColourValues->SetNumberOfComponents(4); 71 cellColourValues->SetNumberOfComponents(4); 72 73 pointColourIndices = vtkSmartPointer<vtkDoubleArray>::New(); 74 cellColourIndices = vtkSmartPointer<vtkDoubleArray>::New(); 75 pointColourIndices->SetNumberOfComponents(1); 76 cellColourIndices->SetNumberOfComponents(1); 77 78 colourLUT = vtkSmartPointer<vtkDiscretizableColorTransferFunction>::New(); 79 colourLUT->DiscretizeOn(); 80 81 unstructuredGrid = vtkSmartPointer<vtkUnstructuredGrid>::New(); 82 unstructuredGrid->SetPoints(points); 83 unstructuredGrid->GetPointData()->SetScalars(pointColourValues); 84 unstructuredGrid->GetCellData()->SetScalars(cellColourValues); 85 86 // clean filter 87 #if 0 88 clean = vtkSmartPointer<vtkStaticCleanUnstructuredGrid>::New(); 89 clean->SetInputData(unstructuredGrid); 90 clean->ToleranceIsAbsoluteOff(); 91 clean->SetTolerance(1e-6); 92 #endif 93 94 // Clip filter 95 clip = vtkSmartPointer<vtkClipDataSet>::New(); 96 vtkNew<vtkPlane> plane; 97 clip->SetClipFunction(plane); 98 clip->SetInputData(unstructuredGrid); 99 100 // Triangle filter 101 auto tri = vtkSmartPointer<vtkDataSetTriangleFilter>::New(); 102 tri->SetInputData(unstructuredGrid); 103 104 // create dataset mapper 105 mapper = vtkSmartPointer<vtkDataSetMapper>::New(); 106 mapper->SetScalarModeToUseCellData(); 107 mapper->SetColorModeToDirectScalars(); 108 mapper->SetInputData(unstructuredGrid); 109 //mapper->SetInputConnection(clip->GetOutputPort()); 110 //mapper->SetInputConnection(tri->GetOutputPort()); 111 112 // create volume mapper 113 volumeMapper = vtkSmartPointer<vtkUnstructuredGridVolumeRayCastMapper>::New(); 114 volumeMapper->SetScalarModeToUseCellData(); 115 volumeMapper->SetInputConnection(tri->GetOutputPort()); 116 117 // create volume properties 118 auto volumeProp = vtkSmartPointer<vtkVolumeProperty>::New(); 119 volumeProp->SetColor(colourLUT); 120 121 // create actor 122 actor = vtkSmartPointer<vtkActor>::New(); 123 actor->SetMapper(mapper); 124 actor->SetVisibility(1); 125 126 // create volume 127 volume = vtkSmartPointer<vtkVolume>::New(); 128 volume->SetMapper(volumeMapper); 129 //volume->SetProperty(volumeProp); 130 volume->SetVisibility(1); 131 132 // add to renderer 133 vc.fViewer->renderer->AddActor(actor); 134 //vc.fViewer->renderer->AddVolume(volume); 135 } 136 137 void G4VtkUnstructuredGridPipeline::PseudoSceneForTetCells::AddSolid(const G4VSolid& solid) { 138 if (fpPVModel->GetCurrentDepth() == fDepth) { // Leaf-level cells only 139 // Need to know it's a tet !!!! or implement G4VSceneHandler::AddSolid (const G4Tet&) !!!! 140 try { 141 const G4Tet& tet = dynamic_cast<const G4Tet&>(solid); 142 const auto* pVisAtts = fpPVModel->GetCurrentLV()->GetVisAttributes(); 143 const auto& colour = pVisAtts->GetColour(); 144 145 G4ThreeVector p0, p1, p2, p3; 146 tet.GetVertices(p0, p1, p2, p3); 147 148 G4int idx[4] = {-1, -1, -1, -1}; 149 150 if (iCell > 0 && iCell < 100000000) { 151 #if 0 152 G4ThreeVector pts[4] = {p0, p1, p2, p3}; 153 for (G4int i = 0; i < 4; i++) { 154 auto h = MakeHash(pts[i]); 155 if (fpPointMap.find(h) == fpPointMap.end()) { 156 fpPointMap.insert(std::make_pair(h, iPoint)); 157 fpPoints->InsertNextPoint(pts[i].x(), pts[i].y(), pts[i].z()); 158 fpPointVector.push_back(pts[i]); 159 idx[i] = iPoint; 160 iPoint++; 161 } 162 else { 163 idx[i] = fpPointMap[h]; 164 } 165 } 166 #endif 167 168 #if 1 169 fpPoints->InsertNextPoint(p0.x(), p0.y(), p0.z()); 170 fpPoints->InsertNextPoint(p1.x(), p1.y(), p1.z()); 171 fpPoints->InsertNextPoint(p2.x(), p2.y(), p2.z()); 172 fpPoints->InsertNextPoint(p3.x(), p3.y(), p3.z()); 173 iPoint += 4; 174 175 idx[0] = 4 * iCellAdd; 176 idx[1] = 4 * iCellAdd + 1; 177 idx[2] = 4 * iCellAdd + 2; 178 idx[3] = 4 * iCellAdd + 3; 179 #endif 180 181 vtkNew<vtkTetra> tetra; 182 tetra->GetPointIds()->SetId(0, idx[0]); 183 tetra->GetPointIds()->SetId(1, idx[1]); 184 tetra->GetPointIds()->SetId(2, idx[2]); 185 tetra->GetPointIds()->SetId(3, idx[3]); 186 187 fpGrid->InsertNextCell(tetra->GetCellType(), tetra->GetPointIds()); 188 189 auto hash = MakeHash(colour); 190 unsigned short int iColour = 0; 191 if (fpColourMap.find(hash) == fpColourMap.end()) { 192 iColour = fpColourMap.size(); 193 fpColourMap.insert(std::make_pair(hash,iColour)); 194 double c[4] = {colour.GetRed(), colour.GetGreen(), colour.GetBlue(), colour.GetAlpha()}; 195 fpColourLUT->SetIndexedColorRGBA(iColour,c); 196 } 197 else { 198 iColour = fpColourMap[hash]; 199 } 200 201 fpCellColourValues->InsertNextTuple4(colour.GetRed(), colour.GetGreen(), colour.GetBlue(), colour.GetAlpha()); 202 fpCellColourIndices->InsertNextTuple1(iColour); 203 204 iCellAdd++; 205 } 206 iCell++; 207 } 208 catch (const std::bad_cast&) { 209 G4ExceptionDescription ed; 210 ed << "Called for a mesh that is not a tetrahedron mesh: " << solid.GetName(); 211 G4Exception("PseudoSceneForTetVertices","visman0108",JustWarning,ed); 212 } 213 } 214 } 215 216 void G4VtkUnstructuredGridPipeline::PseudoSceneForCubicalCells::AddSolid(const G4Box& box) { 217 if (fpPVModel->GetCurrentDepth() == fDepth) { // Leaf-level cells only 218 try { 219 const auto* pVisAtts = fpPVModel->GetCurrentLV()->GetVisAttributes(); 220 const auto& colour = pVisAtts->GetColour(); 221 const G4ThreeVector& position = fpCurrentObjectTransformation->getTranslation(); 222 223 fpPoints->InsertNextPoint(position.x()-box.GetXHalfLength(),position.y()-box.GetYHalfLength(),position.z()-box.GetZHalfLength()); 224 fpPoints->InsertNextPoint(position.x()-box.GetXHalfLength(),position.y()+box.GetYHalfLength(),position.z()-box.GetZHalfLength()); 225 fpPoints->InsertNextPoint(position.x()+box.GetXHalfLength(),position.y()-box.GetYHalfLength(),position.z()-box.GetZHalfLength()); 226 fpPoints->InsertNextPoint(position.x()+box.GetXHalfLength(),position.y()+box.GetYHalfLength(),position.z()-box.GetZHalfLength()); 227 228 fpPoints->InsertNextPoint(position.x()-box.GetXHalfLength(),position.y()-box.GetYHalfLength(),position.z()+box.GetZHalfLength()); 229 fpPoints->InsertNextPoint(position.x()-box.GetXHalfLength(),position.y()+box.GetYHalfLength(),position.z()+box.GetZHalfLength()); 230 fpPoints->InsertNextPoint(position.x()+box.GetXHalfLength(),position.y()-box.GetYHalfLength(),position.z()+box.GetZHalfLength()); 231 fpPoints->InsertNextPoint(position.x()+box.GetXHalfLength(),position.y()+box.GetYHalfLength(),position.z()+box.GetZHalfLength()); 232 233 vtkNew<vtkVoxel> voxel; 234 voxel->GetPointIds()->SetId(0, 8*iCell); 235 voxel->GetPointIds()->SetId(1, 8*iCell+1); 236 voxel->GetPointIds()->SetId(2, 8*iCell+2); 237 voxel->GetPointIds()->SetId(3, 8*iCell+3); 238 voxel->GetPointIds()->SetId(4, 8*iCell+4); 239 voxel->GetPointIds()->SetId(5, 8*iCell+5); 240 voxel->GetPointIds()->SetId(6, 8*iCell+6); 241 voxel->GetPointIds()->SetId(7, 8*iCell+7); 242 243 fpGrid->InsertNextCell(voxel->GetCellType(), voxel->GetPointIds()); 244 245 double cols[] = {colour.GetRed(), 246 colour.GetGreen(), 247 colour.GetBlue(), 248 colour.GetAlpha()}; 249 fpCellColourValues->InsertNextTuple(cols); 250 //fpCellColourIndices->InsertNextTuple1(iColour); 251 252 253 iCell++; 254 255 } 256 catch (const std::bad_cast&) { 257 G4ExceptionDescription ed; 258 ed << "Called for a mesh that is not a cubical mesh: " << box.GetName(); 259 G4Exception("PseudoSceneForCubicalVertices", "visman0108", JustWarning, ed); 260 } 261 } 262 } 263 264 void G4VtkUnstructuredGridPipeline::SetUnstructuredGridData(const G4Mesh &mesh) { 265 266 // Modelling parameters 267 G4ModelingParameters tmpMP; 268 tmpMP.SetCulling(true); // This avoids drawing transparent... 269 tmpMP.SetCullingInvisible(true); // ... or invisble volumes. 270 271 // Physical volume model 272 const auto& container = mesh.GetContainerVolume(); 273 const G4bool useFullExtent = true; // To avoid calculating the extent 274 G4PhysicalVolumeModel tmpPVModel(container, 275 G4PhysicalVolumeModel::UNLIMITED, 276 G4Transform3D(), // so that positions are in local coordinates 277 &tmpMP, 278 useFullExtent); 279 280 // Graphics scene 281 if(mesh.GetMeshType() == G4Mesh::tetrahedron) { 282 PseudoSceneForTetCells pseudoScene(&tmpPVModel, mesh.GetMeshDepth(), points, 283 pointColourValues, cellColourValues, 284 pointColourIndices, cellColourIndices, 285 colourLUT, unstructuredGrid); 286 tmpPVModel.DescribeYourselfTo(pseudoScene); 287 //G4cout << pseudoScene.GetNumberOfPoints() << " " << pseudoScene.GetNumberOfCells() << " " << pseudoScene.GetNumberOfAddedCells() << G4endl; 288 //pseudoScene.DumpColourMap(); 289 } 290 else if(mesh.GetMeshType() == G4Mesh::nested3DRectangular) { 291 PseudoSceneForCubicalCells pseudoScene(&tmpPVModel, mesh.GetMeshDepth(), points, 292 pointColourValues, cellColourValues, 293 pointColourIndices, cellColourIndices, 294 colourLUT, unstructuredGrid); 295 tmpPVModel.DescribeYourselfTo(pseudoScene); 296 } 297 else if(mesh.GetMeshType() == G4Mesh::rectangle) { 298 PseudoSceneForCubicalCells pseudoScene(&tmpPVModel, mesh.GetMeshDepth(), points, 299 pointColourValues, cellColourValues, 300 pointColourIndices, cellColourIndices, 301 colourLUT, unstructuredGrid); 302 tmpPVModel.DescribeYourselfTo(pseudoScene); 303 } 304 305 }