I’m building a feature that requires turning on and off the splitting option inside the vtkPolyDataNormals filter after a user action. The problem is the recalling of the normal filter on the polydata coming from the previous iteration. The splitting does not take effect after the second iteration. Below is an example.
This example works. After clicking a button, I got the splitting set correctly, because the normals are calculated from the original clear polydata.
var Splitting = true;
var filename = "path to a STL file";
var reader = new vtkSTLReader();
reader.SetFileName(filename);
reader.Update();
vtkCleanPolyData cleanFilter = new vtkCleanPolyData();
cleanFilter.SetInputData(reader.GetOutput());
cleanFilter.Update();
var PolyData = cleanFilter.GetOutput();
vtkPolyDataNormals normals = new vtkPolyDataNormals();
normals.SetInputData(PolyData);
normals.SetSplitting(Splitting ? 1 : 0);
normals.Update();
Mapper = vtkPolyDataMapper.New();
Mapper.SetInputDataObject(normals.GetOutput());
Mapper.Update();
Actor = new vtkActor();
Actor.SetMapper(Mapper);
// Button clicked...
Splitting = false;
vtkPolyDataNormals normals = new vtkPolyDataNormals();
normals.SetInputData(PolyData);
normals.SetSplitting(Splitting ? 1 : 0);
normals.Update();
Mapper.SetInputDataObject(normals.GetOutput());
Mapper.Update();
In this second example, the behavior is the same, but when I click the button and I run the normal filter on the already filtered polydata. I do not get the same correct result as the previous example.
var Splitting = true;
var filename = "path to a STL file";
var reader = new vtkSTLReader();
reader.SetFileName(filename);
reader.Update();
vtkCleanPolyData cleanFilter = new vtkCleanPolyData();
cleanFilter.SetInputData(reader.GetOutput());
cleanFilter.Update();
vtkPolyDataNormals normals = new vtkPolyDataNormals();
normals.SetInputData(PolyData);
normals.SetSplitting(Splitting ? 1 : 0);
normals.Update();
var PolyData = normals.GetOutput();
Mapper = vtkPolyDataMapper.New();
Mapper.SetInputDataObject(PolyData);
Mapper.Update();
Actor = new vtkActor();
Actor.SetMapper(Mapper);
// Button clicked...
Splitting = false;
vtkPolyDataNormals normals = new vtkPolyDataNormals();
normals.SetInputData(PolyData);
normals.SetSplitting(Splitting ? 1 : 0);
normals.Update();
Mapper.SetInputDataObject(normals.GetOutput());
Mapper.Update();
It seems that the normal filter checks if the normals are already created so it skips the process. So my question is how can reset the polydata normals to force the splitting set?
according to the splitting On or Off the render of the actor is different. With splitting on (the vtk default one I guess) the rendering is a good one.
I’m building a feature that requires splitting off and I’m keeping in one of my classes a reference of the polydata coming from the vtkPolyDataNormals with splitting on.
When a call the callback of a particular action of my software, I use the polydata reference and I need to recalculate the normals but with slitting off. Doing that by re-applying the vtkPolyDataNormals to the polydata (that in the past has the normals already available with splicing omn) the result does not take effect.
In the example above I showed the behavior of applying a vtkPolyDataNormals filter for the second time to a polydata that already had the computed normals and not.
So I would like to understand if it’s possible to clear the normals of a polydata after applying the vtkPolyDataNormals filter or why if applying the vtkPolyDataNormals multiple times switching splitting on and off the result does not take effect.
You defined your PolyData with GetOutput(), which means the geometry will be computed at that point. In your first example you call it before applying the normals filter, thus you can apply it with splitting on and splitting off and get the expected result.
In the second example I am not sure where the first PolyData is coming from, but I suspect it is the output of a normals filter, thus applying the normals filter another time with splitting off won’t work as expected.
As a solution, I suggest using .GetOutputPort() and .SetInputConnection() instead. This not only makes it easier to adjust your pipeline on the fly, but also avoids computing geometries that you won’t be using directly.
So something like this:
var filename = "path to a STL file";
var reader = new vtkSTLReader();
reader.SetFileName(filename);
reader.Update();
vtkCleanPolyData cleanFilter = new vtkCleanPolyData();
cleanFilter.SetInputConnection(reader.GetOutputPort());
cleanFilter.Update();
vtkPolyDataNormals normals = new vtkPolyDataNormals();
normals.SetInputConnection(cleanFilter.GetOutputPort());
normals.SetSplitting(1);
normals.Update();
mapper = new vtkPolyDataMapper();
mapper.SetInputConnection(normals.GetOutputPort());
mapper.Update();
actor = new vtkActor();
actor.SetMapper(mapper);
Then the button-click could do the following:
normals.SetSplitting(0);
mapper.Update();
mapper.Update() should then re-compute the pipeline.
Thank you @David_Berger for your suggestion. I have tried it in a demo application and it works. The problem is that my official application (which is a very complex one) keeps a reference of the final polydata coming from the latest filter, then I keep a reference of the mapper and the actor. The polydata is used as input of several filters according to the feature that the user uses, so I can not keep the pipeline because I set new polydata to come from different filters to the mapper.
With your solution, I have to make a big refactor to my application so it’s not possible right now.
The point is, is it possible to reset/clean the normals of a vtkPolydata so when I apply the vtkPolydataNormal filter again it seems the first time?
@David_Berger the problem is not related to the STL file, because I have tried with different ones and the issue is the same. Today I have made several tries and I found if I apply a vtkCleanPolyData filter on the second iteration, it seems to work. I do know if the filter deletes, resets the polydata normals, or just because it creates a new polydata based on the input one then the output will not have the normals anymore so applying the vtkPolyDataNormals the result works.
// In the button click callback.
vtkCleanPolyData cleanFilter = new vtkCleanPolyData();
cleanFilter.SetInputData(PolyData);
cleanFilter.Update();
vtkPolyDataNormals normals = new vtkPolyDataNormals();
normals.SetInputConnection(cleanFilter.GetOutputPort());
if (Splitting)
{
normals.SplittingOn();
}
else
{
normals.SplittingOff();
}
normals.Update();
PolyData = normals.GetOutput();
Mapper.SetInputDataObject(normals.GetOutput());
Mapper.Update();
I have found a solution, but I would like to know the reason why it works and if there is a better way to delete the normals of a polydata without applying a filter that does different things.