From faf5d205651f65e0da386f7df840a6be79d8707e Mon Sep 17 00:00:00 2001
From: "Andrew J. P. Maclean" <andrew.amaclean@gmail.com>
Date: Thu, 23 Nov 2017 13:05:35 +1100
Subject: [PATCH] C++ and Python implementation of the very old Hanoi.cxx.

Former-commit-id: 65ae6b660e6d9b80d465d59af17f51b710c32029
---
 src/Cxx.md                                  |   1 +
 src/Cxx/Visualization/CMakeLists.txt        |   8 +
 src/Cxx/Visualization/Hanoi.cxx             | 505 ++++++++++++++++++++
 src/Cxx/Visualization/Hanoi.md              |  11 +
 src/Cxx/Visualization/HanoiInitial.cxx      |   2 +
 src/Cxx/Visualization/HanoiIntermediate.cxx |   2 +
 src/Python.md                               |   1 +
 src/Python/Visualization/Hanoi.md           |  11 +
 src/Python/Visualization/Hanoi.py           | 362 ++++++++++++++
 9 files changed, 903 insertions(+)
 create mode 100644 src/Cxx/Visualization/Hanoi.cxx
 create mode 100644 src/Cxx/Visualization/Hanoi.md
 create mode 100644 src/Cxx/Visualization/HanoiInitial.cxx
 create mode 100644 src/Cxx/Visualization/HanoiIntermediate.cxx
 create mode 100644 src/Python/Visualization/Hanoi.md
 create mode 100755 src/Python/Visualization/Hanoi.py

diff --git a/src/Cxx.md b/src/Cxx.md
index ccc0fb4622c..e400c9aa66c 100644
--- a/src/Cxx.md
+++ b/src/Cxx.md
@@ -871,6 +871,7 @@ See [this tutorial](http://www.vtk.org/Wiki/VTK/Tutorials/3DDataTypes) for a bri
 [Glyph3D](/Cxx/Filtering/Glyph3D) | vtkGlyph3D|
 [Glyph3DImage](/Cxx/Visualization/Glyph3DImage)| vtkGlyph3DMapper | Glyph the points in a vtkImageData.
 [Glyph3DMapper](/Cxx/Visualization/Glyph3DMapper)| vtkGlyph3DMapper |
+[Hanoi](/Cxx/Visualization/Hanoi)|  | Towers of Hanoi.
 [Hawaii](/Cxx/Visualization/Hawaii)| vtkElevationFilter vtkColorSeries vtkLookupTable | Visualize elevations by coloring the scalar values with a lookup table.
 [HedgeHog](/Cxx/Visualization/HedgeHog)| vtkHedgeHog vtkStructuredGrid |Create oriented lines (hedgehogs) from vector data.
 [HideActor](/Cxx/Visualization/HideActor)| vtkPropCollection vtkProp | visible
diff --git a/src/Cxx/Visualization/CMakeLists.txt b/src/Cxx/Visualization/CMakeLists.txt
index 74f861315a3..da211e7a27d 100644
--- a/src/Cxx/Visualization/CMakeLists.txt
+++ b/src/Cxx/Visualization/CMakeLists.txt
@@ -63,6 +63,8 @@ set(NEEDS_ARGS
   FontFile
   Glyph3DImage
   Glyph3DMapper
+  HanoiInitial
+  HanoiIntermediate
   Hawaii
   HedgeHog
   Kitchen
@@ -133,6 +135,12 @@ add_test(${KIT}-Glyph3DImage ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KIT}CxxTests
 add_test(${KIT}-Glyph3DMapper ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KIT}CxxTests
   TestGlyph3DMapper -E 40)
 
+add_test(${KIT}-HanoiInitial ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KIT}CxxTests
+  TestHanoiInitial -c 1)
+
+add_test(${KIT}-HanoiIntermediate ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KIT}CxxTests
+  TestHanoiIntermediate -c 2)
+
 add_test(${KIT}-Hawaii ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KIT}CxxTests
   TestHawaii ${DATA}/honolulu.vtk)
 
diff --git a/src/Cxx/Visualization/Hanoi.cxx b/src/Cxx/Visualization/Hanoi.cxx
new file mode 100644
index 00000000000..bc45c6a8d42
--- /dev/null
+++ b/src/Cxx/Visualization/Hanoi.cxx
@@ -0,0 +1,505 @@
+/*
+
+Translated from:
+   http://www.new-npac.org/projects/sv2all/sv2/vtk/graphics/examplesCxx/Hanoi.cxx
+
+
+Hanoi - application example does 3D towers of hanoi.
+Usage:
+ Hanoi -p # -s # -r # -c #
+ where -p is the number of starting pucks on the peg;
+       -s is the number of steps to take during animation;
+       -r is the resolution of each puck
+       -c controls output of the program.
+*/
+
+#include <vtkActor.h>
+#include <vtkCallbackCommand.h>
+#include <vtkCamera.h>
+#include <vtkCylinderSource.h>
+#include <vtkLight.h>
+#include <vtkMath.h>
+#include <vtkMinimalStandardRandomSequence.h>
+#include <vtkNamedColors.h>
+#include <vtkPNGWriter.h>
+#include <vtkPlaneSource.h>
+#include <vtkPolyDataMapper.h>
+#include <vtkProperty.h>
+#include <vtkRenderWindow.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkRenderer.h>
+#include <vtkRendererCollection.h>
+#include <vtkSmartPointer.h>
+#include <vtkWindowToImageFilter.h>
+
+#include <algorithm>
+#include <array>
+#include <cstdlib>
+#include <iomanip>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+#include <stack>
+#include <string>
+#include <vector>
+
+namespace
+{
+void PrintCameraOrientation(vtkCamera* cam);
+
+/**
+Here we inherit from vtkCallbackCommand and set pointers to any
+client and/or call data as needed.
+When the class is implemented, it becomes the callback function.
+*/
+class CameraModifiedCallback : public vtkCallbackCommand
+{
+public:
+  static CameraModifiedCallback* New() { return new CameraModifiedCallback; }
+  // Here we Create a vtkCallbackCommand and reimplement it.
+  void Execute(vtkObject* caller, unsigned long evId, void*) override
+  {
+    // Note the use of reinterpret_cast to cast the caller to the expected type.
+    vtkRenderWindowInteractor* interactor =
+      reinterpret_cast<vtkRenderWindowInteractor*>(caller);
+    // Just do this to demonstrate who called callback and the event that
+    // triggered it.
+    std::cout << interactor->GetClassName() << "  Event Id: " << evId
+              << std::endl;
+
+    // Now print the camera orientation.
+    PrintCameraOrientation(this->cam);
+  }
+  CameraModifiedCallback()
+    : cam(nullptr)
+  {
+  }
+  // Set pointers to any clientData or callData here.
+  vtkCamera* cam;
+
+private:
+  CameraModifiedCallback(const CameraModifiedCallback&) = delete;
+  void operator=(const CameraModifiedCallback&) = delete;
+};
+
+// Find command line parameters.
+std::vector<std::string>::iterator FindParameter(std::string const& p,
+                                                 std::vector<std::string>& v);
+
+// This routine is responsible for moving pucks from one peg to the next.
+void MovePuck(int peg1, int peg2);
+
+/**
+* Tower of Hanoi.
+*
+* @param n Number of disks.
+* @param peg1 Source.
+* @param peg2 Target.
+* @param peg3 Number of disks.
+
+*/
+void Hanoi(int n, int peg1, int peg2, int peg3);
+
+// Save a screenshot.
+void Screenshot(std::string fileName, vtkRenderWindow* renWin);
+
+// Default values.
+auto numberOfPucks = 5;
+auto numberOfSteps = 5;
+auto puckResolution = 48;
+auto configuration = 0; // Selecting output.
+auto gotFigure2 = false; // Used to bail out of recursion if configuration == 2.
+auto L = 1.0; // Puck height.
+auto H = 1.1 * numberOfPucks * L; // Peg height.
+auto R = 0.5; // Peg radius.
+auto rMin = 4.0 * R; // The minimum allowable radius of disks.
+auto rMax = 12.0 * R; // The maximum allowable radius of disks
+auto D = 1.1 * 1.25 * rMax; // The distance between the pegs.
+auto numberOfMoves = 0;
+auto const maxPucks = 20;
+
+// Our rendering window.
+vtkSmartPointer<vtkRenderWindow> renWin =
+  vtkSmartPointer<vtkRenderWindow>::New();
+
+// Three pegs, each a stack of a vector of actors.
+std::array<std::stack<vtkSmartPointer<vtkActor>>, 3> pegStack;
+}
+
+int main(int argc, char* argv[])
+{
+  // Here we parse the command line.
+  std::vector<std::string> parameters;
+  for (auto i = 1; i < argc; ++i)
+  {
+    parameters.push_back(argv[i]);
+  }
+  auto p = FindParameter(std::string("?"), parameters);
+  if (p != parameters.end())
+  {
+    std::cerr << "Usage:   " << argv[0] << " [-p #] [-s #] [r #] [-c #]"
+              << std::endl;
+    std::cerr << "Where:        -p specifies the number of pucks." << std::endl;
+    std::cerr << "              -s specifies the number of steps." << std::endl;
+    std::cerr << "              -r specifies the puck resolution." << std::endl;
+    std::cerr << "              -c specifies configuration." << std::endl;
+    std::cerr << "                 0 final configuration." << std::endl;
+    std::cerr << "                 1 initial configuration." << std::endl;
+    std::cerr << "                 2 intermediate configuration." << std::endl;
+    std::cerr << "                 3 final configuration and save images"
+              << std::endl;
+    std::cerr << "Defaults:  -p 5 -s 5 -r 48 -c 0" << std::endl;
+    return EXIT_FAILURE;
+  }
+  p = FindParameter(std::string("-p"), parameters);
+  if (p != parameters.end() && std::next(p) != parameters.end())
+  {
+    numberOfPucks = std::abs(atoi(std::next(p)->c_str()));
+  }
+  p = FindParameter(std::string("-s"), parameters);
+  if (p != parameters.end() && std::next(p) != parameters.end())
+  {
+    numberOfSteps = std::abs(atoi(std::next(p)->c_str()));
+  }
+  p = FindParameter(std::string("-r"), parameters);
+  if (p != parameters.end() && std::next(p) != parameters.end())
+  {
+    puckResolution = std::abs(atoi(std::next(p)->c_str()));
+  }
+  p = FindParameter(std::string("-c"), parameters);
+  if (p != parameters.end() && std::next(p) != parameters.end())
+  {
+    configuration = std::abs(atoi(std::next(p)->c_str()));
+  }
+
+  // Initialize variables and check input.
+  if (numberOfPucks < 2)
+  {
+    cerr << "Please use more pucks!\n";
+    return EXIT_FAILURE;
+  }
+
+  if (numberOfPucks > maxPucks)
+  {
+    cerr << "Too many pucks specified! Maximum is " << maxPucks << "\n";
+    return EXIT_FAILURE;
+  }
+
+  if (numberOfSteps < 3)
+  {
+    cerr << "Please use more steps!\n";
+    return EXIT_FAILURE;
+  }
+
+  if (configuration > 3)
+  {
+    cerr << "0>= configuration <= 3\n";
+    return EXIT_FAILURE;
+  }
+
+  vtkSmartPointer<vtkNamedColors> colors =
+    vtkSmartPointer<vtkNamedColors>::New();
+
+  // Create renderer and render window interactor.
+  vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
+  renWin->AddRenderer(ren);
+  renWin->SetSize(1200, 750);
+  vtkSmartPointer<vtkRenderWindowInteractor> iren =
+    vtkSmartPointer<vtkRenderWindowInteractor>::New();
+  iren->SetRenderWindow(renWin);
+
+  ren->SetBackground(colors->GetColor3d("PapayaWhip").GetData());
+
+  vtkSmartPointer<vtkLight> light = vtkSmartPointer<vtkLight>::New();
+
+  vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
+  camera->SetPosition(41.0433, 27.9637, 30.442);
+  camera->SetFocalPoint(11.5603, -1.51931, 0.95899);
+  camera->SetClippingRange(18.9599, 91.6042);
+  camera->SetViewUp(0, 1, 0);
+
+  ren->SetActiveCamera(camera);
+
+  // Create geometry: table, pegs, and pucks.
+  vtkSmartPointer<vtkCylinderSource> pegGeometry =
+    vtkSmartPointer<vtkCylinderSource>::New();
+  pegGeometry->SetResolution(8);
+  vtkSmartPointer<vtkPolyDataMapper> pegMapper =
+    vtkSmartPointer<vtkPolyDataMapper>::New();
+  pegMapper->SetInputConnection(pegGeometry->GetOutputPort());
+
+  vtkSmartPointer<vtkCylinderSource> puckGeometry =
+    vtkSmartPointer<vtkCylinderSource>::New();
+  puckGeometry->SetResolution(puckResolution);
+  vtkSmartPointer<vtkPolyDataMapper> puckMapper =
+    vtkSmartPointer<vtkPolyDataMapper>::New();
+  puckMapper->SetInputConnection(puckGeometry->GetOutputPort());
+
+  vtkSmartPointer<vtkPlaneSource> tableGeometry =
+    vtkSmartPointer<vtkPlaneSource>::New();
+  tableGeometry->SetResolution(10, 10);
+  vtkSmartPointer<vtkPolyDataMapper> tableMapper =
+    vtkSmartPointer<vtkPolyDataMapper>::New();
+  tableMapper->SetInputConnection(tableGeometry->GetOutputPort());
+
+  // Create the actors: table top, pegs, and pucks
+  // The table
+  vtkSmartPointer<vtkActor> table = vtkSmartPointer<vtkActor>::New();
+  ren->AddActor(table);
+  table->SetMapper(tableMapper);
+  // table->GetProperty()->SetColor(0.9569, 0.6431, 0.3765);
+  table->GetProperty()->SetColor(colors->GetColor3d("SaddleBrown").GetData());
+  table->AddPosition(D, 0, 0);
+  table->SetScale(4 * D, 2 * D, 3 * D);
+  table->RotateX(90);
+
+  // The pegs (using cylinder geometry).  Note that the pegs have to translated
+  // in the  y-direction because the cylinder is centered about the origin.
+  H = 1.1 * numberOfPucks * L;
+  std::vector<vtkSmartPointer<vtkActor>> peg;
+  for (auto i = 0; i < 3; ++i)
+  {
+    peg.push_back(vtkSmartPointer<vtkActor>::New());
+    ren->AddActor(peg[i]);
+    peg[i]->SetMapper(pegMapper);
+    // peg[i]->GetProperty()->SetColor(1, 1, 1);
+    peg[i]->GetProperty()->SetColor(colors->GetColor3d("Lavender").GetData());
+    peg[i]->AddPosition(i * D, H / 2, 0);
+    peg[i]->SetScale(1, H, 1);
+  }
+
+  // The pucks (using cylinder geometry). Always loaded on peg# 0.
+  auto scale = 0.0;
+  std::vector<vtkSmartPointer<vtkActor>> puck;
+  vtkSmartPointer<vtkMinimalStandardRandomSequence> randomSequence =
+    vtkSmartPointer<vtkMinimalStandardRandomSequence>::New();
+  randomSequence->SetSeed(1);
+  for (auto i = 0; i < numberOfPucks; ++i)
+  {
+    puck.push_back(vtkSmartPointer<vtkActor>::New());
+    puck[i]->SetMapper(puckMapper);
+    std::array<double, 3> color = {0, 0, 0};
+    for (auto j = 0; j < 3; ++j)
+    {
+      color[j] = randomSequence->GetValue();
+      randomSequence->Next();
+    }
+    puck[i]->GetProperty()->SetColor(color.data());
+    puck[i]->AddPosition(0, i * L + L / 2, 0);
+    scale = rMax - i * (rMax - rMin) / (numberOfPucks - 1);
+    puck[i]->SetScale(scale, 1, scale);
+    ren->AddActor(puck[i]);
+    pegStack[0].push(puck[i]);
+  }
+
+  // Reset the camera to view all actors.
+  renWin->Render();
+  renWin->SetWindowName("Towers of Hanoi");
+
+  if (configuration == 3)
+  {
+    Screenshot("hanoi0.png", renWin);
+  }
+  if (configuration != 1)
+  {
+    // Begin recursion.
+    Hanoi(numberOfPucks - 1, 0, 2, 1);
+    Hanoi(1, 0, 1, 2);
+    if (!gotFigure2)
+    {
+      Hanoi(numberOfPucks - 1, 2, 1, 0);
+
+      renWin->Render();
+      if (configuration == 3)
+      {
+        Screenshot("hanoi2.png", renWin);
+      }
+    }
+    // Report output.
+    cout << "Number of moves: " << numberOfMoves << "\n"
+         << "Polygons rendered each frame: "
+         << 3 * 8 + 1 + numberOfPucks * (2 + puckResolution) << "\n"
+         << "Total number of frames: " << numberOfMoves * 3 * numberOfSteps
+         << "\n";
+  }
+  vtkSmartPointer<CameraModifiedCallback> getOrientation =
+    vtkSmartPointer<CameraModifiedCallback>::New();
+  // Set the camera to use.
+  getOrientation->cam = ren->GetActiveCamera();
+  iren->AddObserver(vtkCommand::EndInteractionEvent, getOrientation);
+
+  // Render the image.
+  iren->Initialize();
+  iren->Start();
+  return EXIT_SUCCESS;
+}
+
+namespace
+{
+
+std::vector<std::string>::iterator FindParameter(std::string const& p,
+                                                 std::vector<std::string>& v)
+{
+  return std::find(v.begin(), v.end(), p);
+}
+
+void MovePuck(int peg1, int peg2)
+{
+  numberOfMoves++;
+
+  // Get the actor to move
+  vtkActor* movingActor = pegStack[peg1].top();
+  pegStack[peg1].pop();
+
+  // Get the distance to move up.
+  auto distance =
+    (H - (L * (static_cast<int>(pegStack[peg1].size()) - 1)) + rMax) /
+    numberOfSteps;
+  for (auto i = 0; i < numberOfSteps; i++)
+  {
+    movingActor->AddPosition(0, distance, 0);
+    renWin->Render();
+  }
+
+  // get the distance to move across
+  distance = (peg2 - peg1) * D / numberOfSteps;
+  auto flipAngle = 180.0 / numberOfSteps;
+  for (auto i = 0; i < numberOfSteps; i++)
+  {
+    movingActor->AddPosition(distance, 0, 0);
+    movingActor->RotateX(flipAngle);
+    renWin->Render();
+    if (numberOfMoves == 13 && i == 3) // for making book image
+    {
+      if (configuration == 3 || configuration == 2)
+      {
+        vtkCamera* cam =
+          renWin->GetRenderers()->GetFirstRenderer()->GetActiveCamera();
+        vtkSmartPointer<vtkCamera> camera1 = vtkSmartPointer<vtkCamera>::New();
+        camera1->SetPosition(54.7263, 41.6467, 44.125);
+        camera1->SetFocalPoint(11.5603, -1.51931, 0.95899);
+        camera1->SetClippingRange(42.4226, 115.659);
+        camera1->SetViewUp(0, 1, 0);
+        renWin->GetRenderers()->GetFirstRenderer()->SetActiveCamera(camera1);
+        renWin->Render();
+        if (configuration == 3)
+        {
+          Screenshot("hanoi1.png", renWin);
+        }
+        if (configuration == 2)
+        {
+          gotFigure2 = true;
+          break;
+        }
+        renWin->GetRenderers()->GetFirstRenderer()->SetActiveCamera(cam);
+        renWin->Render();
+      }
+    }
+  }
+
+  if (gotFigure2)
+  {
+    pegStack[peg2].push(movingActor);
+    return;
+  }
+
+  // Get the distance to move down.
+  distance = ((L * (static_cast<int>(pegStack[peg2].size()) - 1)) - H - rMax) /
+             numberOfSteps;
+
+  for (auto i = 0; i < numberOfSteps; i++)
+  {
+    movingActor->AddPosition(0, distance, 0);
+    renWin->Render();
+  }
+
+  pegStack[peg2].push(movingActor);
+}
+
+void Hanoi(int n, int peg1, int peg2, int peg3)
+{
+  // If gotFigure2 is true, we break out of the recursion.
+  if (gotFigure2)
+  {
+    return;
+  }
+  if (n != 1)
+  {
+    Hanoi(n - 1, peg1, peg3, peg2);
+    if (gotFigure2)
+    {
+      return;
+    }
+    Hanoi(1, peg1, peg2, peg3);
+    Hanoi(n - 1, peg3, peg2, peg1);
+  }
+  else
+  {
+    MovePuck(peg1, peg2);
+  }
+  return;
+}
+
+void Screenshot(std::string fileName, vtkRenderWindow* renWin1)
+{
+  vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter =
+    vtkSmartPointer<vtkWindowToImageFilter>::New();
+  windowToImageFilter->SetInput(renWin1);
+
+#if VTK_MAJOR_VERSION > 8 || VTK_MAJOR_VERSION == 8 && VTK_MINOR_VERSION >= 1
+  windowToImageFilter->SetScale(1); // image quality
+#else
+  windowToImageFilter->SetMagnification(1); // image quality
+#endif
+
+  // We are not recording the alpha (transparency) channel.
+  // windowToImageFilter->SetInputBufferTypeToRGBA();
+  windowToImageFilter->SetInputBufferTypeToRGB();
+  // Read from the front buffer.
+  windowToImageFilter->ReadFrontBufferOff();
+  windowToImageFilter->Update();
+
+  vtkSmartPointer<vtkPNGWriter> writer = vtkSmartPointer<vtkPNGWriter>::New();
+  writer->SetFileName(fileName.c_str());
+  writer->SetInputConnection(windowToImageFilter->GetOutputPort());
+  writer->Write();
+}
+
+/**
+Get a comma separated list.
+*/
+template <typename T>
+std::string CommaSeparatedList(std::vector<T> v)
+{
+  std::ostringstream os;
+  std::copy(v.begin(), v.end() - 1, std::ostream_iterator<T>(os, ", "));
+  os << v.back();
+  return os.str();
+}
+
+/**
+Print the camera orientation.
+*/
+void PrintCameraOrientation(vtkCamera* cam)
+{
+  auto width = 16;
+  double pos[3];
+  cam->GetPosition(pos);
+  double fp[3];
+  cam->GetFocalPoint(fp);
+  double vu[3];
+  cam->GetViewUp(vu);
+  double cr[2];
+  cam->GetClippingRange(cr);
+  std::cout << setw(width) << "Position: "
+            << CommaSeparatedList(std::vector<double>(pos, pos + 3))
+            << std::endl;
+  std::cout << setw(width) << "Focal point: "
+            << CommaSeparatedList(std::vector<double>(fp, fp + 3)) << std::endl;
+  std::cout << setw(width) << "Clipping range: "
+            << CommaSeparatedList(std::vector<double>(cr, cr + 2)) << std::endl;
+  std::cout << setw(width) << "View up: "
+            << CommaSeparatedList(std::vector<double>(vu, vu + 3)) << std::endl;
+  std::cout << setw(width) << "Distance: " << cam->GetDistance() << std::endl;
+};
+}
diff --git a/src/Cxx/Visualization/Hanoi.md b/src/Cxx/Visualization/Hanoi.md
new file mode 100644
index 00000000000..5f02e9f4538
--- /dev/null
+++ b/src/Cxx/Visualization/Hanoi.md
@@ -0,0 +1,11 @@
+### Description
+
+This is three-dimensional implementation of the Towers of Hanoi.
+
+Here we visualize the operation of the recursive Towers of Hanoi puzzle. In this puzzle there are three pegs. In the initial position there are one or more disks(or pucks) of varying diameter on the pegs. The disks are sorted according to disk diameter, so that
+the largest disk is on the bottom, followed by the next largest, and so on. The goal of the puzzle is to move the disks from one peg to another, moving the disks one at a time, and never placing a larger disk on top of a smaller disk.
+
+Here we first set up the scene with the table, pegs and pucks. Then we use a function called `Hanoi()` to begin the recursion. A second function `MovePuck()` moves the dick from one peg to another.
+
+To give a pleasing visual effect we move the disk in small, user-specified increments, flipping the disc over as it moves
+from one peg to the next. Option `-s` controls the user-defined increments. The option `-c 2` freezes a disk in mid air moving from one peg to another.
diff --git a/src/Cxx/Visualization/HanoiInitial.cxx b/src/Cxx/Visualization/HanoiInitial.cxx
new file mode 100644
index 00000000000..72a8905a727
--- /dev/null
+++ b/src/Cxx/Visualization/HanoiInitial.cxx
@@ -0,0 +1,2 @@
+// Start this program with the parameter: -c 1
+#include "Hanoi.cxx"
diff --git a/src/Cxx/Visualization/HanoiIntermediate.cxx b/src/Cxx/Visualization/HanoiIntermediate.cxx
new file mode 100644
index 00000000000..67296d39e6d
--- /dev/null
+++ b/src/Cxx/Visualization/HanoiIntermediate.cxx
@@ -0,0 +1,2 @@
+// Start this program with the parameter: -c 2
+#include "Hanoi.cxx"
diff --git a/src/Python.md b/src/Python.md
index 8ce266a4b80..01201733adc 100644
--- a/src/Python.md
+++ b/src/Python.md
@@ -192,6 +192,7 @@ This section includes examples of manipulating meshes.
 [DisplacementPlot](/Python/VisualizationAlgorithms/DisplacementPlot) | vtkColorTransferFunction vtkWarpVector vtkVectorDot | Show modal lines for a vibrating beam.
 [ElevationBandsWithGlyphs](/Python/Visualization/ElevationBandsWithGlyphs) | vtkBandedPolyDataContourFilter vtkLookupTable vtkColorSeries vtkGlyph3D | Demonstrates the coloring of a surface by partitioning the elevation into bands and using arrows to display the normals on the surface.
 [GlyphTable](/Python/Visualization/GlyphTable) | vtkGlyph3D | Vary the shapes of glyphed points using a glyph table
+[Hanoi](/Python/Visualization/Hanoi)|  | Towers of Hanoi.
 [Hawaii](/Python/Visualization/Hawaii)| vtkElevationFilter vtkColorSeries vtkLookupTable | Visualize elevations by coloring the scalar values with a lookup table.
 [HardwareSelector](/Python/Visualization/HardwareSelector) | vtkHardwareSelector |
 [InteractorStyleTrackballActor](/Python/Visualization/InteractorStyleTrackballActor) | vtkInteractorStyleTrackBallActor |
diff --git a/src/Python/Visualization/Hanoi.md b/src/Python/Visualization/Hanoi.md
new file mode 100644
index 00000000000..5f02e9f4538
--- /dev/null
+++ b/src/Python/Visualization/Hanoi.md
@@ -0,0 +1,11 @@
+### Description
+
+This is three-dimensional implementation of the Towers of Hanoi.
+
+Here we visualize the operation of the recursive Towers of Hanoi puzzle. In this puzzle there are three pegs. In the initial position there are one or more disks(or pucks) of varying diameter on the pegs. The disks are sorted according to disk diameter, so that
+the largest disk is on the bottom, followed by the next largest, and so on. The goal of the puzzle is to move the disks from one peg to another, moving the disks one at a time, and never placing a larger disk on top of a smaller disk.
+
+Here we first set up the scene with the table, pegs and pucks. Then we use a function called `Hanoi()` to begin the recursion. A second function `MovePuck()` moves the dick from one peg to another.
+
+To give a pleasing visual effect we move the disk in small, user-specified increments, flipping the disc over as it moves
+from one peg to the next. Option `-s` controls the user-defined increments. The option `-c 2` freezes a disk in mid air moving from one peg to another.
diff --git a/src/Python/Visualization/Hanoi.py b/src/Python/Visualization/Hanoi.py
new file mode 100755
index 00000000000..2d8edae84c4
--- /dev/null
+++ b/src/Python/Visualization/Hanoi.py
@@ -0,0 +1,362 @@
+#!/usr/bin/env python
+
+#  Translated from Hanoi.cxx.
+
+import vtk
+
+
+class GV(object):
+    """
+    Used to store global variables.
+    """
+
+    def __init__(self, numberOfPucks=5, numberOfSteps=5, puckResolution=48, configuration=0):
+        self.numberOfPucks = numberOfPucks
+        self.numberOfSteps = numberOfSteps
+        self.puckResolution = puckResolution
+        self.configuration = configuration
+        self.gotFigure2 = False  # Used to bail out of recursion if configuration == 2.
+        self.L = 1.0  # Puck height.
+        self.H = 1.1 * self.numberOfPucks * self.L  # Peg height.
+        self.R = 0.5  # Peg radius.
+        self.rMin = 4.0 * self.R  # The minimum allowable radius of disks.
+        self.rMax = 12.0 * self.R  # The maximum allowable radius of disks
+        self.D = 1.1 * 1.25 * self.rMax  # The distance between the pegs.
+        self.numberOfMoves = 0
+
+    def update(self, numberOfPucks, numberOfSteps, puckResolution, configuration):
+        self.numberOfPucks = numberOfPucks
+        self.numberOfSteps = numberOfSteps
+        self.puckResolution = puckResolution
+        self.configuration = configuration
+        self.H = 1.1 * self.numberOfPucks * self.L  # Peg height.
+
+
+# Globals
+gv = GV()
+renWin = vtk.vtkRenderWindow()
+"""
+   For the pegStack we use a list of lists where the sublists correspond to the
+      source, target and helper pegs.
+   Python lists can be used as a stack since they have append() (corresponding
+      to push()) and pop().
+"""
+pegStack = [[], [], []]
+
+
+def main():
+    maxPucks = 20
+    if not verify_parameters(maxPucks):
+        return
+
+    colors = vtk.vtkNamedColors()
+
+    # Create the renderer and render window interactor.
+    ren = vtk.vtkRenderer()
+    renWin.AddRenderer(ren)
+    renWin.SetSize(1200, 750)
+    iren = vtk.vtkRenderWindowInteractor()
+    iren.SetRenderWindow(renWin)
+
+    ren.SetBackground(colors.GetColor3d("PapayaWhip"))
+
+    camera = vtk.vtkCamera()
+    camera.SetPosition(41.0433, 27.9637, 30.442)
+    camera.SetFocalPoint(11.5603, -1.51931, 0.95899)
+    camera.SetClippingRange(18.9599, 91.6042)
+    camera.SetViewUp(0, 1, 0)
+
+    ren.SetActiveCamera(camera)
+
+    # Create geometry: table, pegs, and pucks.
+    pegGeometry = vtk.vtkCylinderSource()
+    pegGeometry.SetResolution(8)
+    pegMapper = vtk.vtkPolyDataMapper()
+    pegMapper.SetInputConnection(pegGeometry.GetOutputPort())
+
+    puckGeometry = vtk.vtkCylinderSource()
+    puckGeometry.SetResolution(gv.puckResolution)
+    puckMapper = vtk.vtkPolyDataMapper()
+    puckMapper.SetInputConnection(puckGeometry.GetOutputPort())
+
+    tableGeometry = vtk.vtkPlaneSource()
+    tableGeometry.SetResolution(10, 10)
+    tableMapper = vtk.vtkPolyDataMapper()
+    tableMapper.SetInputConnection(tableGeometry.GetOutputPort())
+
+    # Create the actors: table top, pegs, and pucks
+    # The table
+    table = vtk.vtkActor()
+    ren.AddActor(table)
+    table.SetMapper(tableMapper)
+    # table.GetProperty().SetColor(0.9569, 0.6431, 0.3765)
+    table.GetProperty().SetColor(colors.GetColor3d("SaddleBrown"))
+    table.AddPosition(gv.D, 0, 0)
+    table.SetScale(4 * gv.D, 2 * gv.D, 3 * gv.D)
+    table.RotateX(90)
+
+    # The pegs (using cylinder geometry).  Note that the pegs have to translated
+    # in the  y-direction because the cylinder is centered about the origin.
+    gv.H = 1.1 * gv.numberOfPucks * gv.L
+    peg = list()
+    for i in range(0, 3):
+        peg.append(vtk.vtkActor())
+        ren.AddActor(peg[i])
+        peg[i].SetMapper(pegMapper)
+        # peg[i].GetProperty().SetColor(1, 1, 1)
+        peg[i].GetProperty().SetColor(colors.GetColor3d("Lavender"))
+        peg[i].AddPosition(i * gv.D, gv.H / 2, 0)
+        peg[i].SetScale(1, gv.H, 1)
+
+    # The pucks (using cylinder geometry). Always loaded on peg# 0.
+    puck = list()
+    randomSequence = vtk.vtkMinimalStandardRandomSequence()
+    randomSequence.SetSeed(1)
+    for i in range(0, gv.numberOfPucks):
+        puck.append(vtk.vtkActor())
+        puck[i].SetMapper(puckMapper)
+        color = [0, 0, 0]
+        for j in range(0, 3):
+            color[j] = randomSequence.GetValue()
+            randomSequence.Next()
+        puck[i].GetProperty().SetColor(*color)
+        puck[i].AddPosition(0, i * gv.L + gv.L / 2, 0)
+        scale = gv.rMax - i * (gv.rMax - gv.rMin) / (gv.numberOfPucks - 1)
+        puck[i].SetScale(scale, 1, scale)
+        ren.AddActor(puck[i])
+        pegStack[0].append(puck[i])
+
+    # Reset the camera to view all actors.
+    renWin.Render()
+    renWin.SetWindowName("Towers of Hanoi")
+
+    if gv.configuration == 3:
+        WriteImage("hanoi0.png", renWin, rgba=False)
+
+    if gv.configuration != 1:
+        # Begin recursion.
+        Hanoi(gv.numberOfPucks - 1, 0, 2, 1)
+        Hanoi(1, 0, 1, 2)
+        if not gv.gotFigure2:
+            Hanoi(gv.numberOfPucks - 1, 2, 1, 0)
+
+            renWin.Render()
+            if gv.configuration == 3:
+                WriteImage("hanoi2.png", renWin, rgba=False)
+        # Report output.
+        s = 'Number of moves: {:d}\nPolygons rendered each frame: {:d}\nTotal number of frames: {:d}'
+        print(s.format(gv.numberOfMoves, 3 * 8 + 1 + gv.numberOfPucks * (2 + gv.puckResolution),
+                       gv.numberOfMoves * 3 * gv.numberOfSteps))
+
+    iren.AddObserver('EndInteractionEvent', OrientationObserver(ren.GetActiveCamera()))
+
+    # Render the image.
+    iren.Initialize()
+    iren.Start()
+
+
+def get_program_parameters():
+    import argparse
+    description = 'Towers of Hanoi. .'
+    epilogue = '''
+Where:  -p specifies the number of pucks.
+        -s specifies the number of steps.
+        -r specifies the puck resolution.
+        -c specifies configuration.
+            0 final configuration.
+            1 initial configuration.
+            2 intermediate configuration.
+            3 final configuration and save images
+Defaults:  -p 5 -s 5 -r 48 -c 0
+    '''
+    parser = argparse.ArgumentParser(description=description, epilog=epilogue,
+                                     formatter_class=argparse.RawDescriptionHelpFormatter)
+    parser.add_argument('--numberOfPucks', '-p', default=5, type=int, nargs='?', help='The number of pucks.')
+    parser.add_argument('--numberOfSteps', '-s', default=5, type=int, nargs='?', help='The number of steps.')
+    parser.add_argument('--puckResolution', '-r', default=48, type=int, nargs='?', help='The puck resolution.')
+    parser.add_argument('--configuration', '-c', default=0, type=int, nargs='?', help='The configuration.')
+    args = parser.parse_args()
+    return args.numberOfPucks, args.numberOfSteps, args.puckResolution, args.configuration
+
+
+def verify_parameters(maxPucks):
+    numberOfPucks, numberOfSteps, puckResolution, configuration = get_program_parameters()
+    numberOfPucks = abs(numberOfPucks)
+    numberOfSteps = abs(numberOfSteps)
+    puckResolution = abs(puckResolution)
+    configuration = abs(configuration)
+    check = True
+    if numberOfPucks < 2:
+        print('Please use more pucks!')
+        check = False
+    if numberOfPucks > maxPucks:
+        print('Too many pucks specified! Maximum is', maxPucks)
+        check = False
+    if numberOfSteps < 3:
+        print('Please use more steps!')
+        check = False
+    if configuration > 3:
+        print('0 >= configuration <= 3')
+        check = False
+    if check:
+        gv.update(numberOfPucks, numberOfSteps, puckResolution, configuration)
+    return check
+
+
+def MovePuck(peg1, peg2):
+    """
+    This routine is responsible for moving pucks from one peg to the next.
+    :param peg1: First peg.
+    :param peg2: Next peg.
+    :return:
+    """
+    gv.numberOfMoves += 1
+
+    # Get the actor to move
+    movingActor = pegStack[peg1].pop()
+
+    # Get the distance to move up.
+    distance = (gv.H - (gv.L * (len(pegStack[peg1]) - 1)) + gv.rMax) / gv.numberOfSteps
+
+    for i in range(0, gv.numberOfSteps):
+        movingActor.AddPosition(0, distance, 0)
+        renWin.Render()
+
+    # Get the distance to move across
+    distance = (peg2 - peg1) * gv.D / gv.numberOfSteps
+    flipAngle = 180.0 / gv.numberOfSteps
+    for i in range(0, gv.numberOfSteps):
+        movingActor.AddPosition(distance, 0, 0)
+        movingActor.RotateX(flipAngle)
+        renWin.Render()
+        if gv.numberOfMoves == 13 and i == 3:  # for making book image
+            if gv.configuration == 3 or gv.configuration == 2:
+                cam = renWin.GetRenderers().GetFirstRenderer().GetActiveCamera()
+                camera1 = vtk.vtkCamera()
+                camera1.SetPosition(54.7263, 41.6467, 44.125)
+                camera1.SetFocalPoint(11.5603, -1.51931, 0.95899)
+                camera1.SetClippingRange(42.4226, 115.659)
+                camera1.SetViewUp(0, 1, 0)
+                renWin.GetRenderers().GetFirstRenderer().SetActiveCamera(camera1)
+                renWin.Render()
+                if gv.configuration == 3:
+                    WriteImage("hanoi1.png", renWin, rgba=False)
+                if gv.configuration == 2:
+                    gv.gotFigure2 = True
+                    break
+                renWin.GetRenderers().GetFirstRenderer().SetActiveCamera(cam)
+                renWin.Render()
+    if gv.gotFigure2:
+        pegStack[peg2].append(movingActor)
+        return
+
+    # Get the distance to move down.
+    distance = ((gv.L * (len(pegStack[peg2]) - 1)) - gv.H - gv.rMax) / gv.numberOfSteps
+
+    for i in range(0, gv.numberOfSteps):
+        movingActor.AddPosition(0, distance, 0)
+        renWin.Render()
+    pegStack[peg2].append(movingActor)
+
+
+def Hanoi(n, peg1, peg2, peg3):
+    """
+    Tower of Hanoi.
+    :param n: Number of disks.
+    :param peg1: Source
+    :param peg2: Target
+    :param peg3: Helper
+    :return:
+    """
+    # If gotFigure2 is true, we break out of the recursion.
+    if gv.gotFigure2:
+        return
+    if n != 1:
+        Hanoi(n - 1, peg1, peg3, peg2)
+        if gv.gotFigure2:
+            return
+        Hanoi(1, peg1, peg2, peg3)
+        Hanoi(n - 1, peg3, peg2, peg1)
+    else:
+        MovePuck(peg1, peg2)
+
+
+class OrientationObserver(object):
+    def __init__(self, cam):
+        self.cam = cam
+
+    def __call__(self, caller, ev):
+        # Just do this to demonstrate who called callback and the event that triggered it.
+        print(caller.GetClassName(), "Event Id:", ev)
+        # Now print the camera orientation.
+        CameraOrientation(self.cam)
+
+
+def CameraOrientation(cam):
+    fmt1 = "{:>15s}"
+    fmt2 = "{:9.6g}"
+    print(fmt1.format("Position:"), ', '.join(map(fmt2.format, cam.GetPosition())))
+    print(fmt1.format("Focal point:"), ', '.join(map(fmt2.format, cam.GetFocalPoint())))
+    print(fmt1.format("Clipping range:"), ', '.join(map(fmt2.format, cam.GetClippingRange())))
+    print(fmt1.format("View up:"), ', '.join(map(fmt2.format, cam.GetViewUp())))
+    print(fmt1.format("Distance:"), fmt2.format(cam.GetDistance()))
+
+
+def WriteImage(fileName, renWin1, rgba=True):
+    """
+    Write the render window view to an image file.
+
+    Image types supported are:
+     BMP, JPEG, PNM, PNG, PostScript, TIFF.
+    The default parameters are used for all writers, change as needed.
+
+    :param fileName: The file name, if no extension then PNG is assumed.
+    :param renWin1: The render window.
+    :param rgba: Used to set the buffer type.
+    :return:
+    """
+
+    import os
+
+    if fileName:
+        # Select the writer to use.
+        path, ext = os.path.splitext(fileName)
+        ext = ext.lower()
+        if not ext:
+            ext = '.png'
+            fileName = fileName + ext
+        if ext == '.bmp':
+            writer = vtk.vtkBMPWriter()
+        elif ext == '.jpg':
+            writer = vtk.vtkJPEGWriter()
+        elif ext == '.pnm':
+            writer = vtk.vtkPNMWriter()
+        elif ext == '.ps':
+            if rgba:
+                rgba = False
+            writer = vtk.vtkPostScriptWriter()
+        elif ext == '.tiff':
+            writer = vtk.vtkTIFFWriter()
+        else:
+            writer = vtk.vtkPNGWriter()
+
+        windowto_image_filter = vtk.vtkWindowToImageFilter()
+        windowto_image_filter.SetInput(renWin1)
+        windowto_image_filter.SetScale(1)  # image quality
+        if rgba:
+            windowto_image_filter.SetInputBufferTypeToRGBA()
+        else:
+            windowto_image_filter.SetInputBufferTypeToRGB()
+            # Read from the front buffer.
+            windowto_image_filter.ReadFrontBufferOff()
+            windowto_image_filter.Update()
+
+        writer.SetFileName(fileName)
+        writer.SetInputConnection(windowto_image_filter.GetOutputPort())
+        writer.Write()
+    else:
+        raise RuntimeError('Need a filename.')
+
+
+if __name__ == '__main__':
+    main()
-- 
GitLab