diff --git a/src/Cxx.md b/src/Cxx.md
index 4fd5234af374445477f9789896946bf4e5caf912..3a9d28a6b7ef37bbfa9374a8c370457732ae8e4c 100644
--- a/src/Cxx.md
+++ b/src/Cxx.md
@@ -783,6 +783,7 @@ This section includes vtkImageData vtkStructuredGrid and vtkRectilinearGrid.
 [Rainbow](/Cxx/Rendering/Rainbow)| vtkLookupTable | Use and manipulation of vtkLookupTables.
 [SpecularSpheres](/Cxx/Rendering/SpecularSpheres)| vtkProperty |Demonstrates the effect of specular lighting on spheres.
 [StippledLine](/Cxx/Rendering/StippledLine)| vtkTexture | Draw a stippled line.
+[WalkCow](/Cxx/Rendering/WalkCow) | vtkBYUReader renWin::EraseOff() vtkActor | This generates Figs. 3-31, 3-32, 3-33 found in VTKTextbook.pdf.
 
 
 ## Lighting
diff --git a/src/Cxx/Rendering/CMakeLists.txt b/src/Cxx/Rendering/CMakeLists.txt
index c9e9d4226635ba33191d6fc7a25a953c6f45cf22..59f5694c81538a50390dfabe1deb8cd5342648ec 100644
--- a/src/Cxx/Rendering/CMakeLists.txt
+++ b/src/Cxx/Rendering/CMakeLists.txt
@@ -29,6 +29,7 @@ SET(KIT Rendering)
 SET(NEEDS_ARGS
   Rainbow
   Rotations
+  WalkCow
 )
 SET(DATA ${WikiExamples_SOURCE_DIR}/src/Testing/Data)
 SET(TEMP ${WikiExamples_BINARY_DIR}/Testing/Temporary)
@@ -39,6 +40,9 @@ ADD_TEST(${KIT}-Rotations ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KIT}CxxTests
 ADD_TEST(${KIT}-Rainbow ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KIT}CxxTests
   TestRainbow ${DATA}/combxyz.bin ${DATA}/combq.bin)
 
+ADD_TEST(${KIT}-WalkCow ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${KIT}CxxTests
+  TestWalkCow ${DATA}/cow.g)
+
 INCLUDE(${WikiExamples_SOURCE_DIR}/CMake/ExamplesTesting.cmake)
 
 endif()
diff --git a/src/Cxx/Rendering/WalkCow.cxx b/src/Cxx/Rendering/WalkCow.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..09e35a43e7300e6a8f8f84b1dab42ef31f10b4d7
--- /dev/null
+++ b/src/Cxx/Rendering/WalkCow.cxx
@@ -0,0 +1,480 @@
+// Translated from walkCow.tcl
+
+#include <vtkActor.h>
+#include <vtkAxes.h>
+#include <vtkBYUReader.h>
+#include <vtkCallbackCommand.h>
+#include <vtkCamera.h>
+#include <vtkNamedColors.h>
+#include <vtkPNGWriter.h>
+#include <vtkPolyDataMapper.h>
+#include <vtkProperty.h>
+#include <vtkRenderWindow.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkRenderer.h>
+#include <vtkSmartPointer.h>
+#include <vtkTransform.h>
+#include <vtkWindowToImageFilter.h>
+
+#include <algorithm>
+#include <vector>
+
+namespace
+{
+/*
+These Rotate* and Walk functions create a scene where multiple
+   views of the object exist.
+
+  They all operate in a similar manner, namely:
+  1) Accept vtkActor, vtkRenderer, vtkRenderWindow as parameters.
+  2) Position the object.
+  3) Position the observer with the focal point sent to the centre
+      of the object.
+  4) Render and set EraseOff() in the render window.
+     Note that:
+      EraseOff() has to be called after a Render() call
+       to work in the desired way.
+  5) Then rotate or walk the object around the scene.
+  6) Write out the scene using Screenshot().
+  6) Set EraseOff() in the render window.
+  7) Reset the object position.
+
+*/
+void Rotate_X(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin);
+void Rotate_Y(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin);
+void Rotate_Z(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin);
+void Rotate_XY(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin);
+void Rotate_V_0(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin);
+void Rotate_V_V(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin);
+void Walk(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin);
+
+/*
+// Used to estimate positions similar to the book illustrations.
+static void CameraModifiedCallback(vtkObject* caller,
+                                   long unsigned int vtkNotUsed(eventId),
+                                   void* vtkNotUsed(clientData),
+                                   void* vtkNotUsed(callData));
+*/
+
+// Save a screenshot.
+void Screenshot(std::string fileName, vtkRenderWindow* renWin);
+}
+
+int main(int argc, char* argv[])
+{
+  auto Scale = [](std::vector<double>& v, double scale) {
+    std::transform(std::begin(v), std::end(v), std::begin(v),
+                   [=](double const& n) { return n / scale; });
+    return;
+  };
+
+  if (argc != 2)
+  {
+    std::cout << "usage: ./WalkCow filename" << std::endl;
+    std::cout << "where: filename is the file cow.g" << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  std::string fileName = argv[1];
+  vtkSmartPointer<vtkNamedColors> colors =
+    vtkSmartPointer<vtkNamedColors>::New();
+  // Set the background color. Match those in VTKTextbook.pdf.
+  auto scale = 256.0;
+  std::vector<double> bkg1 = {60, 93, 144};
+  std::vector<double> bkg2 = {25, 51, 102};
+  Scale(bkg1, scale);
+  colors->SetColor("BkgColor1", bkg1[0], bkg1[1], bkg1[2]);
+  Scale(bkg2, scale);
+  colors->SetColor("BkgColor2", bkg2[0], bkg2[1], bkg2[2]);
+
+  vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
+  vtkSmartPointer<vtkRenderWindow> renWin =
+    vtkSmartPointer<vtkRenderWindow>::New();
+  renWin->AddRenderer(ren);
+
+  vtkSmartPointer<vtkRenderWindowInteractor> iren =
+    vtkSmartPointer<vtkRenderWindowInteractor>::New();
+  iren->SetRenderWindow(renWin);
+
+  // The cow pipeline.
+  vtkSmartPointer<vtkBYUReader> cow = vtkSmartPointer<vtkBYUReader>::New();
+  cow->SetGeometryFileName(fileName.c_str());
+  cow->Update();
+
+  vtkSmartPointer<vtkPolyDataMapper> cowMapper =
+    vtkSmartPointer<vtkPolyDataMapper>::New();
+  cowMapper->SetInputConnection(cow->GetOutputPort());
+  cowMapper->ScalarVisibilityOff();
+
+  vtkSmartPointer<vtkActor> cowActor = vtkSmartPointer<vtkActor>::New();
+  cowActor->SetMapper(cowMapper);
+  cowActor->GetProperty()->SetColor(colors->GetColor3d("Wheat").GetData());
+
+  ren->AddActor(cowActor);
+
+  // Axes pipeline.
+  vtkSmartPointer<vtkAxes> cowAxesSource = vtkSmartPointer<vtkAxes>::New();
+  cowAxesSource->SetScaleFactor(10.0);
+  cowAxesSource->SetOrigin(0, 0, 0);
+
+  vtkSmartPointer<vtkPolyDataMapper> cowAxesMapper =
+    vtkSmartPointer<vtkPolyDataMapper>::New();
+  cowAxesMapper->SetInputConnection(cowAxesSource->GetOutputPort());
+
+  vtkSmartPointer<vtkActor> cowAxes = vtkSmartPointer<vtkActor>::New();
+  cowAxes->SetMapper(cowAxesMapper);
+  cowAxes->VisibilityOff();
+
+  ren->AddActor(cowAxes);
+
+  ren->SetBackground(colors->GetColor3d("BkgColor1").GetData());
+  renWin->SetSize(600, 480);
+
+  iren->Initialize();
+  cowAxes->VisibilityOn();
+  renWin->Render();
+
+  // Activate this if you want to see the Position and Focal point.
+  // vtkSmartPointer<vtkCallbackCommand> modifiedCallback =
+  // vtkSmartPointer<vtkCallbackCommand>::New();
+  // modifiedCallback->SetCallback(CameraModifiedCallback);
+  // ren->GetActiveCamera()->AddObserver(vtkCommand::ModifiedEvent,
+  // modifiedCallback);
+
+  // These four rotations use the same camera position.
+  Rotate_X(cowActor, ren, renWin);
+  Rotate_Y(cowActor, ren, renWin);
+  Rotate_Z(cowActor, ren, renWin);
+  Rotate_XY(cowActor, ren, renWin);
+
+  ren->SetBackground(colors->GetColor3d("BkgColor2").GetData());
+  Rotate_V_0(cowActor, ren, renWin);
+  Rotate_V_V(cowActor, ren, renWin);
+  // Walk() needs to go after Rotate_V_0() or Rotate_V_V().
+  Walk(cowActor, ren, renWin);
+
+  // Interact with data.
+  // Keep the last rendered image.
+  renWin->EraseOff();
+  iren->Start();
+  return EXIT_SUCCESS;
+}
+
+namespace
+{
+
+void Rotate_X(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin)
+{
+  // Six rotations about the x axis.
+  ren->ResetCamera();
+  ren->ResetCameraClippingRange();
+  cowActor->SetOrientation(0.0, 0.0, 0.0);
+  cowActor->SetOrigin(0.0, 0.0, 0);
+  cowActor->SetPosition(0, 0, 0);
+  // Get the focal point.
+  double* bounds = cowActor->GetBounds();
+  double fp[3];
+  for (int i = 0; i < 3; ++i)
+  {
+    fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0;
+  }
+  // This closely matches the original illustration.
+  ren->GetActiveCamera()->SetPosition(2, 25, 0);
+  ren->GetActiveCamera()->SetFocalPoint(fp);
+  ren->GetActiveCamera()->SetViewUp(0, 0, -1);
+  ren->ResetCameraClippingRange();
+  renWin->Render();
+  renWin->Render();
+  renWin->EraseOff();
+  for (int idx = 0; idx < 6; idx++)
+  {
+    cowActor->RotateX(60);
+    renWin->Render();
+    renWin->Render();
+  }
+  Screenshot("Fig3-31a.png", renWin);
+  renWin->EraseOn();
+}
+
+void Rotate_Y(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin)
+{
+  // Six rotations about the y axis.
+  ren->ResetCamera();
+  ren->ResetCameraClippingRange();
+  cowActor->SetOrientation(0.0, 0.0, 0.0);
+  cowActor->SetOrigin(0.0, 0.0, 0);
+  cowActor->SetPosition(0, 0, 0);
+  // Get the focal point.
+  double* bounds = cowActor->GetBounds();
+  double fp[3];
+  for (int i = 0; i < 3; ++i)
+  {
+    fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0;
+  }
+  // This closely matches the original illustration.
+  ren->GetActiveCamera()->SetPosition(2, 0, 25);
+  ren->GetActiveCamera()->SetFocalPoint(fp);
+  ren->GetActiveCamera()->SetViewUp(0, 1, 0);
+  ren->ResetCameraClippingRange();
+  renWin->Render();
+  renWin->Render();
+  renWin->EraseOff();
+  for (int idx = 0; idx < 6; idx++)
+  {
+    cowActor->RotateY(60);
+    renWin->Render();
+    renWin->Render();
+  }
+  Screenshot("Fig3-31b.png", renWin);
+  renWin->EraseOn();
+}
+
+void Rotate_Z(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin)
+{
+  // Six rotations about the z axis.
+  ren->ResetCamera();
+  ren->ResetCameraClippingRange();
+  cowActor->SetOrientation(0.0, 0.0, 0.0);
+  cowActor->SetOrigin(0.0, 0.0, 0);
+  cowActor->SetPosition(0, 0, 0);
+  // Get the focal point.
+  double* bounds = cowActor->GetBounds();
+  double fp[3];
+  for (int i = 0; i < 3; ++i)
+  {
+    fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0;
+  }
+  // This closely matches the original illustration.
+  ren->GetActiveCamera()->SetPosition(2, 0, 25);
+  ren->GetActiveCamera()->SetFocalPoint(fp);
+  ren->GetActiveCamera()->SetViewUp(0, 1, 0);
+  ren->ResetCameraClippingRange();
+  renWin->Render();
+  renWin->Render();
+  renWin->EraseOff();
+  for (int idx = 0; idx < 6; idx++)
+  {
+    cowActor->RotateZ(60);
+    renWin->Render();
+    renWin->Render();
+  }
+  Screenshot("Fig3-31c.png", renWin);
+  renWin->EraseOn();
+}
+
+void Rotate_XY(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin)
+{
+  // First a rotation about the x axis, then six rotations about the y axis.
+  ren->ResetCamera();
+  ren->ResetCameraClippingRange();
+  cowActor->SetOrientation(0.0, 0.0, 0.0);
+  cowActor->SetOrigin(0.0, 0.0, 0);
+  cowActor->SetPosition(0, 0, 0);
+  // Get the focal point.
+  double* bounds = cowActor->GetBounds();
+  double fp[3];
+  for (int i = 0; i < 3; ++i)
+  {
+    fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0;
+  }
+  // This closely matches the original illustration.
+  ren->GetActiveCamera()->SetPosition(2, 0, 25);
+  ren->GetActiveCamera()->SetFocalPoint(fp);
+  ren->GetActiveCamera()->SetViewUp(0, 1, 0);
+  ren->ResetCameraClippingRange();
+  renWin->Render();
+  renWin->Render();
+  renWin->EraseOff();
+  cowActor->RotateX(60);
+  for (int idx = 0; idx < 6; idx++)
+  {
+    cowActor->RotateY(60);
+    renWin->Render();
+    renWin->Render();
+  }
+  cowActor->RotateX(-60);
+  Screenshot("Fig3-31d.png", renWin);
+  renWin->EraseOn();
+}
+
+void Rotate_V_0(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin)
+{
+  // The cow rotating about a vector passing through her nose.
+  // With the origin at (0, 0, 0).
+  ren->ResetCamera();
+  ren->ResetCameraClippingRange();
+  cowActor->SetOrientation(0.0, 0.0, 0.0);
+  cowActor->SetOrigin(0.0, 0.0, 0);
+  cowActor->SetPosition(0, 0, 0);
+  // Get the focal point.
+  double* bounds = cowActor->GetBounds();
+  double fp[3];
+  for (int i = 0; i < 3; ++i)
+  {
+    fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0;
+  }
+  vtkSmartPointer<vtkTransform> cowPos = vtkSmartPointer<vtkTransform>::New();
+  cowPos->Identity();
+  cowPos->SetMatrix(cowActor->GetMatrix());
+  vtkSmartPointer<vtkTransform> cowTransform =
+    vtkSmartPointer<vtkTransform>::New();
+  cowTransform->Identity();
+  cowActor->SetUserMatrix(cowTransform->GetMatrix());
+  // This closely matches the original illustration.
+  ren->GetActiveCamera()->SetPosition(16, 9, -12);
+  ren->GetActiveCamera()->SetFocalPoint(fp);
+  ren->ResetCameraClippingRange();
+  renWin->Render();
+  renWin->Render();
+  renWin->EraseOff();
+  for (int idx = 0; idx < 6; idx++)
+  {
+    cowActor->RotateWXYZ(60, 2.19574, -1.42455, -0.0331036);
+    renWin->Render();
+    renWin->Render();
+  }
+  Screenshot("Fig3-33a.png", renWin);
+  renWin->EraseOn();
+  // Put the cow back on the origin.
+  for (int idx = 0; idx < 6; idx++)
+  {
+    cowActor->RotateWXYZ(-60, 2.19574, -1.42455, -0.0331036);
+  }
+  cowActor->SetUserMatrix(cowPos->GetMatrix());
+  ren->GetActiveCamera()->SetPosition(0, 0, 1);
+  ren->GetActiveCamera()->SetViewUp(0, 1, 0);
+  ren->ResetCamera();
+}
+
+void Rotate_V_V(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin)
+{
+  // The cow rotating about a vector passing through her nose.
+  // With the origin at (6.11414, 1.27386, 0.015175).
+  ren->ResetCamera();
+  ren->ResetCameraClippingRange();
+  cowActor->SetOrientation(0.0, 0.0, 0.0);
+  cowActor->SetOrigin(0.0, 0.0, 0);
+  cowActor->SetPosition(0, 0, 0);
+  // Get the focal point.
+  double* bounds = cowActor->GetBounds();
+  double fp[3];
+  for (int i = 0; i < 3; ++i)
+  {
+    fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0;
+  }
+  vtkSmartPointer<vtkTransform> cowPos = vtkSmartPointer<vtkTransform>::New();
+  cowPos->Identity();
+  cowPos->SetMatrix(cowActor->GetMatrix());
+  cowActor->SetOrigin(6.11414, 1.27386, 0.015175); // The cow's nose
+  vtkSmartPointer<vtkTransform> cowTransform =
+    vtkSmartPointer<vtkTransform>::New();
+  cowTransform->Identity();
+  cowActor->SetUserMatrix(cowTransform->GetMatrix());
+  // This closely matches the original illustration.
+  ren->GetActiveCamera()->SetPosition(31, 23, -21);
+  ren->GetActiveCamera()->SetFocalPoint(fp);
+  ren->ResetCameraClippingRange();
+  renWin->Render();
+  renWin->Render();
+  renWin->EraseOff();
+  for (int idx = 0; idx < 6; idx++)
+  {
+    cowActor->RotateWXYZ(60, 2.19574, -1.42455, -0.0331036);
+    renWin->Render();
+    renWin->Render();
+  }
+  Screenshot("Fig3-33b.png", renWin);
+  renWin->EraseOn();
+  // Put the cow back on the origin.
+  for (int idx = 0; idx < 6; idx++)
+  {
+    cowActor->RotateWXYZ(-60, 2.19574, -1.42455, -0.0331036);
+  }
+  cowActor->SetUserMatrix(cowPos->GetMatrix());
+}
+
+void Walk(vtkActor* cowActor, vtkRenderer* ren, vtkRenderWindow* renWin)
+{
+  // The cow "walking" around the global origin
+  vtkSmartPointer<vtkTransform> cowPos = vtkSmartPointer<vtkTransform>::New();
+  cowPos->Identity();
+  cowPos->SetMatrix(cowActor->GetMatrix());
+  cowActor->SetOrientation(0.0, 0.0, 0.0);
+  cowActor->SetOrigin(0.0, 0.0, 0.0);
+  // Get the focal point.
+  double* bounds = cowActor->GetBounds();
+  double fp[3];
+  for (int i = 0; i < 3; ++i)
+  {
+    fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0;
+  }
+  vtkSmartPointer<vtkTransform> cowTransform =
+    vtkSmartPointer<vtkTransform>::New();
+  cowTransform->Identity();
+  cowTransform->Translate(0, 0, 5);
+  cowActor->SetUserMatrix(cowTransform->GetMatrix());
+  // This closely matches the original illustration.
+  ren->GetActiveCamera()->SetPosition(1, 24, 16);
+  ren->GetActiveCamera()->SetFocalPoint(fp);
+  ren->GetActiveCamera()->SetViewUp(0, 0, -1);
+  ren->ResetCameraClippingRange();
+  renWin->Render();
+  renWin->Render();
+  renWin->EraseOff();
+  for (int idx = 0; idx < 6; idx++)
+  {
+    cowTransform->Identity();
+    cowTransform->RotateY(idx * 60);
+    cowTransform->Translate(0, 0, 5);
+    cowActor->SetUserMatrix(cowTransform->GetMatrix());
+    renWin->Render();
+    renWin->Render();
+  }
+  Screenshot("Fig3-32.png", renWin);
+  renWin->EraseOn();
+  // Walkies are over, put the cow back on the origin.
+  // cowActor->SetUserMatrix(cowPos->GetMatrix());
+}
+
+/*
+static void CameraModifiedCallback(vtkObject* caller,
+                                   long unsigned int vtkNotUsed(eventId),
+                                   void* vtkNotUsed(clientData),
+                                   void* vtkNotUsed(callData))
+{
+  std::cout << caller->GetClassName() << " modified" << std::endl;
+  vtkCamera* camera = static_cast<vtkCamera*>(caller);
+  // Print the interesting stuff.
+  std::cout << "\tPosition: " << camera->GetPosition()[0] << ", "
+            << camera->GetPosition()[1] << ", " << camera->GetPosition()[2]
+            << std::endl;
+  std::cout << "\tFocal point: " << camera->GetFocalPoint()[0] << ", "
+            << camera->GetFocalPoint()[1] << ", " << camera->GetFocalPoint()[2]
+            << std::endl;
+}
+*/
+
+void Screenshot(std::string fileName, vtkRenderWindow* renWin)
+{
+  vtkSmartPointer<vtkWindowToImageFilter> windowToImageFilter =
+    vtkSmartPointer<vtkWindowToImageFilter>::New();
+  windowToImageFilter->SetInput(renWin);
+#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();
+}
+
+}
diff --git a/src/Cxx/Rendering/WalkCow.md b/src/Cxx/Rendering/WalkCow.md
new file mode 100644
index 0000000000000000000000000000000000000000..3221ab11c88b9e2bc0edfe3d1bbf5378a4294b72
--- /dev/null
+++ b/src/Cxx/Rendering/WalkCow.md
@@ -0,0 +1,2 @@
+### Description
+This generates Fig 3-31: Rotations of a cow about her axes.; Fig. 3-32: The cow "walking" around the global origin; Fig. 3-33: The cow rotating about a vector passing through her nose found in VTKTextbook.pdf.
diff --git a/src/Python.md b/src/Python.md
index a917604269f3831550771d19ba632d93e47ad2a3..732544f083cbbade4f65becd413bf910b59ffb9d 100644
--- a/src/Python.md
+++ b/src/Python.md
@@ -161,6 +161,11 @@ This section includes examples of manipulating meshes.
 [Variant](/Python/Variant) | vtkVariant |
 vtkVersion |
 
+## Rendering
+| Example Name | Classes Demonstrated | Description | Image |
+|--------------|----------------------|-------------|-------|
+[WalkCow](/Python/Rendering/WalkCow) | vtkBYUReader renWin::EraseOff() vtkActor | This generates Figs. 3-31, 3-32, 3-33 found in VTKTextbook.pdf.
+
 ## Visualization
 
 | Example Name | Classes Demonstrated | Description | Image |
diff --git a/src/Python/Rendering/WalkCow.md b/src/Python/Rendering/WalkCow.md
new file mode 100644
index 0000000000000000000000000000000000000000..3221ab11c88b9e2bc0edfe3d1bbf5378a4294b72
--- /dev/null
+++ b/src/Python/Rendering/WalkCow.md
@@ -0,0 +1,2 @@
+### Description
+This generates Fig 3-31: Rotations of a cow about her axes.; Fig. 3-32: The cow "walking" around the global origin; Fig. 3-33: The cow rotating about a vector passing through her nose found in VTKTextbook.pdf.
diff --git a/src/Python/Rendering/WalkCow.py b/src/Python/Rendering/WalkCow.py
new file mode 100644
index 0000000000000000000000000000000000000000..f6b2cb6d4447cc68bcb343097be0a996209a5189
--- /dev/null
+++ b/src/Python/Rendering/WalkCow.py
@@ -0,0 +1,393 @@
+#!/usr/local/bin/python
+
+#  Translated from walkCow.tcl
+
+import vtk
+
+
+def main():
+    file_name = get_program_parameters()
+
+    colors = vtk.vtkNamedColors()
+    # Set the background color. Match those in VTKTextbook.pdf.
+    bkg1 = map(lambda x: x / 256.0, [60, 93, 144])
+    bkg2 = map(lambda x: x / 256.0, [25, 51, 102])
+    colors.SetColor("BkgColor1", *bkg1)
+    colors.SetColor("BkgColor2", *bkg2)
+
+    ren = vtk.vtkRenderer()
+    renWin = vtk.vtkRenderWindow()
+    renWin.AddRenderer(ren)
+
+    iren = vtk.vtkRenderWindowInteractor()
+    iren.SetRenderWindow(renWin)
+
+    # The cow pipeline.
+    cow = vtk.vtkBYUReader()
+    cow.SetGeometryFileName(file_name)
+    cow.Update()
+
+    cowMapper = vtk.vtkPolyDataMapper()
+    cowMapper.SetInputConnection(cow.GetOutputPort())
+    cowMapper.ScalarVisibilityOff()
+
+    cowActor = vtk.vtkActor()
+    cowActor.SetMapper(cowMapper)
+    cowActor.GetProperty().SetColor(colors.GetColor3d("Wheat"))
+
+    ren.AddActor(cowActor)
+
+    # Axes pipeline.
+    cowAxesSource = vtk.vtkAxes()
+    cowAxesSource.SetScaleFactor(10.0)
+    cowAxesSource.SetOrigin(0, 0, 0)
+
+    cowAxesMapper = vtk.vtkPolyDataMapper()
+    cowAxesMapper.SetInputConnection(cowAxesSource.GetOutputPort())
+
+    cowAxes = vtk.vtkActor()
+    cowAxes.SetMapper(cowAxesMapper)
+    cowAxes.VisibilityOff()
+
+    ren.AddActor(cowAxes)
+
+    ren.SetBackground(colors.GetColor3d("BkgColor1"))
+    renWin.SetSize(600, 480)
+
+    iren.Initialize()
+    cowAxes.VisibilityOn()
+    renWin.Render()
+
+    # A general comment:
+    # EraseOff() has to be called after a Render() call to work in the desired way.
+
+    # Activate this if you want to see the Position and Focal point.
+    # ren.GetActiveCamera().AddObserver('ModifiedEvent', CameraModifiedCallback)
+
+    # These four walks use the same camera position.
+    Rotate_X(cowActor, ren, renWin)
+    Rotate_Y(cowActor, ren, renWin)
+    Rotate_Z(cowActor, ren, renWin)
+    Rotate_XY(cowActor, ren, renWin)
+
+    ren.SetBackground(colors.GetColor3d("BkgColor2"))
+    Rotate_V_0(cowActor, ren, renWin)
+    Rotate_V_V(cowActor, ren, renWin)
+    # Walk() needs to go after Rotate_V_0() or Rotate_V_V().
+    Walk(cowActor, ren, renWin)
+
+    # Interact with data.
+    renWin.EraseOff()
+    iren.Start()
+
+
+def get_program_parameters():
+    import argparse
+    description = 'Produce figures: 3-31, 3-32, 3-33 from the VTK Textbook.'
+    epilogue = '''
+        Produce figures 3-31, 3-32, 3-33 from the VTK Textbook.
+        It is a translation of the original WalkCow.tcl with a few additional enhancements.
+   '''
+    parser = argparse.ArgumentParser(description=description, epilog=epilogue)
+    parser.add_argument('filename', help='The file cow.g.')
+    args = parser.parse_args()
+    return args.filename
+
+
+"""
+  These Rotate* and Walk functions create a scene where multiple
+     views of the object exist.
+
+    They all operate in a similar manner, namely:
+    1) Accept vtkActor, vtkRenderer, vtkRenderWindow as parameters.
+    2) Position the object.
+    3) Position the observer with the focal point sent to the centre
+        of the object.
+    4) Render and set EraseOff() in the render window.
+       Note that:
+        EraseOff() has to be called after a Render() call
+         to work in the desired way.
+    5) Then rotate or Walk the object around the scene.
+    6) Write out the scene using Screenshot().
+    6) Set EraseOff() in the render window.
+    7) Reset the object position.
+
+"""
+
+
+def Rotate_X(cowActor, ren, renWin):
+    # Six rotations about the x axis.
+    ren.ResetCamera()
+    ren.ResetCameraClippingRange()
+    cowActor.SetOrientation(0.0, 0.0, 0.0)
+    cowActor.SetOrigin(0.0, 0.0, 0)
+    cowActor.SetPosition(0, 0, 0)
+    # Get the focal point.
+    bounds = cowActor.GetBounds()
+    fp = [0.0] * 3
+    for i in range(0, 3):
+        fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0
+    # This closely matches the original illustration.
+    ren.GetActiveCamera().SetPosition(2, 25, 0)
+    ren.GetActiveCamera().SetFocalPoint(fp)
+    ren.GetActiveCamera().SetViewUp(0, 0, -1)
+    ren.ResetCameraClippingRange()
+    renWin.Render()
+    renWin.Render()
+    renWin.EraseOff()
+    for idx in range(0, 6):
+        cowActor.RotateX(60)
+        renWin.Render()
+        renWin.Render()
+    Screenshot("Fig3-31a.png", renWin)
+    renWin.EraseOn()
+
+
+def Rotate_Y(cowActor, ren, renWin):
+    # Six rotations about the y axis.
+    ren.ResetCamera()
+    ren.ResetCameraClippingRange()
+    cowActor.SetOrientation(0.0, 0.0, 0.0)
+    cowActor.SetOrigin(0.0, 0.0, 0)
+    cowActor.SetPosition(0, 0, 0)
+    # Get the focal point.
+    bounds = cowActor.GetBounds()
+    fp = [0.0] * 3
+    for i in range(0, 3):
+        fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0
+    # This closely matches the original illustration.
+    ren.GetActiveCamera().SetPosition(2, 0, 25)
+    ren.GetActiveCamera().SetFocalPoint(fp)
+    ren.GetActiveCamera().SetViewUp(0, 1, 0)
+    ren.ResetCameraClippingRange()
+    renWin.Render()
+    renWin.Render()
+    renWin.EraseOff()
+    for idx in range(0, 6):
+        cowActor.RotateY(60)
+        renWin.Render()
+        renWin.Render()
+    Screenshot("Fig3-31b.png", renWin)
+    renWin.EraseOn()
+
+
+def Rotate_Z(cowActor, ren, renWin):
+    # Six rotations about the z axis.
+    ren.ResetCamera()
+    ren.ResetCameraClippingRange()
+    cowActor.SetOrientation(0.0, 0.0, 0.0)
+    cowActor.SetOrigin(0.0, 0.0, 0)
+    cowActor.SetPosition(0, 0, 0)
+    # Get the focal point.
+    bounds = cowActor.GetBounds()
+    fp = [0.0] * 3
+    for i in range(0, 3):
+        fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0
+    # This closely matches the original illustration.
+    # ren.GetActiveCamera().SetPosition(2, 0, 25)
+    ren.GetActiveCamera().SetPosition(2, 0, 25)
+    ren.GetActiveCamera().SetFocalPoint(fp)
+    ren.GetActiveCamera().SetViewUp(0, 1, 0)
+    ren.ResetCameraClippingRange()
+    renWin.Render()
+    renWin.Render()
+    renWin.EraseOff()
+    for idx in range(0, 6):
+        cowActor.RotateZ(60)
+        renWin.Render()
+        renWin.Render()
+    Screenshot("Fig3-31c.png", renWin)
+    renWin.EraseOn()
+
+
+def Rotate_XY(cowActor, ren, renWin):
+    # First a rotation about the x axis, then six rotations about the y axis.
+    ren.ResetCamera()
+    ren.ResetCameraClippingRange()
+    cowActor.SetOrientation(0.0, 0.0, 0.0)
+    cowActor.SetOrigin(0.0, 0.0, 0)
+    cowActor.SetPosition(0, 0, 0)
+    # Get the focal point.
+    bounds = cowActor.GetBounds()
+    fp = [0.0] * 3
+    for i in range(0, 3):
+        fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0
+    # This closely matches the original illustration.
+    # ren.GetActiveCamera().SetPosition(2, 0, 24)
+    ren.GetActiveCamera().SetPosition(2, 0, 25)
+    ren.GetActiveCamera().SetFocalPoint(fp)
+    ren.GetActiveCamera().SetViewUp(0, 1, 0)
+    ren.ResetCameraClippingRange()
+    renWin.Render()
+    renWin.Render()
+    renWin.EraseOff()
+    cowActor.RotateX(60)
+    for idx in range(0, 6):
+        cowActor.RotateY(60)
+        renWin.Render()
+        renWin.Render()
+    cowActor.RotateX(-60)
+    Screenshot("Fig3-31d.png", renWin)
+    renWin.EraseOn()
+
+
+def Rotate_V_0(cowActor, ren, renWin):
+    # The cow rotating about a vector passing through her nose.
+    # With the origin at (0, 0, 0).
+    ren.ResetCamera()
+    ren.ResetCameraClippingRange()
+    cowActor.SetOrientation(0.0, 0.0, 0.0)
+    cowActor.SetOrigin(0.0, 0.0, 0)
+    cowActor.SetPosition(0, 0, 0)
+    # Get the focal point.
+    bounds = cowActor.GetBounds()
+    fp = [0.0] * 3
+    for i in range(0, 3):
+        fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0
+    cowPos = vtk.vtkTransform()
+    cowPos.Identity()
+    cowPos.SetMatrix(cowActor.GetMatrix())
+    cowTransform = vtk.vtkTransform()
+    cowTransform.Identity()
+    cowActor.SetUserMatrix(cowTransform.GetMatrix())
+    # This closely matches the original illustration.
+    ren.GetActiveCamera().SetPosition(16, 9, -12)
+    ren.GetActiveCamera().SetFocalPoint(fp)
+    ren.ResetCameraClippingRange()
+    renWin.Render()
+    renWin.Render()
+    renWin.EraseOff()
+    for idx in range(0, 6):
+        cowActor.RotateWXYZ(60, 2.19574, -1.42455, -0.0331036)
+        renWin.Render()
+        renWin.Render()
+    Screenshot("Fig3-33a.png", renWin)
+    renWin.EraseOn()
+    # Put the cow back on the origin.
+    for idx in range(0, 6):
+        cowActor.RotateWXYZ(-60, 2.19574, -1.42455, -0.0331036)
+    cowActor.SetUserMatrix(cowPos.GetMatrix())
+    ren.GetActiveCamera().SetPosition(0, 0, 1)
+    ren.GetActiveCamera().SetViewUp(0, 1, 0)
+    ren.ResetCamera()
+
+
+def Rotate_V_V(cowActor, ren, renWin):
+    # The cow rotating about a vector passing through her nose.
+    # With the origin at (6.11414, 1.27386, 0.015175).
+    ren.ResetCamera()
+    ren.ResetCameraClippingRange()
+    cowActor.SetOrientation(0.0, 0.0, 0.0)
+    cowActor.SetOrigin(0.0, 0.0, 0)
+    cowActor.SetPosition(0, 0, 0)
+    # Get the focal point.
+    bounds = cowActor.GetBounds()
+    fp = [0.0] * 3
+    for i in range(0, 3):
+        fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0
+    cowPos = vtk.vtkTransform()
+    cowPos.Identity()
+    cowPos.SetMatrix(cowActor.GetMatrix())
+    cowActor.SetOrigin(6.11414, 1.27386, 0.015175)  # The cow's nose
+    cowTransform = vtk.vtkTransform()
+    cowTransform.Identity()
+    cowActor.SetUserMatrix(cowTransform.GetMatrix())
+    # This closely matches the original illustration.
+    ren.GetActiveCamera().SetPosition(31, 23, -21)
+    ren.GetActiveCamera().SetFocalPoint(fp)
+    ren.ResetCameraClippingRange()
+    renWin.Render()
+    renWin.Render()
+    renWin.EraseOff()
+    for idx in range(0, 6):
+        cowActor.RotateWXYZ(60, 2.19574, -1.42455, -0.0331036)
+        renWin.Render()
+        renWin.Render()
+    Screenshot("Fig3-33b.png", renWin)
+    renWin.EraseOn()
+    # Put the cow back on the origin.
+    for idx in range(0, 6):
+        cowActor.RotateWXYZ(-60, 2.19574, -1.42455, -0.0331036)
+    cowActor.SetUserMatrix(cowPos.GetMatrix())
+
+
+def Walk(cowActor, ren, renWin):
+    # The cow "walking" around the global origin
+    cowPos = vtk.vtkTransform()
+    cowPos.Identity()
+    cowPos.SetMatrix(cowActor.GetMatrix())
+    cowActor.SetOrientation(0.0, 0.0, 0.0)
+    cowActor.SetOrigin(0.0, 0.0, 0.0)
+    # Get the focal point.
+    bounds = cowActor.GetBounds()
+    fp = [0.0] * 3
+    for i in range(0, 3):
+        fp[i] = (bounds[i * 2 + 1] + bounds[i * 2]) / 2.0
+    cowTransform = vtk.vtkTransform()
+    cowTransform.Identity()
+    cowTransform.Translate(0, 0, 5)
+    cowActor.SetUserMatrix(cowTransform.GetMatrix())
+    # This closely matches the original illustration.
+    ren.GetActiveCamera().SetPosition(1, 24, 16)
+    ren.GetActiveCamera().SetFocalPoint(fp)
+    ren.GetActiveCamera().SetViewUp(0, 0, -1)
+    ren.ResetCameraClippingRange()
+    renWin.Render()
+    renWin.Render()
+    renWin.EraseOff()
+    for idx in range(1, 7):
+        cowTransform.Identity()
+        cowTransform.RotateY(idx * 60)
+        cowTransform.Translate(0, 0, 5)
+        cowActor.SetUserMatrix(cowTransform.GetMatrix())
+        renWin.Render()
+        renWin.Render()
+    Screenshot("Fig3-32.png", renWin)
+    renWin.EraseOn()
+    # Walkies are over, put the cow back on the origin.
+    # cowActor.SetUserMatrix(cowPos.GetMatrix())
+
+
+def CameraModifiedCallback(caller):
+    """
+     Used to estimate positions similar to the book illustrations.
+    :param caller:
+    :return:
+    """
+    print(caller.GetClassName(), "modified")
+    # Print the interesting stuff.
+    print("\tPosition: ",
+          caller.GetPosition()[0], ", ",
+          caller.GetPosition()[1], ", ",
+          caller.GetPosition()[2])
+    print("\tFocal point: ",
+          caller.GetFocalPoint()[0], ", ",
+          caller.GetFocalPoint()[1], ", ",
+          caller.GetFocalPoint()[2])
+
+
+def Screenshot(fileName, renWin):
+    """
+    Save a screenshot.
+    :param fileName:
+    :param renWin:
+    :return:
+    """
+    windowToImageFilter = vtk.vtkWindowToImageFilter()
+    windowToImageFilter.SetInput(renWin)
+    windowToImageFilter.SetScale(1)  # image quality
+    # We are not recording the alpha (transparency) channel.
+    # windowToImageFilter.SetInputBufferTypeToRGBA()
+    windowToImageFilter.SetInputBufferTypeToRGB()
+    # Read from the front buffer.
+    windowToImageFilter.ReadFrontBufferOff()
+    windowToImageFilter.Update()
+
+    writer = vtk.vtkPNGWriter()
+    writer.SetFileName(fileName)
+    writer.SetInputConnection(windowToImageFilter.GetOutputPort())
+    writer.Write()
+
+
+if __name__ == '__main__':
+    main()