DMRITool  v0.1.1-139-g860d86b4
Diffusion MRI Tool
VTKViewer.cxx
Go to the documentation of this file.
1 // VTK Viewer
2 // Written 2012-2013 Hal Canary <http://cs.unc.edu/~hal>
3 // Copyright 2012-2013 University of North Carolina at Chapel Hill.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License"); you
6 // may not use this file except in compliance with the License. You
7 // may obtain a copy of the License at
8 //
9 // LICENSE.md in this repository or
10 // http://www.apache.org/licenses/LICENSE-2.0
11 //
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 // implied. See the License for the specific language governing
16 // permissions and limitations under the License.
17 
18 #include <iostream>
19 
20 #include <vtkAppendPolyData.h>
21 #include <vtkCamera.h>
22 #include <vtkColorTransferFunction.h>
23 #include <vtkDataSetReader.h>
24 #include <vtkDataSetSurfaceFilter.h>
25 #include <vtkFloatArray.h>
26 #include <vtkGlyph3D.h>
27 #include <vtkOBJReader.h>
28 #include <vtkPDBReader.h>
29 #include <vtkPLYReader.h>
30 #include <vtkPNGWriter.h>
31 #include <vtkPointData.h>
32 #include <vtkPolyData.h>
33 #include <vtkPolyDataMapper.h>
34 #include <vtkPolyDataNormals.h>
35 #include <vtkPolyDataReader.h>
36 #include <vtkProperty.h>
37 #include <vtkRenderWindow.h>
38 #include <vtkSphereSource.h>
39 #include <vtkSTLReader.h>
40 #include <vtkTubeFilter.h>
41 #include <vtkVersion.h>
42 #include <vtkWindowToImageFilter.h>
43 #include <vtkXMLImageDataReader.h>
44 #include <vtkXMLPolyDataReader.h>
45 #include <vtkXMLRectilinearGridReader.h>
46 #include <vtkXMLStructuredGridReader.h>
47 #include <vtkXMLUnstructuredGridReader.h>
48 #if VTK_MAJOR_VERSION <= 5
49  #define setInputData(x,y) ((x)->SetInput(y))
50  #define addInputData(x,y) ((x)->AddInput(y))
51 #else
52  #define setInputData(x,y) ((x)->SetInputData(y))
53  #define addInputData(x,y) ((x)->AddInputData(y))
54 #endif
55 
56 #include "VTKViewer.h"
57 
58 using std::cout;
59 
60 static vtkSmartPointer< vtkPolyData > ReadPDB(
61  const char * file_name)
62 {
63  vtkSmartPointer<vtkPDBReader> pdb =
64  vtkSmartPointer<vtkPDBReader>::New();
65  pdb->SetFileName(file_name);
66  pdb->SetHBScale(1.0);
67  pdb->SetBScale(1.0);
68  pdb->Update();
69 
70  vtkSmartPointer<vtkSphereSource> sphere =
71  vtkSmartPointer<vtkSphereSource>::New();
72  sphere->SetCenter(0, 0, 0);
73  sphere->SetRadius(1);
74 
75  vtkSmartPointer<vtkGlyph3D> glyph =
76  vtkSmartPointer<vtkGlyph3D>::New();
77  glyph->SetInputConnection(pdb->GetOutputPort());
78  glyph->SetSourceConnection(sphere->GetOutputPort());
79  glyph->SetOrient(1);
80  glyph->SetColorMode(1);
81  glyph->SetScaleMode(2);
82  glyph->SetScaleFactor(.25);
83  glyph->Update();
84 
85  vtkSmartPointer<vtkTubeFilter> tube =
86  vtkSmartPointer<vtkTubeFilter>::New();
87  tube->SetInputConnection(pdb->GetOutputPort());
88  tube->SetNumberOfSides(6);
89  tube->CappingOff();
90  tube->SetRadius(0.2);
91  tube->SetVaryRadius(0);
92  tube->SetRadiusFactor(10);
93  tube->Update();
94 
95  vtkSmartPointer< vtkPolyData > tubeMesh =
96  vtkSmartPointer< vtkPolyData >::New();
97  tubeMesh->ShallowCopy(tube->GetOutput());
98  vtkIdType N = tubeMesh->GetNumberOfPoints();
99 
100  vtkUnsignedCharArray * rgb_colors
101  = vtkUnsignedCharArray::SafeDownCast(
102  tubeMesh->GetPointData()->GetArray("rgb_colors"));
103  const unsigned char tuple[3] = {127,127,127};
104  if ((rgb_colors != NULL) & (rgb_colors->GetNumberOfComponents() == 3))
105  for (vtkIdType i = 0; i < N ; ++i)
106  rgb_colors->SetTupleValue(i, tuple);
107 
108  vtkSmartPointer< vtkAppendPolyData > appendFilter =
109  vtkSmartPointer< vtkAppendPolyData >::New();
110  appendFilter->AddInputConnection(glyph->GetOutputPort());
111  addInputData(appendFilter, tubeMesh);
112  appendFilter->Update();
113 
114  vtkSmartPointer< vtkPolyData > polyData = appendFilter->GetOutput();
115  return polyData;
116 }
117 
118 static vtkSmartPointer< vtkPolyData > ConvertDataSetToSurface(
119  vtkAlgorithmOutput * outputPort)
120 {
121  vtkSmartPointer< vtkDataSetSurfaceFilter > dataSetSurfaceFilter =
122  vtkSmartPointer< vtkDataSetSurfaceFilter >::New();
123  dataSetSurfaceFilter->SetInputConnection(outputPort);
124  dataSetSurfaceFilter->Update();
125  vtkSmartPointer< vtkPolyData > polyData =
126  dataSetSurfaceFilter->GetOutput();
127  return polyData;
128 }
129 
130 template <typename T>
131 static vtkSmartPointer< vtkPolyData > read(const char * file_name)
132 {
133  vtkSmartPointer< T > reader = vtkSmartPointer< T >::New();
134  reader->SetFileName(file_name);
135  reader->Update();
136  vtkSmartPointer< vtkPolyData > polyData =
137  reader->GetOutput();
138  return polyData;
139 }
140 
141 template <typename T>
142 static vtkSmartPointer< vtkPolyData > readDataSet(const char * file_name)
143 {
144  vtkSmartPointer< T > reader = vtkSmartPointer< T >::New();
145  reader->SetFileName(file_name);
146  reader->Update();
147  return ConvertDataSetToSurface(reader->GetOutputPort());
148 }
149 
150 static vtkSmartPointer< vtkPolyData > ReadLegacyVTK(const char * file_name)
151 {
152  vtkSmartPointer < vtkDataSetReader > reader =
153  vtkSmartPointer < vtkDataSetReader >::New();
154  reader->SetFileName(file_name);
155  reader->Update();
156  if (NULL != reader->GetPolyDataOutput())
157  {
158  vtkSmartPointer< vtkPolyData > polyData =
159  reader->GetPolyDataOutput();
160  return polyData;
161  }
162  else if (
163  (NULL != reader->GetUnstructuredGridOutput()) ||
164  (NULL != reader->GetStructuredPointsOutput()) ||
165  (NULL != reader->GetStructuredGridOutput()) ||
166  (NULL != reader->GetRectilinearGridOutput()))
167  {
168  return ConvertDataSetToSurface(reader->GetOutputPort());
169  }
170  else
171  {
172  std::cerr << "unsupported: ????????\n";
173  return vtkSmartPointer< vtkPolyData >::New();
174  }
175 }
176 
177 int GetVTKStereoType(const QByteArray & stereoType) {
178  if (stereoType == "CRYSTAL_EYES")
179  {
180  return (VTK_STEREO_CRYSTAL_EYES);
181  }
182  else if (stereoType == "RED_BLUE")
183  {
184  return (VTK_STEREO_RED_BLUE);
185  }
186  else if (stereoType == "INTERLACED")
187  {
188  return (VTK_STEREO_INTERLACED);
189  }
190  else if (stereoType == "LEFT")
191  {
192  return (VTK_STEREO_LEFT);
193  }
194  else if (stereoType == "RIGHT")
195  {
196  return (VTK_STEREO_RIGHT);
197  }
198  else if (stereoType == "DRESDEN")
199  {
200  return (VTK_STEREO_DRESDEN);
201  }
202  else if (stereoType == "ANAGLYPH")
203  {
204  return (VTK_STEREO_ANAGLYPH);
205  }
206  else if (stereoType == "CHECKERBOARD")
207  {
208  return (VTK_STEREO_CHECKERBOARD);
209  }
210  #ifdef VTK_STEREO_SPLITVIEWPORT_HORIZONTAL
211  else if (stereoType == "SPLITVIEWPORT_HORIZONTAL")
212  {
213  return (VTK_STEREO_SPLITVIEWPORT_HORIZONTAL);
214  }
215  #endif
216  else
217  {
218  return -1;
219  }
220 }
221 
223  m_renderer(vtkSmartPointer < vtkRenderer >::New())
224 {
225  vtkSmartPointer < vtkRenderWindow > renderWindow =
226  vtkSmartPointer < vtkRenderWindow >::New();
227  renderWindow->StereoCapableWindowOn();
228  renderWindow->AddRenderer(m_renderer);
229  QByteArray stereoType = qgetenv( "STEREO_TYPE" );
230  int vtkStereoType = GetVTKStereoType(stereoType);
231  if (vtkStereoType != -1)
232  {
233  renderWindow->SetStereoType(vtkStereoType);
234  }
235  else
236  {
237  renderWindow->SetStereoType(VTK_STEREO_RED_BLUE);
238  }
239  m_size[0]=600; m_size[1]=600;
240  m_renderer->ResetCamera();
241  m_renderer->SetBackground(0,0,0);
242  this->SetRenderWindow(renderWindow);
243  this->resize(480, 480);
244  this->setMinimumSize(m_size[0], m_size[1]);
245  connect(&(m_timer), SIGNAL(timeout()), this, SLOT(rotate()));
246  // m_timer.start(66);
247 }
248 
249 void VTKViewer::setsize(double s1, double s2)
250 {
251  m_size[0]=s1; m_size[1]=s2;
252  this->setMinimumSize(m_size[0], m_size[1]);
253 }
254 
255 void VTKViewer::add(vtkPolyData * polyData)
256 {
257  double range[2];
258  polyData->GetScalarRange(range);
259  // vtkSmartPointer< vtkColorTransferFunction > colorMap
260  // = vtkSmartPointer< vtkColorTransferFunction >::New();
261  // colorMap->SetColorSpaceToLab();
262  // colorMap->AddRGBPoint(range[0], 0.865, 0.865, 0.865);
263  // colorMap->AddRGBPoint(range[1], 0.706, 0.016, 0.150);
264  // colorMap->Build();
265 
266  vtkSmartPointer < vtkPolyDataMapper > mapper =
267  vtkSmartPointer < vtkPolyDataMapper >::New();
268  // mapper->SetLookupTable(colorMap);
269  if (polyData->GetPointData()->GetNormals() == NULL)
270  {
271  vtkSmartPointer< vtkPolyDataNormals > polyDataNormals
272  = vtkSmartPointer< vtkPolyDataNormals >::New();
273  setInputData(polyDataNormals, polyData);
274  // polyDataNormals->SetFeatureAngle(90.0);
275  mapper->SetInputConnection(polyDataNormals->GetOutputPort());
276  }
277  else
278  {
279  setInputData(mapper, polyData);
280  }
281  vtkSmartPointer < vtkActor > actor =
282  vtkSmartPointer < vtkActor >::New();
283  actor->GetProperty()->SetPointSize(3);
284  actor->SetMapper(mapper);
285  m_renderer->AddActor(actor);
286 }
287 
288 void VTKViewer::add(const char * file_name)
289 {
290  // TODO: add logic for other file formats.
291  QString filename = QString::fromUtf8(file_name).toLower();
292  if (filename.endsWith(".vtk"))
293  {
294  this->add(ReadLegacyVTK(file_name));
295  }
296  else if (filename.endsWith(".vtp"))
297  {
298  this->add(read< vtkXMLPolyDataReader >(file_name));
299  }
300  else if (filename.endsWith(".ply"))
301  {
302  this->add(read< vtkPLYReader >(file_name));
303  }
304  else if (filename.endsWith(".obj"))
305  {
306  this->add(read< vtkOBJReader >(file_name));
307  }
308  else if (filename.endsWith(".stl"))
309  {
310  this->add(read< vtkSTLReader >(file_name));
311  }
312  else if (filename.endsWith(".vtu"))
313  {
314  vtkSmartPointer< vtkXMLUnstructuredGridReader > reader =
315  vtkSmartPointer< vtkXMLUnstructuredGridReader >::New();
316  reader->SetFileName(file_name);
317  reader->Update();
318  this->add(ConvertDataSetToSurface(reader->GetOutputPort()));
319  }
320  else if (filename.endsWith(".pdb"))
321  {
322  this->add(ReadPDB(file_name));
323  }
324  else if (filename.endsWith(".vti"))
325  {
326  this->add(readDataSet< vtkXMLImageDataReader >(file_name));
327  }
328  else if (filename.endsWith(".vts"))
329  {
330  this->add(readDataSet< vtkXMLStructuredGridReader >(file_name));
331  }
332  else if (filename.endsWith(".vtr"))
333  {
334  this->add(readDataSet< vtkXMLRectilinearGridReader >(file_name));
335  }
336  else
337  {
338  std::cerr << file_name
339  << ": BAD FILE NAME. "
340  "Should end in VTK, VTP, PLY, OBJ, STL, VTU, or PDB.\n";
341  exit(1);
342  return;
343  }
344 }
345 
347 {
348  if (m_timer.isActive())
349  m_timer.stop();
350  else
351  m_timer.start(33);
352 }
353 
355 {
356  vtkCamera * camera = m_renderer->GetActiveCamera();
357  assert(camera != NULL);
358  camera->Azimuth(1);
359  m_renderer->GetRenderWindow()->Render();
360 }
361 
362 void VTKViewer::setStereoType(int vtkStereoType)
363 {
364  vtkRenderWindow * rw = m_renderer->GetRenderWindow();
365  assert(rw != NULL);
366  rw->SetStereoType(vtkStereoType);
367 }
368 
370 {
371  vtkRenderWindow * rw = m_renderer->GetRenderWindow();
372  assert(rw != NULL);
373  rw->SetStereoRender(! rw->GetStereoRender());
374  rw->Render();
375 }
376 
378 {
379  vtkRenderWindow * rw = m_renderer->GetRenderWindow();
380  assert(rw != NULL);
381  int type = rw->GetStereoType();
382  type = (type % 9) + 1;
383  this->setStereoType(type);
384  switch(type)
385  {
386  case 1: cout << "VTK_STEREO_CRYSTAL_EYES\n"; break;
387  case 2: cout << "VTK_STEREO_RED_BLUE\n"; break;
388  case 3: cout << "VTK_STEREO_INTERLACED\n"; break;
389  case 4: cout << "VTK_STEREO_LEFT\n"; break;
390  case 5: cout << "VTK_STEREO_RIGHT\n"; break;
391  case 6: cout << "VTK_STEREO_DRESDEN\n"; break;
392  case 7: cout << "VTK_STEREO_ANAGLYPH\n"; break;
393  case 8: cout << "VTK_STEREO_CHECKERBOARD\n"; break;
394  case 9: cout << "VTK_STEREO_SPLITVIEWPORT_HORIZONTAL\n"; break;
395  }
396  rw->Render();
397 }
398 
400 {
401  vtkSmartPointer< vtkWindowToImageFilter > windowToImageFilter =
402  vtkSmartPointer< vtkWindowToImageFilter >::New();
403  windowToImageFilter->SetInput( this->GetRenderWindow() );
404  windowToImageFilter->SetMagnification(2);
405  windowToImageFilter->SetInputBufferTypeToRGBA();
406  windowToImageFilter->Update();
407  vtkSmartPointer< vtkPNGWriter > writer =
408  vtkSmartPointer< vtkPNGWriter >::New();
409  writer->SetInputConnection(windowToImageFilter->GetOutputPort());
410  const char filename[] = "/tmp/screenshot.png";
411  writer->SetFileName(filename);
412  writer->Write();
413  cout << filename << '\n';
414 }
#define setInputData(x, y)
Definition: VTKViewer.cxx:49
void nextStereoType()
Definition: VTKViewer.cxx:377
void toggleStereo()
Definition: VTKViewer.cxx:369
void add(vtkPolyData *polyData)
Definition: VTKViewer.cxx:255
vtkSmartPointer< vtkRenderer > m_renderer
Definition: VTKViewer.h:42
static vtkSmartPointer< vtkPolyData > ConvertDataSetToSurface(vtkAlgorithmOutput *outputPort)
Definition: VTKViewer.cxx:118
static vtkSmartPointer< vtkPolyData > read(const char *file_name)
Definition: VTKViewer.cxx:131
static vtkSmartPointer< vtkPolyData > readDataSet(const char *file_name)
Definition: VTKViewer.cxx:142
QTimer m_timer
Definition: VTKViewer.h:41
static vtkSmartPointer< vtkPolyData > ReadLegacyVTK(const char *file_name)
Definition: VTKViewer.cxx:150
static vtkSmartPointer< vtkPolyData > ReadPDB(const char *file_name)
Definition: VTKViewer.cxx:60
void screenshot()
Definition: VTKViewer.cxx:399
void rotate()
Definition: VTKViewer.cxx:354
void setsize(double s1, double s2)
Definition: VTKViewer.cxx:249
int GetVTKStereoType(const QByteArray &stereoType)
Definition: VTKViewer.cxx:177
double m_size[2]
Definition: VTKViewer.h:44
void toggleRotate()
Definition: VTKViewer.cxx:346
void setStereoType(int vtkStereoType)
Definition: VTKViewer.cxx:362
#define addInputData(x, y)
Definition: VTKViewer.cxx:50