# ContoursToSurface

vtk-examples/Cxx/PolyData/ContoursToSurface

### Description¶

This example creates a stack of 21 circles and creates a closed surface from them.

Question

### Code¶

ContoursToSurface.cxx

#include <vtkActor.h>
#include <vtkAppendPolyData.h>
#include <vtkCellArray.h>
#include <vtkMath.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkVoxelContoursToSurfaceFilter.h>

namespace {
void CreateCircle(const double& z, const double& radius, const int& resolution,
vtkPolyData* polyData);
}

int main(int, char*[])
{
vtkNew<vtkNamedColors> colors;

// Create the data: a series of discs representing the intersections of x-y
// planes through a unit sphere centered at 0, 0, 0
//
int numDivisions = 20;
int resolution = 100;
double lastz = 0.0;
double z = 0.0;
double zmin = -0.9 * sphereRadius;
double zmax = 0.9 * sphereRadius;

// Append all the discs into one polydata
//
vtkNew<vtkAppendPolyData> appendFilter;

for (int i = 0; i <= numDivisions; ++i)
{
lastz = z;
double u = i / double(numDivisions);
z = (1. - u) * zmin + u * zmax;
vtkNew<vtkPolyData> circle;
}

double deltaz = z - lastz;

if (!appendFilter->GetNumberOfInputConnections(0))
{
cerr << "error, no contours!" << endl;
return EXIT_FAILURE;
}

appendFilter->Update();

// Convert to ijk coordinates for the contour to surface filter
//
double bounds[6];
vtkPolyData* contours = appendFilter->GetOutput();
contours->GetBounds(bounds);
double origin[3] = {bounds[0], bounds[2], bounds[4]};
double spacing[3] = {(bounds[1] - bounds[0]) / 40,
(bounds[3] - bounds[2]) / 40, deltaz};

vtkNew<vtkPolyData> poly;
vtkNew<vtkPoints> points;
vtkPoints* contourPoints = contours->GetPoints();
int numPoints = contourPoints->GetNumberOfPoints();
points->SetNumberOfPoints(numPoints);
for (int i = 0; i < numPoints; ++i)
{
double pt[3];
contourPoints->GetPoint(i, pt);
pt[0] = static_cast<int>((pt[0] - origin[0]) / spacing[0] + 0.5);
pt[1] = static_cast<int>((pt[1] - origin[1]) / spacing[1] + 0.5);
pt[2] = static_cast<int>((pt[2] - origin[2]) / spacing[2] + 0.5);
points->SetPoint(i, pt);
}
poly->SetPolys(contours->GetPolys());
poly->SetPoints(points);

// Create the contour to surface filter
//
vtkNew<vtkVoxelContoursToSurfaceFilter> contoursToSurface;
contoursToSurface->SetInputData(poly);
contoursToSurface->SetSpacing(spacing[0], spacing[1], spacing[2]);
contoursToSurface->Update();

// Rescale the output back into world coordinates and center it
//
double scaleCenter[3];
contoursToSurface->GetOutput()->GetCenter(scaleCenter);
double scaleBounds[6];
contoursToSurface->GetOutput()->GetBounds(scaleBounds);
double center[3];
contours->GetCenter(center);

vtkNew<vtkTransformPolyDataFilter> transformFilter;
transformFilter->SetInputConnection(contoursToSurface->GetOutputPort());
vtkNew<vtkTransform> transform;
transformFilter->SetTransform(transform);
transform->Translate(-scaleCenter[0], -scaleCenter[1], -scaleCenter[2]);
transform->Scale((bounds[1] - bounds[0]) / (scaleBounds[1] - scaleBounds[0]),
(bounds[3] - bounds[2]) / (scaleBounds[3] - scaleBounds[2]),
(bounds[5] - bounds[4]) / (scaleBounds[5] - scaleBounds[4]));
transform->Translate(center[0], center[1], center[2]);

// Visualize the contours
//
vtkNew<vtkPolyDataMapper> contoursMapper;
contoursMapper->SetInputData(contours);
contoursMapper->ScalarVisibilityOff();

vtkNew<vtkActor> contoursActor;
contoursActor->SetMapper(contoursMapper);
contoursActor->GetProperty()->SetRepresentationToWireframe();
contoursActor->GetProperty()->SetColor(
colors->GetColor3d("MistyRose").GetData());

// Visualize the surface
//
vtkNew<vtkPolyDataMapper> surfaceMapper;
surfaceMapper->SetInputConnection(transformFilter->GetOutputPort());
surfaceMapper->ScalarVisibilityOff();

vtkNew<vtkActor> surfaceActor;
surfaceActor->SetMapper(surfaceMapper);
surfaceActor->GetProperty()->SetRepresentationToWireframe();
surfaceActor->GetProperty()->SetColor(
colors->GetColor3d("MistyRose").GetData());

// Create two renderers side by side to show the contours and the surface
// separately
//
std::cout << "Press 't' for trackball interaction" << std::endl;
std::cout << "Press 'r' to reset the camera" << std::endl;
std::cout << "Press 'w' for wireframe representation" << std::endl;
std::cout << "Press 's' for surface representation" << std::endl;

vtkNew<vtkRenderer> renderer1;
renderer1->SetViewport(0., 0., 0.5, 1.);

vtkNew<vtkRenderer> renderer2;
renderer2->SetViewport(0.5, 0., 1., 1.);
renderer2->SetBackground(colors->GetColor3d("BurlyWood").GetData());

vtkNew<vtkRenderWindow> renderWindow;
renderWindow->SetSize(800, 400);
renderWindow->SetWindowName("ContoursToSurface");

vtkNew<vtkRenderWindowInteractor> interactor;
interactor->SetRenderWindow(renderWindow);

renderWindow->Render();

interactor->Start();

return EXIT_SUCCESS;
}

namespace {
void CreateCircle(const double& z, const double& radius, const int& resolution,
vtkPolyData* polyData)
{
vtkNew<vtkPoints> points;
vtkNew<vtkCellArray> cells;

points->SetNumberOfPoints(resolution);
cells->Allocate(1, resolution);
cells->InsertNextCell(resolution);

for (int i = 0; i < resolution; ++i)
{
double theta = vtkMath::RadiansFromDegrees(360. * i / double(resolution));
double x = radius * cos(theta);
double y = radius * sin(theta);
points->SetPoint(i, x, y, z);
cells->InsertCellPoint(i);
}

polyData->Initialize();
polyData->SetPolys(cells);
polyData->SetPoints(points);
}
} // namespace


### CMakeLists.txt¶

cmake_minimum_required(VERSION 3.12 FATAL_ERROR)

project(ContoursToSurface)

find_package(VTK COMPONENTS
CommonColor
CommonCore
CommonDataModel
CommonTransforms
FiltersCore
FiltersGeneral
InteractionStyle
RenderingContextOpenGL2
RenderingCore
RenderingFreeType
RenderingGL2PSOpenGL2
RenderingOpenGL2
)

if (NOT VTK_FOUND)
message(FATAL_ERROR "ContoursToSurface: Unable to find the VTK build folder.")
endif()

# Prevent a "command line is too long" failure in Windows.
set(CMAKE_NINJA_FORCE_RESPONSE_FILE "ON" CACHE BOOL "Force Ninja to use response files.")
target_link_libraries(ContoursToSurface PRIVATE ${VTK_LIBRARIES} ) # vtk_module_autoinit is needed vtk_module_autoinit( TARGETS ContoursToSurface MODULES${VTK_LIBRARIES}
)


cd ContoursToSurface/build


If VTK is installed:

cmake ..


If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:

cmake -DVTK_DIR:PATH=/home/me/vtk_build ..


Build the project:

make


and run it:

./ContoursToSurface


WINDOWS USERS

Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.