OrientedCylinder
VTKExamples/Cxx/GeometricObjects/OrientedCylinder
Description¶
This example illustrates how to create and display a cylinder that passes through two points.
It demonstrates two different ways to apply the transform:
-
Use vtkTransformPolyDataFilter to create a new transformed polydata. This method is useful if the transformed polydata is needed later in the pipeline, e.g. vtkGlyph3DFilter.
-
Apply the transform directly to the actor using vtkProp3D's SetUserMatrix. No new data is produced.
Switch between the two methods by #defining USER_MATRIX or leaving out the #define.
Seealso
Compare this example with Oriented Arrow . The transform is different because the cylinder height direction is along the y-axis and the arrow height is along the x axis.
Code¶
OrientedCylinder.cxx
#define USER_MATRIX #include <vtkCylinderSource.h> #include <vtkPolyData.h> #include <vtkSmartPointer.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkRenderWindow.h> #include <vtkRenderer.h> #include <vtkRenderWindowInteractor.h> #include <vtkMath.h> #include <vtkSphereSource.h> #include <vtkProperty.h> #include <vtkTransform.h> #include <vtkTransformPolyDataFilter.h> #include <time.h> int main(int, char *[]) { //Create an cylinder. // Cylinder height vector is (0,1,0). // Cylinder center is in the middle of the cylinder vtkSmartPointer<vtkCylinderSource> cylinderSource = vtkSmartPointer<vtkCylinderSource>::New(); cylinderSource->SetResolution(15); // Generate a random start and end point double startPoint[3], endPoint[3]; #ifndef main vtkMath::RandomSeed(time(NULL)); #else vtkMath::RandomSeed(8775070); #endif startPoint[0] = vtkMath::Random(-10,10); startPoint[1] = vtkMath::Random(-10,10); startPoint[2] = vtkMath::Random(-10,10); endPoint[0] = vtkMath::Random(-10,10); endPoint[1] = vtkMath::Random(-10,10); endPoint[2] = vtkMath::Random(-10,10); // Compute a basis double normalizedX[3]; double normalizedY[3]; double normalizedZ[3]; // The X axis is a vector from start to end vtkMath::Subtract(endPoint, startPoint, normalizedX); double length = vtkMath::Norm(normalizedX); vtkMath::Normalize(normalizedX); // The Z axis is an arbitrary vector cross X double arbitrary[3]; arbitrary[0] = vtkMath::Random(-10,10); arbitrary[1] = vtkMath::Random(-10,10); arbitrary[2] = vtkMath::Random(-10,10); vtkMath::Cross(normalizedX, arbitrary, normalizedZ); vtkMath::Normalize(normalizedZ); // The Y axis is Z cross X vtkMath::Cross(normalizedZ, normalizedX, normalizedY); vtkSmartPointer<vtkMatrix4x4> matrix = vtkSmartPointer<vtkMatrix4x4>::New(); // Create the direction cosine matrix matrix->Identity(); for (unsigned int i = 0; i < 3; i++) { matrix->SetElement(i, 0, normalizedX[i]); matrix->SetElement(i, 1, normalizedY[i]); matrix->SetElement(i, 2, normalizedZ[i]); } // Apply the transforms vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); transform->Translate(startPoint); // translate to starting point transform->Concatenate(matrix); // apply direction cosines transform->RotateZ(-90.0); // align cylinder to x axis transform->Scale(1.0, length, 1.0); // scale along the height vector transform->Translate(0, .5, 0); // translate to start of cylinder // Transform the polydata vtkSmartPointer<vtkTransformPolyDataFilter> transformPD = vtkSmartPointer<vtkTransformPolyDataFilter>::New(); transformPD->SetTransform(transform); transformPD->SetInputConnection(cylinderSource->GetOutputPort()); //Create a mapper and actor for the cylinder vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); #ifdef USER_MATRIX mapper->SetInputConnection(cylinderSource->GetOutputPort()); actor->SetUserMatrix(transform->GetMatrix()); #else mapper->SetInputConnection(transformPD->GetOutputPort()); #endif actor->SetMapper(mapper); // Create spheres for start and end point vtkSmartPointer<vtkSphereSource> sphereStartSource = vtkSmartPointer<vtkSphereSource>::New(); sphereStartSource->SetCenter(startPoint); vtkSmartPointer<vtkPolyDataMapper> sphereStartMapper = vtkSmartPointer<vtkPolyDataMapper>::New(); sphereStartMapper->SetInputConnection(sphereStartSource->GetOutputPort()); vtkSmartPointer<vtkActor> sphereStart = vtkSmartPointer<vtkActor>::New(); sphereStart->SetMapper(sphereStartMapper); sphereStart->GetProperty()->SetColor(1.0, 1.0, .3); vtkSmartPointer<vtkSphereSource> sphereEndSource = vtkSmartPointer<vtkSphereSource>::New(); sphereEndSource->SetCenter(endPoint); vtkSmartPointer<vtkPolyDataMapper> sphereEndMapper = vtkSmartPointer<vtkPolyDataMapper>::New(); sphereEndMapper->SetInputConnection(sphereEndSource->GetOutputPort()); vtkSmartPointer<vtkActor> sphereEnd = vtkSmartPointer<vtkActor>::New(); sphereEnd->SetMapper(sphereEndMapper); sphereEnd->GetProperty()->SetColor(1.0, .3, .3); //Create a renderer, render window, and interactor vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New(); vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); renderWindow->AddRenderer(renderer); vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); renderWindowInteractor->SetRenderWindow(renderWindow); //Add the actor to the scene renderer->AddActor(actor); renderer->AddActor(sphereStart); renderer->AddActor(sphereEnd); renderer->SetBackground(.1, .2, .3); // Background color dark blue //Render and interact renderWindow->Render(); renderWindowInteractor->Start(); return EXIT_SUCCESS; }
CMakeLists.txt¶
cmake_minimum_required(VERSION 2.8) PROJECT(OrientedCylinder) find_package(VTK REQUIRED) include(${VTK_USE_FILE}) add_executable(OrientedCylinder MACOSX_BUNDLE OrientedCylinder.cxx) target_link_libraries(OrientedCylinder ${VTK_LIBRARIES})
Download and Build OrientedCylinder¶
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 OrientedCylinder and its CMakeLists.txt file. Once the tarball OrientedCylinder.tar has been downloaded and extracted,
cd OrientedCylinder/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:
./OrientedCylinder
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.