Point Cloud Cutting with no results

I’m stuck trying to slice a vtkCutter through my vtkPolyData object. Normally this is not a problem but for some reason, I’m getting no results from the cutter on datasets where I need to use vtkVertexGlyphFilter on the polydata object. If I do not use a vtkVertexGlyphFilter the polydata object is not displayed in the view.

Here is the shortened code I used for testing. What am I doing wrong?

int main(int argc, char *argv[])
{

	string fileName = "c:\\TheFile.ply";
	
	vtkSmartPointer <vtkPLYReader> pvtkPlyReader = vtkSmartPointer <vtkPLYReader>::New();
	pvtkPlyReader->SetFileName(fileName.c_str());

	vtkSmartPointer < vtkPolyData> polyDataN = pvtkPlyReader->GetOutput();
	pvtkPlyReader->Update();

	double means[3] = { 0 };
	polyDataN->GetCenter(means);

	vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
	camera->SetPosition(0, 0, 4.0 * means[2]);
	camera->SetFocalPoint(means[0], means[1], means[2]);

	vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
	vtkSmartPointer<vtkRenderWindowInteractor> modelInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();

	vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	// Create a renderer, render window, and interactor
	vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();

	vtkSmartPointer<vtkActor> modelActor = vtkSmartPointer<vtkActor>::New();

	std::string renderWindowName;

	// Create a new polyData structure
	vtkSmartPointer<vtkPolyData> pointsPolydata = vtkSmartPointer<vtkPolyData>::New();
	vtkSmartPointer<vtkPolyData> polyDataNN = vtkSmartPointer<vtkPolyData>::New();
	// Set up arrays for the points, vertices and the colours
	vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
	vtkSmartPointer<vtkCellArray> vertices = vtkSmartPointer<vtkCellArray>::New();

	vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
	colors->SetNumberOfComponents(3);
	colors->SetName("Colors");

	//bool useColors = false;
	vtkSmartPointer<vtkUnsignedCharArray> pointColours = vtkSmartPointer<vtkUnsignedCharArray>::New();

	pointColours = vtkUnsignedCharArray::SafeDownCast(polyDataN->GetPointData()->GetArray(0));

	unsigned long nColours = pointColours->GetDataSize();
	vtkIdType nPoints = polyDataN->GetNumberOfPoints();
	for (int i = 0; i < nPoints; i++)
	{
		double p[3];
		polyDataN->GetPoint(i, p);
		unsigned char c[3] = { 0,0,0 };
		// Declare a variable to store the index of the point that gets added. 
		// This behaves just like an unsigned int.
		vtkIdType pid[1];

		int ncc = i * 3;
		c[0] = pointColours->GetValue(ncc);
		c[1] = pointColours->GetValue(ncc + 1);
		c[2] = pointColours->GetValue(ncc + 2);
		colors->InsertNextTypedTuple(c);

		pid[0] = points->InsertNextPoint(p[0], p[1], p[2]);

		// Create a vertex cell on the point that was just added.
		vertices->InsertNextCell(1, pid);
	}
	pointsPolydata->SetPoints(points);
	pointsPolydata->SetVerts(vertices);
	pointsPolydata->GetCellData()->SetScalars(colors);

	vtkSmartPointer<vtkVertexGlyphFilter> vertexFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New();

	vertexFilter->SetInputData(pointsPolydata);
	vertexFilter->Update();

	polyDataNN->ShallowCopy(vertexFilter->GetOutput());
	polyDataNN->GetPointData()->SetScalars(colors);
	mapper->SetInputData(polyDataNN);

	modelActor->SetMapper(mapper);
	modelActor->GetProperty()->SetPointSize(1);
	
	// Display the result
	// The axes are positioned with a user transform
	vtkSmartPointer<vtkTransform> axesTransform = vtkSmartPointer<vtkTransform>::New();
	axesTransform->Translate(0.0, 0.0, 0.0);

	axesTransform->Update();

	vtkSmartPointer<vtkAxesActor> axes = vtkSmartPointer<vtkAxesActor>::New();
	axes->SetUserTransform(axesTransform);
	vtkSmartPointer<vtkOrientationMarkerWidget> widget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
	widget->SetOrientationMarker(axes);

	renderer->SetBackground(.1, .2, .3);
	renderer->SetActiveCamera(camera);

	// Add the renderer to the window
	renderWindow->AddRenderer(renderer);

	modelInteractor->SetRenderWindow(renderWindow);

	widget->SetInteractor(modelInteractor);
	widget->SetViewport(0.0, 0.0, 0.4, 0.4);
	widget->SetEnabled(1);
	widget->InteractiveOn();

	double center[3] = { 0 };
	mapper->GetCenter(center);
	double zLevel = center[2];

	// Create a plane to cut the model, here it cuts in the XY plane (normal=(0,0,1))
	vtkSmartPointer < vtkPlane > cuttingPlane = vtkSmartPointer < vtkPlane >::New();
	cuttingPlane->SetOrigin(0, 0, zLevel);
	cuttingPlane->SetNormal(0, 0, 1);

	// Create cutter
	vtkSmartPointer < vtkCutter > planeCutter = vtkSmartPointer < vtkCutter >::New();
	planeCutter->SetCutFunction(cuttingPlane);
	planeCutter->SetInputData(mapper->GetInput());

	planeCutter->Update();
	vtkIdType numberOfLines = planeCutter->GetOutput()->GetNumberOfLines();  //<-- this is always 0

	vtkSmartPointer < vtkPolyDataMapper > planeCutterMapper = vtkSmartPointer < vtkPolyDataMapper >::New();
	planeCutterMapper->SetInputConnection(planeCutter->GetOutputPort());
	//planeCutterMapper->SetResolveCoincidentTopologyToPolygonOffset();
	planeCutterMapper->Update();



	vtkSmartPointer<vtkActor> cutterActor = vtkSmartPointer<vtkActor>::New();
	cutterActor->GetProperty()->SetPointSize(2);
	vtkNew<vtkNamedColors> color;
	cutterActor->GetProperty()->SetColor(color->GetColor3d("Red").GetData());
	cutterActor->GetProperty()->SetLineWidth(2);
	cutterActor->SetMapper(planeCutterMapper);

	renderer->AddActor(cutterActor);
	cutterActor->GetProperty()->SetInterpolationToFlat();

	renderer->AddActor(modelActor);
	modelActor->GetProperty()->SetInterpolationToFlat();

	modelInteractor->Initialize();

	renderWindow->SetWindowName(renderWindowName.c_str());

	// Set trackball mode of interaction
	vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
	modelInteractor->SetInteractorStyle(style);

	renderer->ResetCamera();

	renderWindow->Render();

	modelInteractor->Start();
	return EXIT_SUCCESS;
}

Thanks!

Typically cutting is thought of extracting a n-1 dimensional surface from a n-dimensional dataset. If you are cutting vertex cells, unless the plane passes precisely through a vertex, nothing will be output.

Are you instead trying to clip a collection of points? Here is the documentation from vtkCutter in case it helps:

  • In VTK, cutting means reducing a cell of dimension N to a cut surface
  • of dimension N-1. For example, a tetrahedron when cut by a plane (i.e.,
  • vtkPlane implicit function) will generate triangles. (In comparison,
  • clipping takes a N dimensional cell and creates N dimension primitives.)

Thanks, Will. I should say I know very little about 3D modelling. I’m given a PLY file and I’m trying to cut through the model to get the circumference at that z level.

Do you suggest that I use something else than the cutter or should I do more filtering on the vertex cells? I have tried using a Delaunay3D filter but the processing whent on for hours and I had to stop it.

Seem to get results now. I’ve pass the data through a 2D Delaunay filter before using the cutter.

Doesn’t the PLY file define polygons (not just vertices)? If so, you should be able to read the PLY data (which will output polydata containg the polygons), and then cut it to get the cut loop (using vtkCutter or vtkPolyDataPlaneCutter).

Anyway, I see that you’ve had some success with Delaunay2D…