SMILX  1.01
milxQtModel.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 =========================================================================*/
18 #include "milxQtModel.h"
19 
20 //Qt
21 #include <QInputDialog>
22 #include <QColorDialog>
23 //Data
24 #include <vtkMath.h>
25 #include <vtkTable.h>
26 //Mapper
27 #include <vtkGraphicsFactory.h>
28 #include <vtkCamera.h>
29 //Graphing
30 #include <vtkDoubleArray.h>
31 #include <vtkDataSetMapper.h>
32 #include <vtkIdFilter.h>
33 #include <vtkSelectVisiblePoints.h>
34 //Contouring
35 #include <vtkGlyph3D.h>
36 #include <vtkOrientedGlyphContourRepresentation.h>
37 #include <vtkPolygonalSurfacePointPlacer.h>
38 #include <vtkPolygonalSurfaceContourLineInterpolator.h>
39 //Filters
40 #include <vtkTextProperty.h>
41 #include <vtkCoordinate.h> //for scalarbar
42 #include <vtkImageQuantizeRGBToIndex.h>
43 #include <vtkImageToPolyDataFilter.h>
44 #include <vtkImageData.h>
45 #include <vtkImageFlip.h>
46 //#include <vtkStreamLine.h>
47 #include <vtkStreamTracer.h>
48 #include <vtkLogLookupTable.h>
49 //SMILI
50 #include "milxMath.h"
51 #include "milxColourMap.h"
52 
53 #include "milxQtFile.h"
54 
56 milxQtModel::milxQtModel(QWidget *theParent, bool contextSystem) : milxQtRenderWindow(theParent, contextSystem)
57 {
59  modelled = false;
60  resetFlags();
61 
62  colourRed = defaultColour;
63  colourGreen = defaultColour;
64  colourBlue = defaultColour;
65 
67  modelCentroid.fill(0.0);
68  modelCovarianceMatrix.set_size(3, 3);
69  modelCovarianceMatrix.fill(0.0);
70 
72  linkProgressEventOf(milx::VTKProgressUpdates->GetUpdateObject()); //link internal observer
73 
75  milxQtWindow::prefix = "Mdl: ";
76 
79 
80  //View defaults
82  setView(AXIAL);
83  setDefaultOrientation(RADIOLOGICAL);
84 
85  createActions();
87 
88  surfaceAct->setChecked(true);
89 }
90 
92 {
94 }
95 
96 //Sets
97 void milxQtModel::AddInput(vtkSmartPointer<vtkPolyData> mesh)
98 {
99  printInfo("Appending Model data");
100 
101  model.Append(mesh);
102 
103  resetFlags();
104  loaded = true;
105  appended = true;
106 }
107 
108 void milxQtModel::AddArray(vtkSmartPointer<vtkDataArray> array)
109 {
110  model.AddArray(array);
111  resetFlags();
112 
113  loaded = true;
114 }
115 
116 void milxQtModel::SetInput(vtkSmartPointer<vtkPolyData> mesh)
117 {
118  model.SetInput(mesh);
119  resetFlags();
120  loaded = true;
121 }
122 /*
123 void milxQtModel::SetInputPointSet(vtkSmartPointer<vtkPointSet> mesh)
124 {
125  if(!modelled)
126  {
127  modelMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
128  modelActor = vtkSmartPointer<vtkLODActor>::New();
129  }
130 
131  printDebug("Generating Model for Point Set.");
132  if(largeMode)
133  modelMapper->GlobalImmediateModeRenderingOn();
134 #if VTK_MAJOR_VERSION <= 5
135  modelMapper->SetInputConnection(mesh->GetProducerPort());
136 #else
137  modelMapper->SetInputData(mesh);
138 #endif
139  modelMapper->ScalarVisibilityOn();
140  modelMapper->SetScalarModeToUsePointData();
141  modelMapper->SetColorModeToMapScalars();
142  modelMapper->Update();
143 
145  modelActor->SetMapper(modelMapper);
146  modelActor->GetProperty()->SetColor(colourRed, colourGreen, colourBlue);
147  modelActor->GetProperty()->SetSpecularColor(1, 1, 1);
148  modelActor->GetProperty()->SetSpecular(0.25);
149  modelActor->GetProperty()->SetSpecularPower(10);
150  modelActor->GetProperty()->SetAmbient(0.2);
151  modelActor->GetProperty()->SetDiffuse(0.8);
152 
153  modelled = true;
154  loaded = true;
155  milxQtRenderWindow::AddActor(modelActor);
156  milxQtRenderWindow::generateRender();
157 }*/
158 
159 //void milxQtModel::SetNumberOfInputs(const int inputs)
160 //{
161 // if(!appendPolyData)
162 // appendPolyData = vtkSmartPointer<vtkAppendPolyData>::New();
163 // appendPolyData->SetNumberOfInputs(inputs);
164 //}
165 
166 //void milxQtModel::SetInput(const int index, vtkSmartPointer<vtkPolyData> mesh)
167 //{
168 // if(!appendPolyData)
169 // appendPolyData = vtkSmartPointer<vtkAppendPolyData>::New();
170 // if(loaded && !appended)
171 // appendPolyData->AddInput(currentMesh);
172 // appendPolyData->SetInput(index, mesh);
173 // linkProgressEventOf(appendPolyData); //Keeps UI responsive
174 // currentMesh = appendPolyData->GetOutput();
175 // resetFlags();
176 // loaded = true;
177 // appended = true;
178 //}
179 
180 void milxQtModel::SetPoints(vtkSmartPointer<vtkPoints> modelPoints)
181 {
182  model.SetPoints(modelPoints);
183  resetFlags();
184  loaded = true;
185 }
186 
187 void milxQtModel::SetPolys(vtkSmartPointer<vtkCellArray> modelPolys)
188 {
189  model.SetPolys(modelPolys);
190  resetFlags();
191  loaded = true;
192 }
193 
194 void milxQtModel::SetScalars(vtkSmartPointer<vtkDataArray> modelScalars)
195 {
196  model.SetScalars(modelScalars);
197  resetFlags();
198 
199  if(modelScalars)
200  scalarsSet = true;
201  loaded = true;
202 }
203 
205 {
207 }
208 
209 void milxQtModel::SetVectors(vtkSmartPointer<vtkDataArray> modelVectors)
210 {
211  model.SetVectors(modelVectors);
212  resetFlags();
213 
214  if(modelVectors)
215  scalarsSet = true;
216  loaded = true;
217 }
218 
219 void milxQtModel::SetTransform(vtkSmartPointer<vtkTransform> newTransform)
220 {
221  if(loaded)
222  {
223  emit working(-1);
225  model.SetTransform(newTransform);
226 
227  if(normalsModel)
228  normalsModel->SetTransform(newTransform);
229  if(centroidModel)
230  centroidModel->SetTransform(newTransform);
231  if(outlineModel)
232  outlineModel->SetTransform(newTransform);
233  emit done(-1);
234 
235  resetFlags();
236  }
237 }
238 
239 void milxQtModel::SetGraph(vtkSmartPointer<vtkMutableUndirectedGraph> graph)
240 {
241  model.SetGraph(graph);
242 
243  resetFlags();
244  loaded = true;
245 }
246 
247 //Gets
248 vtkSmartPointer<vtkPolyData> milxQtModel::GetPolyDataInput()
249 {
250  return model.PreviousResult();
251 }
252 
253 vtkSmartPointer<vtkPolyData> milxQtModel::GetOutput()
254 {
255  return model.Result();
256 }
257 
258 //Operators
260 {
261  if(this != &operand)
262  {
264  loaded = operand.loaded;
267 
269  modelCentroid = operand.modelCentroid;
271  }
272 
273  return *this;
274 }
275 
277 {
278  if(!modelled)
279  reset();
280  else
281  {
282  model.Update();
283  #if VTK_MAJOR_VERSION <=5
284  modelMapper->SetInput(model.Result());
285  #else
286  modelMapper->SetInputData(model.Result());
287  #endif
289  modelMapper->Update();
291  }
292 }
293 
295 {
296  if(!computedCentroid)
297  {
299  computedCentroid = true;
300  }
301 
302  if(centroidAct->isChecked())
303  {
304  printInfo("Displaying Centroid: (" + QString::number(modelCentroid[0]) + ", " + QString::number(modelCentroid[1]) + ", " + QString::number(modelCentroid[2]) + ")");
305  if(!centroidModel)
306  centroidModel = new milxQtModel;
307 
308  vtkPoints *centroidPoint = vtkPoints::New();
309  centroidPoint->InsertNextPoint(modelCentroid.data_block());
310  centroidModel->SetPoints(centroidPoint);
311  centroidModel->generatePointModel(2.0, 1.0, 0.0, 0.0);
312 
313  milxQtRenderWindow::AddActor(centroidModel->GetActor());
315  }
316  else
317  {
318  if(centroidModel)
319  milxQtRenderWindow::RemoveActor(centroidModel->GetActor());
320  }
321 
322  return modelCentroid;
323 }
324 
325 double milxQtModel::centroidSize(bool average)
326 {
327  coordinate currentCentroid = centroid();
328  return milx::Math<coordinateType>::CentroidSize(model.Result()->GetPoints(), currentCentroid, average);
329 }
330 
331 vnl_matrix<double>& milxQtModel::covarianceMatrix()
332 {
333  if(!computedCovariance)
334  {
335  coordinate currentCentroid = centroid();
337  computedCovariance = true;
338  }
339 
340  return modelCovarianceMatrix;
341 }
342 
343 void milxQtModel::generateDelaunayGraph(float red, float green, float blue)
344 {
345  if(loaded)
346  {
347  emit working(-1);
349  emit done(-1);
350 
352  generateModel(red, green, blue);
353  }
354 }
355 
357 {
358  if(loaded)
359  {
360  emit working(-1);
362 
363  vtkSmartPointer<vtkPolyDataMapper> delaunayMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
364  #if VTK_MAJOR_VERSION <=5
365  delaunayMapper->SetInput(model.Result());
366  #else
367  delaunayMapper->SetInputData(model.Result());
368  #endif
369 
370  if(!delaunayActor)
371  delaunayActor = vtkSmartPointer<vtkLODActor>::New();
372  delaunayActor->SetMapper(delaunayMapper);
373 
376  emit done(-1);
377  }
378 }
379 
380 void milxQtModel::generateDelaunayTriangulation(float red, float green, float blue)
381 {
382  if(loaded)
383  {
384  if(!genDelaunayTriAct->isChecked())
386  else
387  {
388  emit working(-1);
391 
392  vtkSmartPointer<vtkDataSetMapper> delaunayMapper = vtkSmartPointer<vtkDataSetMapper>::New();
393  #if VTK_MAJOR_VERSION <=5
394  delaunayMapper->SetInput(model.Result());
395  #else
396  delaunayMapper->SetInputData(model.Result());
397  #endif
398 
399  if(!delaunayActor)
400  delaunayActor = vtkSmartPointer<vtkLODActor>::New();
401  delaunayActor->SetMapper(delaunayMapper);
402  // delaunayActor->GetProperty()->SetColor(1,0,0);
403 
406  emit done(-1);
407  }
408  }
409 }
410 
411 void milxQtModel::generateWireframe(float red, float green, float blue)
412 {
413  if(!loaded)
414  return;
415  if(!modelled)
416  generateModel(red, green, blue);
417 
418  modelActor->GetProperty()->SetRepresentationToWireframe();
419 
420  wireframeAct->setChecked(true);
421 }
422 
423 void milxQtModel::generateVertices(float red, float green, float blue)
424 {
425  if(loaded)
426  {
427  emit working(-1);
429  emit done(-1);
430 
432  generateModel(red, green, blue);
433  }
434 }
435 
436 void milxQtModel::generateVerticesAs(const GlyphType glyphType, float red, float green, float blue)
437 {
438  if(loaded)
439  {
440  emit working(-1);
442  emit done(-1);
443 
445  generateModel(red, green, blue);
446  }
447 }
448 
449 void milxQtModel::generateTubes(float red, float green, float blue)
450 {
451  if(loaded)
452  {
453  emit working(-1);
455  emit done(-1);
456 
458  generateModel(red, green, blue);
459  }
460 }
461 
462 void milxQtModel::generatePoints(float red, float green, float blue)
463 {
464  if(!loaded)
465  return;
466  if(!modelled)
467  generateModel(red, green, blue);
468 
469  modelActor->GetProperty()->SetRepresentationToPoints();
470 
471  pointsAct->setChecked(true);
472 }
473 
474 void milxQtModel::generatePointModel(double newScale, float red, float green, float blue)
475 {
476  if(loaded)
477  {
478  emit working(-1);
479  double bounds[6];
480  model.Result()->GetBounds(bounds);
481  double scaling = ( (bounds[1]-bounds[0]) + (bounds[3]-bounds[2]) + (bounds[5]-bounds[4]) )/150;
482 
483  if(newScale == 1) //default scaling, so do automatically
484  scaling *= newScale;
485  else
486  scaling = newScale;
487 
488  model.GeneratePointModel(scaling);
489  emit done(-1);
490 
492  generateModel(red, green, blue);
493  }
494 }
495 
496 void milxQtModel::generateSampledPoints(float distance, float red, float green, float blue)
497 {
498  if(loaded)
499  {
500  bool ok = false;
501 
502  if(distance <= 0)
503  {
504  distance = QInputDialog::getDouble(this, tr("Please Provide the sample distance"),
505  tr("Distance:"), 0.1, 0.0, 2147483647, 7, &ok);
506  }
507  else
508  ok = true;
509 
510  if(!ok)
511  return;
512 
513  emit working(-1);
514  model.GenerateSampledPoints(distance);
515  emit done(-1);
516 
518  generateModel(red, green, blue);
519  }
520 }
521 
522 void milxQtModel::generateVectorField(double newScale, float red, float green, float blue)
523 {
524  if(loaded)
525  {
526  emit working(-1);
527  bool useNormals = false;
528  vtkSmartPointer<vtkFloatArray> vectorArray;
529  if(!GetVectors()) //use scalars instead
530  {
531  printInfo("No Vectors found.");
532  if(!GetNormals())
533  {
534  printInfo("Generating Vector Field from Scalars (with normals).");
536  }
537 
539  vectorArray = vtkFloatArray::SafeDownCast(model.GetNormals());
540  useNormals = true;
541  }
542  else
543  {
544  printInfo("Generating Vector Field from Vectors.");
545  vectorArray = vtkFloatArray::SafeDownCast(model.GetVectors());
546  }
547 
548  if(newScale == 0.0 && vectorArray) //auto rescale
549  {
550  coordinate meanDirection(0.0); //used to set scale
551  for(vtkIdType j = 0; j < model.GetNumberOfPoints(); j ++)
552  {
553  coordinate vectorData(vectorArray->GetTuple3(j));
554 
555  meanDirection += vectorData;
556  }
557  meanDirection /= model.GetNumberOfPoints();
558  printDebug("Mean Vector: " + QString::number(meanDirection[0]) + ", " + QString::number(meanDirection[1]) + ", " + QString::number(meanDirection[2]) + ", ");
559  printDebug("Mean Vector L2 Norm: " + QString::number(meanDirection.two_norm()));
560 
561  bool ok1 = false;
562  double newScaling = 1.0/meanDirection.two_norm();
563  newScaling = QInputDialog::getDouble(this, tr("Please enter scaling for the vector field"),
564  tr("Scaling:"), newScaling, -2147483647, 2147483647, 7, &ok1);
565 
566  if(!ok1)
567  newScale = 0.0;
568  else
569  newScale = newScaling;
570  printInfo("Vectors will be scaled by " + QString::number(newScale) + " for display.");
571  }
572 
574  model.GenerateVectorField(newScale, useNormals);
575  emit done(-1);
577  generateModel(red, green, blue);
578  }
579 }
580 
581 void milxQtModel::generateTensorField(double newScale, float red, float green, float blue)
582 {
583  if(!loaded)
584  return;
585 
586  if(!GetTensors())
587  {
588  printError("No tensors found in polydata. Exiting.");
589  return;
590  }
591 
592  emit working(-1);
593  if(newScale == 0.0) //auto rescale
594  {
595  vnl_matrix<double> meanDirection(3, 3, 0.0); //used to set scale
596  for(vtkIdType j = 0; j < model.GetNumberOfPoints(); j ++)
597  {
598  vnl_matrix<double> vectorData(GetTensors()->GetTuple9(j), 3 ,3);
599 
600  meanDirection += vectorData;
601  }
602  meanDirection /= model.GetNumberOfPoints();
603  printDebug("Mean Vector L2 Norm: " + QString::number(meanDirection.frobenius_norm()));
604 
605  bool ok1 = false;
606  double newScaling = 1.0/meanDirection.frobenius_norm();
607  newScaling = QInputDialog::getDouble(this, tr("Please enter scaling for the vector field"),
608  tr("Scaling:"), newScaling, -2147483647, 2147483647, 7, &ok1);
609 
610  if(!ok1)
611  newScale = 0.0;
612  else
613  newScale = newScaling;
614  printInfo("Vectors will be scaled by " + QString::number(newScale) + " for display.");
615  }
616 
617  printInfo("Generating Tensor Field.");
618  model.GenerateTensorField(newScale);
619  emit done(-1);
620 
622  generateModel(red, green, blue);
623 }
624 
625 void milxQtModel::generateStreamLines(vtkSmartPointer<vtkImageData> vectorFieldData, float timestep)
626 {
627  if(!loaded)
628  return;
629 
630  if(!GetPoints())
631  {
632  printError("No points found in polydata. Exiting.");
633  return;
634  }
635 
636  bool ok = false;
637  if(timestep == 0.0)
638  {
639  timestep = QInputDialog::getDouble(this, tr("Please Provide the timestep"),
640  tr("Timestep:"), 0.1, 0.0, 100.0, 5, &ok);
641  }
642 
643  if(!ok)
644  return;
645 
646  emit working(-1);
647 
648  double bounds[6];
649  vectorFieldData->GetBounds(bounds);
650 
651  const double maxProp = bounds[1]-bounds[0];
652  const double maxSteps = maxProp/timestep;
653 
656  printInfo("Generating Streamlines.");
657  // Streamline itself
658  vtkSmartPointer<vtkStreamTracer> streamLines = vtkSmartPointer<vtkStreamTracer>::New();
659  #if VTK_MAJOR_VERSION <= 5
660  streamLines->SetInput(vectorFieldData);
661  streamLines->SetSource(model.Result());
662  #else
663  streamLines->SetInputData(vectorFieldData);
664  streamLines->SetSourceData(model.Result());
665  #endif
666 // streamLines->SetMaximumPropagationTime(200);
667  streamLines->SetMaximumPropagation(maxProp);
668  streamLines->SetMaximumNumberOfSteps(maxSteps);
669  streamLines->SetInitialIntegrationStep(timestep);
670 // streamLines->SetIntegrationDirectionToForward();
671  streamLines->SetIntegrationDirectionToBoth();
672  streamLines->SetIntegratorTypeToRungeKutta4();
673 // streamLines->SetInterpolatorTypeToDataSetPointLocator();
674 // streamLines->SetInterpolatorTypeToCellLocator();
675 // streamLines->SetIntegrationStepUnit(1); //LENGTH_UNIT
676 // streamLines->VorticityOn();
677  linkProgressEventOf(streamLines);
678  streamLines->Update();
679  emit done(-1);
680 
681  model.SetInput(streamLines->GetOutput());
682 
684  generateModel();
685 }
686 
687 void milxQtModel::generateHedgehog(double newScale, float red, float green, float blue)
688 {
689  if(loaded)
690  {
691  emit working(-1);
692  printInfo("Generated Hedgehog.");
693  model.GenerateHedgehog(newScale);
694  emit done(-1);
695 
697  generateModel(red, green, blue);
698  }
699 }
700 
701 void milxQtModel::generateSurface(float red, float green, float blue)
702 {
703  if(!loaded)
704  return;
705  if(!modelled)
706  generateModel(red, green, blue);
707 
708  modelActor->GetProperty()->SetRepresentationToSurface();
709 
710  surfaceAct->setChecked(true);
711 }
712 
713 void milxQtModel::generateNormals(int pointNormals)
714 {
715  if(!loaded)
716  return;
717 
718  emit working(-1);
719  printInfo("Generating Normals for the model");
720  model.GenerateNormals(pointNormals);
721  emit done(-1);
722 }
723 
724 void milxQtModel::generateModel(float red, float green, float blue)
725 {
726  if(loaded)
727  {
728  if(!modelled)
729  {
730  modelMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
731  modelActor = vtkSmartPointer<vtkLODActor>::New();
732  }
733 
734  if(model.Result()->GetPointData()->GetScalars())
735  scalarsSet = true;
736 
737  printDebug("Generating Model.");
738  if(largeMode)
739  modelMapper->GlobalImmediateModeRenderingOn();
740  #if VTK_MAJOR_VERSION <=5
741  modelMapper->SetInput(model.Result());
742  #else
743  modelMapper->SetInputData(model.Result());
744  #endif // VTK_MAJOR_VERSION
745  modelMapper->ScalarVisibilityOn();
746  modelMapper->SetScalarModeToUsePointData();
747 // modelMapper->SetColorModeToMapScalars(); //force colour unsigned char scalars with this option
748  modelMapper->SetColorModeToDefault();
749  if(scalarsSet && !customScalarBar)
750  {
751  vtkSmartPointer<vtkLookupTable> tmpLookupTable = vtkLookupTable::SafeDownCast(lookupTable);
752 
753  tmpLookupTable->SetTableRange(model.Result()->GetScalarRange());
754  tmpLookupTable->Build();
755 
757  }
758  modelMapper->Update();
759 
760  colourRed = red;
761  colourGreen = green;
762  colourBlue = blue;
763 
765  modelActor->SetMapper(modelMapper);
766  modelActor->GetProperty()->SetColor(colourRed, colourGreen, colourBlue);
767  enableSpecularDisplay(true);
768 
769  modelled = true; //dont move down, ordering necessary
771  if(!rendered)
772  {
776  }
778  }
779 }
780 
782 {
783  if(loaded)
784  {
785  emit working(-1);
786  if(!labelled)
787  modelLabelsActor = vtkSmartPointer<vtkActor2D>::New();
788 
789  vtkSmartPointer<vtkIdFilter> ids = vtkSmartPointer<vtkIdFilter>::New();
790  #if VTK_MAJOR_VERSION <=5
791  ids->SetInput(model.Result());
792  #else
793  ids->SetInputData(model.Result());
794  #endif // VTK_MAJOR_VERSION
795  ids->PointIdsOn();
796 
797  vtkSmartPointer<vtkSelectVisiblePoints> visPts = vtkSmartPointer<vtkSelectVisiblePoints>::New();
798  visPts->SetInputConnection( ids->GetOutputPort() );
799  visPts->SetRenderer( renderer );
800 
801  vtkSmartPointer<vtkLabeledDataMapper> labeller = vtkSmartPointer<vtkLabeledDataMapper>::New();
802  labeller->SetInputConnection( visPts->GetOutputPort() );
803  linkProgressEventOf(labeller);
804  labeller->SetLabelModeToLabelFieldData();
805 
806  modelLabelsActor->SetMapper( labeller );
807  emit done(-1);
808  labelled = true;
809 
812  }
813 }
814 
816 {
817  if(loaded)
818  {
819  emit working(-1);
821  emit done(-1);
822 
824  generateModel();
825  }
826 }
827 
828 void milxQtModel::generateIsoSurface(vtkSmartPointer<vtkImageData> img, int contourNumber, double value)
829 {
830  bool ok1 = false, ok2 = false;
831 
832  if(contourNumber < 0)
833  {
834 // contourNumber = QInputDialog::getInteger(this, tr("Please enter minimum iso surface value"),
835 // tr("Contour Number:"), 0, -2147483647, 2147483647, 1, &ok1);
836  contourNumber = 0;
837  ok1 = true;
838  value = QInputDialog::getDouble(this, tr("Please enter label/iso surface value"),
839  tr("Value:"), 0.5, -2147483647, 2147483647, 7, &ok2);
840  }
841  else
842  ok1 = ok2 = true;
843 
844  if(ok1 && ok2)
845  {
846  emit working(-1);
847  vtkSmartPointer<vtkImageFlip> imageReorient = vtkSmartPointer<vtkImageFlip>::New();
848  #if VTK_MAJOR_VERSION <=5
849  imageReorient->SetInput(img);
850  #else
851  imageReorient->SetInputData(img);
852  #endif // VTK_MAJOR_VERSION
853  imageReorient->SetFilteredAxis(1);
854  imageReorient->FlipAboutOriginOn();
855  linkProgressEventOf(imageReorient);
856  imageReorient->Update(); //ITK image would have been flipped
857 
858  model.IsoSurface(imageReorient->GetOutput(), value);
859  setName("Iso Surface");
860  loaded = true;
861  emit done(-1);
862 
863  refresh();
864  }
865  else
866  loaded = false;
867 }
868 
869 void milxQtModel::generatePolyDataFromImage(vtkSmartPointer<vtkImageData> img)
870 {
871  emit working(-1);
872  vtkSmartPointer<vtkImageFlip> imageReorient = vtkSmartPointer<vtkImageFlip>::New();
873  #if VTK_MAJOR_VERSION <=5
874  imageReorient->SetInput(img);
875  #else
876  imageReorient->SetInputData(img);
877  #endif
878  imageReorient->SetFilteredAxis(1);
879  imageReorient->FlipAboutOriginOn();
880  imageReorient->Update(); //ITK image would have been flipped
881 
882 // vtkSmartPointer<vtkImageQuantizeRGBToIndex> quant = vtkSmartPointer<vtkImageQuantizeRGBToIndex>::New();
883 // quant->SetInput(img);
884 // quant->SetNumberOfColors(16);
885 
886  vtkSmartPointer<vtkImageToPolyDataFilter> imgToModel = vtkSmartPointer<vtkImageToPolyDataFilter>::New();
887 // imgToModel->SetInputConnection(quant->GetOutputPort());
888 #if VTK_MAJOR_VERSION <=5
889  imgToModel->SetInput(imageReorient->GetOutput());
890 #else
891  imgToModel->SetInputData(imageReorient->GetOutput());
892 #endif // VTK_MAJOR_VERSION
893 // imgToModel->SetLookupTable(quant->GetLookupTable());
894 // imgToModel->SetColorModeToLUT();
895  imgToModel->SetOutputStyleToPolygonalize();
896 // imgToModel->SetError(0);
897  imgToModel->DecimationOn();
898 // imgToModel->SetDecimationError(0.0);
899 // imgToModel->SetSubImageSize(25);
900  linkProgressEventOf(imgToModel); //Keeps UI responsive
901  imgToModel->Update();
902 
903  model.SetInput(imgToModel->GetOutput());
904  loaded = true;
905 
906  triangulate();
907  emit done(-1);
908 
909  refresh();
910 }
911 
912 void milxQtModel::generateKMeansClustering(int numberOfClusters)
913 {
914  if(loaded)
915  {
916  bool ok = false;
917 
918  if(numberOfClusters <= 0)
919  {
920  numberOfClusters = QInputDialog::getInt(this, tr("Please Provide the number of clusters to use"),
921  tr("Clusters:"), 2, 0, 2147483647, 1, &ok);
922  }
923  else
924  ok = true;
925 
926  if(!ok)
927  return;
928 
929  emit working(-1);
930  model.GenerateKMeansClustering(numberOfClusters);
931  emit done(-1);
932 
933  refresh();
934  }
935 }
936 
937 void milxQtModel::generateQuantisedPoints(float quantiseFactor)
938 {
939  if(loaded)
940  {
941  bool ok = false;
942 
943  if(quantiseFactor <= 0)
944  {
945  quantiseFactor = QInputDialog::getDouble(this, tr("Please Provide the Quantise Factor"),
946  tr("Factor:"), 0.25, 0.0, 2147483647, 5, &ok);
947  }
948  else
949  ok = true;
950 
951  if(!ok)
952  return;
953 
954  emit working(-1);
955  model.GenerateQuantisedPoints(quantiseFactor);
956  emit done(-1);
957 
958  refresh();
959  }
960 }
961 
963 {
964  if(loaded)
965  {
966  emit working(-1);
968  emit done(-1);
969 
970  refresh();
971  }
972 }
973 
975 {
976  if(loaded)
977  {
978  emit working(-1);
980  emit done(-1);
981 
982  refresh();
983  }
984 }
985 
987 {
988  if(loaded)
989  {
990  emit working(-1);
992  emit done(-1);
993 
994  refresh();
995  }
996 }
997 
998 //~ void milxQtModel::generateReebGraphs()
999 //~ {
1000  //~ if(loaded)
1001  //~ {
1002  //~ emit working(-1);
1003  //~ model.GenerateReebGraph();
1004  //~ emit done(-1);
1005 
1006  //~ refresh();
1007  //~ }
1008 //~ }
1009 
1011 {
1012  if(!loaded || !model.PreviousResult())
1013  return;
1014 
1015  //Switch current and previous mesh pointers
1016  milx::Swap< vtkSmartPointer<vtkPolyData> >(model.Result(), model.PreviousResult());
1017 
1018  if(!undidProcess)
1019  {
1020  doAct->setText(QApplication::translate("Model", "&Redo Last Processing", 0, QApplication::UnicodeUTF8));
1021  undidProcess = true;
1022  }
1023  else
1024  {
1025  doAct->setText(QApplication::translate("Model", "&Undo Last Processing", 0, QApplication::UnicodeUTF8));
1026  undidProcess = false;
1027  }
1028 
1029  refresh();
1030  modelInfo();
1031 }
1032 
1034 {
1035  if(!loaded)
1036  return;
1037 
1038  emit working(-1);
1039  model.Clean();
1040  refresh();
1041  emit done(-1);
1042 }
1043 
1045 {
1046  if(!loaded)
1047  return;
1048 
1049  emit working(-1);
1050  model.Triangulate();
1051  refresh();
1052  emit done(-1);
1053 }
1054 
1055 void milxQtModel::decimate(double factor)
1056 {
1057  if(!loaded)
1058  return;
1059 
1060  bool ok = false;
1061 
1062  if(factor == 0.0)
1063  {
1064  factor = QInputDialog::getDouble(this, tr("Please Provide the reduction factor"),
1065  tr("Factor:"), 0.5, 0.0, 1.0, 3, &ok);
1066  }
1067  else
1068  ok = true;
1069 
1070  if( factor > 0.0 && ok )
1071  {
1072  emit working(-1);
1073  printInfo("There were " + QString::number(model.Result()->GetNumberOfPoints()) + " points.");
1074  printInfo("There were " + QString::number(model.Result()->GetNumberOfPolys()) + " polygons.");
1075  printInfo("--- Decimating with using DecimatePro");
1076 
1077  triangulate();
1078  model.Decimate(factor);
1079 
1080  printInfo("There are " + QString::number(model.Result()->GetNumberOfPoints()) + " points.");
1081  printInfo("There are " + QString::number(model.Result()->GetNumberOfPolys()) + " polygons.");
1082 
1083  refresh();
1084  emit done(-1);
1085  }
1086 }
1087 
1088 void milxQtModel::quadricDecimate(double factor)
1089 {
1090  if(!loaded)
1091  return;
1092 
1093  bool ok = false;
1094 
1095  if(factor == 0.0)
1096  {
1097  factor = QInputDialog::getDouble(this, tr("Please Provide the target reduction factor"),
1098  tr("Target Factor:"), 0.5, 0.0, 1.0, 3, &ok);
1099  }
1100  else
1101  ok = true;
1102 
1103  if( factor > 0.0 && ok )
1104  {
1105  emit working(-1);
1106  printInfo("There were " + QString::number(model.Result()->GetNumberOfPoints()) + " points.");
1107  printInfo("There were " + QString::number(model.Result()->GetNumberOfPolys()) + " polygons.");
1108  printInfo("--- Decimating with using Quadric Decimation");
1109 
1110  model.Triangulate();
1111  model.QuadricDecimate(factor);
1112 
1113  printInfo("There are " + QString::number(model.Result()->GetNumberOfPoints()) + " points.");
1114  printInfo("There are " + QString::number(model.Result()->GetNumberOfPolys()) + " polygons.");
1115 
1116  refresh();
1117  emit done(-1);
1118  }
1119 }
1120 
1122 {
1123  if(!loaded)
1124  return;
1125 
1126  emit working(-1);
1127  printInfo("There were " + QString::number(model.Result()->GetNumberOfPoints()) + " points.");
1128  printInfo("There were " + QString::number(model.Result()->GetNumberOfPolys()) + " polygons.");
1129  printInfo("--- Decimating with using Quadric Clustering Decimation");
1130 
1131  triangulate();
1133 
1134  printInfo("There are " + QString::number(model.Result()->GetNumberOfPoints()) + " points.");
1135  printInfo("There are " + QString::number(model.Result()->GetNumberOfPolys()) + " polygons.");
1136 
1137  refresh();
1138  emit done(-1);
1139 }
1140 
1141 void milxQtModel::renameScalars(QString newName)
1142 {
1143  if(!loaded)
1144  return;
1145 
1146  if(newName.isEmpty())
1147  {
1148  QSettings settings("Shekhar Chandra", "milxQt");
1149  QString path = settings.value("recentPath").toString();
1150  newName = QInputDialog::getText(this, tr("New Name for Scalars"),
1151  tr("New name:"), QLineEdit::Normal,
1152  "Scalars");
1153  }
1154 
1155  if(newName.isEmpty())
1156  return;
1157 
1158  model.Result()->GetPointData()->GetScalars()->SetName(newName.toStdString().c_str());
1160  if(scaleBefore)
1161  scale->SetTitle(newName.toStdString().c_str());
1162 
1163  refresh();
1164 }
1165 
1166 void milxQtModel::threshold(double lowValue, double upValue)
1167 {
1168  if(!loaded)
1169  return;
1170 
1171  bool ok = false;
1172 
1173  if(upValue == 0.0 && lowValue == 0.0)
1174  {
1175  double range[2];
1176  model.Result()->GetScalarRange(range);
1177 
1178  lowValue = QInputDialog::getDouble(this, tr("Lower level of band to keep"),
1179  tr("Lower Value (inclusive):"), range[0], -2147483647, 2147483647, 12, &ok);
1180  upValue = QInputDialog::getDouble(this, tr("Upper level of band to keep (inclusive)"),
1181  tr("Upper Value (inclusive):"), range[1], -2147483647, 2147483647, 12, &ok);
1182  }
1183  else
1184  ok = true;
1185 
1186  if(ok)
1187  {
1188  emit working(-1);
1190  printInfo("Thresholding Scalars and clipping mesh");
1191  model.Clip(lowValue, upValue);
1192 
1193  reset();
1194  emit done(-1);
1195  }
1196 }
1197 
1198 void milxQtModel::thresholdScalars(double lowValue, double upValue, double outsideVal)
1199 {
1200  if(!loaded)
1201  return;
1202 
1203  bool ok = false;
1204 
1205  if(upValue == 0.0 && lowValue == 0.0 && outsideVal == 0.0)
1206  {
1207  double range[2];
1208  model.Result()->GetScalarRange(range);
1209 
1210  lowValue = QInputDialog::getDouble(this, tr("Lower level of band to keep"),
1211  tr("Lower Value (inclusive):"), range[0], -2147483647, 2147483647, 12, &ok);
1212  upValue = QInputDialog::getDouble(this, tr("Upper level of band to keep (inclusive)"),
1213  tr("Upper Value (inclusive):"), range[1], -2147483647, 2147483647, 12, &ok);
1214  outsideVal = QInputDialog::getDouble(this, tr("Value to give scalars outside the range"),
1215  tr("Outside Value:"), 0.0, -2147483647, 2147483647, 12, &ok);
1216  }
1217  else
1218  ok = true;
1219 
1220  if(ok)
1221  {
1222  emit working(-1);
1223  printInfo("Thresholding Scalars");
1224  model.Threshold(lowValue, upValue, outsideVal);
1225  reset();
1226  emit done(-1);
1227  }
1228 }
1229 
1230 void milxQtModel::thresholdScalarsBinary(double lowValue, double upValue, double insideVal, double outsideVal)
1231 {
1232  if(!loaded)
1233  return;
1234 
1235  bool ok = false;
1236 
1237  if(upValue == 0.0 && lowValue == 0.0)
1238  {
1239  double range[2];
1240  model.Result()->GetScalarRange(range);
1241 
1242  lowValue = QInputDialog::getDouble(this, tr("Lower level of band to keep"),
1243  tr("Lower Value (inclusive):"), range[0], -2147483647, 2147483647, 12, &ok);
1244  upValue = QInputDialog::getDouble(this, tr("Upper level of band to keep"),
1245  tr("Upper Value (inclusive):"), range[1], -2147483647, 2147483647, 12, &ok);
1246  insideVal = QInputDialog::getDouble(this, tr("Value to give scalars inside the range"),
1247  tr("Inside Value:"), 1.0, -2147483647, 2147483647, 12, &ok);
1248  outsideVal = QInputDialog::getDouble(this, tr("Value to give scalars outside the range"),
1249  tr("Outside Value:"), 0.0, -2147483647, 2147483647, 12, &ok);
1250  }
1251  else
1252  ok = true;
1253 
1254  if(ok)
1255  {
1256  emit working(-1);
1257  printInfo("Binary Thresholding Scalars");
1258  model.Threshold(lowValue, upValue, insideVal, outsideVal);
1259  reset();
1260  emit done(-1);
1261  }
1262 }
1263 
1264 void milxQtModel::maskScalars(QString filename)
1265 {
1266  if(!loaded)
1267  return;
1268 
1269  if(filename.isEmpty())
1270  {
1271  QSettings settings("Shekhar Chandra", "milxQt");
1272  QString path = settings.value("recentPath").toString();
1273  QFileDialog *fileOpener = new QFileDialog(this);
1274  filename = fileOpener->getOpenFileName(this,
1275  tr("Select File to Open"),
1276  path,
1277  tr(openModelExts.c_str()) );
1278  }
1279 
1280  if(filename.isEmpty())
1281  return;
1282 
1283  QPointer<milxQtModel> otherModel = new milxQtModel;
1284  QPointer<milxQtFile> reader = new milxQtFile;
1285  bool success = reader->openModel(filename, otherModel);
1286 
1287  printInfo("Matching model information: ");
1288  otherModel->modelInfo();
1289 
1290  if(!success)
1291  return;
1292 
1293  emit working(-1);
1294  printInfo("Masking Scalars");
1295  model.Mask(otherModel->GetOutput());
1296  reset();
1297  emit done(-1);
1298 
1299  refresh();
1300 }
1301 
1303 {
1304  if(!loaded || !GetScalars())
1305  return;
1306 
1307  emit working(-1);
1308  printInfo("Computing Gradient of Scalar Field");
1309  model.Gradient();
1310 // model.Result()->GetPointData()->SetActiveVectors("Gradient");
1311 // generateVectorField();
1312  refresh();
1313  emit done(-1);
1314 }
1315 
1316 void milxQtModel::smooth(int iterations)
1317 {
1318  if(!loaded)
1319  return;
1320 
1321  bool ok = false;
1322 
1323  if(iterations == 0)
1324  {
1325  iterations = QInputDialog::getInt(this, tr("Please Provide the number of Iterations"),
1326  tr("Iterations:"), 50, 0, 10000, 1, &ok);
1327  }
1328  else
1329  ok = true;
1330 
1331  if(ok && iterations > 0)
1332  {
1333  emit working(-1);
1334  model.LaplacianSmoothing(iterations);
1335 
1336  printInfo("Smoothed for " + QString::number(iterations) + " iterations.");
1337  refresh();
1338  emit done(-1);
1339  }
1340 }
1341 
1342 void milxQtModel::smoothSinc(int iterations)
1343 {
1344  if(!loaded)
1345  return;
1346 
1347  bool ok = false;
1348 
1349  if(iterations == 0)
1350  {
1351  iterations = QInputDialog::getInt(this, tr("Please Provide the number of Iterations"),
1352  tr("Iterations:"), 15, 0, 10000, 1, &ok);
1353  }
1354  else
1355  ok = true;
1356 
1357  if(ok && iterations > 0)
1358  {
1359  emit working(-1);
1360  model.WindowedSincSmoothing(iterations);
1361  printInfo("Smoothed for " + QString::number(iterations) + " iterations with a pass band of 0.1");
1362  refresh();
1363  emit done(-1);
1364  }
1365 }
1366 
1368 {
1369  if(!loaded)
1370  return;
1371 
1372  emit working(-1);
1373  model.Curvature();
1374  scalarsSet = true;
1375 
1376  printInfo("Mean Curvature marked as scalars on mesh");
1377 
1378  refresh();
1379  emit done(-1);
1380 }
1381 
1382 void milxQtModel::transform(QString filename, bool inverse)
1383 {
1384  if(!loaded)
1385  return;
1386 
1387  if(filename.isEmpty())
1388  {
1389  QSettings settings("Shekhar Chandra", "milxQt");
1390  QString path = settings.value("recentPath").toString();
1391  QFileDialog *fileOpener = new QFileDialog(this);
1392  filename = fileOpener->getOpenFileName(this,
1393  tr("Select File to Open"),
1394  path,
1395  tr("ITK Transform Files (*.txt *.tfm);;VTK Transform Files (*.trsf)") );
1396 
1397  QMessageBox msgBox;
1398  msgBox.setText("Invert Transform");
1399  msgBox.setInformativeText("Do you want to invert the transform?");
1400  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1401  msgBox.setDefaultButton(QMessageBox::Yes);
1402  int ret = msgBox.exec();
1403 
1404  if(ret == QMessageBox::Yes)
1405  inverse = true;
1406  }
1407 
1408  if(filename.isEmpty())
1409  return;
1410 
1411  vtkSmartPointer<vtkTransform> transformer = vtkSmartPointer<vtkTransform>::New();
1412  vtkMatrix4x4* matrix;
1413 
1414  if(filename.contains(".trsf", Qt::CaseInsensitive))
1415  matrix = milx::File::OpenVTKTransform(filename.toStdString());
1416  else
1417  matrix = milx::File::OpenITKTransform(filename.toStdString());
1418 
1419  transformer->SetMatrix(matrix);
1420 
1421  if(inverse)
1422  transformer->Inverse();
1423 
1424  SetTransform(transformer);
1425 
1426  refresh();
1427 }
1428 
1430 {
1431  if(!loaded)
1432  return;
1433 
1434  printInfo("Removing all arrays");
1435  model.RemoveScalars();
1436 
1437  refresh();
1438 }
1439 
1440 void milxQtModel::loadScalars(QString filename)
1441 {
1442  if(!loaded)
1443  return;
1444 
1445  bool fileProvided = false;
1446  int ret = QMessageBox::No;
1447  if(filename.isEmpty())
1448  {
1449  QSettings settings("Shekhar Chandra", "milxQt");
1450  QString path = settings.value("recentPath").toString();
1451  QFileDialog *fileOpener = new QFileDialog(this);
1452  filename = fileOpener->getOpenFileName(this,
1453  tr("Select File to Open"),
1454  path,
1455  tr(openModelExts.c_str()) );
1456  QMessageBox msgBox;
1457  msgBox.setText("Append Scalars into Model");
1458  msgBox.setInformativeText("Do you want to add scalars into model?");
1459  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1460  msgBox.setDefaultButton(QMessageBox::Yes);
1461  ret = msgBox.exec();
1462  }
1463  else
1464  fileProvided = true;
1465 
1466  if(filename.isEmpty())
1467  return;
1468 
1469  QPointer<milxQtModel> otherModel = new milxQtModel;
1470  QPointer<milxQtFile> reader = new milxQtFile;
1471  bool success = reader->openModel(filename, otherModel);
1472 
1473  if(!success)
1474  {
1475  printError("Failed reading model. Stopping.");
1476  return;
1477  }
1478 
1479  if(GetNumberOfPoints() != otherModel->GetNumberOfPoints())
1480  {
1481  printError("Models must have the same number of points! Stopping.");
1482  return;
1483  }
1484 
1485  if(!otherModel->GetScalars())
1486  {
1487  printError("Model " + filename + " does not have scalars");
1488  return;
1489  }
1490 
1491  //Check if multiple arrays present, if so ask if name wasnt provided initally
1492  int index = 0;
1493  if(otherModel->GetNumberOfArrays() > 1 && !fileProvided)
1494  {
1495  QDialog *arrayPossibilities = new QDialog(this);
1496  QComboBox *integerValues = new QComboBox(this);
1497  QPushButton *okButton = new QPushButton(this);
1498  okButton->setText("Ok");
1499  QLabel *lblMessage = new QLabel(this);
1500  lblMessage->setText("Choose Scalars from possibilities.");
1501  QFormLayout *formLayout = new QFormLayout(this);
1502  formLayout->addRow(lblMessage);
1503  formLayout->addRow(tr("&Select Scalars: "), integerValues);
1504  formLayout->addRow(okButton);
1505  arrayPossibilities->setLayout(formLayout);
1506 
1507  connect(okButton, SIGNAL(clicked(bool)), arrayPossibilities, SLOT(accept()));
1508 
1509  //Fill combox box
1510  for(int j = 0; j < otherModel->GetOutput()->GetPointData()->GetNumberOfArrays(); j ++)
1511  integerValues->addItem(otherModel->GetOutput()->GetPointData()->GetArray(j)->GetName());
1512 
1513  arrayPossibilities->exec();
1514 
1515  index = integerValues->currentIndex();
1516  }
1517  else if(otherModel->GetNumberOfArrays() > 1 && fileProvided) //copy all arrays
1518  {
1519  RemoveScalars();
1520 
1521  for(int j = 0; j < otherModel->GetOutput()->GetPointData()->GetNumberOfArrays(); j ++)
1522  AddArray(otherModel->GetOutput()->GetPointData()->GetArray(j));
1523  }
1524 
1525  if(ret == QMessageBox::Yes)
1526  {
1527  AddArray(otherModel->GetOutput()->GetPointData()->GetArray(index));
1528  SetActiveScalars(otherModel->GetOutput()->GetPointData()->GetArray(index)->GetName());
1529  }
1530  else
1531  SetScalars(otherModel->GetScalars());
1532  printInfo("Loaded Scalars from " + filename);
1533 
1534  if(modelled)
1536 }
1537 
1539 {
1540  if(!loaded)
1541  return;
1542 
1543  cout << "Centroid: " << centroid() << " with Size: " << centroidSize() << endl;
1544  cout << "Covariance Matrix: " << endl << covarianceMatrix() << endl;
1545  printInfo("There are " + QString::number(model.Result()->GetNumberOfPoints()) + " points.");
1546  printInfo("There are " + QString::number(model.Result()->GetNumberOfPolys()) + " polygons.");
1547  printInfo("There are " + QString::number(model.Result()->GetNumberOfLines()) + " lines.");
1548  printInfo("There are " + QString::number(model.Result()->GetNumberOfStrips()) + " strips.");
1549  printInfo("There are " + QString::number(model.Result()->GetPointData()->GetNumberOfArrays()) + " arrays:");
1550  for(int j = 0; j < model.Result()->GetPointData()->GetNumberOfArrays(); j ++)
1551  printInfo(QString(model.Result()->GetPointData()->GetArray(j)->GetName()) + " ("
1552  + QString::number(model.Result()->GetPointData()->GetArray(j)->GetNumberOfComponents())
1553  + " component(s))");
1554 }
1555 
1556 void milxQtModel::matchInfo(QString filename, bool rescale, double factor)
1557 {
1558  if(!loaded)
1559  return;
1560 
1561  printInfo("Initial model information: ");
1562  modelInfo();
1563 
1564  if(filename.isEmpty())
1565  {
1566  QSettings settings("Shekhar Chandra", "milxQt");
1567  QString path = settings.value("recentPath").toString();
1568  QFileDialog *fileOpener = new QFileDialog(this);
1569  filename = fileOpener->getOpenFileName(this,
1570  tr("Select File to Open"),
1571  path,
1572  tr(openModelExts.c_str()) );
1573 
1574  QMessageBox msgBox;
1575  msgBox.setText("Rescale");
1576  msgBox.setInformativeText("Do you want to match the scale also?");
1577  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1578  msgBox.setDefaultButton(QMessageBox::Yes);
1579  int ret = msgBox.exec();
1580 
1581  if(ret == QMessageBox::No)
1582  rescale = false;
1583  }
1584 
1585  if(filename.isEmpty())
1586  return;
1587 
1588  QPointer<milxQtModel> otherModel = new milxQtModel;
1589  QPointer<milxQtFile> reader = new milxQtFile;
1590  bool success = reader->openModel(filename, otherModel);
1591 
1592  printInfo("Matching model information: ");
1593  otherModel->modelInfo();
1594 
1595  if(!success)
1596  return;
1597 
1598  coordinate otherCentroid = otherModel->centroid();
1599  coordinate newCentroid = otherCentroid - centroid();
1600  double currentCentroidSize = centroidSize(true);
1601  double otherCentroidSize = otherModel->centroidSize(true);
1602  double scaling = otherCentroidSize/currentCentroidSize;
1603  if(rescale)
1604  {
1605  printInfo("Scale of Current model: " + QString::number(currentCentroidSize));
1606  printInfo("Scale of Other model: " + QString::number(otherCentroidSize));
1607  printInfo("Scale to be applied: " + QString::number(scaling));
1608  printInfo("Scale (with factor) to be applied: " + QString::number(factor*scaling));
1609  }
1610 
1611  vtkSmartPointer<vtkTransform> transformer = vtkSmartPointer<vtkTransform>::New();
1612  transformer->Translate(newCentroid[0], newCentroid[1], newCentroid[2]);
1613  if(rescale)
1614  transformer->Scale(factor*scaling, factor*scaling, factor*scaling);
1615 
1616  SetTransform(transformer);
1617 
1618  refresh();
1619 
1620  printInfo("Final model information: ");
1621  modelInfo();
1622 }
1623 
1624 void milxQtModel::registerICP(QString filename, bool similarity)
1625 {
1626  if(!loaded)
1627  return;
1628 
1629  if(filename.isEmpty())
1630  {
1631  QSettings settings("Shekhar Chandra", "milxQt");
1632  QString path = settings.value("recentPath").toString();
1633  QFileDialog *fileOpener = new QFileDialog(this);
1634  filename = fileOpener->getOpenFileName(this,
1635  tr("Select File to Open"),
1636  path,
1637  tr(openModelExts.c_str()) );
1638 
1639  QMessageBox msgBox;
1640  msgBox.setText("Similarity Transform");
1641  msgBox.setInformativeText("Do you want to use similarity matching? Rigid Body will be used otherwise.");
1642  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1643  msgBox.setDefaultButton(QMessageBox::No);
1644  int ret = msgBox.exec();
1645 
1646  if(ret == QMessageBox::Yes)
1647  similarity = true;
1648  }
1649 
1650  if(filename.isEmpty())
1651  return;
1652 
1653  QPointer<milxQtModel> otherModel = new milxQtModel;
1654  QPointer<milxQtFile> reader = new milxQtFile;
1655  bool success = reader->openModel(filename, otherModel);
1656 
1657  if(!success)
1658  return;
1659 
1660  emit working(-1);
1661  printInfo("MSE of points before ICP: " + QString::number( milx::Math<double>::MeanSquaredError(model.Result()->GetPoints(), otherModel->GetOutput()->GetPoints()) ));
1662  printInfo("Registering Meshes using ICP.");
1663  model.IterativeClosestPointsRegistration(otherModel->GetOutput(), similarity);
1664  refresh();
1665  emit done(-1);
1666  printInfo("Registration Done.");
1667  printInfo("MSE of points after ICP: " + QString::number( milx::Math<double>::MeanSquaredError(model.Result()->GetPoints(), otherModel->GetOutput()->GetPoints()) ));
1668 }
1669 
1670 void milxQtModel::registerLandmarks(QString filename, bool similarity)
1671 {
1672  if(!loaded)
1673  return;
1674 
1675  if(filename.isEmpty())
1676  {
1677  QSettings settings("Shekhar Chandra", "milxQt");
1678  QString path = settings.value("recentPath").toString();
1679  QFileDialog *fileOpener = new QFileDialog(this);
1680  filename = fileOpener->getOpenFileName(this,
1681  tr("Select File to Open"),
1682  path,
1683  tr(openModelExts.c_str()) );
1684 
1685  QMessageBox msgBox;
1686  msgBox.setText("Similarity Transform");
1687  msgBox.setInformativeText("Do you want to use similarity matching? Rigid Body will be used otherwise.");
1688  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1689  msgBox.setDefaultButton(QMessageBox::No);
1690  int ret = msgBox.exec();
1691 
1692  if(ret == QMessageBox::Yes)
1693  similarity = true;
1694  }
1695 
1696  if(filename.isEmpty())
1697  return;
1698 
1699  QPointer<milxQtModel> otherModel = new milxQtModel;
1700  QPointer<milxQtFile> reader = new milxQtFile;
1701  bool success = reader->openModel(filename, otherModel);
1702 
1703  if(!success)
1704  return;
1705 
1706  if(otherModel->GetNumberOfPoints() != model.Result()->GetNumberOfPoints())
1707  {
1708  printError("Meshes must have same number of points to use this registration method.");
1709  return;
1710  }
1711 
1712  emit working(-1);
1713  printInfo("MSE of points before Landmark Transform: " + QString::number( milx::Math<double>::MeanSquaredError(model.Result()->GetPoints(), otherModel->GetOutput()->GetPoints()) ));
1714  printInfo("Registering Meshes using Landmark Transform.");
1715  model.LandmarkBasedRegistration(otherModel->GetOutput(), similarity);
1716  refresh();
1717  emit done(-1);
1718  printInfo("Registration Done.");
1719  printInfo("MSE of points after Landmark Transform: " + QString::number( milx::Math<double>::MeanSquaredError(model.Result()->GetPoints(), otherModel->GetOutput()->GetPoints()) ));
1720 }
1721 
1723 {
1724  if(!loaded)
1725  return;
1726 
1727  printInfo("Extracting Texture of Model as an Image.");
1728  if(modelActor->GetTexture())
1729  {
1730  vtkSmartPointer<vtkImageData> tex = modelActor->GetTexture()->GetInput();
1731 
1732  emit imageAvailable(tex, "Texture Map");
1733  }
1734  else
1735  printError("No Texture Found.");
1736 }
1737 
1739 {
1740  refresh();
1741 
1742  emit surfaceToImage(model.Result());
1743 }
1744 
1746 {
1748  {
1749  model.GenerateNormals(2); //for polygonal line placer (needs point norms) and interp (needs cell norms)
1750 
1751  milxQtRenderWindow::contourWidget = vtkSmartPointer<vtkContourWidget>::New();
1752  milxQtRenderWindow::contourWidget->SetInteractor(QVTKWidget::GetInteractor());
1753 
1754  printInfo("Contour Surface Mode enabled.\nLeft Click to place points, Right click to place end point.");
1755  printInfo("Delete key to delete point, Shift+Delete key to reset.");
1756 
1757  vtkSmartPointer<vtkOrientedGlyphContourRepresentation> rep = vtkOrientedGlyphContourRepresentation::SafeDownCast( milxQtRenderWindow::contourWidget->GetRepresentation() );
1758  rep->GetLinesProperty()->SetColor(1, 0.2, 0);
1759  rep->GetLinesProperty()->SetLineWidth(3.0);
1760 
1761  vtkSmartPointer<vtkPolygonalSurfacePointPlacer> pointPlacer = vtkSmartPointer<vtkPolygonalSurfacePointPlacer>::New();
1762  pointPlacer->AddProp(modelActor);
1763  pointPlacer->GetPolys()->AddItem(model.Result());
1764 // #if VTK_MAJOR_VERSION > 5
1765 // pointPlacer->SnapToClosestPointOn();
1766 // #endif
1767  rep->SetPointPlacer(pointPlacer);
1768 
1769  vtkSmartPointer<vtkPolygonalSurfaceContourLineInterpolator> interpolator = vtkSmartPointer<vtkPolygonalSurfaceContourLineInterpolator>::New();
1770  interpolator->GetPolys()->AddItem(model.Result());
1771  rep->SetLineInterpolator(interpolator);
1772 
1773  milxQtRenderWindow::contourWidget->SetRepresentation(rep);
1774  }
1775 
1776  if(milxQtRenderWindow::contourAct->isChecked())
1777  {
1778  milxQtRenderWindow::contourWidget->EnabledOn();
1779  printInfo("Enabled Contouring");
1780  }
1781  else
1782  {
1783  milxQtRenderWindow::contourWidget->EnabledOff();
1784  printInfo("Disabled Contouring");
1785  }
1786 
1787  refresh();
1788 }
1789 
1791 {
1792  if(!milxQtRenderWindow::contourAct->isChecked())
1793  {
1794  printInfo("Contouring not enabled. Stopping.");
1795  return;
1796  }
1797 
1798  vtkSmartPointer<vtkContourRepresentation> rep = milxQtRenderWindow::contourWidget->GetContourRepresentation();
1799  vtkSmartPointer<vtkPolyData> contourMesh = rep->GetContourRepresentationAsPolyData();
1800 
1801  model.DistanceMap(contourMesh->GetPoints());
1802 
1803  refresh();
1804 }
1805 
1806 void milxQtModel::weightGaussianFromContour(float stddev, float clampValue)
1807 {
1808  if(!milxQtRenderWindow::contourAct->isChecked())
1809  {
1810  printInfo("Contouring not enabled. Stopping.");
1811  return;
1812  }
1813 
1814  //get stddev for Gaussian
1815  bool ok1 = false, ok2 = false;
1816  if(stddev < 0)
1817  stddev = QInputDialog::getDouble(this, tr("Please enter the standard deviation of the Gaussian"), tr("Standard Dev.:"), 3.0, 0.0, 1000.0, 3, &ok1);
1818  if(clampValue < 0)
1819  clampValue = QInputDialog::getDouble(this, tr("Please enter the clamp (lowest allowed) value"), tr("Clamp Value:"), 1e-6, 0, 1.0, 10, &ok2);
1820 
1821  if(!ok1 || !ok2)
1822  return;
1823 
1824  //get dmap first
1826 
1827  double range[2];
1828  model.GetScalarRange(range);
1829  thresholdScalars(0.0, range[1], 0.0);
1830 
1831  model.GaussianWeightScalars(stddev, clampValue);
1832 
1834 
1835  refresh();
1836 }
1837 
1838 void milxQtModel::changeColour(float red, float green, float blue)
1839 {
1840  if(red < 0 || green < 0 || blue < 0) //Already provided so change
1841  {
1842  QPointer<QColorDialog> newColours = new QColorDialog(this);
1843 
1844  QColor newColour = newColours->getColor(QColor(defaultChannelValue, defaultChannelValue, defaultChannelValue),
1845  this, "Choose New Colour", QColorDialog::ShowAlphaChannel);
1846 
1847  if(newColour.isValid())
1848  {
1849  printInfo("Colour selected was: " + QString::number(newColour.redF()) + ", " + QString::number(newColour.greenF()) + ", " + QString::number(newColour.blueF()));
1850 
1851  colourRed = newColour.redF();
1852  colourGreen = newColour.greenF();
1853  colourBlue = newColour.blueF();
1854 
1855  SetOpacity(newColour.alphaF());
1856 
1857  reset();
1858  }
1859  }
1860  else
1861  {
1862  colourRed = red;
1863  colourGreen = green;
1864  colourBlue = blue;
1865 
1866  reset();
1867 
1868  return;
1869  }
1870 }
1871 
1872 void milxQtModel::changeOpacity(float opacity)
1873 {
1874  bool ok = false;
1875 
1876  if(opacity < 0)
1877  opacity = QInputDialog::getDouble(this, tr("Please enter the new opacity"),
1878  tr("Opacity:"), opacity, 0.0, 1.0, 3, &ok);
1879 
1880  if(ok)
1881  {
1882  SetOpacity(opacity);
1883 
1884  reset();
1885  }
1886 }
1887 
1889 {
1891 
1892  if(interpAct->isChecked())
1893  modelActor->GetProperty()->SetInterpolationToPhong();
1894  else
1895  modelActor->GetProperty()->SetInterpolationToFlat();
1896 
1897  QString shadingStr = modelActor->GetProperty()->GetInterpolationAsString();
1898  printInfo("Using " + shadingStr + " Shading");
1899 
1900  if(!quiet)
1901  refresh();
1902 }
1903 
1905 {
1906  if(!specularAct->isChecked())
1907  {
1908  modelActor->GetProperty()->SetSpecularColor(0, 0, 0);
1909  modelActor->GetProperty()->SetSpecular(0.1);
1910  modelActor->GetProperty()->SetSpecularPower(0.01);
1911  modelActor->GetProperty()->SetAmbient(0.1);
1912  modelActor->GetProperty()->SetDiffuse(0.9);
1913  printInfo("Using Flat Lighting");
1914  }
1915  else
1916  {
1917  modelActor->GetProperty()->SetSpecularColor(1, 1, 1);
1918  modelActor->GetProperty()->SetSpecular(0.25);
1919  modelActor->GetProperty()->SetSpecularPower(10);
1920  modelActor->GetProperty()->SetAmbient(0.2);
1921  modelActor->GetProperty()->SetDiffuse(0.8);
1922  printInfo("Using Specular Lighting");
1923  }
1924 
1925  if(!quiet)
1926  refresh();
1927 }
1928 
1929 void milxQtModel::normals(const bool turnOn)
1930 {
1931  if(turnOn)
1932  normalsAct->setChecked(true);
1933 
1934  if(normalsAct->isChecked())
1935  {
1936  // Double point normals
1937  vtkSmartPointer<vtkFloatArray> normalData2 = vtkFloatArray::SafeDownCast(model.Result()->GetPointData()->GetNormals());
1938 
1939  if(!normalData2)
1940  {
1941  printInfo("No normals found. Generating point normals.");
1942  generateNormals();
1943  normalData2 = vtkFloatArray::SafeDownCast(model.Result()->GetPointData()->GetNormals());
1944  }
1945 
1946  printInfo("There are " + QString::number(normalData2->GetNumberOfComponents()) + " components in the current model (double Point Normals)");
1947 
1948  if(!normalsModel)
1949  normalsModel = new milxQtModel;
1950  normalsModel->SetPoints(model.Result()->GetPoints());
1951  normalsModel->SetVectors(normalData2);
1952  normalsModel->generateVectorField();
1953 
1954  milxQtRenderWindow::AddActor(normalsModel->GetActor());
1956  }
1957  else
1958  {
1959  if(normalsModel)
1960  milxQtRenderWindow::RemoveActor(normalsModel->GetActor());
1961  }
1962 }
1963 
1964 void milxQtModel::rotate(bool xAxis, bool yAxis, bool zAxis, float angle)
1965 {
1966  if(!loaded)
1967  return;
1968 
1969  if(!xAxis && !yAxis && !zAxis)
1970  {
1971  QMessageBox msgBoxX, msgBoxY, msgBoxZ;
1972  msgBoxX.setText("The model will be rotated");
1973  msgBoxX.setInformativeText("Do you want to flip the x-axis?");
1974  msgBoxX.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1975  msgBoxX.setDefaultButton(QMessageBox::No);
1976  msgBoxY.setText("The model will be rotated");
1977  msgBoxY.setInformativeText("Do you want to flip the y-axis?");
1978  msgBoxY.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1979  msgBoxY.setDefaultButton(QMessageBox::Yes);
1980  msgBoxZ.setText("The model will be rotated");
1981  msgBoxZ.setInformativeText("Do you want to flip the z-axis?");
1982  msgBoxZ.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
1983  msgBoxZ.setDefaultButton(QMessageBox::No);
1984  int retX = msgBoxX.exec();
1985  int retY = msgBoxY.exec();
1986  int retZ = msgBoxZ.exec();
1987 
1988  bool ok1 = false;
1989  angle = QInputDialog::getDouble(this, tr("Enter angle to rotate by"),
1990  tr("Angle:"), 90, -2147483647, 2147483647, 5, &ok1);
1991 
1992  if(retX == QMessageBox::Yes)
1993  xAxis = true;
1994  if(retY == QMessageBox::Yes)
1995  yAxis = true;
1996  if(retZ == QMessageBox::Yes)
1997  zAxis = true;
1998  if(!ok1)
1999  return;
2000  }
2001 
2002  printInfo("Rotating Model along chosen axes from the model centroid.");
2003  emit working(-1);
2004  model.Rotate(xAxis, yAxis, zAxis, angle, centroid());
2005  refresh();
2006  emit done(-1);
2007 }
2008 
2009 void milxQtModel::flip(bool xAxis, bool yAxis, bool zAxis)
2010 {
2011  if(!loaded)
2012  return;
2013 
2014  if(!xAxis && !yAxis && !zAxis)
2015  {
2016  QMessageBox msgBoxX, msgBoxY, msgBoxZ;
2017  msgBoxX.setText("The model will be flipped");
2018  msgBoxX.setInformativeText("Do you want to flip the x-axis?");
2019  msgBoxX.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
2020  msgBoxX.setDefaultButton(QMessageBox::No);
2021  msgBoxY.setText("The model will be flipped");
2022  msgBoxY.setInformativeText("Do you want to flip the y-axis?");
2023  msgBoxY.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
2024  msgBoxY.setDefaultButton(QMessageBox::Yes);
2025  msgBoxZ.setText("The model will be flipped");
2026  msgBoxZ.setInformativeText("Do you want to flip the z-axis?");
2027  msgBoxZ.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
2028  msgBoxZ.setDefaultButton(QMessageBox::No);
2029  int retX = msgBoxX.exec();
2030  int retY = msgBoxY.exec();
2031  int retZ = msgBoxZ.exec();
2032 
2033  if(retX == QMessageBox::Yes)
2034  xAxis = true;
2035  if(retY == QMessageBox::Yes)
2036  yAxis = true;
2037  if(retZ == QMessageBox::Yes)
2038  zAxis = true;
2039  }
2040 
2041  printInfo("Flipping/Reflecting Model along chosen axes.");
2042  emit working(-1);
2043  model.Flip(xAxis, yAxis, zAxis);
2044  refresh();
2045  emit done(-1);
2046 }
2047 
2048 void milxQtModel::background(bool white)
2049 {
2050  if(milxQtRenderWindow::backgroundAct->isChecked() || white)
2051  {
2052  if(scaleBefore)
2053  {
2054  scale->GetLabelTextProperty()->SetColor(0, 0, 0);
2055  scale->GetTitleTextProperty()->SetColor(0, 0, 0);
2056  }
2057  if(outlineBefore)
2058  outlineActor->GetProperty()->SetColor(0, 0, 0);
2059  if(cubeAxesBefore)
2060  cubeAxesActor->GetProperty()->SetColor(0, 0, 0);
2061  }
2062  else
2063  {
2064  if(scaleBefore)
2065  {
2066  scale->GetLabelTextProperty()->SetColor(1.0, 1.0, 1.0);
2067  scale->GetTitleTextProperty()->SetColor(1.0, 1.0, 1.0);
2068  }
2069  if(outlineBefore)
2070  outlineActor->GetProperty()->SetColor(1, 1, 1);
2071  if(cubeAxesBefore)
2072  cubeAxesActor->GetProperty()->SetColor(1, 1, 1);
2073  }
2074 
2076 }
2077 
2078 void milxQtModel::enableOutline(vtkDataObject *dataOutline)
2079 {
2080  outlineMesh = vtkSmartPointer<vtkOutlineFilter>::New();
2081  if(dataOutline)
2082  #if VTK_MAJOR_VERSION <=5
2083  outlineMesh->SetInput(dataOutline);
2084  #else
2085  outlineMesh->SetInputData(dataOutline);
2086  #endif // VTK_MAJOR_VERSION
2087  else
2088  #if VTK_MAJOR_VERSION <=5
2089  outlineMesh->SetInput(model.Result());
2090  #else
2091  outlineMesh->SetInputData(model.Result());
2092  #endif
2093  outlineMesh->Update();
2094 
2095  if(!outlineModel)
2096  outlineModel = new milxQtModel;
2097  outlineModel->SetInput(outlineMesh->GetOutput());
2098  outlineModel->generateModel();
2099 
2100  outlineActor = outlineModel->GetActor();
2101  if(milxQtRenderWindow::backgroundAct->isChecked())
2102  outlineActor->GetProperty()->SetColor(0, 0, 0);
2103  else
2104  outlineActor->GetProperty()->SetColor(1, 1, 1);
2105 
2108 
2109  outlineBefore = true;
2110  outlineAct->setChecked(true);
2111 }
2112 
2114 {
2115  if(!outlineActor)
2116  return; //nothing to do then
2117 
2119  outlineBefore = false;
2120 }
2121 
2123 {
2124  if(outlineAct->isChecked())
2125  enableOutline();
2126  else
2127  disableOutline();
2128 
2129  Render();
2130 }
2131 
2132 void milxQtModel::enableCubeAxes(double *range, double *bounds)
2133 {
2134  cubeAxesActor = vtkSmartPointer<vtkCubeAxesActor>::New();
2135  if(bounds)
2136  cubeAxesActor->SetBounds(bounds);
2137  else
2138  cubeAxesActor->SetBounds(model.Result()->GetBounds());
2139  cubeAxesActor->SetCamera(milxQtRenderWindow::GetRenderer()->GetActiveCamera());
2140  if(range)
2141  {
2142  #if (VTK_MAJOR_VERSION > 5 || (VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 6))
2143  cubeAxesActor->SetXAxisRange(range[0], range[1]);
2144  cubeAxesActor->SetYAxisRange(range[2], range[3]);
2145  cubeAxesActor->SetZAxisRange(range[4], range[5]);
2146  #else
2147  printWarning("A scaling has been applied to the z-axis. Upgrade your VTK version to at least 5.8.x or above.");
2148  #endif
2149  }
2150  cubeAxesActor->SetFlyModeToOuterEdges();
2151  if(milxQtRenderWindow::backgroundAct->isChecked())
2152  cubeAxesActor->GetProperty()->SetColor(0, 0, 0);
2153  else
2154  cubeAxesActor->GetProperty()->SetColor(1, 1, 1);
2155 
2158 
2159  cubeAxesBefore = true;
2160  cubeAxesAct->setChecked(true);
2161 }
2162 
2164 {
2165  if(!cubeAxesActor)
2166  return; //nothing to do then
2167 
2169  cubeAxesBefore = false;
2170 }
2171 
2172 void milxQtModel::cubeAxesDisplay(double *range)
2173 {
2174  if(cubeAxesAct->isChecked())
2175  enableCubeAxes(range);
2176  else
2177  disableCubeAxes();
2178 
2179  Render();
2180 }
2181 
2183 {
2184  vtkSmartPointer<vtkActorCollection> collection = renderer->GetActors();
2185 
2186  const size_t n = collection->GetNumberOfItems();
2187  printDebug("Detected "+QString::number(n)+" overlays");
2188 
2189  collection->InitTraversal();
2190  for(size_t j = 0; j < n; j ++)
2191  {
2192  vtkSmartPointer<vtkActor> actor = collection->GetNextItem();
2193  if(modelActor != actor)
2194  removeModelActor(actor);
2195  }
2196 
2197  for(int j = 0; j < imageActors.size(); j ++)
2198  RemoveActor(imageActors[j].imageActor);
2199  imageActors.clear();
2200 
2201  Render();
2202 }
2203 
2204 void milxQtModel::enableScale(QString title, const bool quiet, double minRange, double maxRange, int noOfLabels)
2205 {
2207  milxQtRenderWindow::scale = vtkSmartPointer<vtkScalarBarActor>::New();
2209  milxQtRenderWindow::scalarBar = vtkSmartPointer<vtkScalarBarWidget>::New();
2210 
2212  QMessageBox msgBox;
2213  msgBox.setText("An auto adjusted bar is about to be created");
2214  msgBox.setInformativeText("Would you like to customise the bar?");
2215  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
2216  msgBox.setDefaultButton(QMessageBox::No);
2217 
2218  int ret = QMessageBox::No;
2219  if(!quiet)
2220  ret = msgBox.exec();
2221 
2222  const float barWidth = 0.1, barHeight = 0.7;
2223 
2224  vtkSmartPointer<vtkLogLookupTable> logLookupTable;
2226  {
2227  printInfo("Detected log scale.");
2228  logLookupTable = vtkSmartPointer<vtkLogLookupTable>::New();
2229  logLookupTable->DeepCopy(vtkLookupTable::SafeDownCast(lookupTable));
2230  }
2231 
2232  if(ret == QMessageBox::Yes && !quiet)
2233  {
2234  bool ok1 = false, ok2 = false, ok3 = false, ok4 = false;
2235 
2236  minRange = QInputDialog::getDouble(this, tr("Enter Table Range of new Lookup Table"),
2237  tr("Minimum:"), 0, -2147483647, 2147483647, 5, &ok1);
2238  maxRange = QInputDialog::getDouble(this, tr("Enter Table Range of new Lookup Table"),
2239  tr("Maximum:"), 1, -2147483647, 2147483647, 5, &ok2);
2240  noOfLabels = QInputDialog::getInt(this, tr("How many labels to show"),
2241  tr("Labels:"), noOfLabels, 0, 99, 1, &ok3);
2242  title = QInputDialog::getText(this, tr("Title of Bar"),
2243  tr("Title:"), QLineEdit::Normal,
2244  title, &ok4);
2245 
2246  if(!ok1 || !ok2 || !ok3 || !ok4)
2247  return;
2248 
2250  scale->SetLookupTable(logLookupTable);
2251  else
2252  scale->SetLookupTable(lookupTable);
2253  scale->SetNumberOfLabels(noOfLabels);
2254  modelMapper->SetLookupTable(lookupTable);
2255  modelMapper->SetScalarRange( minRange, maxRange );
2256  customScalarBar = true;
2257  }
2258  else if(quiet && minRange != maxRange)
2259  {
2260  printInfo("Using custom scalar range for scalars.");
2262  scale->SetLookupTable(logLookupTable);
2263  else
2264  scale->SetLookupTable(lookupTable);
2265  scale->SetNumberOfLabels(noOfLabels);
2266  modelMapper->SetLookupTable(lookupTable);
2267  modelMapper->SetScalarRange( minRange, maxRange );
2268  customScalarBar = true;
2269  }
2270  else
2271  {
2272  modelMapper->SetScalarRange( model.Result()->GetScalarRange() );
2274  scale->SetLookupTable(logLookupTable);
2275  else
2276  scale->SetLookupTable(lookupTable);
2277  scale->SetNumberOfLabels(3);
2278  customScalarBar = false;
2279  }
2280 
2281  scale->SetTitle(title.toStdString().c_str());
2282  scale->GetLabelTextProperty()->SetFontFamilyToArial();
2283  scale->GetLabelTextProperty()->SetFontSize(8);
2284  scale->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
2285  scale->GetPositionCoordinate()->SetValue(.2,.05);
2286  scale->SetWidth( barWidth );
2287  scale->SetHeight( barHeight );
2288  scale->SetPosition( 0.99 - barWidth, 0.1 );
2289  scale->SetLabelFormat("%-#6.3f");
2290  scale->GetTitleTextProperty()->SetFontFamilyToArial();
2291  scale->GetTitleTextProperty()->SetFontSize(8);
2292  scale->GetLabelTextProperty()->SetJustificationToCentered();
2293 
2294  if(milxQtRenderWindow::backgroundAct->isChecked())
2295  {
2296  scale->GetLabelTextProperty()->SetColor(0, 0, 0);
2297  scale->GetTitleTextProperty()->SetColor(0, 0, 0);
2298  }
2299 
2300  //Add scale to scale widget
2301  scalarBar->SetInteractor(QVTKWidget::GetInteractor());
2302  scalarBar->SetScalarBarActor(scale);
2303  scalarBar->EnabledOn();
2304 
2305  scaleBefore = true;
2306  scaleAct->setChecked(true);
2307 }
2308 
2309 void milxQtModel::scaleDisplay(const bool forceDisplay)
2310 {
2311  if(model.Result()->GetPointData()->GetScalars() == NULL)
2312  {
2313  printError("No scalars present.");
2314  scaleAct->setChecked(false); //reset
2315  return;
2316  }
2317 
2318  if(scaleAct->isChecked() || forceDisplay)
2319  enableScale(model.Result()->GetPointData()->GetScalars()->GetName(), forceDisplay);
2320  else
2321  disableScale();
2322 
2323  Render();
2324 }
2325 
2326 void milxQtModel::outputScalars(QString filename)
2327 {
2328  if(filename.isEmpty())
2329  {
2330  QSettings settings("Shekhar Chandra", "milxQt");
2331  QString path = settings.value("recentPath").toString();
2332  QFileDialog *fileOpener = new QFileDialog(this);
2333  filename = fileOpener->getSaveFileName(this,
2334  tr("Select File to Save"),
2335  path,
2336  tr("CSV Files (*.txt *.csv)") );
2337  }
2338 
2339  if(filename.isEmpty())
2340  return;
2341 
2342  QPointer<milxQtFile> scalarsWriter = new milxQtFile;
2343 
2344  scalarsWriter->saveScalarsOfModel(filename, this);
2345 }
2346 
2348 {
2349  if(modelled)
2350  {
2351  if(!computedCentroid)
2352  centroid();
2353 
2354  //viewToAxial
2355  vtkCamera *cam = milxQtRenderWindow::GetRenderer()->GetActiveCamera();
2356  if(!milxQtRenderWindow::GetRenderer()->IsActiveCameraCreated())
2357  milxQtRenderWindow::GetRenderer()->ResetCamera(); //just in case if new camera
2358  cam->SetFocalPoint(modelCentroid.data_block());
2359  if(orientationView == RADIOLOGICAL)
2360  {
2361  cam->SetPosition(0,0,centroidSize());
2362  cam->SetViewUp(0,-centroidSize(),0);
2363  }
2364  else //Neurological
2365  {
2366  cam->SetPosition(0,0,-centroidSize());
2367  cam->SetViewUp(0,centroidSize(),0);
2368  }
2369  milxQtRenderWindow::GetRenderer()->ResetCamera();
2371 
2372  currentView = AXIAL;
2373  }
2374 }
2375 
2377 {
2378  if(modelled)
2379  {
2380  if(!computedCentroid)
2381  centroid();
2382 
2383  //viewToCoronal
2384  vtkCamera *cam = milxQtRenderWindow::GetRenderer()->GetActiveCamera();
2385  if(!milxQtRenderWindow::GetRenderer()->IsActiveCameraCreated())
2386  milxQtRenderWindow::GetRenderer()->ResetCamera(); //just in case if new camera
2387  cam->SetFocalPoint(modelCentroid.data_block());
2388  if(orientationView == RADIOLOGICAL)
2389  {
2390  cam->SetPosition(0,-centroidSize(),0);
2391  cam->SetViewUp(0,0,centroidSize());
2392  }
2393  else //Neurological
2394  {
2395  cam->SetPosition(0,centroidSize(),0);
2396  cam->SetViewUp(0,0,centroidSize());
2397  }
2398  milxQtRenderWindow::GetRenderer()->ResetCamera();
2400 
2401  currentView = CORONAL;
2402  }
2403 }
2404 
2406 {
2407  if(modelled)
2408  {
2409  if(!computedCentroid)
2410  centroid();
2411 
2412  //viewToSagittal
2413  vtkCamera *cam = milxQtRenderWindow::GetRenderer()->GetActiveCamera();
2414  if(!milxQtRenderWindow::GetRenderer()->IsActiveCameraCreated())
2415  milxQtRenderWindow::GetRenderer()->ResetCamera(); //just in case if new camera
2416  cam->SetFocalPoint(modelCentroid.data_block());
2417  cam->SetPosition(-centroidSize(),0,0);
2418  cam->SetViewUp(0,0,centroidSize());
2419  milxQtRenderWindow::GetRenderer()->ResetCamera();
2421 
2422  currentView = SAGITTAL;
2423  }
2424 }
2425 
2426 void milxQtModel::showArray(QAction * action)
2427 {
2428  showArray(action->text());
2429 }
2430 
2431 void milxQtModel::showArray(const QString arrayName)
2432 {
2434  if(model.Result()->GetPointData()->GetArray(arrayName.toStdString().c_str())->GetNumberOfComponents() == 1)
2435  {
2436  printInfo("Loaded Array " + arrayName + " as scalars");
2437  model.Result()->GetPointData()->SetActiveAttribute( arrayName.toStdString().c_str(), vtkDataSetAttributes::SCALARS );
2438  }
2439  else if(model.Result()->GetPointData()->GetArray(arrayName.toStdString().c_str())->GetNumberOfComponents() == 3)
2440  {
2441  printInfo("Loaded Array " + arrayName + " as vectors");
2442  model.Result()->GetPointData()->SetActiveAttribute( arrayName.toStdString().c_str(), vtkDataSetAttributes::VECTORS );
2443  printInfo("Use 'Generate Vector Field' to see the vectors.");
2444  }
2445  else
2446  printInfo("Cannot Load Array " + arrayName + ". Too many components.");
2447 
2448  if(modelled)
2450 }
2451 
2453 {
2454  double range[2] = {0, 1.0};
2455 
2456  if(GetScalars())
2457  {
2458  model.Result()->GetScalarRange(range);
2459  if(GetScalars()->GetNumberOfComponents() > 1)
2460  printInfo("Found multi-component scalars. Not using colour map and using colours directly.");
2461  }
2462 
2465  double zeroRGBA[4];
2466  lookupTable->GetTableValue(0, zeroRGBA);
2467  if(zeroRGBA[3] == 0.0)
2468  lookupTable->SetTableValue(0, zeroRGBA[0], zeroRGBA[1], zeroRGBA[2], 1.0); //opaque
2469 
2470  modelMapper->SetLookupTable(lookupTable);
2471  modelMapper->SetScalarRange( range[0], range[1] );
2472 
2473  scaleDisplay();
2474 }
2475 
2476 void milxQtModel::createMenu(QMenu *menu)
2477 {
2478  if(!menu)
2479  return;
2480 
2481  menu->clear();
2482  menu->addMenu(basicContextMenu());
2483 
2484  if(!extActionsToAdd.empty())
2485  menu->addSeparator()->setText(tr("Extensions"));
2486  foreach(QAction *currAct, extActionsToAdd)
2487  {
2488  menu->addAction(currAct);
2489  }
2490  menu->addSeparator();
2491  menu->addAction(scaleAct);
2492  menu->addMenu(milxQtRenderWindow::contourMenu);
2494 
2495  menu->addSeparator();
2496  foreach(QAction *currAct, milxQtWindow::actionsToAppend)
2497  {
2498  menu->addAction(currAct);
2499  }
2500  foreach(QMenu *currMenu, milxQtWindow::menusToAppend)
2501  {
2502  menu->addMenu(currMenu);
2503  }
2504  menu->addAction(milxQtRenderWindow::refreshAct);
2505  menu->addAction(milxQtRenderWindow::resetAct);
2506 
2509 
2510  //disabling
2511  milxQtRenderWindow::contourPolyDataAct->setDisabled(!contourAct->isChecked());
2512  milxQtRenderWindow::contourNodePolyDataAct->setDisabled(!contourAct->isChecked());
2513  milxQtRenderWindow::contourInitAct->setDisabled(!contourAct->isChecked());
2514  selectPointsAct->setDisabled(!contourAct->isChecked());
2515  weightAct->setDisabled(!contourAct->isChecked());
2516  milxQtRenderWindow::contourInitAct->setDisabled(true);
2517 }
2518 
2519 void milxQtModel::updateCoords(vtkObject *obj)
2520 {
2522  vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::SafeDownCast(obj);
2523 
2524  QString message = "";
2525 
2530  if (dataPicker->Pick(iren->GetEventPosition()[0],
2531  iren->GetEventPosition()[1],
2532  0, // always zero.
2533  renderer))
2534  {
2535  // Get the volume index within the entire volume now.
2536  vtkIdType nVolIdx = dataPicker->GetPointId();
2537 
2538  if(nVolIdx >= 0) //-1 means no point picked
2539  {
2540  double *coords = model.Result()->GetPoint(nVolIdx);
2541 
2542  if(model.Result()->GetPointData()->GetScalars())
2543  {
2544  double *scalar = model.Result()->GetPointData()->GetScalars()->GetTuple(nVolIdx);
2545 
2546  if(model.Result()->GetPointData()->GetScalars()->GetNumberOfComponents() == 3)
2547  message = "Point " + QString::number(nVolIdx) + ": (" + QString::number(coords[0]) + ", " + QString::number(coords[1]) + ", " + QString::number(coords[2]) + ") = "
2548  + "[" + QString::number(scalar[0]) + ", " + QString::number(scalar[1]) + ", " + QString::number(scalar[2]) + "]";
2549  else if(model.Result()->GetPointData()->GetScalars()->GetNumberOfComponents() == 2)
2550  message = "Point " + QString::number(nVolIdx) + ": (" + QString::number(coords[0]) + ", " + QString::number(coords[1]) + ", " + QString::number(coords[2]) + ") = "
2551  + "[" + QString::number(scalar[0]) + ", " + QString::number(scalar[1]) + "]";
2552  else
2553  message = "Point " + QString::number(nVolIdx) + ": (" + QString::number(coords[0]) + ", " + QString::number(coords[1]) + ", " + QString::number(coords[2]) + ") = "
2554  + QString::number(scalar[0]);
2555  }
2556  else
2557  {
2558  message = "Point " + QString::number(nVolIdx) + ": (" + QString::number(coords[0]) + ", " + QString::number(coords[1]) + ", " + QString::number(coords[2]) + ")";
2559  }
2560  }
2561  }
2562 
2564  updateBar->showMessage(message);
2565 }
2566 
2567 void milxQtModel::copyToContextMenu(QMenu *copyMenu)
2568 {
2570  createCustomConnections(copyMenu->actions());
2571  printDebug("Model Copy to Context");
2572 }
2573 
2574 //Helper Members
2576 {
2577  computedCentroid = false;
2578  computedCovariance = false;
2579  if(!modelled)
2580  {
2581  appended = false;
2582  labelled = false;
2583  scalarsSet = false;
2584  customScalarBar = false;
2585  transformed = false;
2586  largeMode = false;
2587  scaleBefore = false;
2588  outlineBefore = false;
2589  cubeAxesBefore = false;
2590  undidProcess = false;
2591  }
2592 }
2593 
2595 {
2596  //Generate
2597  generateMenu = new QMenu(this);
2598  generateMenu->setTitle(QApplication::translate("Model", "Generate", 0, QApplication::UnicodeUTF8));
2599  genModelAct = new QAction(this);
2600  genModelAct->setText(QApplication::translate("Model", "Model", 0, QApplication::UnicodeUTF8));
2601  genModelAct->setShortcut(tr("Shift+Alt+m"));
2602  genVerticesAct = new QAction(this);
2603  genVerticesAct->setText(QApplication::translate("Model", "Vertices (Vertex Glyphs)", 0, QApplication::UnicodeUTF8));
2604  genVerticesAct->setShortcut(tr("Shift+Alt+v"));
2605  genNormalsAct = new QAction(this);
2606  genNormalsAct->setText(QApplication::translate("Model", "Normals", 0, QApplication::UnicodeUTF8));
2607  genNormalsAct->setShortcut(tr("Shift+Alt+n"));
2608  genVectorsAct = new QAction(this);
2609  genVectorsAct->setText(QApplication::translate("Model", "Vector Field", 0, QApplication::UnicodeUTF8));
2610  genVectorsAct->setShortcut(tr("Shift+Alt+v"));
2611  genTensorsAct = new QAction(this);
2612  genTensorsAct->setText(QApplication::translate("Model", "Tensor Field", 0, QApplication::UnicodeUTF8));
2613  genTensorsAct->setShortcut(tr("Shift+Alt+t"));
2614  genHedgehogAct = new QAction(this);
2615  genHedgehogAct->setText(QApplication::translate("Model", "Hedgehog Field", 0, QApplication::UnicodeUTF8));
2616  genHedgehogAct->setShortcut(tr("Shift+Alt+h"));
2617  genDelaunayAct = new QAction(this);
2618  genDelaunayAct->setText(QApplication::translate("Model", "Delaunay Graph", 0, QApplication::UnicodeUTF8));
2619  genDelaunayAct->setShortcut(tr("Shift+Alt+g"));
2620  genDelaunayTri2DAct = new QAction(this);
2621  genDelaunayTri2DAct->setText(QApplication::translate("Model", "Delaunay 2D Triangulation", 0, QApplication::UnicodeUTF8));
2622  genDelaunayTri2DAct->setShortcut(tr("Shift+Ctrl+t"));
2623  genDelaunayTriAct = new QAction(this);
2624  genDelaunayTriAct->setText(QApplication::translate("Model", "Delaunay Triangulation", 0, QApplication::UnicodeUTF8));
2625  genDelaunayTriAct->setShortcut(tr("Shift+Alt+t"));
2626  genDelaunayTriAct->setCheckable(true);
2627  genDelaunayTriAct->setChecked(false);
2628  genPointModelAct = new QAction(this);
2629  genPointModelAct->setText(QApplication::translate("Model", "Point Model", 0, QApplication::UnicodeUTF8));
2630  genPointModelAct->setShortcut(tr("Shift+Alt+p"));
2631  genLabelsAct = new QAction(this);
2632  genLabelsAct->setText(QApplication::translate("Model", "Vertex Labels", 0, QApplication::UnicodeUTF8));
2633  genLabelsAct->setShortcut(tr("Shift+Alt+l"));
2634  genPointIDsAct = new QAction(this);
2635  genPointIDsAct->setText(QApplication::translate("Model", "Point ID Scalars", 0, QApplication::UnicodeUTF8));
2636  genPointIDsAct->setShortcut(tr("Shift+Alt+i"));
2637  genSamplesAct = new QAction(this);
2638  genSamplesAct->setText(QApplication::translate("Model", "Sampled Points", 0, QApplication::UnicodeUTF8));
2639  genSamplesAct->setShortcut(tr("Shift+Alt+s"));
2640  genKmeansAct = new QAction(this);
2641  genKmeansAct->setText(QApplication::translate("Model", "K-Means Point Clustering", 0, QApplication::UnicodeUTF8));
2642  genKmeansAct->setShortcut(tr("Shift+Alt+k"));
2643  genQuantiseAct = new QAction(this);
2644  genQuantiseAct->setText(QApplication::translate("Model", "Snap/Quantise Points to a Grid", 0, QApplication::UnicodeUTF8));
2645  genQuantiseAct->setShortcut(tr("Shift+Alt+q"));
2646  genCapBoundaries = new QAction(this);
2647  genCapBoundaries->setText(QApplication::translate("Model", "Cap the Boundaries of Model", 0, QApplication::UnicodeUTF8));
2648  genCapBoundaries->setShortcut(tr("Shift+Alt+c"));
2649  genRegionLabels = new QAction(this);
2650  genRegionLabels->setText(QApplication::translate("Model", "Label Unconnected Regions", 0, QApplication::UnicodeUTF8));
2651  genRegionLabels->setShortcut(tr("Shift+Alt+u"));
2652  genElevation = new QAction(this);
2653  genElevation->setText(QApplication::translate("Model", "Elevation", 0, QApplication::UnicodeUTF8));
2654  genElevation->setShortcut(tr("Shift+Alt+e"));
2655  genReebGraph = new QAction(this);
2656  genReebGraph->setText(QApplication::translate("Model", "Reeb Graph", 0, QApplication::UnicodeUTF8));
2657  genReebGraph->setShortcut(tr("Shift+Alt+r"));
2658  genReebGraph->setDisabled(true); //Not working so disable tmp
2659 
2660  //Operations
2661  operateMenu = new QMenu(this);
2662  operateMenu->setTitle(QApplication::translate("Model", "Operations", 0, QApplication::UnicodeUTF8));
2663  cleanAct = new QAction(this);
2664  cleanAct->setText(QApplication::translate("Model", "&Clean Mesh", 0, QApplication::UnicodeUTF8));
2665  cleanAct->setShortcut(tr("Alt+c"));
2666  triAct = new QAction(this);
2667  triAct->setText(QApplication::translate("Model", "&Triangulate", 0, QApplication::UnicodeUTF8));
2668  triAct->setShortcut(tr("Alt+t"));
2669  decimateAct = new QAction(this);
2670  decimateAct->setText(QApplication::translate("Model", "&Decimate Mesh", 0, QApplication::UnicodeUTF8));
2671  decimateAct->setShortcut(tr("Alt+d"));
2672  quadricDecimateAct = new QAction(this);
2673  quadricDecimateAct->setText(QApplication::translate("Model", "&Quadric Decimate Mesh", 0, QApplication::UnicodeUTF8));
2674  quadricDecimateAct->setShortcut(tr("Alt+q"));
2675  clusterDecimateAct = new QAction(this);
2676  clusterDecimateAct->setText(QApplication::translate("Model", "&Quadric Cluster Decimate Mesh", 0, QApplication::UnicodeUTF8));
2677  clusterDecimateAct->setShortcut(tr("Shift+Alt+q"));
2678  smoothAct = new QAction(this);
2679  smoothAct->setText(QApplication::translate("Model", "Smooth/&Fair (Laplacian) Mesh", 0, QApplication::UnicodeUTF8));
2680  smoothAct->setShortcut(tr("Alt+f"));
2681  smoothSincAct = new QAction(this);
2682  smoothSincAct->setText(QApplication::translate("Model", "Smooth/&Fair (Windowed Sinc) Mesh", 0, QApplication::UnicodeUTF8));
2683  smoothSincAct->setShortcut(tr("Shift+Alt+f"));
2684  curvatureAct = new QAction(this);
2685  curvatureAct->setText(QApplication::translate("Model", "Mean Curvature", 0, QApplication::UnicodeUTF8));
2686  curvatureAct->setShortcut(tr("Shift+Alt+c"));
2687 
2688  //Transform
2689  transformMenu = new QMenu(this);
2690  transformMenu->setTitle(QApplication::translate("Model", "Transforms", 0, QApplication::UnicodeUTF8));
2691  transformAct = new QAction(this);
2692  transformAct->setText(QApplication::translate("Model", "Transform (via File) from ...", 0, QApplication::UnicodeUTF8));
2693  transformAct->setShortcut(tr("Alt+i"));
2694  matchAct = new QAction(this);
2695  matchAct->setText(QApplication::translate("Model", "&Match Info to ...", 0, QApplication::UnicodeUTF8));
2696  matchAct->setShortcut(tr("Alt+a"));
2697  registerAct = new QAction(this);
2698  registerAct->setText(QApplication::translate("Model", "&Register (via ICP) to ...", 0, QApplication::UnicodeUTF8));
2699  registerAct->setShortcut(tr("Alt+r"));
2700  registerLandmarkAct = new QAction(this);
2701  registerLandmarkAct->setText(QApplication::translate("Model", "&Register (via Landmarks) to ...", 0, QApplication::UnicodeUTF8));
2702  registerLandmarkAct->setShortcut(tr("Shift+Alt+r"));
2703  voxeliseAct = new QAction(this);
2704  voxeliseAct->setText(QApplication::translate("Model", "&Voxelise Model", 0, QApplication::UnicodeUTF8));
2705  voxeliseAct->setShortcut(tr("Alt+v"));
2706 
2707  //Scalars
2708  scalarMenu = new QMenu(this);
2709  scalarMenu->setTitle(QApplication::translate("Model", "Scalar Operations", 0, QApplication::UnicodeUTF8));
2710  renameScalarsAct = new QAction(this);
2711  renameScalarsAct->setText(QApplication::translate("Model", "Rename Scalars", 0, QApplication::UnicodeUTF8));
2712  renameScalarsAct->setShortcut(tr("Shift+Alt+r"));
2713  thresholdAct = new QAction(this);
2714  thresholdAct->setText(QApplication::translate("Model", "Clip Mesh based on Scalar Threshold", 0, QApplication::UnicodeUTF8));
2715  thresholdAct->setShortcut(tr("Shift+Alt+t"));
2716  thresholdScalarsAct = new QAction(this);
2717  thresholdScalarsAct->setText(QApplication::translate("Model", "Threshold Scalar Values", 0, QApplication::UnicodeUTF8));
2718  thresholdScalarsAct->setShortcut(tr("Shift+Ctrl+t"));
2719  thresholdScalarsBinaryAct = new QAction(this);
2720  thresholdScalarsBinaryAct->setText(QApplication::translate("Model", "Binary Threshold Scalar Values", 0, QApplication::UnicodeUTF8));
2721  thresholdScalarsBinaryAct->setShortcut(tr("Shift+Ctrl+b"));
2722  maskScalarsAct = new QAction(this);
2723  maskScalarsAct->setText(QApplication::translate("Model", "Mask Scalar Values", 0, QApplication::UnicodeUTF8));
2724  maskScalarsAct->setShortcut(tr("Shift+Ctrl+m"));
2725  gradientAct = new QAction(this);
2726  gradientAct->setText(QApplication::translate("Model", "Scalar Gradient Field", 0, QApplication::UnicodeUTF8));
2727  gradientAct->setShortcut(tr("Shift+Alt+c"));
2728  removeScalarsAct = new QAction(this);
2729  removeScalarsAct->setText(QApplication::translate("Model", "&Remove All Scalars", 0, QApplication::UnicodeUTF8));
2730  removeScalarsAct->setShortcut(tr("Shift+Alt+x"));
2731  scalarsAct = new QAction(this);
2732  scalarsAct->setText(QApplication::translate("Model", "&Load Scalars from ...", 0, QApplication::UnicodeUTF8));
2733  scalarsAct->setShortcut(tr("Shift+Alt+s"));
2734  outScalarsAct = new QAction(this);
2735  outScalarsAct->setText(QApplication::translate("Model", "&Output Scalars as CSV File", 0, QApplication::UnicodeUTF8));
2736  outScalarsAct->setShortcut(tr("Shift+Alt+o"));
2737  scalarsGroup = new QActionGroup(this);
2738  scalarsGroup->addAction(renameScalarsAct);
2739  scalarsGroup->addAction(thresholdAct);
2740  scalarsGroup->addAction(thresholdScalarsAct);
2742  scalarsGroup->addAction(gradientAct);
2743  scalarsGroup->addAction(removeScalarsAct);
2744  scalarsGroup->addAction(outScalarsAct);
2745 
2746  //Misc
2747  doAct = new QAction(this);
2748  doAct->setText(QApplication::translate("Model", "&Undo Last Processing", 0, QApplication::UnicodeUTF8));
2749  doAct->setShortcut(tr("Alt+u"));
2750  infoAct = new QAction(this);
2751  infoAct->setText(QApplication::translate("Model", "&Model Information", 0, QApplication::UnicodeUTF8));
2752  infoAct->setShortcut(tr("Alt+m"));
2753  textureAct = new QAction(this);
2754  textureAct->setText(QApplication::translate("Model", "&Extract Texture", 0, QApplication::UnicodeUTF8));
2755  textureAct->setShortcut(tr("Alt+t"));
2756  flipAct = new QAction(this);
2757  flipAct->setText(QApplication::translate("Model", "Flip Model", 0, QApplication::UnicodeUTF8));
2758  flipAct->setShortcut(tr("Ctrl+Alt+f"));
2759  rotateAct = new QAction(this);
2760  rotateAct->setText(QApplication::translate("Model", "Rotate Model", 0, QApplication::UnicodeUTF8));
2761  rotateAct->setShortcut(tr("Ctrl+Alt+r"));
2762 
2763  //View as
2764  pointsAct = new QAction(this);
2765  pointsAct->setText(QApplication::translate("Model", "&Points", 0, QApplication::UnicodeUTF8));
2766  pointsAct->setShortcut(tr("Alt+p"));
2767  pointsAct->setCheckable(true);
2768  wireframeAct = new QAction(this);
2769  wireframeAct->setText(QApplication::translate("Model", "&Wireframe", 0, QApplication::UnicodeUTF8));
2770  wireframeAct->setShortcut(tr("Alt+w"));
2771  wireframeAct->setCheckable(true);
2772  surfaceAct = new QAction(this);
2773  surfaceAct->setText(QApplication::translate("Model", "&Surface", 0, QApplication::UnicodeUTF8));
2774  surfaceAct->setShortcut(tr("Alt+s"));
2775  surfaceAct->setCheckable(true);
2776  displayGroup = new QActionGroup(this);
2777  displayGroup->addAction(pointsAct);
2778  displayGroup->addAction(wireframeAct);
2779  displayGroup->addAction(surfaceAct);
2780 
2781  colourAct = new QAction(this);
2782  colourAct->setText(QApplication::translate("Model", "Change Mesh &Colour/Transparency", 0, QApplication::UnicodeUTF8));
2783  colourAct->setShortcut(tr("Alt+c"));
2784  interpAct = new QAction(this);
2785  interpAct->setText(QApplication::translate("Model", "Best (Phong) Shading", 0, QApplication::UnicodeUTF8));
2786  interpAct->setShortcut(tr("Alt+g"));
2787  interpAct->setCheckable(true);
2788  interpAct->setChecked(false);
2789  specularAct = new QAction(this);
2790  specularAct->setText(QApplication::translate("Model", "Specular Lighting", 0, QApplication::UnicodeUTF8));
2791  specularAct->setShortcut(tr("Ctrl+Alt+s"));
2792  specularAct->setCheckable(true);
2793  specularAct->setChecked(false);
2794 
2795  normalsAct = new QAction(this);
2796  normalsAct->setText(QApplication::translate("Model", "Show Normals", 0, QApplication::UnicodeUTF8));
2797  normalsAct->setShortcut(tr("Alt+n"));
2798  normalsAct->setCheckable(true);
2799  normalsAct->setChecked(false);
2800  centroidAct = new QAction(this);
2801  centroidAct->setText(QApplication::translate("Model", "Show Centroid", 0, QApplication::UnicodeUTF8));
2802  centroidAct->setShortcut(tr("Alt+m"));
2803  centroidAct->setCheckable(true);
2804  centroidAct->setChecked(false);
2805  outlineAct = new QAction(this);
2806  outlineAct->setText(QApplication::translate("Model", "Show Outline Box", 0, QApplication::UnicodeUTF8));
2807  outlineAct->setShortcut(tr("Alt+b"));
2808  outlineAct->setCheckable(true);
2809  outlineAct->setChecked(false);
2810  cubeAxesAct = new QAction(this);
2811  cubeAxesAct->setText(QApplication::translate("Model", "Show Cube (Plot) Axes", 0, QApplication::UnicodeUTF8));
2812  cubeAxesAct->setShortcut(tr("Alt+a"));
2813  cubeAxesAct->setCheckable(true);
2814  cubeAxesAct->setChecked(false);
2815  overlaysAct = new QAction(this);
2816  overlaysAct->setText(QApplication::translate("Model", "Remove Overlays/Actors", 0, QApplication::UnicodeUTF8));
2817  overlaysAct->setShortcut(tr("Alt+o"));
2818 
2819  //Contour
2820  selectPointsAct = new QAction(this);
2821  selectPointsAct->setText(QApplication::translate("Model", "Select Points within Contour", 0, QApplication::UnicodeUTF8));
2822  weightAct = new QAction(this);
2823  weightAct->setText(QApplication::translate("Model", "Gaussian Weights from Contour", 0, QApplication::UnicodeUTF8));
2824 }
2825 
2827 {
2828  //Generation
2829  connect(genModelAct, SIGNAL(triggered()), this, SLOT(generateModel()));
2830  connect(genVerticesAct, SIGNAL(triggered()), this, SLOT(generateVertices()));
2831  connect(genNormalsAct, SIGNAL(triggered()), this, SLOT(generateNormals()));
2832  connect(genVectorsAct, SIGNAL(triggered()), this, SLOT(generateVectorField()));
2833  connect(genTensorsAct, SIGNAL(triggered()), this, SLOT(generateTensorField()));
2834  connect(genHedgehogAct, SIGNAL(triggered()), this, SLOT(generateHedgehog()));
2835  connect(genDelaunayAct, SIGNAL(triggered()), this, SLOT(generateDelaunayGraph()));
2836  connect(genDelaunayTri2DAct, SIGNAL(triggered()), this, SLOT(generateDelaunay2DTriangulation()));
2837  connect(genDelaunayTriAct, SIGNAL(triggered()), this, SLOT(generateDelaunayTriangulation()));
2838  connect(genPointModelAct, SIGNAL(triggered()), this, SLOT(generatePointModel()));
2839  connect(genLabelsAct, SIGNAL(triggered()), this, SLOT(generateLabels()));
2840  connect(genPointIDsAct, SIGNAL(triggered()), this, SLOT(generatePointIDsScalars()));
2841  connect(genSamplesAct, SIGNAL(triggered()), this, SLOT(generateSampledPoints()));
2842  connect(genKmeansAct, SIGNAL(triggered()), this, SLOT(generateKMeansClustering()));
2843  connect(genQuantiseAct, SIGNAL(triggered()), this, SLOT(generateQuantisedPoints()));
2844  connect(genCapBoundaries, SIGNAL(triggered()), this, SLOT(generateCappedBoundaries()));
2845  connect(genRegionLabels, SIGNAL(triggered()), this, SLOT(generateRegionLabels()));
2846  connect(genElevation, SIGNAL(triggered()), this, SLOT(generateElevation()));
2847  //~ connect(genReebGraph, SIGNAL(triggered()), this, SLOT(generateReebGraphs()));
2848  //Operations
2849  connect(doAct, SIGNAL(triggered()), this, SLOT(undoProcessing()));
2850  connect(cleanAct, SIGNAL(triggered()), this, SLOT(clean()));
2851  connect(triAct, SIGNAL(triggered()), this, SLOT(triangulate()));
2852  connect(decimateAct, SIGNAL(triggered()), this, SLOT(decimate()));
2853  connect(quadricDecimateAct, SIGNAL(triggered()), this, SLOT(quadricDecimate()));
2854  connect(clusterDecimateAct, SIGNAL(triggered()), this, SLOT(clusterDecimate()));
2855  connect(smoothAct, SIGNAL(triggered()), this, SLOT(smooth()));
2856  connect(smoothSincAct, SIGNAL(triggered()), this, SLOT(smoothSinc()));
2857  connect(curvatureAct, SIGNAL(triggered()), this, SLOT(curvature()));
2858  //Transformations
2859  connect(transformAct, SIGNAL(triggered()), this, SLOT(transform()));
2860  connect(matchAct, SIGNAL(triggered()), this, SLOT(matchInfo()));
2861  connect(registerAct, SIGNAL(triggered()), this, SLOT(registerICP()));
2862  connect(registerLandmarkAct, SIGNAL(triggered()), this, SLOT(registerLandmarks()));
2863  connect(voxeliseAct, SIGNAL(triggered()), this, SLOT(voxelise()));
2864  //Scalars
2865  connect(renameScalarsAct, SIGNAL(triggered()), this, SLOT(renameScalars()));
2866  connect(thresholdAct, SIGNAL(triggered()), this, SLOT(threshold()));
2867  connect(thresholdScalarsAct, SIGNAL(triggered()), this, SLOT(thresholdScalars()));
2868  connect(thresholdScalarsBinaryAct, SIGNAL(triggered()), this, SLOT(thresholdScalarsBinary()));
2869  connect(maskScalarsAct, SIGNAL(triggered()), this, SLOT(maskScalars()));
2870  connect(gradientAct, SIGNAL(triggered()), this, SLOT(gradient()));
2871  connect(removeScalarsAct, SIGNAL(triggered()), this, SLOT(removeScalars()));
2872  connect(scalarsAct, SIGNAL(triggered()), this, SLOT(loadScalars()));
2873  connect(outScalarsAct, SIGNAL(triggered()), this, SLOT(outputScalars()));
2874  //Misc
2875  connect(infoAct, SIGNAL(triggered()), this, SLOT(modelInfo()));
2876  connect(textureAct, SIGNAL(triggered()), this, SLOT(texture()));
2877  connect(flipAct, SIGNAL(triggered()), this, SLOT(flip()));
2878  connect(rotateAct, SIGNAL(triggered()), this, SLOT(rotate()));
2879  //View as
2880  connect(pointsAct, SIGNAL(triggered()), this, SLOT(generatePoints()));
2881  connect(wireframeAct, SIGNAL(triggered()), this, SLOT(generateWireframe()));
2882  connect(surfaceAct, SIGNAL(triggered()), this, SLOT(generateSurface()));
2883  //Properties
2884  connect(colourAct, SIGNAL(triggered()), this, SLOT(changeColour()));
2885  connect(interpAct, SIGNAL(triggered()), this, SLOT(toggleInterpolation()));
2886  connect(specularAct, SIGNAL(triggered()), this, SLOT(toggleSpecular()));
2887  //Show
2888  connect(normalsAct, SIGNAL(triggered()), this, SLOT(normals()));
2889  connect(centroidAct, SIGNAL(triggered()), this, SLOT(centroid()));
2890  connect(outlineAct, SIGNAL(triggered()), this, SLOT(outlineDisplay()));
2891  connect(cubeAxesAct, SIGNAL(triggered()), this, SLOT(cubeAxesDisplay()));
2892  connect(overlaysAct, SIGNAL(triggered()), this, SLOT(removeOverlays()));
2893  //Contouring
2894  connect(selectPointsAct, SIGNAL(triggered()), this, SLOT(selectPointsInContour()));
2895  connect(weightAct, SIGNAL(triggered()), this, SLOT(weightGaussianFromContour()));
2896 
2897 // connect(milxQtRenderWindow::backgroundAct, SIGNAL(triggered()), this, SLOT(background())); //Also connected to milxQtRenderWindow background member
2898  connect(milxQtRenderWindow::refreshAct, SIGNAL(triggered()), this, SLOT(refresh()));
2899  connect(milxQtRenderWindow::resetAct, SIGNAL(triggered()), this, SLOT(reset()));
2900 
2901  milxQtWindow::createConnections(); //consume right click events etc.
2902 }
2903 
2905 {
2906  doAct->setToolTip("Undo/Redo last processing computed.");
2907  doAct->setStatusTip("Undo/Redo last processing computed.");
2908  cleanAct->setToolTip("Clean the mesh removing and merging duplicate points");
2909  cleanAct->setStatusTip("Clean the mesh removing and merging duplicate points");
2910  triAct->setToolTip("Triangulate the mesh. Often a prerequisite to many algorithms");
2911  triAct->setStatusTip("Triangulate the mesh. Often a prerequisite to many algorithms");
2912  decimateAct->setToolTip("Reduce the number of polygon and vertices of the mesh by factor");
2913  decimateAct->setStatusTip("Reduce the number of polygon and vertices of the mesh by factor");
2914  smoothAct->setToolTip("Denoise the mesh using the standard Laplacian smoothing algorithm");
2915  smoothAct->setStatusTip("Denoise the mesh using the standard Laplacian smoothing algorithm");
2916  smoothSincAct->setToolTip("Denoise the mesh using the windowed sinc smoothing algorithm");
2917  smoothSincAct->setStatusTip("Denoise the mesh using the windowed sinc smoothing algorithm");
2918  transformAct->setToolTip("Affine transform the model using a ITK transform file");
2919  transformAct->setStatusTip("Affine transform the model using a ITK transform file");
2920  infoAct->setToolTip("Show the centroid, centroid size and covariance matrix of the model");
2921  infoAct->setStatusTip("Show the centroid, centroid size and covariance matrix of the model");
2922  matchAct->setToolTip("Match the information (centroid and scale) of another model to this model");
2923  matchAct->setStatusTip("Match the information (centroid and scale) of another model to this model");
2924  registerAct->setToolTip("Register or align this model to another model using Iterative Closest Point algorithm");
2925  registerAct->setStatusTip("Register or align this model to another model using Iterative Closest Point algorithm");
2926  voxeliseAct->setToolTip("Convert the surface to an image volume by voxelising it.");
2927  voxeliseAct->setStatusTip("Convert the surface to an image volume by voxelising it.");
2928  colourAct->setToolTip("Change the mesh colour and transparency (colour is only applicable for meshes with no scalars)");
2929  colourAct->setStatusTip("Change the mesh colour and transparency (colour is only applicable for meshes with no scalars)");
2930  interpAct->setToolTip("Change the interpolation of the mesh");
2931  interpAct->setStatusTip("Change the interpolation of the mesh");
2932  specularAct->setToolTip("Change the lighting to be shiny or not");
2933  specularAct->setStatusTip("Change the lighting to be shiny or not");
2934  scaleAct->setToolTip("Show a colour bar of the mesh scalars");
2935  scaleAct->setStatusTip("Show a colour bar of the mesh scalars");
2936 }
2937 
2938 void milxQtModel::contextMenuEvent(QContextMenuEvent *currentEvent)
2939 {
2941 
2942  contextMenu->exec(currentEvent->globalPos());
2943 }
2944 
2946 {
2947  contextMenu = new QMenu(this);
2948  contextMenu->setTitle(QApplication::translate("MainWindow", "Modelling", 0, QApplication::UnicodeUTF8));
2949 
2950  foreach(QAction *currAct, milxQtWindow::actionsToAdd)
2951  {
2952  contextMenu->addAction(currAct);
2953  }
2954  foreach(QMenu *currMenu, milxQtWindow::menusToAdd)
2955  {
2956  contextMenu->addMenu(currMenu);
2957  }
2958  contextMenu->addMenu(generationMenu());
2959  contextMenu->addMenu(operationsMenu());
2960  contextMenu->addMenu(transformsMenu());
2961  contextMenu->addMenu(scalarsMenu());
2962  contextMenu->addSeparator()->setText(tr("Options"));
2963  contextMenu->addAction(doAct);
2964  contextMenu->addAction(infoAct);
2965  contextMenu->addAction(textureAct);
2966  contextMenu->addAction(colourAct);
2967  contextMenu->addAction(interpAct);
2968  contextMenu->addAction(specularAct);
2969  contextMenu->addSeparator()->setText(tr("Display"));
2970  contextMenu->addAction(pointsAct);
2971  contextMenu->addAction(wireframeAct);
2972  contextMenu->addAction(surfaceAct);
2983  showMenu = contextMenu->addMenu("Show");
2984  showMenu->addAction(normalsAct);
2985  showMenu->addAction(centroidAct);
2986  showMenu->addAction(outlineAct);
2987  showMenu->addAction(cubeAxesAct);
2988  showMenu->addAction(overlaysAct);
2990  showMenu->addMenu(arraysMenu());
2991 
2992  if(GetScalars() && GetScalars()->GetNumberOfComponents() > 1 && vtkUnsignedCharArray::SafeDownCast(GetScalars()))
2993  milxQtRenderWindow::colourMapMenu->setDisabled(true);
2994  else if(!GetScalars() && !GetVectors() && !GetTensors())
2995  milxQtRenderWindow::colourMapMenu->setDisabled(true);
2996  else
2997  milxQtRenderWindow::colourMapMenu->setDisabled(false);
2998 
2999  return contextMenu;
3000 }
3001 
3003 {
3004  generateMenu->addAction(genModelAct);
3005  generateMenu->addAction(genVerticesAct);
3006  generateMenu->addAction(genNormalsAct);
3007  generateMenu->addAction(genVectorsAct);
3008  generateMenu->addAction(genTensorsAct);
3009  generateMenu->addAction(genHedgehogAct);
3010  generateMenu->addAction(genDelaunayAct);
3011  generateMenu->addAction(genDelaunayTri2DAct);
3012  generateMenu->addAction(genDelaunayTriAct);
3013  generateMenu->addAction(genPointModelAct);
3014  generateMenu->addAction(genLabelsAct);
3015  generateMenu->addAction(genPointIDsAct);
3016  generateMenu->addAction(genSamplesAct);
3017  generateMenu->addAction(genKmeansAct);
3018  generateMenu->addAction(genQuantiseAct);
3019  generateMenu->addAction(genCapBoundaries);
3020  generateMenu->addAction(genRegionLabels);
3021  generateMenu->addAction(genElevation);
3022  generateMenu->addAction(genReebGraph);
3023 
3024  return generateMenu;
3025 }
3026 
3028 {
3029  operateMenu->addAction(cleanAct);
3030  operateMenu->addAction(triAct);
3031  operateMenu->addAction(decimateAct);
3032  operateMenu->addAction(quadricDecimateAct);
3033  operateMenu->addAction(clusterDecimateAct);
3034  operateMenu->addAction(smoothAct);
3035  operateMenu->addAction(smoothSincAct);
3036  operateMenu->addAction(curvatureAct);
3037 
3038  return operateMenu;
3039 }
3040 
3042 {
3043  transformMenu->addAction(flipAct);
3044  transformMenu->addAction(rotateAct);
3045  transformMenu->addAction(transformAct);
3046  transformMenu->addAction(matchAct);
3047  transformMenu->addAction(registerAct);
3048  transformMenu->addAction(registerLandmarkAct);
3049  transformMenu->addAction(voxeliseAct);
3050 
3051  return transformMenu;
3052 }
3053 
3055 {
3056  scalarMenu->addAction(renameScalarsAct);
3057  scalarMenu->addAction(thresholdAct);
3058  scalarMenu->addAction(thresholdScalarsAct);
3060  scalarMenu->addAction(maskScalarsAct);
3061  scalarMenu->addAction(gradientAct);
3062  scalarMenu->addAction(removeScalarsAct);
3063  scalarMenu->addAction(scalarsAct);
3064  scalarMenu->addAction(outScalarsAct);
3065 
3066  if(!model.Result()->GetPointData()->GetScalars())
3067  scalarsGroup->setDisabled(true);
3068  else
3069  scalarsGroup->setDisabled(false);
3070 
3071  return scalarMenu;
3072 }
3073 
3075 {
3076  arrayGroup = new QActionGroup(this);
3077  arrayMenu = new QMenu(this);
3078  arrayMenu->setTitle(QApplication::translate("Model", "&Load Array as Scalars/Vectors", 0, QApplication::UnicodeUTF8));
3079 
3080  for(int j = 0; j < model.Result()->GetPointData()->GetNumberOfArrays(); j ++)
3081  {
3082  QAction *act = new QAction(this);
3083  act->setText(QApplication::translate("Model", model.Result()->GetPointData()->GetArrayName(j), 0, QApplication::UnicodeUTF8));
3084  arrayMenu->addAction(act);
3085  arrayGroup->addAction(act);
3086  }
3087  connect(arrayGroup, SIGNAL(triggered(QAction *)), this, SLOT(showArray(QAction *)));
3088 
3089  if(model.Result()->GetPointData()->GetNumberOfArrays() == 0)
3090  arrayMenu->setDisabled(true);
3091  else
3092  arrayMenu->setDisabled(false);
3093 
3094  return arrayMenu;
3095 }
QAction * scaleAct
Action for the scale bar of the display.
void printWarning(QString msg)
Warning message wrapper for console.
QAction * infoAct
Action for showing the model info.
Definition: milxQtModel.h:1061
QMenu * generationMenu()
Return the generate menu with the milxQtModel class ordering. This is for the benefit of derived clas...
static Type Centroid(const vnl_vector< Type > &data)
Compute the centroid (or the mean) of a data vector.
Definition: milxMath.h:177
void toggleInterpolation(bool quiet=false)
Toggles the interpolation of the mesh between Phong and Gouraud. Default is Gouraud.
int defaultView
Default view for data (default is axial)
void DelaunayTriangulation()
Compute the Delaunay 3D triangluation of the points in the mesh.
Definition: milxModel.cxx:911
bool logScale
Using custom scalar bar?
void GenerateVertexScalars()
Generate vertex scalars for display from point data. This colours the mesh by point ids...
Definition: milxModel.cxx:953
void undoProcessing()
Undo/Redo the processing last done. Only applies to processing such as clean() etc.
void printError(QString msg)
Error message wrapper for console.
void GenerateCappedBoundaries()
Generate capped boundaries for open meshes. This closes off open ends of a mesh.
Definition: milxModel.cxx:1273
void Update()
Updates the model to be the most current.
Definition: milxModel.h:292
void generateDelaunay2DTriangulation()
Generates the Delaunay 2D Triangulation (resulting in triangulated cells) for the model...
void AddArray(vtkSmartPointer< vtkDataArray > array)
Appends an array to the model.
Definition: milxModel.h:146
virtual void createMenu(QMenu *menu)
Create the menu for the data in this object. Used for context menu and file menus.
float colourRed
Saved colour, used for refresh etc.
Definition: milxQtModel.h:975
virtual void viewToZXPlane()
Change view to zx-plane.
vtkSmartPointer< vtkLODActor > delaunayActor
Delaunay triangulator actor.
Definition: milxQtModel.h:988
milxQtModel(QWidget *theParent=0, bool contextSystem=true)
The standard constructor.
Definition: milxQtModel.cpp:56
void RemoveActor(vtkSmartPointer< vtkProp > actor)
Remove the VTK actor from this window.
QAction * gradientAct
Action for calculating gradient of the scalars of a model.
Definition: milxQtModel.h:1041
void changeOpacity(float opacity=-1)
Changes the opacity/transparency of the model. You should use the changeColour() member and set its a...
QAction * genKmeansAct
Action for calculating k-means clustering of points in a model.
Definition: milxQtModel.h:1010
double centroidSize(bool average=false)
Computes and returns the centroid size of the model currently held which can be used for rescaling...
QAction * normalsAct
Action for showing the normals of a model.
Definition: milxQtModel.h:1047
QAction * outlineAct
show outline action
Definition: milxQtModel.h:1049
QActionGroup * arrayGroup
Grouping for check boxes.
Definition: milxQtModel.h:1076
QAction * voxeliseAct
Action for voxelising surface.
Definition: milxQtModel.h:1032
void GenerateHedgehog(const double newScale=0.0)
Generate a line field for vectors present (as an array) in the mesh at given scaling.
Definition: milxModel.cxx:1137
QAction * saveViewFileAct
Save camera view to file.
void generateLabels()
Generates the model vertices with labels. It requires that data has been set or assigned already...
QMenu * viewMenu
Context Menu.
void generateRegionLabels()
Generates scalars for unconnected regions of the mesh.
void surfaceToImage(vtkSmartPointer< vtkPolyData >)
Emit signal to compute surface to image process.
bool openModel(const QString filename, vtkPolyData *data)
Opens a model file, which can be a VTK XML, Legacy VTK PolyData File (i.e. either a *...
Definition: milxQtFile.cpp:752
void generateIsoSurface(vtkSmartPointer< vtkImageData > img, int contourNumber=-1, double value=0.0)
Generates a iso surface or contour from image data, i.e. the result of Marching Cubes algorithm at va...
void generateDelaunayGraph(float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates the Delaunay 3D graph for the dataset. Arguments provided are for the colours of the edges ...
static vtkMatrix4x4 * OpenVTKTransform(std::string filename)
Opens a VTK transform file and converts it to a VTK transform matrix.
Definition: milxFile.cxx:346
int currentView
Current view for data.
void contextMenuEvent(QContextMenuEvent *event)
The context menu setup member.
void RemoveScalars()
Removes all the scalars from the current model. Same as ClearScalars()
Definition: milxModel.cxx:265
vtkSmartPointer< vtkActor2D > modelLabelsActor
Label Actor.
Definition: milxQtModel.h:989
QAction * maskScalarsAct
Action for masking scalar values on model.
Definition: milxQtModel.h:1040
void generateDelaunayTriangulation(float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates the Delaunay 3D Triangulation (resulting in tetrahdral cells) for the dataset. Arguments provided are for the colours of the cells of the model.
void GenerateVertices()
Generate (only) vertices for display from point data. Good for when only points in mesh...
Definition: milxModel.cxx:935
void setName(const QString filename)
Set the name of the data.
QList< QAction * > extActionsToAdd
Extension actions to add.
Definition: milxQtWindow.h:253
void createConnections()
Create the connections for context menu etc.
QAction * overlaysAct
removes actors/overlays action
Definition: milxQtModel.h:1051
QAction * weightAct
produce Gaussian weights from contour
Definition: milxQtModel.h:1054
QAction * textureAct
Action for extracting texture.
Definition: milxQtModel.h:1062
void generateCappedBoundaries()
Generates capped boundaries for meshes with boundaries (such as large holes or voids).
vtkSmartPointer< vtkLODActor > modelActor
Model actor.
Definition: milxQtModel.h:987
void Flip(const bool xAxis, const bool yAxis, const bool zAxis)
Flip the mesh along the selected axes.
Definition: milxModel.cxx:643
void loadScalars(QString filename="")
Loads the scalars from another model, where both models must have the same number of points...
QAction * smoothSincAct
Action for smooth model.
Definition: milxQtModel.h:1024
QAction * pointsAct
Show points.
Definition: milxQtModel.h:1073
void GenerateTensorField(const double newScale=0.0)
Generate tensor field for tensors present (as an array) in the mesh at given scaling.
Definition: milxModel.cxx:1108
QAction * genVectorsAct
Action for generating vector fields.
Definition: milxQtModel.h:1000
vnl_matrix< double > modelCovarianceMatrix
Covariance matrix of the model.
Definition: milxQtModel.h:983
vtkSmartPointer< vtkPolyDataMapper > modelMapper
Model mapper.
Definition: milxQtModel.h:986
vtkSmartPointer< vtkContourWidget > contourWidget
contour interaction
vtkSmartPointer< vtkRenderer > renderer
Renderer for the data.
A general math object for computing common operations such a centroids etc.
Definition: milxMath.h:44
void AddActor(vtkSmartPointer< vtkProp > actor)
Add a VTK actor to this window.
void generateSurface(float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates a surface display of the model, i.e. points at each point for the dataset. Arguments provided are for the colours of the points.
This class represents the MILX Qt Render Window Display object using QVTK.
void cubeAxesDisplay(double *range=NULL)
Toggles the cube (plot) axes display.
void GenerateRegions()
Generate connected regions for the mesh labelled by scalar values.
Definition: milxModel.cxx:1307
QAction * scalarsAct
Action for loading scalars from another model.
Definition: milxQtModel.h:1043
QActionGroup * scalarsGroup
Grouping for scalars.
Definition: milxQtModel.h:1035
coordinate modelCentroid
Centroid coordinate of the model.
Definition: milxQtModel.h:982
void Mask(vtkSmartPointer< vtkPolyData > maskMesh)
Mask the scalars on the mesh based on values of maskMesh being >= 1.
Definition: milxModel.cxx:730
void generateVertices(float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates the vertices for the dataset. Arguments provided are for the colours of the vertices...
QAction * genDelaunayTri2DAct
Action for generating Delaunay triangulation.
Definition: milxQtModel.h:1004
QAction * genLabelsAct
Action for generating labels.
Definition: milxQtModel.h:1006
vtkSmartPointer< vtkLookupTable > lookupTable
Lookup table for the shapes/images, base class is used to allow references to different look up table...
vtkSmartPointer< vtkDataArray > GetTensors()
Returns the tensors (3x3 matrix per vertex) of the model currently held.
Definition: milxQtModel.h:323
void decimate(double factor=0.0)
Reduce the polygon count (decimate) the model. Factor to reduce by is acquired by input a dialog...
vtkSmartPointer< vtkPoints > GetPoints()
Returns the points of the model currently held.
Definition: milxQtModel.h:291
void enableCubeAxes(double *range=NULL, double *bounds=NULL)
Display cube (plot) axes of data.
QAction * viewZY
Change view to zy-plane (Coronal)
void disableOutline()
Disables the outline box display.
QAction * genReebGraph
Action for Reeb graphs of mesh.
Definition: milxQtModel.h:1015
QAction * surfaceAct
Show surface.
Definition: milxQtModel.h:1075
bool loaded
Loaded Image from file?
void SetPolys(vtkSmartPointer< vtkCellArray > modelPolys)
Assign polygons to the model via the array given.
Definition: milxModel.cxx:202
void generatePointIDsScalars()
Generates scalars for the vertices in the model based on their point IDs. It requires that model has ...
void generateStreamLines(vtkSmartPointer< vtkImageData > seeds, float timestep=0.0)
Generates stream lines i.e. integrates a vector field starting at seed points.
void registerICP(QString filename="", bool similarity=false)
Register or align current mesh to another mesh using Iterative Closest Point algorithm, whose filename is provided. If not provided, then Open File dialog will apear.
QAction * genTensorsAct
Action for generating vector fields.
Definition: milxQtModel.h:1001
QMenu * contextMenu
Context Menu.
Definition: milxQtWindow.h:250
virtual void contour()
Draw contour interactively.
void SetGraph(vtkSmartPointer< vtkMutableUndirectedGraph > graph)
Converts a graph to polydata/mesh ready for display.
Definition: milxModel.cxx:176
This class represents the MILX Qt File I/O object using VTK/ITK/Qt.
Definition: milxQtFile.h:60
void createActions()
Create the actions for context menu etc.
milxQtModel & operator=(const milxQtModel &operand)
Assignment operator for models. Only copies the data as given by GetOutput() of operand. EXPERIMENTAL.
void GenerateSampledPoints(const double distance)
Generate sampled points (only points) for the mesh at given spacing on triangles. ...
Definition: milxModel.cxx:1050
void SetVectors(vtkSmartPointer< vtkDataArray > modelVectors)
Sets the vectors for the model to be generated. Must pass a vtkFloatArray objects, which is easy to use.
void removeScalars()
Removes all the scalars from the model.
void RemoveScalars()
Removes the scalars of the model.
void generateKMeansClustering(int numberOfClusters=0)
Generates K-means clustering of the points in the model with the number of clusters provided...
QAction * smoothAct
Action for smooth model.
Definition: milxQtModel.h:1023
bool transformed
Transformed?
Definition: milxQtModel.h:967
coordinate & centroid()
Computes and returns the centroid of the model currently held.
QAction * removeScalarsAct
Action for removing scalars from model.
Definition: milxQtModel.h:1042
virtual void viewToZYPlane()
Change view to zy-plane.
void DelaunayGraph3D()
Compute the Delaunay 3D graph of the points in the mesh.
Definition: milxModel.cxx:853
void AddInput(vtkSmartPointer< vtkPolyData > mesh)
Assigns and coninually appends meshes provided to the class, preparing for display. Call generateModel() and then show() to display.
Definition: milxQtModel.cpp:97
virtual void weightGaussianFromContour(float stddev=-1.0, float clampValue=-1.0)
Select model points inside contour, compute distance map and Gaussian weight the result.
bool largeMode
Large Data set mode enabled?
Definition: milxQtModel.h:970
void generateTubes(float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates the tubes for the dataset. Arguments provided are for the colours of the tubes...
QAction * wireframeAct
Show wireframe.
Definition: milxQtModel.h:1074
QAction * quadricDecimateAct
Action for Quadric decimating model.
Definition: milxQtModel.h:1021
QAction * renameScalarsAct
Action for renaming scalars array.
Definition: milxQtModel.h:1036
void thresholdScalarsBinary(double lowValue=0.0, double upValue=0.0, double insideVal=1.0, double outsideVal=0.0)
Binary threshold scalar values on the mesh. Geometry and topology is unchanged, and scalars become tw...
QAction * humanAct
Show human view orientation glyph?
float colourGreen
Saved colour, used for refresh etc.
Definition: milxQtModel.h:976
void SetInput(vtkSmartPointer< vtkPolyData > mesh)
Assigns the mesh provided to the class, preparing for display. Call generateModel() and then show() t...
QAction * registerLandmarkAct
Action for registering two models via landmark transform.
Definition: milxQtModel.h:1031
void voxelise()
Convert surface to an image volume.
void setDeletableOnClose(bool delOnClose)
Set if the window deletable on close. Default is true.
Definition: milxQtWindow.h:178
QList< QMenu * > menusToAdd
Context Menu&#39;s to add.
Definition: milxQtWindow.h:254
bool appended
Appended data present?
Definition: milxQtModel.h:963
void generateNormals(int pointNormals=0)
Generates normals of the model, with point normals being default.
virtual void copyToContextMenu(QMenu *copyMenu)
Copies the menu, by duplicating the entries, to the context menu. Connections are assumed to be made ...
QAction * backgroundAct
Action for axes of the display.
QAction * triAct
Action for triangulate model.
Definition: milxQtModel.h:1019
vtkSmartPointer< vtkOutlineFilter > outlineMesh
outline box
Definition: milxQtModel.h:991
QAction * registerAct
Action for registering two models.
Definition: milxQtModel.h:1030
void createConnections()
Create the connections for context menu etc.
void Delaunay2DTriangulation()
Compute the Delaunay 2D triangluation of the points in the mesh.
Definition: milxModel.cxx:885
static vtkMatrix4x4 * OpenITKTransform(std::string filename)
Opens an ITK transform file and converts it to a VTK transform matrix.
Definition: milxFile.cxx:190
QString prefix
Prefix of the data.
Definition: milxQtWindow.h:242
void SetPolys(vtkSmartPointer< vtkCellArray > modelPolys)
Sets the polygons for the model to be generated. Must pass a vtkCellArray objects, which is easy to use.
QAction * centroidAct
show centroid action
Definition: milxQtModel.h:1048
vtkSmartPointer< vtkPolyData > & Result()
Returns the current model, i.e. the result of the latest operation.
Definition: milxModel.h:202
void printDebug(QString msg)
Debug message wrapper for console.
QAction * contourPolyDataAct
Save contour surface points as polydata.
vtkIdType GetNumberOfPoints()
Returns the total number of points of the model currently held.
Definition: milxQtModel.h:275
QAction * genQuantiseAct
Action for quantising points in a model.
Definition: milxQtModel.h:1011
bool modelled
Model has been generated?
Definition: milxQtModel.h:964
void generateWireframe(float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates the 3D graph for the dataset. Arguments provided are for the colours of the edges of the gr...
void enableOutline(vtkDataObject *dataOutline=NULL)
Display outline box of data.
void AddArray(vtkSmartPointer< vtkDataArray > array)
Adds an array to the model, appending it to the current list of arrays.
This class represents the MILX Qt Model/Mesh Display object using VTK.
Definition: milxQtModel.h:115
virtual void scaleDisplay(const bool forceDisplay=false)
Toggles the scale bar display.
bool computedCovariance
Computed covariance matrix already?
Definition: milxQtModel.h:969
QAction * contourAct
Action for contouring surface points using Dijkstras algorithm.
void SetPoints(vtkSmartPointer< vtkPoints > modelPoints)
Assign points to the model.
Definition: milxModel.cxx:194
void outputScalars(QString filename="")
Output the scalars of model to file.
void generatePoints(float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates points display of the model, i.e. points at each point for the dataset. Arguments provided ...
void generatePointModel(double newScale=1.0, float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates a point model, i.e. glyphs at each point for the dataset. Arguments provided are for the co...
QList< ImageActorItem > imageActors
Images actors being displayed in model view.
void Render()
Force Render or Update of the display.
void Decimate(const float reduceFactor)
Decimate the mesh (in terms of points) using the Decimate PRO. Generally use QuadricDecimate() instea...
Definition: milxModel.cxx:416
void SetVectors(vtkSmartPointer< vtkDataArray > modelVectors)
Sets the vector field of the mesh (vectors per vertex of the surface)
Definition: milxModel.cxx:210
QAction * genCapBoundaries
Action for capping the boundaries of a open mesh.
Definition: milxQtModel.h:1012
QAction * decimateAct
Action for decimating model.
Definition: milxQtModel.h:1020
QAction * specularAct
Action for changing the specular of a model to flat.
Definition: milxQtModel.h:1068
void setDefaultOrientation(int orientMode)
Change orientation mode to one of the supported standards. Default: Radiological. ...
void registerLandmarks(QString filename="", bool similarity=false)
Register or align current mesh to another mesh using the landmark transform, whose filename is provid...
vnl_matrix< double > & covarianceMatrix()
Computes and returns the covariance matrix of the model currently held.
QAction * cleanAct
Action for cleaning model.
Definition: milxQtModel.h:1018
bool scalarsSet
Scalars set to points of mesh?
Definition: milxQtModel.h:966
virtual void enableScale(QString title="", const bool quiet=false, double minRange=0.0, double maxRange=0.0, int noOfLabels=3)
Enable scale bar display with the title provided.
void refresh()
Refresh the display of the model.
QMenu * basicContextMenu()
Return the basic context menu with the milxQtModel class ordering. This is for the benefit of derived...
bool outlineBefore
scale displayed?
Definition: milxQtModel.h:971
QMenu * scalarsMenu()
Return the scalars menu with the milxQtModel class ordering. This is for the benefit of derived class...
QAction * curvatureAct
Action for calculating mean curvation of a model.
Definition: milxQtModel.h:1025
void matchInfo(QString filename="", bool rescale=true, double factor=1.0)
Loads another model and matches its centroid and (optionally) scales this model to match...
void SetOpacity(double opacity)
Adjusts the opacity of the model in the display. 1.0 is totally opaque and 0.0 is completely transpar...
Definition: milxQtModel.h:219
QAction * genDelaunayTriAct
Action for generating Delaunay triangulation.
Definition: milxQtModel.h:1005
void rotate(bool xAxis=false, bool yAxis=false, bool zAxis=false, float angle=90)
Rotate model along any axis, useful for matching orientation with ITK etc.
void Append(vtkSmartPointer< vtkPolyData > model)
Appends the model provided to the member into the current model.
Definition: milxModel.cxx:1459
void modelInfo()
Computes and prints the centroid, centroid size and covariance matrix to standard out...
int orientationView
view orientation standard
void GenerateVerticesAs2DGlyphs(const GlyphType glyphType)
Generate (only) vertices (as 2D glyphs like crosses etc.) for display from point data. Good for when only points in mesh.
Definition: milxModel.cxx:973
void Threshold(const coordinateType belowVal, const coordinateType aboveVal, const coordinateType outsideVal)
Threshold the scalars on the mesh based on a levels provided.
Definition: milxModel.cxx:702
void QuadricDecimate(const float reduceFactor)
Decimate the mesh (in terms of points) using the Quadric algorithm.
Definition: milxModel.cxx:435
float colourBlue
Saved colour, used for refresh etc.
Definition: milxQtModel.h:977
QAction * colourAct
Action for changing colours of a model.
Definition: milxQtModel.h:1066
QList< QAction * > actionsToAppend
Context actions to append.
Definition: milxQtWindow.h:252
QAction * contourNodePolyDataAct
Save contour surface nodes as polydata.
void WindowedSincSmoothing(const int iterations, const float passBand=0.1)
Smooth the mesh (in terms of points) using the Taubin (1995) optimal filter.
Definition: milxModel.cxx:493
vtkSmartPointer< vtkDataArray > GetNormals()
Returns the normal vectors of the model.
Definition: milxModel.h:280
QAction * cubeAxesAct
show cube axes action
Definition: milxQtModel.h:1050
bool saveScalarsOfModel(const QString filename, milxQtModel *data)
Saves the scalars of a model as a CSV or VTK Text file. The CSV format is output if the extension is ...
void Curvature(const bool meanCurvature=true)
Compute the curvature (using Laplace-Beltrami operator) of the mesh.
Definition: milxModel.cxx:514
vtkSmartPointer< vtkDataArray > GetVectors()
Returns the active vectors of the model.
Definition: milxModel.h:274
QAction * genRegionLabels
Action for labelling unconnected regions of mesh.
Definition: milxQtModel.h:1013
QAction * refreshAct
Action for refreshing the display.
void resetFlags()
Reset the flags for pointers and computations. Useful when the data changes and all previous results ...
QAction * contourInitAct
Load contour surface points from polydata.
bool scaleBefore
scale displayed?
void maskScalars(QString filename="")
Mask scalar values on the mesh using scalars on another mesh. Assumes point correspondence between me...
void SetInput(vtkSmartPointer< vtkPolyData > model)
Assigns the input model to class.
Definition: milxModel.cxx:130
void gradient()
Compute the gradient of the scalar field on the model.
void enableActionBasedOnView()
Enables the view actions corresponding to current view set.
QMenu * contourMenu
Contour Menu.
void SetTransform(vtkSmartPointer< vtkTransform > transform)
Sets the transform for the model that will be generated. Must pass a vtkTransform objects...
void LaplacianSmoothing(const int iterations)
Smooth the mesh (in terms of points) using the Laplacian algorithm. It is unstable, use WindowedSincSmoothing() instead unless massive non-edge preserving smoothing is required.
Definition: milxModel.cxx:473
void generateModel(float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates the model so that its ready for display. It requires that data has been set or assigned alr...
QMenu * arraysMenu()
Return the arrays menu with the milxQtModel class ordering. This is for the benefit of derived class ...
bool cubeAxesBefore
scale displayed?
Definition: milxQtModel.h:972
void changeColour(float red=-1, float green=-1, float blue=-1)
Changes the colour of the model if no scalars are present.
void SetPoints(vtkSmartPointer< vtkPoints > modelPoints)
Sets the points for the model to be generated. Must pass a vtkPoints objects, which is easy to use...
virtual void updateCoords(vtkObject *obj)
Picks the coordinates and pixel value from the current mouse position in the window.
void SetTransform(vtkSmartPointer< vtkAbstractTransform > newTransform)
Transforms the model by given transform.
Definition: milxModel.cxx:143
void generateSampledPoints(float distance=0.0, float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates points sampled "distance" apart on the model with glyphs at each point. ...
QAction * thresholdScalarsAct
Action for thresholding scalar values on model.
Definition: milxQtModel.h:1038
void smoothSinc(int iterations=0)
Smooth the model using the Windowed Sinc approach of Taubin et al. Iterations to smooth by is acquire...
virtual void updateLookupTable()
Sets the necessary LUTs to model view.
QAction * clusterDecimateAct
Action for Cluster decimating model.
Definition: milxQtModel.h:1022
QAction * resetAct
Action for refreshing the display.
void clusterDecimate()
Reduce the polygon count (decimate) the model using Quadric Clustering Decimation. The final result is the best simplification of the mesh, preserving topology.
QAction * flipAct
Action for flipping surface.
Definition: milxQtModel.h:1063
QMenu * colourMapMenu
Colour map menu.
bool computedCentroid
Computed centroid already?
Definition: milxQtModel.h:968
QAction * genModelAct
Action for generating model.
Definition: milxQtModel.h:997
void quadricDecimate(double factor=0.0)
Reduce the polygon count (decimate) the model using Quadric Decimation. The final result is the best ...
void generateRender()
Generate the render so it is ready for display. Should be called before showing the window...
virtual void disableScale()
Disables the scale bar display.
void linkProgressEventOf(vtkObject *obj)
Link the progress of filters etc to keep the UI responsive.
void triangulate()
Triangulate the model cells.
void LandmarkBasedRegistration(vtkSmartPointer< vtkPolyData > fixedMesh, const bool similarity=false)
Computes the landmark transform registration of the current mesh to the one provided. Requires point correspondence and same number of points.
Definition: milxModel.cxx:387
void thresholdScalars(double lowValue=0.0, double upValue=0.0, double outsideVal=0.0)
Threshold scalar values on the mesh. Geometry and topology is unchanged.
vtkSmartPointer< vtkPolyData > GetOutput()
Returns the mesh data object (PolyData) used internally VTK style.
QMenu * arrayMenu
arrays Menu
Definition: milxQtModel.h:1077
void generateQuantisedPoints(float quantiseFactor=0.0)
Generates points that are snapped to a grid given by factor.
QAction * saveViewAct
Save camera view.
vtkSmartPointer< vtkDataArray > GetScalars()
Returns the scalars of the model currently held.
Definition: milxQtModel.h:299
QAction * genVerticesAct
Action for generating vertices.
Definition: milxQtModel.h:998
QAction * viewXY
Change view to xy-plane (Axial)
void reset()
Reset the display of the model, includes camera and regeneration.
Definition: milxQtModel.h:435
void resetScalarRange()
Restores the scalar range of the model currently held to current max range for display.
Definition: milxQtModel.h:358
static vnl_matrix< Type > CovarianceMatrix(vnl_vector< Type > sourceVector)
Compute the covariance matrix from a vector. EXPERIMENTAL.
Definition: milxMath.h:310
void Clean()
Removes duplicate points etc. from model.
Definition: milxModel.cxx:286
void curvature()
Compute the mean curvature of mesh and place the curvature as scalars on mesh.
void outlineDisplay()
Toggles the outline box display.
bool labelled
Labels generated?
Definition: milxQtModel.h:965
void smooth(int iterations=0)
Smooth the model using the standard Laplacian approach. Iterations to smooth by is acquired by input ...
QAction * genPointModelAct
Action for generating labels.
Definition: milxQtModel.h:1008
void Gradient()
Compute the gradient (using Laplace-Beltrami operator) of the scalars on the mesh.
Definition: milxModel.cxx:537
void flip(bool xAxis=false, bool yAxis=false, bool zAxis=false)
Flip model along any axis, useful for matching coordinate systems with ITK or flipping left to right...
void AddActor2D(vtkSmartPointer< vtkProp > actor)
Add a VTK actor to this window.
QAction * selectPointsAct
select points within contour
Definition: milxQtModel.h:1053
QMenu * transformMenu
Transform Menu.
Definition: milxQtModel.h:1027
void renameScalars(QString newName="")
Rename the scalars on the mesh.
QMenu * scalarMenu
Context Menu.
Definition: milxQtModel.h:1034
QAction * genSamplesAct
Action for generating sampled points on mesh.
Definition: milxQtModel.h:1009
vtkSmartPointer< vtkActor > outlineActor
Outline box actor.
Definition: milxQtModel.h:990
void GetScalarRange(double *range)
Returns the scalar range of the model.
Definition: milxModel.h:268
vtkSmartPointer< vtkPolyData > & PreviousResult()
Returns the previous model, i.e. the result of the penultimate operation.
Definition: milxModel.h:210
bool rendered
Scene as been setup for rendering? (by generateRender())
void generateTensorField(double newScale=0.0, float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates a tensor field model, i.e. ellipses at each point for the dataset. Arguments provided are f...
QList< QAction * > actionsToAdd
Context actions to add.
Definition: milxQtWindow.h:251
static Type CentroidSize(const vnl_matrix< Type > &data, const vnl_vector< Type > &centroid, bool norm=false)
Compute the centroid size or scale for a series of points.
Definition: milxMath.h:206
QAction * thresholdScalarsBinaryAct
Action for binary thresholding scalar values on model.
Definition: milxQtModel.h:1039
virtual ~milxQtModel()
The standard destructor.
Definition: milxQtModel.cpp:91
vtkSmartPointer< vtkDataArray > GetVectors()
Returns the vectors of the model currently held.
Definition: milxQtModel.h:307
void showArray(QAction *action)
Change scalars on model to one given by string or action.
void GenerateVectorField(const double newScale=0.0, const bool useNormals=false)
Generate vector field for vectors present (as an array) in the mesh at given scaling.
Definition: milxModel.cxx:1071
void transform(QString filename="", bool inverse=false)
Transform the model using a loaded affine transform file. File is asked for within this member...
void setupTooltips()
Assign tooltips to each action for users benefit. The tooltips explains the function of each action...
void SetScalars(vtkSmartPointer< vtkDataArray > modelScalars)
Sets the scalars for the model to be generated. Must pass a vtkDataArray or its derivatives (such as ...
virtual void copyToContextMenu(QMenu *copyMenu)
Copies the menu, by duplicating the entries, to the context menu. Connections are assumed to be made ...
void SetActiveScalars(std::string nameOfArray)
Sets the array of name as scalars for the model to be generated.
Definition: milxQtModel.h:191
QAction * viewZX
Change view to zx-plane (Sagittal)
void imageAvailable(vtkImageData *, QString)
Send signal that an image is available for showing.
QMenu * operationsMenu()
Return the operations menu with the milxQtModel class ordering. This is for the benefit of derived cl...
void generateVerticesAs(const GlyphType glyphType=Circle, float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates the vertices as 2D circles for the dataset. Arguments provided are for the colours of the v...
QMenu * showMenu
Camera Menu.
Definition: milxQtModel.h:1046
vtkSmartPointer< vtkPolyData > GetPolyDataInput()
Returns the original mesh data object (PolyData) used internally VTK style.
void generateVectorField(double newScale=0.0, float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates a vector field model, i.e. arrows at each point for the dataset. Arguments provided are for...
void DistanceMap(vtkSmartPointer< vtkPoints > loopPoints)
Compute the distance map of the mesh points given a loop (as points) assumed to be on the mesh surfac...
Definition: milxModel.cxx:562
void disableCubeAxes()
Disables the cube axes display.
vtkIdType GetNumberOfPoints()
Returns the total number of points of the model currently held.
Definition: milxModel.h:238
QAction * genNormalsAct
Action for generating normals.
Definition: milxQtModel.h:999
void done(int value)
Send signal that computation is done. Value carries the progress,.
vtkSmartPointer< vtkScalarBarActor > scale
Scale for the display.
QMenu * transformsMenu()
Return the transform menu with the milxQtModel class ordering. This is for the benefit of derived cla...
void setView(int viewMode)
Change view to view mode identified by number. 0-axial, 1-coronal, 2-sagittal.
QAction * genHedgehogAct
Action for generating Hedgehog fields.
Definition: milxQtModel.h:1002
QAction * thresholdAct
Action for thresholding model.
Definition: milxQtModel.h:1037
void background(bool white=false)
Changes background to white.
QAction * matchAct
Action for matching scale and centroids of two models.
Definition: milxQtModel.h:1029
void GenerateNormals(const int pointNormals=0)
Generate normal vectors for each point on the mesh. If pointNormals is (0,1,2), then normals are for ...
Definition: milxModel.cxx:1158
void generatePolyDataFromImage(vtkSmartPointer< vtkImageData > img)
Generates polygonal data from image data, i.e. the result is a surface.
QAction * outScalarsAct
Action for output of scalars.
Definition: milxQtModel.h:1044
void setDefaultView(int viewMode)
Change default view to view mode identified by number. 0-axial, 1-coronal, 2-sagittal.
void removeOverlays()
Removes all actors that are overlaid with the model.
void GeneratePointModel(const double newScale)
Generate spheres of scaling for each point of the mesh.
Definition: milxModel.cxx:1027
void Clip(const coordinateType belowValue, const coordinateType aboveValue)
Clip the mesh based on a scalar threshold of the mesh scalars.
Definition: milxModel.cxx:675
void GenerateElevation(double x, double y, double z)
Generate scalar field for the mesh proportional to the elevation (dot product) with a given vector/di...
Definition: milxModel.cxx:1333
void IterativeClosestPointsRegistration(vtkSmartPointer< vtkPolyData > fixedMesh, const bool similarity=false, const int maxPoints=1024)
Computes the ICP registration of the current mesh to the one provided.
Definition: milxModel.cxx:359
milx::Model model
Actual model and its operations (from SMILI)
Definition: milxQtModel.h:979
virtual void selectPointsInContour()
Select model points inside contour and compute distance map.
void GenerateKMeansClustering(int numberOfClusters)
Generate k-means clustering for the point positions in the mesh.
Definition: milxModel.cxx:1197
void GenerateTubes()
Generate tubes along edges of the mesh.
Definition: milxModel.cxx:1007
void texture()
Emit texture of the model.
QMenu * generateMenu
Menu for generating viewing options.
Definition: milxQtModel.h:996
void refresh()
Refresh the display of the model including widgets. Camera remains as is.
vtkSmartPointer< vtkDataArray > GetNormals()
Returns the normals of the model currently held.
Definition: milxQtModel.h:315
QMenu * operateMenu
Operate Menu.
Definition: milxQtModel.h:1017
void GenerateQuantisedPoints(float quantiseFactor)
Generate points of the mesh to have integral cordinates.
Definition: milxModel.cxx:1254
QAction * interpAct
Action for changing the interpolation of a model.
Definition: milxQtModel.h:1067
void SetScalars(vtkSmartPointer< vtkDataArray > modelScalars)
Sets the scalar field of the mesh (values per vertex of the surface)
Definition: milxModel.cxx:218
void Triangulate()
Ensures the polygons in the model are triangulated. Useful when some filters required triangulation b...
Definition: milxModel.cxx:305
QAction * genDelaunayAct
Action for generating Delaunay graphs.
Definition: milxQtModel.h:1003
QActionGroup * displayGroup
Grouping for check boxes.
Definition: milxQtModel.h:1072
void printInfo(QString msg)
Info message wrapper for console.
void GaussianWeightScalars(float stddev, float clampValue)
Evaluate the Gaussian function with the given standard deviation for all values of the scalars on the...
Definition: milxModel.cxx:584
bool useDefaultView
Using log scalar map?
QAction * rotateAct
Action for rotating surface.
Definition: milxQtModel.h:1064
void ClusterDecimate()
Decimate the mesh (in terms of points) using the Quadric Clustering algorithm.
Definition: milxModel.cxx:454
void IsoSurface(vtkSmartPointer< vtkImageData > img, double minValue)
Definition: milxModel.cxx:744
void generateElevation()
Generates scalars based on the elevation from the bounding box extremes of the mesh.
void working(int value)
Send signal that computation is in progress. Value carries the progress,.
vtkSmartPointer< vtkScalarBarWidget > scalarBar
Scalar Bar Widget for the display.
QMenu * windowPropertiesMenu
Context Menu.
vtkRenderer * GetRenderer()
Returns the VTK Renderer object.
QAction * doAct
Action for undoing and redoing actions.
Definition: milxQtModel.h:1059
virtual void background(bool white=false)
Changes background to white.
void Rotate(const bool xAxis, const bool yAxis, const bool zAxis, const float angle, const coordinate centre)
Rotate the mesh along the selected axes from the centre by angle.
Definition: milxModel.cxx:608
vtkSmartPointer< vtkCubeAxesActor > cubeAxesActor
outline box
Definition: milxQtModel.h:992
bool undidProcess
Undid a process?
Definition: milxQtModel.h:973
QStatusBar * updateBar
Pointer to bar, not allocated or deleted. To be passed to only.
void normals(const bool turnOn=false)
Shows the point normals of the model.
QAction * genElevation
Action for elevation scalars of mesh.
Definition: milxQtModel.h:1014
QList< QMenu * > menusToAppend
Context Menu&#39;s to append.
Definition: milxQtWindow.h:255
virtual void viewToXYPlane()
Change view to xy-plane.
QAction * loadViewAct
Load camera view.
void toggleSpecular(bool quiet=false)
Toggles the specular or shininess of the mesh between Flat and Shiny. Default is Shiny.
void SetGraph(vtkSmartPointer< vtkMutableUndirectedGraph > graph)
Assigns the graph provided to the class, preparing for display. Call generateModel() and then show() ...
QAction * genPointIDsAct
Action for generating labels.
Definition: milxQtModel.h:1007
void removeModelActor(vtkSmartPointer< vtkActor > mdlActor)
Directly remove model actor from generic view.
vtkSmartPointer< vtkPointPicker > dataPicker
For determining coordinates and points from the window.
void threshold(double lowValue=0.0, double upValue=0.0)
Clip the mesh based on scalar values on the mesh.
QAction * transformAct
Action for transforming model.
Definition: milxQtModel.h:1028
void clean()
Clean the model of duplicate points by merging appropriately.
QAction * loadViewFileAct
Load camera view to file.
void generateHedgehog(double newScale=0.0, float red=defaultColour, float green=defaultColour, float blue=defaultColour)
Generates a hedgehog model, i.e. lines at each point for the dataset whose lengths are given by the v...