Contour filter - add nodes programatically

(Andyjk1406) #1

I’m struggling to add nodes programatically. I can add one, but then things crash when I try to add a second or try to interact to add more nodes.
I have modified this example with about 6 more lines near the end as shown below https://vtk.org/Wiki/VTK/Examples/Cxx/PolyData/PolygonalSurfaceContourLineInterpolator

#include <vtkVersion.h>
#include "vtkSmartPointer.h"

#include "vtkActor.h"
#include "vtkCamera.h"
#include "vtkCellArray.h"
#include "vtkImageDataGeometryFilter.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkPolyDataCollection.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkSphereSource.h"
#include "vtkTriangleFilter.h"
#include "vtkXMLPolyDataReader.h"

#include "vtkContourWidget.h"
#include "vtkOrientedGlyphContourRepresentation.h"
#include "vtkPolygonalSurfacePointPlacer.h"
#include "vtkPolygonalSurfaceContourLineInterpolator.h"


int main(int argc, char *argv[])
{
  vtkSmartPointer<vtkPolyData> polyData;
  if (argc < 2)
    {
    vtkSmartPointer<vtkSphereSource> sphereSource = 
      vtkSmartPointer<vtkSphereSource>::New();
    sphereSource->SetThetaResolution(40);
    sphereSource->SetPhiResolution(20);
    sphereSource->Update();

    polyData = sphereSource->GetOutput();
    }
  else
    {
    vtkSmartPointer<vtkXMLPolyDataReader> reader = 
      vtkSmartPointer<vtkXMLPolyDataReader>::New();
    reader->SetFileName(argv[1]);
    reader->Update();
    polyData = reader->GetOutput();
    }
      
  // The Dijkistra interpolator will not accept cells that aren't triangles
  vtkSmartPointer<vtkTriangleFilter> triangleFilter = 
    vtkSmartPointer<vtkTriangleFilter>::New();
#if VTK_MAJOR_VERSION <= 5
  triangleFilter->SetInput( polyData );
#else
  triangleFilter->SetInputData( polyData );
#endif
  triangleFilter->Update();
  
  vtkSmartPointer<vtkPolyData> pd = triangleFilter->GetOutput();
  
  //Create a mapper and actor
  vtkSmartPointer<vtkPolyDataMapper> mapper = 
    vtkSmartPointer<vtkPolyDataMapper>::New();
  mapper->SetInputConnection(triangleFilter->GetOutputPort());
 
  vtkSmartPointer<vtkActor> actor = 
    vtkSmartPointer<vtkActor>::New();
  actor->SetMapper(mapper);
  actor->GetProperty()->SetInterpolationToFlat();
  
  // Create the render window, renderer and interactor.
 
  vtkSmartPointer<vtkRenderer> renderer = 
    vtkSmartPointer<vtkRenderer>::New();
  vtkSmartPointer<vtkRenderWindow> renderWindow = 
    vtkSmartPointer<vtkRenderWindow>::New();
  renderWindow->AddRenderer(renderer);
  vtkSmartPointer<vtkRenderWindowInteractor> interactor = 
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
  interactor->SetRenderWindow(renderWindow);
  
  // Add the actors to the renderer, set the background and size
  
  renderer->AddActor(actor);
  renderer->SetBackground (.3, .4, .5);

  // Here comes the contour widget stuff...

  vtkSmartPointer<vtkContourWidget> contourWidget = 
    vtkSmartPointer<vtkContourWidget>::New();
  contourWidget->SetInteractor(interactor);
  vtkSmartPointer<vtkOrientedGlyphContourRepresentation> rep = 
    vtkOrientedGlyphContourRepresentation::SafeDownCast(
      contourWidget->GetRepresentation());
  rep->GetLinesProperty()->SetColor(1, 0.2, 0);
  rep->GetLinesProperty()->SetLineWidth(3.0);

  vtkSmartPointer<vtkPolygonalSurfacePointPlacer> pointPlacer =
    vtkSmartPointer<vtkPolygonalSurfacePointPlacer>::New();
  pointPlacer->AddProp(actor);
  pointPlacer->GetPolys()->AddItem( pd );
  rep->SetPointPlacer(pointPlacer);

  vtkSmartPointer<vtkPolygonalSurfaceContourLineInterpolator> interpolator =
    vtkSmartPointer<vtkPolygonalSurfaceContourLineInterpolator>::New();
  interpolator->GetPolys()->AddItem( pd );
  rep->SetLineInterpolator(interpolator);
  
  renderWindow->Render();
  interactor->Initialize();

  contourWidget->EnabledOn();
  contourWidget->Initialize();
  contourWidget->EnabledOff();

  double pt1[3]; pt1[0] = -0.107433; pt1[1] = 0.112549; pt1[2] = 0.474558;
  contourWidget->SetWidgetState(vtkContourWidget::Define);
  contourWidget->GetContourRepresentation()->AddNodeAtWorldPosition(pt1);

  //double pt2[3]; pt2[0] = 0.187556; pt2[1] = 0.187556; pt2[2] = 0.42192;
  //contourWidget->GetContourRepresentation()->AddNodeAtWorldPosition(pt2); // This causes a crash!
 
  contourWidget->EnabledOn();
  interactor->Start();

  return EXIT_SUCCESS;
}
(Andras Lasso) #2

We’ve struggled with trying to make VTK widgets work in our application for several years. It was extremely complicated to update state of widgets from outside (we needed that because we had to display widgets in multiple views and VTK widgets cannot share any information), it was very slow (because many objects are created for each handle, etc.), GUI->widget event translation was very rigid (not possible to define shortcuts for specific widget states, basic events, such as click and double-click was very complicated to implement, …), design of various widgets was very inconsistent (there seemed to ne 2-3 different generations of widgets, each suffering from different limitations).

We finally gave up on using VTK’s widgets infrastructure and developed on our own (based on MRML library in 3D Slicer). It took several months to recreate basic widgets (point list, line, angle, open and closed curves, image slice intersection, window/level, camera), but now we can do things that we were just dreaming about in the last few years. Things are much simpler, most VTK data objects (point positions, pickers, interpolators, locators) are stored only once and shared between all widget instances in views, speed is magnitudes faster (we could not have more than a few hundred interactive handles because interaction slowed down with them so much; now we can easily interact with tens of thousands of points).

Unfortunately, this implementation cannot be easily detached from the MRML library, so if you are suffering from the pain of trying to make VTK widgets work then you may either need to develop your own (from scratch or based on our implementation) or use MRML or 3D Slicer. Maybe in a few years we will revisit if the widgets can be decoupled from MRML and merge back to VTK, but for now we are focusing on adding more widgets, improve virtual reality/touchpad/multi-touch support, etc.

1 Like