SMILX  1.01
milxOverlay.cpp
1 /*=========================================================================
2  The Software is copyright (c) Commonwealth Scientific and Industrial Research Organisation (CSIRO)
3  ABN 41 687 119 230.
4  All rights reserved.
5 
6  Licensed under the CSIRO BSD 3-Clause License
7  You may not use this file except in compliance with the License.
8  You may obtain a copy of the License in the file LICENSE.md or at
9 
10  https://stash.csiro.au/projects/SMILI/repos/smili/browse/license.txt
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 implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 =========================================================================*/
29 //Qt
30 #include <QApplication>
31 
32 #include "milxQtModel.h"
33 #include "milxQtImage.h"
34 #include "milxQtFile.h"
35 
36 #include <vtkMath.h>
37 #include <vtkWindowToImageFilter.h>
38 
39 #include <tclap/CmdLine.h> //Command line parser library
40 
41 using namespace TCLAP;
42 
43 int main(int argc, char* argv[])
44 {
45  QApplication app(argc,argv);
46  QMainWindow mainWindow;//app takes ownership so need to be on stack, not heap
47 
48  //---------------------------
50  milx::PrintInfo("--------------------------------------------------------");
51  milx::PrintInfo("SMILI Overlay Tool for Medical Imaging");
52  milx::PrintInfo("(c) Copyright Chandra et al., 2015.");
53  milx::PrintInfo("University of Queensland, Australia.");
54  milx::PrintInfo("Australian e-Health Research Centre, CSIRO, Australia.");
55  milx::PrintInfo("SMILI Version: " + milx::NumberToString(milx::Version));
56  milx::PrintInfo("milxQt Version: " + milx::NumberToString(milxQtVersion));
57  milx::PrintInfo("Application Version: 1.03");
58  milx::PrintInfo("--------------------------------------------------------\n");
59 
60  //---------------------------
62  CmdLine cmd("An overlay tool for models/images", ' ', milx::NumberToString(milx::Version));
63 
65  ValueArg<std::string> outputArg("o", "output", "Output Screenshot name", false, "screenshot.png", "Output");
66  ValueArg<std::string> imageArg("i", "image", "Load and generate image slices as planes (axial, coronal & saggital)", false, "image.nii.gz", "Image");
67  ValueArg<std::string> vectorsArg("v", "vectors", "Generate and display vector field from model. If no vectors are present then scalars and normals will be used", false, "vectors.vtk", "Vectors");
68  ValueArg<std::string> maskArg("s", "scalarmask", "Clip the main mesh based on binary scalar values in model", false, "mask.vtk", "Scalar Mask");
69  ValueArg<std::string> setScalarsArg("", "setscalars", "Set active scalars of model as array name given", false, "Stats", "Set Scalars");
70  ValueArg<std::string> labelArg("l", "label", "Overlay binary image/label on the image", false, "labelling.nii.gz", "Label");
71  ValueArg<std::string> transformArg("t", "transform", "Transform (ITK Format) to apply to objects being rendered", false, "rigid.txt", "Transform");
72  ValueArg<std::string> isoArg("", "isosurface", "Generate Iso-surface (surface from label image) from the image", false, "data.nii.gz", "Isosurface");
73  ValueArg<std::string> loadScalarsArg("", "loadscalars", "Load scalars for the mesh from another mesh", false, "scalars.vtk", "Scalars");
74  ValueArg<std::string> loadViewFileArg("", "loadviewfile", "Load saved view from file (use onscreen mode to save view files)", false, "camera.cam", "Load View File");
75  ValueArg<std::string> scalarBarArg("", "scalarbar", "Enable the scalar bar for display with given name.", false, "Scalars", "Scalar Bar");
76  ValueArg<float> opacityArg("", "opacity", "Set the opacity of the models", false, 0.5, "Opacity");
77  ValueArg<float> isoValueArg("", "isovalue", "Set the label or iso-surface value for option --isosurface.", false, 0.5, "Isovalue");
78  ValueArg<float> minArg("", "min", "Set the minimum value for scalars on model.", false, 0.0, "Minimum Scalar");
79  ValueArg<float> maxArg("", "max", "Set the maximum value for scalars on model.", false, 1.0, "Maximum Scalar");
80  ValueArg<float> redArg("", "redbackground", "Set the redness value (0-1) for the background.", false, 1.0, "Red Component");
81  ValueArg<float> greenArg("", "greenbackground", "Set the greenness value (0-1) for the background.", false, 1.0, "Green Component");
82  ValueArg<float> blueArg("", "bluebackground", "Set the blueness value (0-1) for the background.", false, 1.0, "Blue Component");
83  ValueArg<float> zoomArg("", "zoom", "Zoom in on the current view by given factor.", false, 2.0, "Zoom");
84  ValueArg<int> heightArg("y", "height", "Set the height of the window.", false, 600, "Height");
85  ValueArg<int> widthArg("x", "width", "Set the width of the window.", false, 800, "Width");
86  ValueArg<int> axialSliceArg("", "axialslice", "Set the axial slice of the image.", false, 0, "Axial Slice");
87  ValueArg<int> coronalSliceArg("", "coronalslice", "Set the coronal slice of the image.", false, 0, "Coronal Slice");
88  ValueArg<int> saggitalSliceArg("", "saggitalslice", "Set the saggital slice of the image.", false, 0, "Saggital Slice");
90  SwitchArg jetArg("", "jet", "Change colourmap of the scalars to the Jet map", false);
91  SwitchArg vtkArg("", "vtk", "Change colourmap of the scalars to blue-red (rainbow VTK) map", false);
92  SwitchArg hsvArg("", "hsv", "Change colourmap of the scalars to blue-red (rainbow HSV) map", false);
93  SwitchArg rainbowArg("", "rainbow", "Change colourmap of the scalars to the rainbow map", false);
94  SwitchArg spectralArg("", "spectral", "Change colourmap of the scalars to the spectral map", false);
95  SwitchArg nihArg("", "NIH", "Change colourmap of the scalars to NIH", false);
96  SwitchArg fireArg("", "NIH_FIRE", "Change colourmap of the scalars to NIH Fire", false);
97  SwitchArg aalArg("", "AAL", "Change colourmap of the scalars to AAL", false);
98  SwitchArg fsArg("", "FS", "Change colourmap of the scalars to FreeSurfer", false);
99  SwitchArg hotArg("", "HOT", "Change colourmap of the scalars to HOT", false);
100  SwitchArg coolArg("", "COOL", "Change colourmap of the scalars to COOL", false);
101  SwitchArg loadViewArg("", "loadview", "Load saved view (use smilx or onscreen render mode to view and save with Right Click->View->Save View", false);
102  SwitchArg onscreenArg("", "onscreen", "Enable on screen rendering, i.e. display the rendering as an interactive window.", false);
103  SwitchArg whiteArg("", "white", "Make background white rather than default gradient colour.", false);
104  SwitchArg inverseArg("", "inverse", "Use the inverse transform when transform file is provided.", false);
105  SwitchArg noaxialArg("", "noaxial", "Do not show axial slice when image is given.", false);
106  SwitchArg nocoronalArg("", "nocoronal", "Do not show coronal slice when image is given.", false);
107  SwitchArg nosaggitalArg("", "nosaggital", "Do not show saggital slice when image is given.", false);
108  SwitchArg axialArg("", "axial", "Show axial view based on position of first surface.", false);
109  SwitchArg coronalArg("", "coronal", "Show coronal view based on position of first surface.", false);
110  SwitchArg saggitalArg("", "saggital", "Show saggital view based on position of first surface.", false);
111  SwitchArg removeScalarsArg("", "removescalars", "Remove the scalars of the models.", false);
112  SwitchArg clampScalarsArg("", "clampscalars", "Clamp the scalars of the models to background colour (outside colourmap) from min/max values provided.", false);
113  SwitchArg clampScalarsBelowArg("", "clampbelow", "Clamp the scalars of the models to background colour (outside colourmap) below min values provided.", false);
114  SwitchArg outlineArg("", "outline", "Display outline box for the model. Model outline overided by image if present.", false);
115  SwitchArg slicesArg("", "noslices", "Prevent any slices from being shown. Other elements from image option etc. will still be displayed.", false);
116  SwitchArg autoColourArg("", "autocolour", "Colour each additional model automatically based on order.", false);
117  SwitchArg wireframeArg("", "wireframe", "Display initial surface as a wireframe model.", false);
118  SwitchArg wireframesArg("", "wireframes", "Display all surfaces as a wireframe models.", false);
119  SwitchArg humanArg("", "nohuman", "Disable human orientation glyph.", false);
120  SwitchArg specularArg("", "nospecular", "Disable specular lighting for the rendered view.", false);
121 
123  UnlabeledMultiArg<std::string> multinames("surfaces", "Surfaces to overlay", true, "Surfaces");
124 
126  std::vector<Arg*> xorlist;
127  xorlist.push_back(&axialArg);
128  xorlist.push_back(&coronalArg);
129  xorlist.push_back(&saggitalArg);
130  cmd.xorAdd(xorlist);
131 
133  cmd.add( multinames );
134  cmd.add( outputArg );
135  cmd.add( imageArg );
136  cmd.add( vectorsArg );
137  cmd.add( maskArg );
138 #ifdef ITK_REVIEW //Review only members
139  cmd.add( labelArg );
140 #endif
141  cmd.add( transformArg );
142  cmd.add( isoArg );
143  cmd.add( minArg );
144  cmd.add( maxArg );
145  cmd.add( redArg );
146  cmd.add( greenArg );
147  cmd.add( blueArg );
148  cmd.add( zoomArg );
149  cmd.add( opacityArg );
150  cmd.add( isoValueArg );
151  cmd.add( loadScalarsArg );
152  cmd.add( setScalarsArg );
153  cmd.add( heightArg );
154  cmd.add( widthArg );
155  cmd.add( axialSliceArg );
156  cmd.add( coronalSliceArg );
157  cmd.add( saggitalSliceArg );
158 
159  cmd.add( jetArg );
160  cmd.add( vtkArg );
161  cmd.add( hsvArg );
162  cmd.add( rainbowArg );
163  cmd.add( spectralArg );
164  cmd.add( nihArg );
165  cmd.add( fireArg );
166  cmd.add( aalArg );
167  cmd.add( fsArg );
168  cmd.add( hotArg );
169  cmd.add( coolArg );
170  cmd.add( loadViewArg );
171  cmd.add( loadViewFileArg );
172  cmd.add( scalarBarArg );
173  cmd.add( onscreenArg );
174  cmd.add( whiteArg );
175  cmd.add( inverseArg );
176  cmd.add( noaxialArg );
177  cmd.add( nocoronalArg );
178  cmd.add( nosaggitalArg );
179  cmd.add( removeScalarsArg );
180  cmd.add( clampScalarsArg );
181  cmd.add( clampScalarsBelowArg );
182  cmd.add( outlineArg );
183  cmd.add( slicesArg );
184  cmd.add( autoColourArg );
185  cmd.add( wireframeArg );
186  cmd.add( wireframesArg );
187  cmd.add( humanArg );
188  cmd.add( specularArg );
189 
191  cmd.parse( argc, argv );
192 
194  //Filenames of surfaces
195  std::vector<std::string> filenames = multinames.getValue();
196  const std::string screenName = outputArg.getValue();
197  const std::string imageName = imageArg.getValue();
198  const std::string vectorsName = vectorsArg.getValue();
199  const std::string scalarMaskName = maskArg.getValue();
200  const std::string labelName = labelArg.getValue();
201  const std::string transformName = transformArg.getValue();
202  const std::string isoName = isoArg.getValue();
203  const std::string loadScalarsName = loadScalarsArg.getValue();
204  const std::string loadViewName = loadViewFileArg.getValue();
205  const std::string arrayName = setScalarsArg.getValue();
206  const std::string barName = scalarBarArg.getValue();
207  const float opacity = opacityArg.getValue();
208  const float isoValue = isoValueArg.getValue();
209  const float minValue = minArg.getValue();
210  const float maxValue = maxArg.getValue();
211  const float redValue = redArg.getValue();
212  const float greenValue = greenArg.getValue();
213  const float blueValue = blueArg.getValue();
214  const float zoomFactor = zoomArg.getValue();
215  const int windowHeight = heightArg.getValue();
216  const int windowWidth = widthArg.getValue();
217  const int axialSliceNumber = axialSliceArg.getValue();
218  const int coronalSliceNumber = coronalSliceArg.getValue();
219  const int saggitalSliceNumber = saggitalSliceArg.getValue();
220 // const float scaleFactor = scaleArg.getValue();
221 
222  //Check arguments
223  //Most of the checking is done by TCLAP
224  if(inverseArg.isSet())
225  {
226  if(!transformArg.isSet())
227  {
228  cerr << "Error in arguments! Inverse argument needs to be used with the transform argument." << endl;
229  exit(EXIT_FAILURE);
230  }
231  }
232  if(noaxialArg.isSet() || nosaggitalArg.isSet() || nocoronalArg.isSet() || axialSliceArg.isSet() || coronalSliceArg.isSet() || saggitalSliceArg.isSet())
233  {
234  if(!imageArg.isSet())
235  {
236  cerr << "Error in arguments! View/Slice arguments need to be used with the image argument." << endl;
237  exit(EXIT_FAILURE);
238  }
239  }
240  if(isoValueArg.isSet())
241  {
242  if(!isoArg.isSet())
243  {
244  cerr << "Error in arguments! Isovalue argument needs to be used with the isosurface argument." << endl;
245  exit(EXIT_FAILURE);
246  }
247  }
248 
250  //Reader object
251  QScopedPointer<milxQtFile> reader(new milxQtFile);
252  bool errorReading = false;
253  bool success = false;
254 
255  //Read model
256  cout << ">> Overlay: Reading Models" << endl;
257  vtkSmartPointer<vtkPolyDataCollection> collection;
258  success = milx::File::OpenModelCollection(filenames, collection);
259  if(!success) //Error printed inside
260  {
261  cerr << "Error reading models!" << endl;
262  exit(EXIT_FAILURE);
263  }
264 
265  //Read transform
266  vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); //transform matrix
267  transform->Identity();
268  transform->PostMultiply();
269  if(transformArg.isSet())
270  {
271  vtkSmartPointer<vtkMatrix4x4> matrix = milx::File::OpenITKTransform(transformName);
272  transform->Concatenate(matrix);
273  if(inverseArg.isSet())
274  transform->Inverse();
275  }
276 
277  //Load Models
278  QList< QSharedPointer<milxQtModel> > models; //Use shared pointer here, more overhead but allows assignment etc.
279  QSharedPointer<milxQtModel> model;
280  const size_t n = collection->GetNumberOfItems();
281 
282  if(n < 1)
283  {
284  cerr << "At least one model must be provided!" << endl;
285  exit(EXIT_FAILURE);
286  }
287 
288  vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();
289  if(autoColourArg.isSet())
290  {
291  lookupTable->SetTableRange(0.0, n+1);
292  lookupTable->Build();
293  }
294 
295  double range[2];
296  collection->InitTraversal();
297  for(size_t j = 0; j < n; j ++)
298  {
299  double colour[3];
300 
301  QSharedPointer<milxQtModel> mdl(new milxQtModel);
302  mdl->setName(filenames[j].c_str());
303  mdl->SetInput(collection->GetNextItem());
304 
305  if(removeScalarsArg.isSet() && mdl->GetScalars())
306  mdl->RemoveScalars();
307  if(loadScalarsArg.isSet())
308  mdl->loadScalars(loadScalarsName.c_str());
309 
310  mdl->generateModel();
311 
312  //Colouring
313  if(autoColourArg.isSet() && j > 0)
314  {
316  lookupTable->GetColor(j, colour);
317  mdl->changeColour(colour[0], colour[1], colour[2]);
318  }
319  if(setScalarsArg.isSet())
320  mdl->showArray(arrayName.c_str());
321 
323  if(mdl->GetScalars())
324  {
325  mdl->GetScalarRange(range);
326  if(clampScalarsBelowArg.isSet())
327  mdl->thresholdScalars(minValue, range[1], vtkMath::Nan());
328  if(clampScalarsArg.isSet())
329  mdl->thresholdScalars(minValue, maxValue, vtkMath::Nan());
330  if(minArg.isSet())
331  range[0] = minValue;
332  if(maxArg.isSet())
333  range[1] = maxValue;
334  }
335 
336  if( opacityArg.isSet() && (!autoColourArg.isSet() || j == 0) ) //needs to be after generate Model
337  mdl->SetOpacity(opacity);
338  if(wireframesArg.isSet())
339  mdl->generateWireframe();
340 
341  models.append(mdl);
342  }
343  model = models[0];
344  mainWindow.setCentralWidget(model.data());
345  std::cerr << "Done" << std::endl;
346 
347  //Read vectors model
348  QScopedPointer<milxQtModel> modelVectors(new milxQtModel); //smart deletion
349  if(vectorsArg.isSet())
350  {
351  success = reader->openModel(vectorsName.c_str(), modelVectors.data());
352  if(success)
353  {
354  cout << ">> Applying Vectors" << endl;
355  modelVectors->setName(vectorsName.c_str());
356  modelVectors->generateModel();
357  modelVectors->generateVectorField();
358 // if(transformArg.isSet())
359 // modelVectors->SetTransform(transform);
360  }
361  else
362  errorReading = true;
363  }
364  //Read mask model
365  QScopedPointer<milxQtModel> modelMask(new milxQtModel); //smart deletion
366  if(maskArg.isSet())
367  {
368  success = reader->openModel(scalarMaskName.c_str(), modelMask.data());
369  if(success)
370  {
371  cout << ">> Overlay: Applying Mask" << endl;
372  modelMask->setName(scalarMaskName.c_str());
373  modelMask->generateModel();
374 
375  //Clipping and scalars stuff
376  modelMask->GetScalars()->SetName("Mask");
377  model->GetScalars()->SetName("Scalars");
378  model->GetOutput()->GetPointData()->AddArray(modelMask->GetScalars());
379  model->showArray("Mask");
380  model->threshold(1.0, 1.0);
381  model->showArray("Scalars");
382 
383  //Reset scalar range for display
384  model->resetScalarRange();
385 
386  if(model->GetNumberOfPoints() == 0)
387  {
388  cerr << "Error using scalar mask. Model no longer has any points!" << endl;
389  exit(EXIT_FAILURE);
390  }
391  }
392  else
393  errorReading = true;
394  }
395  //Read iso surface
396  QScopedPointer<milxQtModel> modelIso(new milxQtModel); //smart deletion
397  QScopedPointer<milxQtImage> imgIso(new milxQtImage); //smart deletion
398  if(isoArg.isSet())
399  {
400  cout << ">> Overlay: Applying Isosurface" << endl;
401  success = reader->openImage(isoName.c_str(), imgIso.data());
402  imgIso->setName(isoName.c_str());
403  imgIso->generateImage();
404  imgIso->threshold(0, isoValue-1.0, isoValue);// fix thresholding here
405 
406  if(!success)
407  errorReading = true;
408 
409 // modelIso->generatePolyDataFromImage(imgIso->GetOutput());
410  modelIso->generateIsoSurface(imgIso->GetOutput(), 0, isoValue-1.0);// fix thresholding here
411  modelIso->generateModel();
412  modelIso->changeColour(0,1,0);
413 // if(transformArg.isSet())
414 // modelIso->SetTransform(transform);
415  }
416 
417  if(errorReading)
418  {
419  cerr << "Error Reading one or more of the input files. Exiting." << endl;
420  exit(EXIT_FAILURE);
421  }
422 
423  //Read Image
424  QScopedPointer<milxQtImage> img(new milxQtImage); //hierarchy deletion
425  QScopedPointer<milxQtImage> imgCoronal(new milxQtImage); //hierarchy deletion
426  QScopedPointer<milxQtImage> imgSagittal(new milxQtImage); //hierarchy deletion
427  vtkSmartPointer<vtkMatrix4x4> orientTransform = vtkSmartPointer<vtkMatrix4x4>::New();
428 
429  //Read image
430  vtkSmartPointer<vtkTransform> transform2 = vtkSmartPointer<vtkTransform>::New(); //transform matrix
431  transform2->Identity();
432  transform2->PostMultiply();
433  if(imageArg.isSet())
434  {
435  cout << ">> Overlay: Reading Image" << endl;
436  errorReading = false;
437  success = reader->openImage(imageName.c_str(), img.data());
438 
440  if(success)
441  {
442  //Generate the images
443  //Axial default view atm
444  img->setName(imageName.c_str());
445  img->generateImage();
446  if(axialSliceArg.isSet())
447  img->setSlice(axialSliceNumber);
448  // if(indexNIH > 0)
449  // img->colourMapToNIH();
450  // if(indexNIH_FIRE > 0)
451  // img->colourMapToNIH_Fire();
452  // if(indexAAL > 0)
453  // img->colourMapToAAL();
454 
455 #ifdef ITK_REVIEW //Review only members
456  if(labelArg.isSet())
457  {
458  img->overlayContour(labelName.c_str()); //Generates an RGB image, from VTK class
459  }
460 #endif
461 
462 // img->flip(false, true, false);
463 
464  //Share to create other views
465  imgCoronal->setDisplayData(img.data());
466  imgSagittal->setDisplayData(img.data());
467 
468  //ATM in API, fastest coding way is to load image for each view desired
469  //Thus need to copy image, memory usage is high here
470  //Setup coronal view
471  if(!nocoronalArg.isSet())
472  {
473  imgCoronal->setName(imageName.c_str());
474  imgCoronal->generateImage();
475  imgCoronal->viewToCoronal();
476  if(coronalSliceArg.isSet())
477  imgCoronal->setSlice(coronalSliceNumber);
478  }
479 
480  //Setup sagittal view
481  if(!nosaggitalArg.isSet())
482  {
483  imgSagittal->setName(imageName.c_str());
484  imgSagittal->generateImage();
485  imgSagittal->viewToSagittal();
486  if(saggitalSliceArg.isSet())
487  imgSagittal->setSlice(saggitalSliceNumber);
488  }
489  }
490  else
491  errorReading = true;
492 
493  if(errorReading)
494  {
495  cerr << "Error Reading the image file. Exiting." << endl;
496  exit(EXIT_FAILURE);
497  }
498 
500  //Flip y to make same coordinates as model
501  orientTransform->DeepCopy(img->getTransformMatrix());
502  orientTransform->Invert();
503  transform2->Concatenate(orientTransform);
504 // transform2->Concatenate(transform->GetMatrix());
505  cout << ">> Overlay: Transforming Actors" << endl;
506  }
507 
509  model->setWindowTitle("MILX-Overlay");
510  model->SetSize(windowHeight, windowWidth);
511  mainWindow.resize(windowWidth, windowHeight);
512  //Add models
513  foreach(QSharedPointer<milxQtModel> mdl, models)
514  {
515  model->addModelActor(mdl->GetActor());
516  }
517  //Add image slices
518  if(imageArg.isSet() && !slicesArg.isSet())
519  {
520  if(!noaxialArg.isSet())
521  model->addImageActor(img->GetImageActor(), transform2->GetMatrix());
522  if(!nocoronalArg.isSet())
523  model->addImageActor(imgCoronal->GetImageActor(), transform2->GetMatrix());
524  if(!nosaggitalArg.isSet())
525  model->addImageActor(imgSagittal->GetImageActor(), transform2->GetMatrix());
526 
529  QObject::connect(img.data(), SIGNAL(modified(vtkSmartPointer<vtkImageActor> )), model.data(), SLOT(updateImageActor(vtkSmartPointer<vtkImageActor>)));
530  QObject::connect(imgCoronal.data(), SIGNAL(modified(vtkSmartPointer<vtkImageActor> )), model.data(), SLOT(updateImageActor(vtkSmartPointer<vtkImageActor>)));
531  QObject::connect(imgSagittal.data(), SIGNAL(modified(vtkSmartPointer<vtkImageActor> )), model.data(), SLOT(updateImageActor(vtkSmartPointer<vtkImageActor>)));
532  }
533 
534  //Colour maps
535  cout << ">>> Overlay: Setting Colourmap" << endl;
536  if(jetArg.isSet())
537  model->colourMapToJet();
538  if(vtkArg.isSet())
539  model->colourMapToVTK();
540  if(hsvArg.isSet())
541  model->colourMapToHSV();
542  if(rainbowArg.isSet())
543  model->colourMapToRainbow();
544  if(spectralArg.isSet())
545  model->colourMapToSpectral();
546  if(nihArg.isSet())
547  model->colourMapToNIH();
548  if(fireArg.isSet())
549  model->colourMapToNIH_Fire();
550  if(aalArg.isSet())
551  model->colourMapToAAL();
552  if(fsArg.isSet())
553  model->colourMapToFS();
554  if(hotArg.isSet())
555  model->colourMapToHOT();
556  if(coolArg.isSet())
557  model->colourMapToCOOL();
558  if(minArg.isSet() || maxArg.isSet()) //set the range if another colour map is used
559  model->SetScalarRange(range);
560  if(scalarBarArg.isSet())
561  {
562  if(minArg.isSet() || maxArg.isSet())
563  model->enableScale(barName.c_str(), true, range[0], range[1]);
564  else
565  model->enableScale(barName.c_str(), true);
566  }
567 
568  if(vectorsArg.isSet())
569  model->AddActor(modelVectors->GetActor());
570  if(isoArg.isSet())
571  {
572 // if(onscreenArg.isSet())
573 // modelIso->show();
574  model->AddActor(modelIso->GetActor());
575  }
576  if(whiteArg.isSet())
577  model->background(true);
578  if(outlineArg.isSet())
579  {
580  if(imageArg.isSet())
581  model->enableOutline(img->GetOutput());
582  else
583  model->enableOutline();
584  }
585 
586  //setup background
587  double backgroundColours[3];
588  model->GetBackground(backgroundColours[0], backgroundColours[1], backgroundColours[2]);
589  if(humanArg.isSet())
590  model->disableOrient();
591  if(redArg.isSet())
592  backgroundColours[0] = redValue;
593  if(greenArg.isSet())
594  backgroundColours[1] = greenValue;
595  if(blueArg.isSet())
596  backgroundColours[2] = blueValue;
597  if(redArg.isSet() || blueArg.isSet() || greenArg.isSet())
598  model->SetBackground(backgroundColours[0], backgroundColours[1], backgroundColours[2]);
599 
600  //Apply transform to main model last to ensure sub models are correctly transform also
601  if(wireframeArg.isSet())
602  model->generateWireframe();
603  if(transformArg.isSet())
604  model->SetTransform(transform);
605  if(axialArg.isSet())
606  model->viewToAxial();
607  if(coronalArg.isSet())
608  model->viewToCoronal();
609  if(saggitalArg.isSet())
610  model->viewToSagittal();
611  if(loadViewArg.isSet())
612  model->loadView();
613  if(loadViewFileArg.isSet())
614  model->loadView(loadViewName.c_str());
615  if(specularArg.isSet())
616  model->disableSpecularDisplay();
617  //Zoom
618  if(zoomArg.isSet())
619  {
620  vtkCamera *camera = model->GetRenderer()->GetActiveCamera();
621  camera->Zoom(zoomFactor);
622  }
623 
624  cout << ">> Overlay: Rendering" << endl;
625  if(!onscreenArg.isSet())
626  model->OffScreenRenderingOn();
627  else
628  mainWindow.show();
629 
630  //Update view
631  model->GetRenderWindow()->Render();
632  qApp->processEvents();
633 
635  vtkSmartPointer<vtkWindowToImageFilter> windowToImage = vtkSmartPointer<vtkWindowToImageFilter>::New();
636  windowToImage->SetInput(model->GetRenderWindow());
637  windowToImage->Update();
638 
639  QScopedPointer<milxQtFile> writer(new milxQtFile); //Smart deletion
640  model->GetRenderWindow()->Render();
641  writer->saveImage(screenName.c_str(), windowToImage->GetOutput());
642  cout << ">> Complete" << endl;
643 
644  model->OffScreenRenderingOff(); //Required to prevent double-free
645  if(!onscreenArg.isSet())
646  return EXIT_SUCCESS;
647  else
648  return app.exec();
649 }
This class represents the MILX Qt Image Display object using VTK.
Definition: milxQtImage.h:118
This class represents the MILX Qt File I/O object using VTK/ITK/Qt.
Definition: milxQtFile.h:60
This program Animates image slices and animates surfaces in the model view for creating movies...
static bool OpenModelCollection(std::vector< std::string > filenames, vtkSmartPointer< vtkPolyDataCollection > &collection)
Opens model files, which can be a VTK XML, Legacy VTK PolyData File (i.e. either a *...
Definition: milxFile.cxx:611
static vtkMatrix4x4 * OpenITKTransform(std::string filename)
Opens an ITK transform file and converts it to a VTK transform matrix.
Definition: milxFile.cxx:190
This class represents the MILX Qt Model/Mesh Display object using VTK.
Definition: milxQtModel.h:115
void PrintInfo(const std::string msg)
Displays a generic msg to standard output with carriage return.
Definition: milxGlobal.h:174
std::string NumberToString(double num, unsigned zeroPad=0)
Number to string converter.
Definition: milxGlobal.h:112
int main(int argc, char *argv[])