vtkPolyDataToImageStencil issue

Hi everyone, I have a question about the usage of vtkPolyDataToImageStencil.

vtkSmartPointer<vtkCylinderSource> cy = vtkSmartPointer<vtkCylinderSource>::New();
cy->SetHeight(20);
cy->SetRadius(40);
cy->SetResolution(20);
cy->SetCenter(m_OriginalImage->GetCenter());	
vtkSmartPointer<vtkPolyDataToImageStencil> poly2Stencil = vtkSmartPointer<vtkPolyDataToImageStencil>::New();
poly2Stencil->SetInputConnection(cy->GetOutputPort());
poly2Stencil->SetOutputOrigin(m_OriginalImage->GetOrigin());
poly2Stencil->SetOutputSpacing(m_OriginalImage->GetSpacing());	
poly2Stencil->SetOutputWholeExtent(extent);
poly2Stencil->Update();

vtkSmartPointer<vtkImageStencil> stencil = vtkSmartPointer<vtkImageStencil>::New();
stencil->SetStencilData(poly2Stencil->GetOutput());
stencil->SetInputData(m_OriginalImage);
stencil->ReverseStencilOff();
double ranges[2];
m_OriginalImage->GetScalarRange(ranges);
stencil->SetBackgroundValue(ranges[0]);
stencil->Update();
m_BoneReductionImage = stencil->GetOutput();

Here is the code. I created a vtkCylinderSource, which is used as the input of the vtkPolyDataToImageStencil. In this block, it works well. But if I change “poly2Stencil->SetInputConnection(cy->GetOutputPort());” to “poly2Stencil->SetInputData(cy->GetOutput());”. This will not work.
Anyone knows how to understand this?

To use cy->GetOutput(), you must call Update() beforehand:

cy->Update();

With SetInputConnection() the upstream update is automatic. But with SetInputData(), you must do the upstream update yourself. That’s the main difference between SetInputConnection() and SetInputData().

2 Likes

Thank you so much for the fast reply and it works well!
So, the thing is I’m building my own polydata for the input. Here’s the code. I thought it was the polydata thing that makes this not work. But maybe I still miss some update call here?

vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
double origin[3];
m_OriginalImage->GetOrigin(origin);
double offsetx[14] = { 0, 5, 10, 15, 15, 10, 5, 0, -5, -10, -15, -15, -10, -5 };
double offsety[14] = { 0, 5, 10, 15, 25, 20, 15, 10, 15, 20, 25, 15, 10 ,5 };
for (int i = 0; i < 14; ++i) {
	points->InsertNextPoint(origin[0] + offsetx[i], origin[1] + offsety[i], origin[2]);
}
for (int i = 0; i < 14; ++i) {
	points->InsertNextPoint(origin[0] + offsetx[i], origin[1] + offsety[i], origin[2] + 20);
}

	// Generate the polygon poly data
	vtkIdType numPoints = points->GetNumberOfPoints();
	vtkSmartPointer<vtkCellArray> polygons = vtkSmartPointer<vtkCellArray>::New();
	vtkSmartPointer<vtkPolygon> boundaryPolygon1 = vtkSmartPointer<vtkPolygon>::New();
	vtkSmartPointer<vtkPolygon> boundaryPolygon2 = vtkSmartPointer<vtkPolygon>::New();
	int oneSidePointsNum = numPoints / 2;
	boundaryPolygon1->GetPointIds()->SetNumberOfIds(oneSidePointsNum);
	boundaryPolygon2->GetPointIds()->SetNumberOfIds(oneSidePointsNum);
	for (vtkIdType i = 0; i < oneSidePointsNum; i++) {
		boundaryPolygon1->GetPointIds()->SetId(i, i);
		boundaryPolygon2->GetPointIds()->SetId(i, i + oneSidePointsNum);
	}
	polygons->InsertNextCell(boundaryPolygon1);
	polygons->InsertNextCell(boundaryPolygon2);

	for (vtkIdType i = 0; i < oneSidePointsNum; i++) {
		vtkIdType ids[4] = { i, (i + 1) % 14, (i + 1) % 14 + 14, i + 14 };
		polygons->InsertNextCell(4, ids);
	}
	polygons->Modified();

	// Create a PolyData
	vtkSmartPointer<vtkPolyData> polygonPolyData = vtkSmartPointer<vtkPolyData>::New();
	polygonPolyData->SetPoints(points);
	polygonPolyData->SetPolys(polygons);
	polygonPolyData->Modified();

	// Generate the stencil according to the poly data
	vtkSmartPointer<vtkPolyDataToImageStencil> poly2Stencil = vtkSmartPointer<vtkPolyDataToImageStencil>::New();
	poly2Stencil->SetInputData(polygonPolyData);

The rest is the same

If you build your own polydata, then the Update() is not needed. When you run this code, does it give an error message, or does it do nothing?

You can check your polydata by writing a short test program that displays it (with vtkPolyDataMapper and vtkActor). Another useful check is vtkOutlineFilter, it will generate a polydata cube around your image, so that you can compare to the polydata that you built by hand.

so, in the the first example, I used the cylinder. The image will be cut out of a cylinder, which is desired.
And in this polydata example, the whole image disappears. But there is no error message

I’ll check the vtkOutlineFilter, thank you for your help!