vtkReverseSense can help us to reverse the direction of point normals and cell normals.
The following code shows a simple example which display vertexes’ normals by cones in a sphere.
Here is its original geometric states.
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkLight.h>
#include <vtkPolyDataNormals.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkTransform.h>
#include <vtkCamera.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkGlyph3D.h>
#include <vtkReverseSense.h>
int main(int argc, char *argv[])
{
vtkSmartPointer<vtkSphereSource> sphere =
vtkSmartPointer<vtkSphereSource>::New();
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection( sphere->GetOutputPort() );
vtkSmartPointer<vtkActor> surfaceActor =
vtkSmartPointer<vtkActor>::New();
surfaceActor->SetMapper( mapper );
vtkSmartPointer<vtkPolyDataNormals> pdNormals =
vtkSmartPointer<vtkPolyDataNormals>::New();
pdNormals->SetInputConnection( sphere->GetOutputPort() );
pdNormals->ComputeCellNormalsOn();
pdNormals->Update();
vtkSmartPointer<vtkConeSource> cone =
vtkSmartPointer<vtkConeSource>::New();
cone->SetResolution( 6 );
vtkSmartPointer<vtkTransform> transform =
vtkSmartPointer<vtkTransform>::New();
transform->RotateY( 180 ); // make vertex outside
vtkSmartPointer<vtkTransformPolyDataFilter> transformF =
vtkSmartPointer<vtkTransformPolyDataFilter>::New();
transformF->SetInputConnection( cone->GetOutputPort() );
transformF->SetTransform( transform );
vtkSmartPointer<vtkGlyph3D> glyph =
vtkSmartPointer<vtkGlyph3D>::New();
glyph->SetInputConnection( pdNormals->GetOutputPort() );
glyph->SetSourceConnection( transformF->GetOutputPort() ); // source => transform => graph3D
glyph->SetVectorModeToUseNormal();
glyph->SetScaleModeToScaleByVector();
glyph->SetScaleFactor( 0.1 );
vtkSmartPointer<vtkPolyDataMapper> spikeMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
spikeMapper->SetInputConnection( glyph->GetOutputPort() );
vtkSmartPointer<vtkActor> spikeActor = vtkSmartPointer<vtkActor>::New();
spikeActor->SetMapper( spikeMapper );
spikeActor->GetProperty()->SetColor( 0.0, 0.79, 0.34 );
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(spikeActor);
renderer->AddActor(surfaceActor);
renderer->SetBackground( 0, 0, 0 );
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer( renderer );
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow( renderWindow );
renderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
We use vtkReverseSense to handle dataset of pdNormals, make all normals point to opposite direction.
vtkSmartPointer<vtkReverseSense> reverseF =
vtkSmartPointer<vtkReverseSense>::New();
reverseF->SetInputConnection( pdNormals->GetOutputPort() );
reverseF->ReverseNormalsOn();
glyph->SetInputConnection( reverseF->GetOutputPort() );
The final result: