The filter vtkWarpScalar can help us to move the point along point normal by the scalar amount times the scale factor. We can change the size of the original model with it as long as there are normals in data.
The following example has two renderers, the left renderer shows the changed sphere by vtkWarpScalar and the right one has the original sphere. I set up the same active camera for both renderers to make interaction operations work on both sides.
#include <vtkActor.h>
#include <vtkDoubleArray.h>
#include <vtkPointData.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkWarpScalar.h>
#include <vtkProperty.h>
#include <vtkCamera.h>
#include <vtkMath.h>
int main(int, char *[])
{
vtkSmartPointer<vtkSphereSource> sphereSource =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource->Update();
vtkSmartPointer<vtkDoubleArray> scalars =
vtkSmartPointer<vtkDoubleArray>::New();
int numberOfPoints = sphereSource->GetOutput()->GetNumberOfPoints();
scalars->SetNumberOfTuples(numberOfPoints);
for(vtkIdType i = 0; i < numberOfPoints; ++i)
{
scalars->SetTuple1(i, 1);
}
sphereSource->GetOutput()->GetPointData()->SetScalars(scalars);
vtkSmartPointer<vtkWarpScalar> warpScalar =
vtkSmartPointer<vtkWarpScalar>::New();
warpScalar->SetInputConnection(sphereSource->GetOutputPort());
warpScalar->SetScaleFactor(1); // use the scalars themselves
warpScalar->UseNormalOff();
warpScalar->Update();
// Visualize
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
sphereMapper->SetInputConnection(sphereSource->GetOutputPort());
vtkSmartPointer<vtkActor> sphereActor =
vtkSmartPointer<vtkActor>::New();
sphereActor->SetMapper(sphereMapper);
sphereActor->GetProperty()->SetColor( 1, 1, 0 );
vtkSmartPointer<vtkPolyDataMapper> warpMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
warpMapper->SetInputConnection(warpScalar->GetOutputPort());
vtkSmartPointer<vtkActor> warpActor =
vtkSmartPointer<vtkActor>::New();
warpActor->SetMapper(warpMapper);
// Define viewport ranges
// (xmin, ymin, xmax, ymax) left-top and right-bottom point
double leftViewport[4] = {0.0, 0.0, 0.5, 1.0};
double rightViewport[4] = {0.5, 0.0, 1.0, 1.0};
// Setup renderers
vtkSmartPointer<vtkRenderer> leftRenderer =
vtkSmartPointer<vtkRenderer>::New();
leftRenderer->SetViewport(leftViewport);
leftRenderer->SetBackground(.6, .5, .4);
vtkSmartPointer<vtkRenderer> rightRenderer =
vtkSmartPointer<vtkRenderer>::New();
rightRenderer->SetViewport(rightViewport);
rightRenderer->SetBackground(.4, .5, .6); // rgb
leftRenderer->AddActor( warpActor );
rightRenderer->AddActor( sphereActor );
renderWindow->AddRenderer(leftRenderer);
renderWindow->AddRenderer(rightRenderer);
vtkSmartPointer<vtkCamera> camera =
vtkSmartPointer<vtkCamera>::New();
leftRenderer->SetActiveCamera( camera );
rightRenderer->SetActiveCamera( camera );
leftRenderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
If we set different scalars for the sphere, then the filter vtkWarpScalar will move a few points further than others due to the different scalar data. The color of spheres will also be changed.
vtkMath::RandomSeed(8775070); // for reproducibility
for(vtkIdType i = 0; i < numberOfPoints; ++i)
{
scalars->SetTuple1(i, vtkMath::Random(0.0, 0.5));
}
If we define normal for vtkWarpScalar object, it will move points along the normal direction.
warpScalar->UseNormalOn();
warpScalar->SetNormal(0, 0, 1);