ImplicitAnnulusWidget
Repository source: ImplicitAnnulusWidget
Other languages
See (PythonicAPI)
Question
If you have a question about this example, please use the VTK Discourse Forum
Code¶
ImplicitAnnulusWidget.cxx
#include <vtkActor.h>
#include <vtkAnnulus.h>
#include <vtkAppendPolyData.h>
#include <vtkCamera.h>
#include <vtkCameraOrientationWidget.h>
#include <vtkClipPolyData.h>
#include <vtkCommand.h>
#include <vtkConeSource.h>
#include <vtkGlyph3D.h>
#include <vtkImplicitAnnulusRepresentation.h>
#include <vtkImplicitAnnulusWidget.h>
#include <vtkInteractorStyleSwitch.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkXMLPolyDataReader.h>
#include <algorithm>
#include <vector>
namespace {
// This does the actual work: updates the vtkAnnulus implicit function.
// This in turn causes the pipeline to update and clip the object.
// Callback for the interaction
class vtkTICWCallback : public vtkCommand
{
public:
static vtkTICWCallback* New()
{
return new vtkTICWCallback;
}
void Execute(vtkObject* caller, unsigned long, void*) override
{
vtkImplicitAnnulusWidget* annulusWidget =
reinterpret_cast<vtkImplicitAnnulusWidget*>(caller);
vtkImplicitAnnulusRepresentation* rep =
reinterpret_cast<vtkImplicitAnnulusRepresentation*>(
annulusWidget->GetRepresentation());
rep->GetAnnulus(this->Annulus);
this->Actor->VisibilityOn();
}
vtkAnnulus* Annulus{nullptr};
vtkActor* Actor{nullptr};
};
vtkNew<vtkAppendPolyData> CreateMace();
} // namespace
int main(int argc, char* argv[])
{
vtkNew<vtkNamedColors> colors;
vtkNew<vtkXMLPolyDataReader> reader;
// This portion of the code clips the mace or the input from the reader with
// the vtkAnnulus implicit function. The clipped region is colored green.
vtkNew<vtkAnnulus> annulus;
vtkNew<vtkClipPolyData> clipper;
clipper->SetClipFunction(annulus);
clipper->InsideOutOn();
vtkSmartPointer<vtkPolyData> source;
if (argc < 2)
{
auto mace = CreateMace();
source = mace->GetOutput();
}
else
{
// For example: cow.vtp
reader->SetFileName(argv[1]);
reader->Update();
source = reader->GetOutput();
}
clipper->SetInputData(source);
auto bounds = source->GetBounds();
std::cout << "bounds: (";
for (auto i = 0; i < 6; ++i)
{
if (i == 0)
{
std::cout << bounds[i];
}
else
{
std::cout << " " << bounds[i];
}
}
std::cout << ")" << std::endl;
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputData(source);
vtkNew<vtkProperty> backFaces;
backFaces->SetDiffuseColor(colors->GetColor3d("Gold").GetData());
vtkNew<vtkActor> actor;
actor->SetBackfaceProperty(backFaces);
actor->SetMapper(mapper);
actor->VisibilityOn();
vtkNew<vtkPolyDataMapper> selectMapper;
selectMapper->SetInputConnection(clipper->GetOutputPort());
vtkNew<vtkActor> selectActor;
selectActor->SetMapper(selectMapper);
selectActor->GetProperty()->SetColor(colors->GetColor3d("Lime").GetData());
selectActor->VisibilityOff();
selectActor->SetScale(1.01, 1.01, 1.01);
// Create the RenderWindow, Renderer and both Actors
vtkNew<vtkRenderer> renderer;
renderer->AddActor(actor);
renderer->AddActor(selectActor);
renderer->SetBackground(colors->GetColor3d("MidnightBlue").GetData());
vtkNew<vtkRenderWindow> renWin;
renWin->SetMultiSamples(0);
renWin->SetSize(600, 600);
renWin->SetWindowName("ImplicitAnnulusWidget");
renWin->AddRenderer(renderer);
vtkNew<vtkRenderWindowInteractor> iren;
renWin->SetInteractor(iren);
auto is = vtkInteractorStyleSwitch::SafeDownCast(iren->GetInteractorStyle());
if (is)
{
is->SetCurrentStyleToTrackballCamera();
}
// The SetInteractor method is how 3D widgets are associated with the render
// window interactor. Internally, SetInteractor sets up a bunch of callbacks
// using the Command/Observer mechanism (AddObserver()).
vtkNew<vtkTICWCallback> myCallback;
myCallback->Annulus = annulus;
myCallback->Actor = selectActor;
std::vector<double> radii;
for (auto i = 1; i < 6; i += 2)
{
radii.push_back((bounds[i] - bounds[i - 1]) / 2.0);
}
auto radius = *std::min_element(radii.cbegin(), radii.cend());
vtkNew<vtkImplicitAnnulusRepresentation> rep;
rep->SetPlaceFactor(1.25);
rep->ScaleEnabledOff();
rep->PlaceWidget(bounds);
rep->SetInnerRadius(radius * 0.5);
rep->SetOuterRadius(radius);
std::cout << "Inner radius: " << rep->GetInnerRadius() << std::endl;
std::cout << "Outer radius: " << rep->GetOuterRadius() << std::endl;
vtkNew<vtkImplicitAnnulusWidget> annulusWidget;
annulusWidget->SetInteractor(iren);
annulusWidget->SetRepresentation(rep);
annulusWidget->AddObserver(vtkCommand::InteractionEvent, myCallback);
annulusWidget->EnabledOn();
renderer->GetActiveCamera()->Azimuth(60);
renderer->GetActiveCamera()->Elevation(30);
renderer->ResetCamera();
renderer->GetActiveCamera()->Zoom(1.0);
vtkNew<vtkCameraOrientationWidget> cow;
cow->SetParentRenderer(renderer);
// Enable the widget.
cow->On();
// Render and interact.
iren->Initialize();
renWin->Render();
annulusWidget->On();
// Begin mouse interaction.
iren->Start();
return EXIT_SUCCESS;
}
namespace {
vtkNew<vtkAppendPolyData> CreateMace()
{
// Create a mace out of filters.
vtkNew<vtkSphereSource> sphere;
vtkNew<vtkConeSource> coneSource;
vtkNew<vtkGlyph3D> glyph;
glyph->SetInputConnection(sphere->GetOutputPort());
glyph->SetSourceConnection(coneSource->GetOutputPort());
glyph->SetVectorModeToUseNormal();
glyph->SetScaleModeToScaleByVector();
glyph->SetScaleFactor(0.25);
// The sphere and spikes are appended into a single polydata.
// This just makes things simpler to manage.
vtkNew<vtkAppendPolyData> apd;
apd->AddInputConnection(glyph->GetOutputPort());
apd->AddInputConnection(sphere->GetOutputPort());
apd->Update();
return apd;
}
} // namespace
CMakeLists.txt¶
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project(ImplicitAnnulusWidget)
find_package(VTK COMPONENTS
CommonColor
CommonCore
CommonDataModel
FiltersCore
FiltersSources
IOXML
InteractionStyle
InteractionWidgets
RenderingContextOpenGL2
RenderingCore
RenderingFreeType
RenderingGL2PSOpenGL2
RenderingOpenGL2
)
if (NOT VTK_FOUND)
message(FATAL_ERROR "ImplicitAnnulusWidget: 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.")
add_executable(ImplicitAnnulusWidget MACOSX_BUNDLE ImplicitAnnulusWidget.cxx )
target_link_libraries(ImplicitAnnulusWidget PRIVATE ${VTK_LIBRARIES}
)
# vtk_module_autoinit is needed
vtk_module_autoinit(
TARGETS ImplicitAnnulusWidget
MODULES ${VTK_LIBRARIES}
)
Download and Build ImplicitAnnulusWidget¶
Click here to download ImplicitAnnulusWidget and its CMakeLists.txt file. Once the tarball ImplicitAnnulusWidget.tar has been downloaded and extracted,
cd ImplicitAnnulusWidget/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:
./ImplicitAnnulusWidget
WINDOWS USERS
Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.