ExtrudePolyDataAlongLine
VTKExamples/Cxx/Visualization/ExtrudePolyDataAlongLine
Description¶
Extrude a 2D polydata along a line. It uses vtkRuledSurfaceFilter.
The example proceeds as follows:
-
Obtain the 2D polydata from a file( or generate a disk).
-
Generates random points in 3D space and fits a spline to the points.
-
Computes an orientation frame at each point on the line.
-
Places a copy of the 2D polydata at each point on the line, oriented by the the frame at that point.
-
For each contour in the 2D polydata, appends all of the copies.
-
Creates a ruled surface for each contour.
Note
This example requires the remote module ''SplineDrivenImageSampler.'' Check to see if the file ''SplineDrivenImageSlicer.remote.cmake'' exists in VTK/Remote. If it does not, copy this file to ''VTK/Remote/SplineDrivenImageSlicer.remote.cmake''.
Warning
A bug in vtkRuledSurfaceFilter occasionally drops triangles. This is being fixed.
Code¶
ExtrudePolyDataAlongLine.cxx
#include <vtkSmartPointer.h> #include <vtkRuledSurfaceFilter.h> #include <vtkParametricSpline.h> #include <vtkParametricFunctionSource.h> #include <vtkFrenetSerretFrame.h> #include <vtkAppendPolyData.h> #include <vtkCleanPolyData.h> #include <vtkPolyDataNormals.h> #include <vtkFeatureEdges.h> #include <vtkStripper.h> #include <vtkPolyDataConnectivityFilter.h> #include <vtkMath.h> #include <vtkTransform.h> #include <vtkTransformPolyDataFilter.h> #include <vtkMatrix4x4.h> #include <vtkDiskSource.h> #include <vtkLineSource.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[]) { // For testing vtkMath::RandomSeed(7859821); // 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 = 10 ; 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(50 * numberOfPoints); functionSource->SetVResolution(50 * numberOfPoints); functionSource->SetWResolution(50 * 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->SetOnRatio(1); ruled->SetDistanceFactor(10000000); ruled->SetInputConnection(skeletons[i]->GetOutputPort()); vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New(); normals->SetInputConnection(ruled->GetOutputPort()); vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(normals->GetOutputPort()); vtkSmartPointer<vtkProperty> backProp = vtkSmartPointer<vtkProperty>::New(); backProp->SetColor(1.0, 0.3882, 0.278); vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); actor->SetBackfaceProperty(backProp); actor->GetProperty()->SetColor(0.8900, 0.8100, 0.3400); actor->SetMapper(mapper); renderer->AddActor(actor); } // 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->SetBackground(.4, .5, .7); // Pick a good view renderer->ResetCamera(); renderer->GetActiveCamera()->Azimuth(120); renderer->GetActiveCamera()->Elevation(30); renderer->GetActiveCamera()->Dolly(1.1); renderer->ResetCameraClippingRange(); renderWindow->SetSize(512, 512); 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(); // Center the data vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); std::cout << reader->GetOutput()->GetCenter()[0] << ", " << reader->GetOutput()->GetCenter()[1] << ", " << reader->GetOutput()->GetCenter()[2] << std::endl; transform->Translate(-reader->GetOutput()->GetCenter()[0], -reader->GetOutput()->GetCenter()[1], -reader->GetOutput()->GetCenter()[2]); vtkSmartPointer<vtkTransformPolyDataFilter> transformPD = vtkSmartPointer<vtkTransformPolyDataFilter>::New(); transformPD->SetTransform(transform); transformPD->SetInputData(reader->GetOutput()); transformPD->Update(); polyData = transformPD->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¶
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
Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.