2828#include < vtkPointData.h>
2929#include < vtkUnsignedShortArray.h>
3030
31+ #include < vtkDecimatePro.h>
3132#include < vtkEventQtSlotConnect.h>
3233#include < vtkInteractorStyleTrackballCamera.h>
3334#include < vtkLookupTable.h>
35+ #include < vtkPolyDataConnectivityFilter.h>
3436#include < vtkPolyDataMapper.h>
3537#include < vtkPropPicker.h>
3638#include < vtkProperty.h>
3739#include < vtkQuadricLODActor.h>
3840#include < vtkRenderWindow.h>
3941#include < vtkRenderer.h>
4042
41- #include < vtkPolyDataConnectivityFilter.h>
42-
4343#include < vtkAutoInit.h>
4444#ifdef ISEG_VTK_OPENGL2
4545VTK_MODULE_INIT (vtkRenderingOpenGL2);
@@ -77,8 +77,7 @@ void transform_slices_vtk(const std::vector<TIn*>& slices, size_t slice_size, TA
7777 }
7878}
7979
80- enum eActions
81- {
80+ enum eActions {
8281 kSelectTissue ,
8382 kGotoSlice ,
8483 kMarkPoint
@@ -111,6 +110,21 @@ SurfaceViewerWidget::SurfaceViewerWidget(SlicesHandler* hand3D1, eInputType inpu
111110 lb_connectivity_count = new QLabel (" " );
112111 lb_connectivity_count->setToolTip (" Number of connected regions" );
113112
113+ reduction = new QLineEdit (QString::number (0 ));
114+ reduction->setValidator (new QIntValidator (0 , 100 ));
115+ reduction->setToolTip (" Reduction of number triangles in percent." );
116+
117+ // set default reduction depending number of voxels.
118+ const auto N = static_cast <float >(hand3D->return_area ()) * hand3D->num_slices ();
119+ if (N > 1e8 )
120+ {
121+ reduction->setText (QString::number (80 ));
122+ }
123+ else if (N > 1e6 )
124+ {
125+ reduction->setText (QString::number (50 ));
126+ }
127+
114128 // layout
115129 auto vbox = new QVBoxLayout;
116130 vbox->addWidget (vtkWidget);
@@ -120,6 +134,10 @@ SurfaceViewerWidget::SurfaceViewerWidget(SlicesHandler* hand3D1, eInputType inpu
120134 transparency_hbox->addWidget (sl_trans);
121135 vbox->addLayout (transparency_hbox);
122136
137+ auto reduction_hbox = new QHBoxLayout;
138+ reduction_hbox->addWidget (reduction);
139+ vbox->addLayout (reduction_hbox);
140+
123141 if (input_type == kSource )
124142 {
125143 auto lb_thresh = new QLabel (" Contour iso-value" );
@@ -145,9 +163,10 @@ SurfaceViewerWidget::SurfaceViewerWidget(SlicesHandler* hand3D1, eInputType inpu
145163 setLayout (vbox);
146164
147165 // connections
148- QObject::connect (sl_trans, SIGNAL (sliderReleased ()), this , SLOT (transp_changed ()));
149- QObject::connect (bt_update, SIGNAL (clicked ()), this , SLOT (reload ()));
150- QObject::connect (bt_connectivity, SIGNAL (clicked ()), this , SLOT (split_surface ()));
166+ connect (sl_trans, SIGNAL (sliderReleased ()), this , SLOT (transp_changed ()));
167+ connect (bt_update, SIGNAL (clicked ()), this , SLOT (reload ()));
168+ connect (bt_connectivity, SIGNAL (clicked ()), this , SLOT (split_surface ()));
169+ connect (reduction, SIGNAL (editingFinished ()), this , SLOT (reduction_changed));
151170
152171 // setup vtk scene
153172 ren3D = vtkSmartPointer<vtkRenderer>::New ();
@@ -177,20 +196,24 @@ SurfaceViewerWidget::SurfaceViewerWidget(SlicesHandler* hand3D1, eInputType inpu
177196 input = vtkSmartPointer<vtkImageData>::New ();
178197 discreteCubes = vtkSmartPointer<vtkDiscreteFlyingEdges3D>::New ();
179198 cubes = vtkSmartPointer<vtkFlyingEdges3D>::New ();
199+ decimate = vtkSmartPointer<vtkDecimatePro>::New ();
200+ decimate->PreserveTopologyOn ();
201+ decimate->BoundaryVertexDeletionOff ();
202+ decimate->SplittingOff ();
203+ decimate->SetTargetReduction (reduction->text ().toDouble () / 100.0 );
180204
181205 load ();
182206
183207 vtkWidget->GetRenderWindow ()->Render ();
184208}
185209
186- SurfaceViewerWidget::~SurfaceViewerWidget ()
210+ SurfaceViewerWidget::~SurfaceViewerWidget ()
187211{
188-
189212}
190213
191214bool SurfaceViewerWidget::isOpenGLSupported ()
192215{
193- // todo: check e.g. via some helper process
216+ // todo: check e.g. via some helper process
194217 return true ;
195218}
196219
@@ -278,7 +301,9 @@ void SurfaceViewerWidget::load()
278301 cubes->SetInputData (input);
279302 cubes->SetValue (0 , range[0 ] + 0.01 * (range[1 ] - range[0 ]) * sl_thresh->value ());
280303
281- mapper->SetInputConnection (cubes->GetOutputPort ());
304+ decimate->SetInputConnection (cubes->GetOutputPort ());
305+
306+ mapper->SetInputConnection (decimate->GetOutputPort ());
282307 mapper->ScalarVisibilityOff ();
283308 }
284309 else
@@ -290,8 +315,9 @@ void SurfaceViewerWidget::load()
290315 // merge duplicate points (check if necessary)
291316 // connectivity filter & set random colors
292317 // mapper set input to connectivity output
318+ decimate->SetInputConnection (discreteCubes->GetOutputPort ());
293319
294- mapper->SetInputConnection (discreteCubes ->GetOutputPort ());
320+ mapper->SetInputConnection (decimate ->GetOutputPort ());
295321 if (input_type == kTarget )
296322 {
297323 mapper->ScalarVisibilityOff ();
@@ -322,7 +348,7 @@ void SurfaceViewerWidget::split_surface()
322348
323349 auto num_regions = connectivity->GetNumberOfExtractedRegions ();
324350 ISEG_INFO (" Number of disconnected regions: " << num_regions);
325-
351+
326352 // attach lookuptable
327353 auto lut = vtkSmartPointer<vtkLookupTable>::New ();
328354 lut->SetNumberOfTableValues (num_regions);
@@ -336,7 +362,7 @@ void SurfaceViewerWidget::split_surface()
336362
337363 auto output = vtkSmartPointer<vtkPolyData>::New ();
338364 output->ShallowCopy (connectivity->GetOutput ());
339-
365+
340366 mapper->SetInputData (output);
341367 mapper->ScalarVisibilityOn ();
342368 mapper->SetColorModeToMapScalars ();
@@ -555,6 +581,13 @@ void SurfaceViewerWidget::thresh_changed()
555581 }
556582}
557583
584+ void SurfaceViewerWidget::reduction_changed ()
585+ {
586+ decimate->SetTargetReduction (reduction->text ().toDouble () / 100.0 );
587+
588+ vtkWidget->GetRenderWindow ()->Render ();
589+ }
590+
558591int SurfaceViewerWidget::get_picked_tissue () const
559592{
560593 double * worldPosition = picker->GetPickPosition ();
@@ -580,4 +613,4 @@ int SurfaceViewerWidget::get_picked_tissue() const
580613 return -1 ;
581614}
582615
583- }// namespace iseg
616+ } // namespace iseg
0 commit comments