PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
ModelRenderer.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2 Program: Plus
3 Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4 See License.txt for details.
5 =========================================================Plus=header=end*/
6 
15 #include "PlusConfigure.h"
16 #include "vtkCamera.h"
17 #include "vtkFeatureEdges.h"
18 #include "vtkInteractorStyleTrackballCamera.h"
19 #include "vtkPNGWriter.h"
20 #include "vtkPolyDataMapper.h"
21 #include "vtkPolyDataNormals.h"
22 #include "vtkProperty.h"
23 #include "vtkRenderWindow.h"
24 #include "vtkRenderWindowInteractor.h"
25 #include "vtkRenderer.h"
26 #include "vtkSmartPointer.h"
27 #include "vtkSTLReader.h"
28 #include "vtkPlusToolAxesActor.h"
29 #include "vtkTriangleFilter.h"
30 #include "vtkWindowToImageFilter.h"
31 #include "vtksys/CommandLineArguments.hxx"
32 #include "vtksys/SystemTools.hxx"
33 
34 int main(int argc, char **argv)
35 {
36  bool printHelp(false);
37  std::string modelFileName;
38  std::string outputImageFileName;
39  std::vector<double> cameraRollPitchYawDeg;
40  double cameraZoomFactor = 1.0;
41  bool renderingOff(false);
42 
43  int verboseLevel=vtkPlusLogger::LOG_LEVEL_UNDEFINED;
44 
45  vtksys::CommandLineArguments args;
46  args.Initialize(argc, argv);
47 
48  args.AddArgument("--help", vtksys::CommandLineArguments::NO_ARGUMENT, &printHelp, "Print this help.");
49  args.AddArgument("--model-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &modelFileName, "Name of the input STL model file");
50  args.AddArgument("--output-image-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outputImageFileName, "Name of the output PNG image file that will be created. Optional. If not specified then an interactive 3D window is displayed.");
51  args.AddArgument("--camera-orientation", vtksys::CommandLineArguments::MULTI_ARGUMENT, &cameraRollPitchYawDeg, "Roll, pitch, yaw angles of the camera in degrees. Optional. Default: 0 20 20.");
52  args.AddArgument("--camera-zoom", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &cameraZoomFactor, "Zoom factor of the camera. Optional. Default: 1.0.");
53  args.AddArgument("--rendering-off", vtksys::CommandLineArguments::NO_ARGUMENT, &renderingOff, "Run test without rendering.");
54  args.AddArgument("--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel, "Verbose level (1=error only, 2=warning, 3=info, 4=debug, 5=trace)");
55 
56  if ( !args.Parse() )
57  {
58  std::cerr << "Problem parsing arguments" << std::endl;
59  std::cout << "Help: " << args.GetHelp() << std::endl;
60  exit(EXIT_FAILURE);
61  }
62 
63  if ( printHelp )
64  {
65  std::cout << args.GetHelp() << std::endl;
66  exit(EXIT_SUCCESS);
67  }
68 
69  vtkPlusLogger::Instance()->SetLogLevel(verboseLevel);
70 
71  if (modelFileName.empty())
72  {
73  std::cerr << "--model-file is required" << std::endl;
74  exit(EXIT_FAILURE);
75  }
76 
77  if (cameraRollPitchYawDeg.size()==0)
78  {
79  cameraRollPitchYawDeg.push_back(0);
80  cameraRollPitchYawDeg.push_back(20);
81  cameraRollPitchYawDeg.push_back(20);
82  }
83  else if (cameraRollPitchYawDeg.size()!=3)
84  {
85  LOG_ERROR("--camera-orientation requires 3 parameters");
86  exit(EXIT_FAILURE);
87  }
88 
89  vtkSmartPointer<vtkSTLReader> modelReader = vtkSmartPointer<vtkSTLReader>::New();
90  modelReader->SetFileName(modelFileName.c_str());
91  modelReader->Update();
92  vtkPolyData* modelPolyData=modelReader->GetOutput();
93  if (modelPolyData->GetNumberOfPoints()==0)
94  {
95  LOG_ERROR("Failed to load model from file: "<<modelFileName);
96  return EXIT_FAILURE;
97  }
98 
99  vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
100  renderer->SetBackground(1,1,1);
101  renderer->SetUseDepthPeeling(1);
102  renderer->SetMaximumNumberOfPeels(100);
103  renderer->SetOcclusionRatio(0.1);
104 
105  vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
106  if (!outputImageFileName.empty())
107  {
108  renWin->OffScreenRenderingOn();
109  }
110  renWin->SetSize(500,500);
111  renWin->SetAlphaBitPlanes(1); // for depth peeling
112  renWin->SetMultiSamples(0); // for depth peeling
113  renWin->AddRenderer(renderer);
114 
115  //Create the interactor that handles the event loop
116  vtkSmartPointer<vtkRenderWindowInteractor> iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();
117  iren->SetInteractorStyle(vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New());
118  iren->SetRenderWindow(renWin);
119 
120  // Must be called after iren and renderer are linked or there will be problems
121  renderer->GetActiveCamera();
122  renderer->Render();
123 
124  // iren must be initialized so that it can handle events
125  iren->Initialize();
126 
127  vtkSmartPointer<vtkPolyDataNormals> modelNormals = vtkSmartPointer<vtkPolyDataNormals>::New();
128 
129  modelNormals->SetInputConnection(modelReader->GetOutputPort());
130 
131  vtkSmartPointer<vtkPolyDataMapper> modelMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
132  modelMapper->SetInputConnection(modelNormals->GetOutputPort());
133 
134  vtkSmartPointer<vtkActor> modelActor = vtkSmartPointer<vtkActor>::New();
135  modelActor->SetMapper(modelMapper);
136  modelActor->GetProperty()->SetColor(0.9, 0.9, 0.9);
137  modelActor->GetProperty()->SetOpacity(0.8);
138  renderer->AddActor(modelActor);
139 
140  vtkSmartPointer<vtkTriangleFilter> triangleFilter = vtkSmartPointer<vtkTriangleFilter>::New();
141  triangleFilter->SetInputConnection(modelNormals->GetOutputPort());
142 
143  vtkSmartPointer<vtkFeatureEdges> edgeExtractor = vtkSmartPointer<vtkFeatureEdges>::New();
144  edgeExtractor->SetInputConnection(triangleFilter->GetOutputPort());
145  edgeExtractor->ColoringOff();
146  edgeExtractor->BoundaryEdgesOn();
147  edgeExtractor->ManifoldEdgesOn();
148  edgeExtractor->NonManifoldEdgesOn();
149 
150  vtkSmartPointer<vtkPolyDataMapper> modelEdgesMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
151  modelEdgesMapper->SetInputConnection(edgeExtractor->GetOutputPort());
152  modelEdgesMapper->SetResolveCoincidentTopologyToPolygonOffset();
153  vtkSmartPointer<vtkActor> modelEdgesActor = vtkSmartPointer<vtkActor>::New();
154  modelEdgesActor->SetMapper(modelEdgesMapper);
155  modelEdgesActor->GetProperty()->SetColor(0.0, 0.0, 0.0);
156  renderer->AddActor(modelEdgesActor);
157 
158  // Add an origin display actor
159  vtkSmartPointer<vtkPlusToolAxesActor> originActor=vtkSmartPointer<vtkPlusToolAxesActor>::New();
160  originActor->SetName("origin");
161  //renderer->AddActor(originActor);
162 
163  // Set projection to parallel to enable estimate distances
164  renderer->GetActiveCamera()->ParallelProjectionOn();
165  renderer->GetActiveCamera()->Roll(cameraRollPitchYawDeg[0]);
166  renderer->GetActiveCamera()->Pitch(cameraRollPitchYawDeg[1]);
167  renderer->GetActiveCamera()->Yaw(cameraRollPitchYawDeg[2]);
168  renderer->ResetCamera();
169  renderer->GetActiveCamera()->Zoom(cameraZoomFactor);
170 
171  if (outputImageFileName.empty())
172  {
173  iren->Start();
174  }
175  else
176  {
177  vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
178  windowToImageFilter->SetInput(renWin);
179  windowToImageFilter->Update();
180 
181  vtkSmartPointer<vtkPNGWriter> writer = vtkSmartPointer<vtkPNGWriter>::New();
182  writer->SetFileName(outputImageFileName.c_str());
183  writer->SetInputData(windowToImageFilter->GetOutput());
184  writer->Write();
185 
186  LOG_INFO("Rendered image is written to "<<outputImageFileName);
187  }
188 
189  return EXIT_SUCCESS;
190 }
vtkRenderWindowInteractor * iren
int main(int argc, char **argv)
static vtkIGSIOLogger * Instance()