ExtrudePolyDataAlongLine

VTKExamples/Cxx/Visualization/ExtrudePolyDataAlongLine

Code

ExtrudePolyDataAlongLine.cxx

#include <vtkFrenetSerretFrame.h>

#include <vtkSmartPointer.h>

#include <vtkParametricSpline.h>
#include <vtkParametricFunctionSource.h>
#include <vtkAppendPolyData.h>
#include <vtkRuledSurfaceFilter.h>
#include <vtkCleanPolyData.h>

#include <vtkLineSource.h>

#include <vtkFeatureEdges.h>
#include <vtkStripper.h>
#include <vtkPolyDataConnectivityFilter.h>

#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkMatrix4x4.h>
#include <vtkDiskSource.h>
#include <vtkPointSource.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>

#include <vtkProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkCamera.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>

#include <vtkPLYReader.h>
#include <vtkSTLReader.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkOBJReader.h>

#include <vtksys/SystemTools.hxx>

static vtkSmartPointer<vtkPolyData> ReadPolyData(const char *fileName);

int main(int argc, char *argv[])
{
  // Read a polydata
  vtkSmartPointer<vtkPolyData> polyData = ReadPolyData(argc > 1 ? argv[1] : "");;

  int numberOfContours = polyData->GetNumberOfLines();
  std::cout << "Number of contours: " << numberOfContours << std::endl;

  // Generate  some random points
  int numberOfPoints = 3;
  vtkSmartPointer<vtkPointSource> pointSource = 
    vtkSmartPointer<vtkPointSource>::New();
  pointSource->SetNumberOfPoints(numberOfPoints);
  pointSource->Update();

  vtkPoints* points = pointSource->GetOutput()->GetPoints();

  vtkSmartPointer<vtkParametricSpline> spline = 
    vtkSmartPointer<vtkParametricSpline>::New();
  spline->SetPoints(points);

  vtkSmartPointer<vtkParametricFunctionSource> functionSource = 
    vtkSmartPointer<vtkParametricFunctionSource>::New();
  functionSource->SetParametricFunction(spline);
  functionSource->SetUResolution(1 * numberOfPoints);
  functionSource->SetVResolution(1 * numberOfPoints);
  functionSource->SetWResolution(1 * numberOfPoints);

  // Create the frame
  vtkSmartPointer<vtkFrenetSerretFrame> frame =
    vtkSmartPointer<vtkFrenetSerretFrame>::New();
  frame->SetInputConnection(functionSource->GetOutputPort());
  frame->ConsistentNormalsOn();
  frame->Update();

  frame->GetOutput()->GetPointData()->SetActiveVectors("FSNormals");
  frame->GetOutput()->GetPointData()->SetActiveVectors("FSTangents");
  frame->GetOutput()->GetPointData()->SetActiveVectors("FSBinormals");

  vtkPoints *linePoints = frame->GetOutput()->GetPoints();

  std::vector<vtkSmartPointer<vtkAppendPolyData> >skeletons;
  for (int i = 0; i < numberOfContours; ++i)
  {
    skeletons.push_back(vtkSmartPointer<vtkAppendPolyData>::New());
  }

  for (int i = 0; i < linePoints->GetNumberOfPoints(); ++i)
  {
    vtkSmartPointer<vtkTransform> transform =
      vtkSmartPointer<vtkTransform>::New();

    // Compute a basis
    double normalizedX[3];
    frame->GetOutput()->GetPointData()->SetActiveVectors("FSNormals");
    frame->GetOutput()->GetPointData()->GetVectors()->GetTuple(i, normalizedX);
    double normalizedY[3];
    frame->GetOutput()->GetPointData()->SetActiveVectors("FSBinormals");
    frame->GetOutput()->GetPointData()->GetVectors()->GetTuple(i, normalizedY);
    double normalizedZ[3];
    frame->GetOutput()->GetPointData()->SetActiveVectors("FSTangents");
    frame->GetOutput()->GetPointData()->GetVectors()->GetTuple(i, normalizedZ);

    // Create the direction cosine matrix
    vtkSmartPointer<vtkMatrix4x4> matrix =
      vtkSmartPointer<vtkMatrix4x4>::New();
    matrix->Identity();
    for (unsigned int j = 0; j < 3; ++j)
    {
      matrix->SetElement(j, 0, normalizedX[j]);
      matrix->SetElement(j, 1, normalizedY[j]);
      matrix->SetElement(j, 2, normalizedZ[j]);
    }

    transform->Translate(linePoints->GetPoint(i)[0], linePoints->GetPoint(i)[1], linePoints->GetPoint(i)[2]);
    transform->Scale(.02, .02, .02);
    transform->Concatenate(matrix);

    vtkSmartPointer<vtkTransformPolyDataFilter> transformPD =
      vtkSmartPointer<vtkTransformPolyDataFilter>::New();
    vtkSmartPointer<vtkPolyData> polyDataCopy =
      vtkSmartPointer<vtkPolyData>::New();
    polyDataCopy->DeepCopy(polyData);
    transformPD->SetTransform(transform);
    transformPD->SetInputData(polyDataCopy);
    transformPD->Update();

    vtkSmartPointer<vtkPolyDataConnectivityFilter> contours =
      vtkSmartPointer<vtkPolyDataConnectivityFilter>::New();
    contours->SetInputConnection(transformPD->GetOutputPort());
    contours->Update();
    for (int r = 0; r < contours->GetNumberOfExtractedRegions(); ++r)
    {
      contours->SetExtractionModeToSpecifiedRegions();
      contours->InitializeSpecifiedRegionList();
      contours->AddSpecifiedRegion(r);
      contours->Update();
      vtkSmartPointer<vtkPolyData> skeleton =
        vtkSmartPointer<vtkPolyData>::New();
      skeleton->DeepCopy(contours->GetOutput());
      skeletons[r]->AddInputData(skeleton);
    }
  }
  vtkSmartPointer<vtkRenderer> renderer = 
    vtkSmartPointer<vtkRenderer>::New();

  for (int i = 0; i < numberOfContours; ++i)
  {
    vtkSmartPointer<vtkRuledSurfaceFilter> ruled = 
      vtkSmartPointer<vtkRuledSurfaceFilter>::New();
    ruled->SetRuledModeToPointWalk();
    ruled->CloseSurfaceOff();
    ruled->SetDistanceFactor(10000000);
    ruled->SetInputConnection(skeletons[i]->GetOutputPort());

    vtkSmartPointer<vtkCleanPolyData> clean = 
      vtkSmartPointer<vtkCleanPolyData>::New();
    clean->SetInputConnection(ruled->GetOutputPort());
    vtkSmartPointer<vtkPolyDataMapper> mapper = 
      vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(clean->GetOutputPort());
    vtkSmartPointer<vtkProperty> backProp = 
      vtkSmartPointer<vtkProperty>::New();
    backProp->SetColor(1,0,0);
    vtkSmartPointer<vtkActor> actor = 
      vtkSmartPointer<vtkActor>::New();
    actor->SetBackfaceProperty(backProp);
    actor->SetMapper(mapper);
    renderer->AddActor(actor);
  }  
  vtkSmartPointer<vtkPolyDataMapper> lineMapper = 
    vtkSmartPointer<vtkPolyDataMapper>::New();
  lineMapper->SetInputConnection(functionSource->GetOutputPort());

  vtkSmartPointer<vtkActor> lineActor = 
    vtkSmartPointer<vtkActor>::New();
  lineActor->SetMapper(lineMapper);

  // Setup render window, renderer, and interactor
  vtkSmartPointer<vtkRenderWindow> renderWindow = 
    vtkSmartPointer<vtkRenderWindow>::New();
  renderWindow->AddRenderer(renderer);
  vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = 
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
  renderWindowInteractor->SetRenderWindow(renderWindow);

  renderer->AddActor(lineActor);

  renderer->SetBackground(.4, .5, .7);

  // Pick a good view
  renderer->ResetCamera();
  renderer->GetActiveCamera()->Azimuth(120);
  renderer->GetActiveCamera()->Elevation(30);
  renderer->GetActiveCamera()->Dolly(1.8);
  renderer->ResetCameraClippingRange();

  renderWindow->SetSize(640, 480);
  renderWindow->Render();
  renderWindowInteractor->Start();

  return EXIT_SUCCESS;
}

static vtkSmartPointer<vtkPolyData> ReadPolyData(const char *fileName)
{
  vtkSmartPointer<vtkPolyData> polyData;
  std::string extension = vtksys::SystemTools::GetFilenameExtension(std::string(fileName));
  if (extension == ".ply")
  {
    vtkSmartPointer<vtkPLYReader> reader =
      vtkSmartPointer<vtkPLYReader>::New();
    reader->SetFileName (fileName);
    reader->Update();
    polyData = reader->GetOutput();
  }
  else if (extension == ".vtp")
  {
    vtkSmartPointer<vtkXMLPolyDataReader> reader =
      vtkSmartPointer<vtkXMLPolyDataReader>::New();
    reader->SetFileName (fileName);
    reader->Update();
    polyData = reader->GetOutput();
  }
  else if (extension == ".obj")
  {
    vtkSmartPointer<vtkOBJReader> reader =
      vtkSmartPointer<vtkOBJReader>::New();
    reader->SetFileName (fileName);
    reader->Update();
    polyData = reader->GetOutput();
  }
  else if (extension == ".stl")
  {
    vtkSmartPointer<vtkSTLReader> reader =
      vtkSmartPointer<vtkSTLReader>::New();
    reader->SetFileName (fileName);
    reader->Update();
    polyData = reader->GetOutput();
  }
  else
  {
    vtkSmartPointer<vtkDiskSource> diskSource = 
      vtkSmartPointer<vtkDiskSource>::New();
    diskSource->SetCircumferentialResolution(3);

    vtkSmartPointer<vtkCleanPolyData> clean = 
      vtkSmartPointer<vtkCleanPolyData>::New();
    clean->SetInputConnection(diskSource->GetOutputPort());

    vtkSmartPointer<vtkFeatureEdges> edges =
      vtkSmartPointer<vtkFeatureEdges>::New();
    edges->SetInputConnection(clean->GetOutputPort());
    edges->NonManifoldEdgesOff();
    edges->ManifoldEdgesOff();
    edges->BoundaryEdgesOn();
    edges->FeatureEdgesOff();

    vtkSmartPointer<vtkStripper> stripper =
      vtkSmartPointer<vtkStripper>::New();
    stripper->SetInputConnection(edges->GetOutputPort());
    stripper->Update();
    polyData = stripper->GetOutput();
#if 0

    vtkSmartPointer<vtkLineSource> lineSource = 
      vtkSmartPointer<vtkLineSource>::New();
    lineSource->SetResolution(10);
    lineSource->Update();

    polyData = lineSource->GetOutput();
#endif
  }
  return polyData;
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

PROJECT(ExtrudePolyDataAlongLine)

find_package(VTK REQUIRED)
include(${VTK_USE_FILE})

add_executable(ExtrudePolyDataAlongLine MACOSX_BUNDLE ExtrudePolyDataAlongLine.cxx)

target_link_libraries(ExtrudePolyDataAlongLine ${VTK_LIBRARIES})

Download and Build ExtrudePolyDataAlongLine

Danger

The generation of tar files has not been ported to the new VTKExamples. Some tarballs may be missing or out-of-date.

Click here to download ExtrudePolyDataAlongLine and its CMakeLists.txt file. Once the tarball ExtrudePolyDataAlongLine.tar has been downloaded and extracted,

cd ExtrudePolyDataAlongLine/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:

./ExtrudePolyDataAlongLine

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