vtkSplineWidget(2) vtkMarchingSquares and vtkImageData

Hello everyone,

I’m working with vtk 8.2 on Windows 10 with VS 2017.

I try to create a closed Spline around the contour of a binary image in purpose to change the value of each pixels inside the closed spline.
To do this, I use vtkMarchingSquares to extract the contour of the binary image.
After that, I try to put the points from the output polydata of the vtkMarchingSquares but the spline is not set at the expected position.

I’m not sure what I did wrong. Maybe there is too much points on the contour?

#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkSplineWidget2.h>
#include <vtkSplineWidget.h>
#include <vtkCardinalSpline.h>
#include <vtkKochanekSpline.h>
#include <vtkParametricSpline.h>
#include <vtkImageData.h>
#include <vtkPointData.h>
#include <vtkDataSetMapper.h>
#include <vtkProperty.h>
#include <vtkImageActor.h>
#include <vtkContourFilter.h>
#include <vtkPolyData.h>
#include <vtkCellData.h>
#include <vtkDataArray.h>
#include <vtkCellArray.h>
#include <vtkPolyDataMapper.h>
#include <vtkMarchingSquares.h>
#include <vtkImageStack.h>
#include <vtkSplineRepresentation.h>

int main(int, char *[])
{
	vtkNew<vtkImageData> image;
	image->SetDimensions(512, 512, 2);
	image->SetOrigin(0, 0, 0);
	image->SetSpacing(0.97, 0.97, 1);
	image->AllocateScalars(VTK_SHORT, 1);
	for (int k = 0; k < 2; ++k)
	{
		for (int j = 0; j < 512; ++j)
		{
			for (int i = 0; i < 512; ++i)
			{
				short * pixel = static_cast<short *>(image->GetScalarPointer(i, j, k));
				if (i > 100 && i < 300 && j > 100 && j < 300)
				{
					pixel[0] = 255;
				}
				else
				{
					pixel[0] = 0;
				}
			}
		}
	}

	vtkNew<vtkMarchingSquares> contourFilter;
	contourFilter->SetInputData(image);
	contourFilter->GenerateValues(1, 255, 255);
	contourFilter->Update();
	vtkSmartPointer<vtkPolyData> contourPolyData = contourFilter->GetOutput();

	//	vtkNew<vtkDataSetMapper> imageMapper;
	//	imageMapper->SetInputData(image);
	vtkNew<vtkImageActor> imageActor;
	imageActor->SetInputData(image);

	vtkNew<vtkPolyDataMapper> contourMapper;
	contourMapper->SetInputData(contourPolyData);
	vtkNew<vtkActor> contourActor;
	contourActor->SetMapper(contourMapper);
	contourActor->GetProperty()->SetLineWidth(2);
	contourActor->GetProperty()->SetColor(1, 0, 0);

	// A renderer and render window
	vtkSmartPointer<vtkRenderer> renderer =
			vtkSmartPointer<vtkRenderer>::New();
	vtkSmartPointer<vtkRenderWindow> renderWindow =
			vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);

	// An interactor
	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
			vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	vtkNew<vtkParametricSpline> parametricSpline;
	parametricSpline->SetPoints(contourPolyData->GetPoints());

	vtkNew<vtkSplineRepresentation> splineRepresentation;
	splineRepresentation->SetParametricSpline(parametricSpline);
	vtkNew<vtkKochanekSpline> xSpline;
	vtkNew<vtkKochanekSpline> ySpline;
	vtkNew<vtkKochanekSpline> zSpline;
	splineRepresentation->GetParametricSpline()->SetXSpline(xSpline);
	splineRepresentation->GetParametricSpline()->SetYSpline(ySpline);
	splineRepresentation->GetParametricSpline()->SetZSpline(zSpline);
	splineRepresentation->GetParametricSpline()->SetPoints(contourPolyData->GetPoints());
	splineRepresentation->ClosedOn();

	vtkSmartPointer<vtkSplineWidget2> splineWidget =
			vtkSmartPointer<vtkSplineWidget2>::New();
	splineWidget->SetRepresentation(splineRepresentation);
	splineWidget->SetInteractor(renderWindowInteractor);

	renderWindowInteractor->Initialize();
	renderWindow->Render();
	splineWidget->On();
	renderer->AddActor(imageActor);
	renderer->ResetCamera();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

Hi everyone,

I really don’t understand the behavior of vtkSplineWidget and vtkSplineWidget2.
I do some tests like this:

I create a vtkParametricSpline with the same points that represents a square:

vtkNew<vtkPoints> points;
points->InsertNextPoint(0.97, 0.97, 0);
points->InsertNextPoint(0.97, 1.94, 0);
points->InsertNextPoint(0.97, 2.91, 0);
points->InsertNextPoint(1.94, 2.91, 0);
points->InsertNextPoint(2.91, 2.91, 0);
points->InsertNextPoint(2.91, 1.94, 0);
points->InsertNextPoint(2.91, 0.97, 0);
points->InsertNextPoint(1.94, 0.97, 0);
vtkNew<vtkParametricSpline> spline;
spline->SetPoints(edgeCoords);
spline->ClosedOn();

Once I display this spline using vtkSplineWidget:

vtkNew<vtkSplineWidget> splineWidget;
splineWidget->SetParametricSpline(spline);
splineWidget->SetInteractor(renderWindowInteractor);

I obtain this result:

vtkSplineWidget

Once I display the same spline using vtkSplineWidget2:

vtkNew<vtkSplineWidget2> splineWidget;
vtkNew<vtkSplineRepresentation> splineRepresentation;
splineRepresentation->SetParametricSpline(spline);
splineWidget->SetRepresentation(splineRepresentation);
splineWidget->SetInteractor(renderWindowInteractor);

I obtain this:

vtkSplineWidget2

And finally when I put the spline inside a vtkParametricFunctionSource and display it using a vtkPolydataMapper/vtkActor:

vtkNew<vtkParametricFunctionSource> functionSource;
functionSource->SetParametricFunction(spline);
functionSource->Update();
vtkNew<vtkPolyDataMapper> splineMapper;
splineMapper->SetInputConnection(functionSource->GetOutputPort());
vtkNew<vtkActor> splineActor;
splineActor->SetMapper(splineMapper);
splineActor->GetProperty()->SetLineWidth(2.0f);
splineActor->GetProperty()->SetColor(1.0, 0.0, 0.0);

I obtain the expected result:

vtkParametricFunctionSource

I really don’t understand what I did wrong using the vtkSplineWidget* object to not obtain the same result.

I read the documentation of those two widgets but I found nothing that can explain this behavior.