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