Skip to content

ImplicitConeWidget

Repository source: ImplicitConeWidget


Description

This is an interactive implicit cone widget. It represents an infinite cone parameterized by an axis, the angle between the sides of the cone and its axis, and an origin point. Users can manipulate the widget through controls similar to the cylinder widget ones. Its underlying cone can be used in any filter relying on implicit functions (i.e. Clip).

Other languages

See (PythonicAPI)

Question

If you have a question about this example, please use the VTK Discourse Forum

Code

ImplicitConeWidget.cxx

#include "vtkActor.h"
#include "vtkAppendPolyData.h"
#include "vtkCamera.h"
#include "vtkClipPolyData.h"
#include "vtkCommand.h"
#include "vtkCone.h"
#include "vtkConeSource.h"
#include "vtkGlyph3D.h"
#include "vtkImplicitConeRepresentation.h"
#include "vtkImplicitConeWidget.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkSphereSource.h"
#include <vtkInteractorStyleSwitch.h>
#include <vtkNamedColors.h>

#include <array>

namespace {

/**
 * The callback for the interaction.
 *
 * This does the actual work: updates the vtkCone implicit function.
 * This in turn causes the pipeline to update and clip the object.
 *
 * @return
 */
class vtkTICWCallback : public vtkCommand
{
public:
  static vtkTICWCallback* New()
  {
    return new vtkTICWCallback;
  }

  void Execute(vtkObject* caller, unsigned long, void*) override
  {
    vtkImplicitConeWidget* coneWidget =
        reinterpret_cast<vtkImplicitConeWidget*>(caller);
    vtkImplicitConeRepresentation* rep =
        reinterpret_cast<vtkImplicitConeRepresentation*>(
            coneWidget->GetRepresentation());
    rep->GetCone(this->cone);
    this->actor->VisibilityOn();
  }

  vtkCone* cone = nullptr;
  vtkActor* actor = nullptr;
};

} // anonymous namespace

int main(int argc, char* argv[])
{
  std::array<unsigned char, 4> bkg{82, 87, 110, 255};
  vtkNew<vtkNamedColors> colors;
  colors->SetColor("ParaViewBkg", bkg.data());

  // 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);
  glyph->Update();

  // 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());

  vtkNew<vtkPolyDataMapper> maceMapper;
  maceMapper->SetInputConnection(apd->GetOutputPort());

  vtkNew<vtkActor> maceActor;
  maceActor->SetMapper(maceMapper);
  maceActor->GetProperty()->SetColor(
      colors->GetColor3d("LightSteelBlue").GetData());
  maceActor->VisibilityOn();

  // This portion of the code clips the mace with the vtkCone's
  // implicit function. The clipped region is colored green.
  vtkNew<vtkCone> cone;
  cone->SetIsDoubleCone(false);

  vtkNew<vtkClipPolyData> clipper;
  clipper->SetInputConnection(apd->GetOutputPort());
  clipper->SetClipFunction(cone);
  clipper->InsideOutOn();

  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(maceActor);
  renderer->AddActor(selectActor);
  renderer->SetBackground(colors->GetColor3d("ParaViewBkg").GetData());

  vtkNew<vtkRenderWindow> renWin;
  renWin->SetMultiSamples(0);
  renWin->SetSize(640, 640);
  renWin->AddRenderer(renderer);

  vtkNew<vtkRenderWindowInteractor> interactor;
  renWin->SetInteractor(interactor);
  auto is =
      vtkInteractorStyleSwitch::SafeDownCast(interactor->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->cone = cone;
  myCallback->actor = selectActor;

  vtkNew<vtkImplicitConeRepresentation> rep;
  rep->SetPlaceFactor(1.25);
  rep->PlaceWidget(glyph->GetOutput()->GetBounds());

  vtkNew<vtkImplicitConeWidget> coneWidget;
  coneWidget->SetInteractor(interactor);
  coneWidget->SetRepresentation(rep);
  coneWidget->AddObserver(vtkCommand::InteractionEvent, myCallback);
  coneWidget->SetEnabled(true);

  interactor->Initialize();
  renderer->ResetCamera();
  renderer->GetActiveCamera()->Elevation(30);
  renderer->GetActiveCamera()->Azimuth(30);
  renderer->GetActiveCamera()->SetRoll(-22.5);
  renderer->ResetCamera();
  renderer->GetActiveCamera()->Zoom(0.65);

  interactor->Start();
  return EXIT_SUCCESS;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.12 FATAL_ERROR)

project(ImplicitConeWidget)

find_package(VTK COMPONENTS 
  CommonColor
  CommonCore
  CommonDataModel
  FiltersCore
  FiltersSources
  InteractionStyle
  InteractionWidgets
  RenderingContextOpenGL2
  RenderingCore
  RenderingFreeType
  RenderingGL2PSOpenGL2
  RenderingOpenGL2
)

if (NOT VTK_FOUND)
  message(FATAL_ERROR "ImplicitConeWidget: 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(ImplicitConeWidget MACOSX_BUNDLE ImplicitConeWidget.cxx )
  target_link_libraries(ImplicitConeWidget PRIVATE ${VTK_LIBRARIES}
)
# vtk_module_autoinit is needed
vtk_module_autoinit(
  TARGETS ImplicitConeWidget
  MODULES ${VTK_LIBRARIES}
)

Download and Build ImplicitConeWidget

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

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

./ImplicitConeWidget

WINDOWS USERS

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