# KochanekSplineDemo

VTKExamples/Cxx/PolyData/KochanekSplineDemo

### Description

The example provides vtkSliderWidget s to change tension, continuity and bias of the vtkKochanekSpline.

1. tension - Changes the length of the tangent vector
2. bias - Primarily changes the direction of the tangent vector
3. continuity - Changes the sharpness in change between tangents

Seealso

This wikipedia article describes the controlsin detail.

### Code

KochanekSplineDemo.cxx

    #include <vtkSmartPointer.h>
    #include <vtkKochanekSpline.h>
    #include <vtkParametricSpline.h>
    #include <vtkParametricFunctionSource.h>

    #include <vtkPoints.h>
    #include <vtkPolyData.h>
    #include <vtkPolyDataMapper.h>
    #include <vtkProperty.h>
    #include <vtkProperty2D.h>
    #include <vtkActor.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderer.h>
    #include <vtkRenderWindowInteractor.h>

    #include <vtkTextProperty.h>
    #include <vtkTextMapper.h>
    #include <vtkActor2D.h>

    #include <vtkSliderRepresentation2D.h>
    #include <vtkGlyph3DMapper.h>
    #include <vtkSphereSource.h>
    #include <vtkNamedColors.h>

    #include <vtkCommand.h>
    #include <vtkSliderWidget.h>
    #include <vtkSliderRepresentation2D.h>

    namespace
    {
    void MakeTensionWidget(vtkSmartPointer<vtkSliderWidget> &,
                           vtkSmartPointer<vtkParametricFunctionSource> &,
                           vtkSmartPointer<vtkParametricSpline> &,
                           vtkSmartPointer<vtkRenderer> &,
                           vtkSmartPointer<vtkRenderWindowInteractor> &);
    void MakeContinuityWidget(vtkSmartPointer<vtkSliderWidget> &,
                           vtkSmartPointer<vtkParametricFunctionSource> &,
                           vtkSmartPointer<vtkParametricSpline> &,
                           vtkSmartPointer<vtkRenderer> &,
                           vtkSmartPointer<vtkRenderWindowInteractor> &);
    void MakeBiasWidget(vtkSmartPointer<vtkSliderWidget> &,
                           vtkSmartPointer<vtkParametricFunctionSource> &,
                           vtkSmartPointer<vtkParametricSpline> &,
                           vtkSmartPointer<vtkRenderer> &,
                           vtkSmartPointer<vtkRenderWindowInteractor> &);
    }

    int main(int, char *[])
    {
      vtkSmartPointer<vtkNamedColors> colors =
        vtkSmartPointer<vtkNamedColors>::New();

      int numberOfPoints = 7;
      vtkSmartPointer<vtkPoints> points =
        vtkSmartPointer<vtkPoints>::New();
      points->SetNumberOfPoints(numberOfPoints);
      double radius = 1.0;
      double delta = 2.0 * vtkMath::Pi() / double (numberOfPoints);
        for (int n = 0; n < numberOfPoints; ++n)
        {
          double theta = delta * n;
          double x = radius * std::cos(theta);
          double y = radius * std::sin(theta);
          double z = n * (vtkMath::Pi() / numberOfPoints);
          points->SetPoint(n, x, y, z);
        }

      vtkSmartPointer<vtkKochanekSpline> xSpline =
        vtkSmartPointer<vtkKochanekSpline>::New();
      vtkSmartPointer<vtkKochanekSpline> ySpline =
        vtkSmartPointer<vtkKochanekSpline>::New();
      vtkSmartPointer<vtkKochanekSpline> zSpline =
        vtkSmartPointer<vtkKochanekSpline>::New();

      vtkSmartPointer<vtkParametricSpline> spline =
        vtkSmartPointer<vtkParametricSpline>::New();
      spline->SetXSpline(xSpline);
      spline->SetYSpline(ySpline);
      spline->SetZSpline(zSpline);
      spline->SetPoints(points);

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

      // Setup actor and mapper
      vtkSmartPointer<vtkPolyDataMapper> mapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
      mapper->SetInputConnection(functionSource->GetOutputPort());

      vtkSmartPointer<vtkActor> actor =
        vtkSmartPointer<vtkActor>::New();
      actor->SetMapper(mapper);
      actor->GetProperty()->SetColor(colors->GetColor3d("DarkSlateGrey").GetData());
      actor->GetProperty()->SetLineWidth(3.0);

      // Glyph the points
      vtkSmartPointer<vtkSphereSource> sphere =
        vtkSmartPointer<vtkSphereSource>::New();
      sphere->SetPhiResolution(21);
      sphere->SetThetaResolution(21);
      sphere->SetRadius(.1);

      // Create a polydata to store everything in
      vtkSmartPointer<vtkPolyData> polyData =
        vtkSmartPointer<vtkPolyData>::New();
      polyData->SetPoints(points);

      vtkSmartPointer<vtkGlyph3DMapper> pointMapper =
        vtkSmartPointer<vtkGlyph3DMapper>::New();
      pointMapper->SetInputData(polyData);
      pointMapper->SetSourceConnection(sphere->GetOutputPort());

      vtkSmartPointer<vtkActor> pointActor =
        vtkSmartPointer<vtkActor>::New();
      pointActor->SetMapper(pointMapper);
      pointActor->GetProperty()->SetColor(colors->GetColor3d("Peacock").GetData());
      pointActor->GetProperty()->SetOpacity(.5);;

      // Setup render window, renderer, and interactor
      vtkSmartPointer<vtkRenderer> renderer =
        vtkSmartPointer<vtkRenderer>::New();
      vtkSmartPointer<vtkRenderWindow> renderWindow =
        vtkSmartPointer<vtkRenderWindow>::New();
      renderWindow->AddRenderer(renderer);
      renderWindow->SetSize(640, 480);

      vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
      renderWindowInteractor->SetRenderWindow(renderWindow);

      renderer->AddActor(actor);
      renderer->AddActor(pointActor);;
      renderer->SetBackground(colors->GetColor3d("Silver").GetData());
      renderWindow->Render();

      vtkSmartPointer<vtkSliderWidget> tensionWidget =
        vtkSmartPointer<vtkSliderWidget>::New();
      MakeTensionWidget(tensionWidget, functionSource, spline, renderer, renderWindowInteractor);
      vtkSmartPointer<vtkSliderWidget> continuityWidget =
        vtkSmartPointer<vtkSliderWidget>::New();
      MakeContinuityWidget(continuityWidget, functionSource, spline, renderer, renderWindowInteractor);
      vtkSmartPointer<vtkSliderWidget> biasWidget =
        vtkSmartPointer<vtkSliderWidget>::New();
      MakeBiasWidget(biasWidget, functionSource, spline, renderer, renderWindowInteractor);

      renderWindow->Render();
      renderWindowInteractor->Start();

      return EXIT_SUCCESS;
    }

    namespace
    {
    // These callbacks do the actual work.
    // Callbacks for the interactions
    class SliderCallbackTension : public vtkCommand
    {
    public:
      static SliderCallbackTension *New()
      {
        return new SliderCallbackTension;
      }
      virtual void Execute(vtkObject *caller, unsigned long, void*)
      {
        vtkSliderWidget *sliderWidget =
          reinterpret_cast<vtkSliderWidget*>(caller);
        double value = static_cast<vtkSliderRepresentation2D *>(sliderWidget->GetRepresentation())->GetValue();
        vtkKochanekSpline::SafeDownCast(this->ParametricSpline->GetXSpline())->SetDefaultTension(value);
        vtkKochanekSpline::SafeDownCast(this->ParametricSpline->GetYSpline())->SetDefaultTension(value);
        vtkKochanekSpline::SafeDownCast(this->ParametricSpline->GetZSpline())->SetDefaultTension(value);
        ParametricSource->Modified();
        ParametricSource->Update();
      }
      SliderCallbackTension():ParametricSource(0), ParametricSpline(0) {}
      vtkParametricSpline *ParametricSpline;
      vtkParametricFunctionSource *ParametricSource;
    };

    void
    MakeTensionWidget(vtkSmartPointer<vtkSliderWidget> &widget,
                      vtkSmartPointer<vtkParametricFunctionSource> &parametricSource,
                      vtkSmartPointer<vtkParametricSpline> &parametricSpline,
                      vtkSmartPointer<vtkRenderer> &renderer,
                      vtkSmartPointer<vtkRenderWindowInteractor> &interactor)
    {
      // Setup a slider widget for each varying parameter
      double tubeWidth(.005);
      double sliderLength(.02);
      double titleHeight(.02);
      double labelHeight(.02);

      vtkSmartPointer<vtkSliderRepresentation2D> sliderRepTension =
        vtkSmartPointer<vtkSliderRepresentation2D>::New();

      sliderRepTension->SetRenderer(renderer);

      sliderRepTension->SetMinimumValue(-1.0);
      sliderRepTension->SetMaximumValue(1.0);
      sliderRepTension->SetValue(vtkKochanekSpline::SafeDownCast(parametricSpline->GetXSpline())->GetDefaultTension());
      sliderRepTension->SetTitleText("Tension");
      sliderRepTension->SetRenderer(renderer);
      sliderRepTension->GetPoint1Coordinate()->SetValue(0.1, 0.1);
      sliderRepTension->GetPoint1Coordinate()->SetCoordinateSystemToNormalizedViewport();
      sliderRepTension->GetPoint2Coordinate()->SetValue(0.3, 0.1);
      sliderRepTension->GetPoint2Coordinate()->SetCoordinateSystemToNormalizedViewport();

      sliderRepTension->SetTubeWidth(tubeWidth);
      sliderRepTension->SetSliderLength(sliderLength);
      sliderRepTension->SetTitleHeight(titleHeight);
      sliderRepTension->SetLabelHeight(labelHeight);
      sliderRepTension->SetEndCapLength(tubeWidth*1.5);
      sliderRepTension->SetSliderWidth(tubeWidth*1.5);
      sliderRepTension->GetSliderProperty()->SetColor(0.0, 0.0, 0.0);
      sliderRepTension->BuildRepresentation();

      widget->SetRepresentation(sliderRepTension);
      widget->SetAnimationModeToAnimate();
      widget->SetNumberOfAnimationSteps(10);
      widget->SetInteractor(interactor);
      widget->EnabledOn();

      vtkSmartPointer<SliderCallbackTension> callbackTension =
        vtkSmartPointer<SliderCallbackTension>::New();
      callbackTension->ParametricSpline = parametricSpline;
      callbackTension->ParametricSource = parametricSource;

      widget->AddObserver(vtkCommand::InteractionEvent,callbackTension);
    }

    class SliderCallbackContinuity : public vtkCommand
    {
    public:
      static SliderCallbackContinuity *New()
      {
        return new SliderCallbackContinuity;
      }
      virtual void Execute(vtkObject *caller, unsigned long, void*)
      {
        vtkSliderWidget *sliderWidget =
          reinterpret_cast<vtkSliderWidget*>(caller);
        double value = static_cast<vtkSliderRepresentation2D *>(sliderWidget->GetRepresentation())->GetValue();
        vtkKochanekSpline::SafeDownCast(this->ParametricSpline->GetXSpline())->SetDefaultContinuity(value);
        vtkKochanekSpline::SafeDownCast(this->ParametricSpline->GetYSpline())->SetDefaultContinuity(value);
        vtkKochanekSpline::SafeDownCast(this->ParametricSpline->GetZSpline())->SetDefaultContinuity(value);
        ParametricSource->Modified();
        ParametricSource->Update();
      }
      SliderCallbackContinuity():ParametricSource(0), ParametricSpline(0) {}
      vtkParametricSpline *ParametricSpline;
      vtkParametricFunctionSource *ParametricSource;
    };

    void
    MakeContinuityWidget(vtkSmartPointer<vtkSliderWidget> &widget,
                      vtkSmartPointer<vtkParametricFunctionSource> &parametricSource,
                      vtkSmartPointer<vtkParametricSpline> &parametricSpline,
                      vtkSmartPointer<vtkRenderer> &renderer,
                      vtkSmartPointer<vtkRenderWindowInteractor> &interactor)
    {
      // Setup a slider widget for each varying parameter
      double tubeWidth(.005);
      double sliderLength(.02);
      double titleHeight(.02);
      double labelHeight(.02);

      vtkSmartPointer<vtkSliderRepresentation2D> sliderRepContinuity =
        vtkSmartPointer<vtkSliderRepresentation2D>::New();

      sliderRepContinuity->SetRenderer(renderer);

      sliderRepContinuity->SetMinimumValue(-1.0);
      sliderRepContinuity->SetMaximumValue(1.0);
      sliderRepContinuity->SetValue(vtkKochanekSpline::SafeDownCast(parametricSpline->GetXSpline())->GetDefaultContinuity());
      sliderRepContinuity->SetTitleText("Continuity");
      sliderRepContinuity->SetRenderer(renderer);
      sliderRepContinuity->GetPoint1Coordinate()->SetValue(0.4, 0.1);
      sliderRepContinuity->GetPoint1Coordinate()->SetCoordinateSystemToNormalizedViewport();
      sliderRepContinuity->GetPoint2Coordinate()->SetValue(0.6, 0.1);
      sliderRepContinuity->GetPoint2Coordinate()->SetCoordinateSystemToNormalizedViewport();

      sliderRepContinuity->SetTubeWidth(tubeWidth);
      sliderRepContinuity->SetSliderLength(sliderLength);
      sliderRepContinuity->SetTitleHeight(titleHeight);
      sliderRepContinuity->SetLabelHeight(labelHeight);
      sliderRepContinuity->SetEndCapLength(tubeWidth*1.5);
      sliderRepContinuity->SetSliderWidth(tubeWidth*1.5);
      sliderRepContinuity->GetSliderProperty()->SetColor(0.0, 0.0, 0.0);
      sliderRepContinuity->BuildRepresentation();

      widget->SetRepresentation(sliderRepContinuity);
      widget->SetAnimationModeToAnimate();
      widget->SetNumberOfAnimationSteps(10);
      widget->SetInteractor(interactor);
      widget->EnabledOn();

      vtkSmartPointer<SliderCallbackContinuity> callbackContinuity =
        vtkSmartPointer<SliderCallbackContinuity>::New();
      callbackContinuity->ParametricSpline = parametricSpline;
      callbackContinuity->ParametricSource = parametricSource;

      widget->AddObserver(vtkCommand::InteractionEvent,callbackContinuity);
    }

    class SliderCallbackBias : public vtkCommand
    {
    public:
      static SliderCallbackBias *New()
      {
        return new SliderCallbackBias;
      }
      virtual void Execute(vtkObject *caller, unsigned long, void*)
      {
        vtkSliderWidget *sliderWidget =
          reinterpret_cast<vtkSliderWidget*>(caller);
        double value = static_cast<vtkSliderRepresentation2D *>(sliderWidget->GetRepresentation())->GetValue();
        vtkKochanekSpline::SafeDownCast(this->ParametricSpline->GetXSpline())->SetDefaultBias(value);
        vtkKochanekSpline::SafeDownCast(this->ParametricSpline->GetYSpline())->SetDefaultBias(value);
        vtkKochanekSpline::SafeDownCast(this->ParametricSpline->GetZSpline())->SetDefaultBias(value);
        ParametricSource->Modified();
        ParametricSource->Update();
      }
      SliderCallbackBias():ParametricSource(0), ParametricSpline(0) {}
      vtkParametricSpline *ParametricSpline;
      vtkParametricFunctionSource *ParametricSource;
    };

    void
    MakeBiasWidget(vtkSmartPointer<vtkSliderWidget> &widget,
                      vtkSmartPointer<vtkParametricFunctionSource> &parametricSource,
                      vtkSmartPointer<vtkParametricSpline> &parametricSpline,
                      vtkSmartPointer<vtkRenderer> &renderer,
                      vtkSmartPointer<vtkRenderWindowInteractor> &interactor)
    {
      // Setup a slider widget for each varying parameter
      double tubeWidth(.005);
      double sliderLength(.02);
      double titleHeight(.02);
      double labelHeight(.02);

      vtkSmartPointer<vtkSliderRepresentation2D> sliderRepBias =
        vtkSmartPointer<vtkSliderRepresentation2D>::New();

      sliderRepBias->SetRenderer(renderer);

      sliderRepBias->SetMinimumValue(-1.0);
      sliderRepBias->SetMaximumValue(1.0);
      sliderRepBias->SetValue(vtkKochanekSpline::SafeDownCast(parametricSpline->GetXSpline())->GetDefaultBias());
      sliderRepBias->SetTitleText("Bias");
      sliderRepBias->SetRenderer(renderer);
      sliderRepBias->GetPoint1Coordinate()->SetValue(0.7, 0.1);
      sliderRepBias->GetPoint1Coordinate()->SetCoordinateSystemToNormalizedViewport();
      sliderRepBias->GetPoint2Coordinate()->SetValue(0.9, 0.1);
      sliderRepBias->GetPoint2Coordinate()->SetCoordinateSystemToNormalizedViewport();

      sliderRepBias->SetTubeWidth(tubeWidth);
      sliderRepBias->SetSliderLength(sliderLength);
      sliderRepBias->SetTitleHeight(titleHeight);
      sliderRepBias->SetLabelHeight(labelHeight);
      sliderRepBias->SetEndCapLength(tubeWidth*1.5);
      sliderRepBias->SetSliderWidth(tubeWidth*1.5);
      sliderRepBias->GetSliderProperty()->SetColor(0.0, 0.0, 0.0);
      sliderRepBias->BuildRepresentation();

      widget->SetRepresentation(sliderRepBias);
      widget->SetAnimationModeToAnimate();
      widget->SetNumberOfAnimationSteps(10);
      widget->SetInteractor(interactor);
      widget->EnabledOn();

      vtkSmartPointer<SliderCallbackBias> callbackBias =
        vtkSmartPointer<SliderCallbackBias>::New();
      callbackBias->ParametricSpline = parametricSpline;
      callbackBias->ParametricSource = parametricSource;

      widget->AddObserver(vtkCommand::InteractionEvent,callbackBias);
    }
    }

### CMakeLists.txt

    cmake_minimum_required(VERSION 2.8)

    PROJECT(KochanekSplineDemo)

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

    add_executable(KochanekSplineDemo MACOSX_BUNDLE KochanekSplineDemo.cxx )

    target_link_libraries(KochanekSplineDemo ${VTK_LIBRARIES})

### Download and Build KochanekSplineDemo

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

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

    ./KochanekSplineDemo

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.