The sample code I provide here allows you to easily compare SetComputePointNormals(true) and SetComputePointNormals(false), so we can compare the correct behavior with the incorrect behavior, shown in this image:
Here is the code:
#include <vtkActor.h>
#include <vtkNew.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkPolyDataNormals.h>
#include <vtkPolyDataReader.h>
#include <vtkPolyDataMapper.h>
#include <vtkCleanPolyData.h>
int main(int argc, char* argv[])
{
if(argc != 3) {
std::cout <<
"Error: We need the filename in argv[1], and argv[2] should be Y or N for ComputePointNormals"
<< std::endl;
return EXIT_FAILURE;
}
vtkNew<vtkPolyDataReader> reader;
reader->SetFileName(argv[1]);
reader->Update();
vtkNew<vtkCleanPolyData> cleaner;
cleaner->SetInputData(reader->GetOutput());
cleaner->ConvertPolysToLinesOn();
cleaner->ConvertLinesToPointsOn();
vtkNew<vtkPolyDataNormals> normals;
normals->SetInputConnection(cleaner->GetOutputPort());
normals->ComputeCellNormalsOn();
normals->SetComputePointNormals(argv[2][0] == 'Y');
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(normals->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
vtkNew<vtkRenderer> renderer;
renderer->AddActor(actor);
renderer->SetBackground(0.1, 0.4, 0.1);
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
renderWindow->SetSize(1500, 1000);
renderWindow->SetWindowName(argv[2]);
vtkNew<vtkRenderWindowInteractor> interactor;
interactor->SetRenderWindow(renderWindow);
interactor->Initialize();
renderWindow->Render();
renderWindow->Render();
interactor->Start();
return EXIT_SUCCESS;
}
And here is the file containing the polydata:
SourceData.vtk (282.7 KB)
You run the program like this:
programName SourceData.vtk Y
or like this:
programName SourceData.vtk N
The Y/N on the command line controls the boolean going into SetComputePointNormals()