From c3507f74f23f539d600d3d4fbb1e4c5cdf634d50 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Sun, 16 Dec 2018 19:14:22 +0100
Subject: [PATCH] ENH: improve file reader support for runTimePostProcessing
 (#1091)

- support .vtp format for geometry, surface, line, cloud.

- use native reader for handling vtk, vtp, obj, stl surface files.
  For other formats, use the MeshedSurface (the surfMesh lib) to
  handle reading and Foam::vtk::Tools::Patch to handle the
  conversion to vtkPolyData. This combination is more memory efficient.

- update tutorial case to include vtp surface geometry
---
 .../dummy/runTimePostProcessingDummy.H        |   6 +-
 .../fieldVisualisationBase.C                  | 124 ++++++++------
 .../fieldVisualisationBase.H                  |  49 +++---
 .../functionObjectBase.C                      |   2 +-
 .../functionObjectBase.H                      |   4 +-
 .../functionObjectCloud.C                     |  18 ++-
 .../functionObjectCloud.H                     |  25 ++-
 .../functionObjectLine.C                      |  78 +++++++--
 .../functionObjectLine.H                      |  22 ++-
 .../functionObjectSurface.C                   |  83 +++++++---
 .../functionObjectSurface.H                   |   9 +-
 .../runTimePostProcessing/geometryBase.C      |   7 +-
 .../runTimePostProcessing/geometryBase.H      |  49 +++---
 .../runTimePostProcessing/geometrySurface.C   | 153 +++++++++++-------
 .../runTimePostProcessing/geometrySurface.H   |  28 ++--
 .../graphics/runTimePostProcessing/pathline.C |  10 +-
 .../graphics/runTimePostProcessing/pathline.H |  29 ++--
 .../runTimePostProcessing/pointData.C         |   8 +-
 .../runTimePostProcessing/pointData.H         |  27 ++--
 .../runTimePostProcessing.C                   | 126 +++++++--------
 .../runTimePostProcessing.H                   |  27 +++-
 .../runTimePostProcessingTemplates.C          |   2 +-
 .../graphics/runTimePostProcessing/scene.C    |   1 -
 .../graphics/runTimePostProcessing/scene.H    |  32 ++--
 .../graphics/runTimePostProcessing/surface.C  |  13 +-
 .../graphics/runTimePostProcessing/surface.H  |  28 ++--
 .../graphics/runTimePostProcessing/text.C     |   6 +-
 .../graphics/runTimePostProcessing/text.H     |  43 +++--
 .../pimpleFoam/RAS/elipsekkLOmega/Allclean    |   3 +
 .../pimpleFoam/RAS/elipsekkLOmega/Allrun.pre  |   3 +
 .../RAS/elipsekkLOmega/system/controlDict     |   4 +-
 .../system/runTimePostProcessing              |  46 ++++--
 .../RAS/elipsekkLOmega/system/streamLines     |  49 ++++++
 33 files changed, 677 insertions(+), 437 deletions(-)
 create mode 100644 tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/system/streamLines

diff --git a/src/functionObjects/graphics/runTimePostProcessing/dummy/runTimePostProcessingDummy.H b/src/functionObjects/graphics/runTimePostProcessing/dummy/runTimePostProcessingDummy.H
index b71e771351f..3ea20d753ea 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/dummy/runTimePostProcessingDummy.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/dummy/runTimePostProcessingDummy.H
@@ -22,14 +22,14 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::functionObjects::runTimePostPro::runTimePostProcessingDummy
+    Foam::functionObjects::runTimePostProcessingDummy
 
 Group
     grpGraphicsFunctionObjects
 
 Description
-    Dummy implementation of runTimePostProcessing to report when
-    the real version is unavailable.
+    Dummy implementation of Foam::functionObjects::runTimePostProcessing
+    to report when the real version is unavailable.
 
 SourceFiles
     runTimePostProcessingDummy.C
diff --git a/src/functionObjects/graphics/runTimePostProcessing/fieldVisualisationBase.C b/src/functionObjects/graphics/runTimePostProcessing/fieldVisualisationBase.C
index 1a804abc4e5..7d76795a1e8 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/fieldVisualisationBase.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/fieldVisualisationBase.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -49,9 +49,11 @@ License
 
 const Foam::Enum
 <
-    Foam::functionObjects::fieldVisualisationBase::colourByType
+    Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
+    colourByType
 >
-Foam::functionObjects::fieldVisualisationBase::colourByTypeNames
+Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
+colourByTypeNames
 ({
     { colourByType::cbColour, "colour" },
     { colourByType::cbField, "field" },
@@ -59,9 +61,11 @@ Foam::functionObjects::fieldVisualisationBase::colourByTypeNames
 
 const Foam::Enum
 <
-    Foam::functionObjects::fieldVisualisationBase::colourMapType
+    Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
+    colourMapType
 >
-Foam::functionObjects::fieldVisualisationBase::colourMapTypeNames
+Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
+colourMapTypeNames
 ({
     { colourMapType::cmRainbow, "rainbow" },
     { colourMapType::cmBlueWhiteRed, "blueWhiteRed" },
@@ -72,7 +76,8 @@ Foam::functionObjects::fieldVisualisationBase::colourMapTypeNames
 
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
-void Foam::functionObjects::fieldVisualisationBase::setColourMap
+void Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
+setColourMap
 (
     vtkLookupTable* lut
 ) const
@@ -130,7 +135,8 @@ void Foam::functionObjects::fieldVisualisationBase::setColourMap
 }
 
 
-void Foam::functionObjects::fieldVisualisationBase::addScalarBar
+void Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
+addScalarBar
 (
     const scalar position,
     vtkRenderer* renderer,
@@ -239,7 +245,8 @@ void Foam::functionObjects::fieldVisualisationBase::addScalarBar
 }
 
 
-void Foam::functionObjects::fieldVisualisationBase::setField
+void Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
+setField
 (
     const scalar position,
     const word& colourFieldName,
@@ -272,11 +279,11 @@ void Foam::functionObjects::fieldVisualisationBase::setField
             // Note: if both point and cell data exists, preferentially
             //       choosing point data.  This is often the case when using
             //       glyphs
-            if (pData->GetPointData()->HasArray(fieldName) == 1)
+            if (pData->GetPointData()->HasArray(fieldName))
             {
                 mapper->SetScalarModeToUsePointFieldData();
             }
-            else if (pData->GetCellData()->HasArray(fieldName) == 1)
+            else if (pData->GetCellData()->HasArray(fieldName))
             {
                 mapper->SetScalarModeToUseCellFieldData();
             }
@@ -302,8 +309,8 @@ void Foam::functionObjects::fieldVisualisationBase::setField
 }
 
 
-
-void Foam::functionObjects::fieldVisualisationBase::addGlyphs
+void Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
+addGlyphs
 (
     const scalar position,
     const word& scaleFieldName,
@@ -320,38 +327,59 @@ void Foam::functionObjects::fieldVisualisationBase::addGlyphs
 
     glyph->SetInputData(data);
     glyph->ScalingOn();
-    bool ok = true;
+
+    bool needPointData = false;
 
     // Determine whether we have scalar or vector data
+    // and if we need to convert CellData -> PointData
+
     label nComponents = -1;
     const char* scaleFieldNameChar = scaleFieldName.c_str();
-    if (data->GetPointData()->HasArray(scaleFieldNameChar) == 1)
+    if (data->GetPointData()->HasArray(scaleFieldNameChar))
     {
         nComponents =
             data->GetPointData()->GetArray(scaleFieldNameChar)
                 ->GetNumberOfComponents();
     }
-    else if (data->GetCellData()->HasArray(scaleFieldNameChar) == 1)
+    else if (data->GetCellData()->HasArray(scaleFieldNameChar))
     {
-        // Need to convert cell data to point data
-        auto cellToPoint = vtkSmartPointer<vtkCellDataToPointData>::New();
-        cellToPoint->SetInputData(data);
-        cellToPoint->Update();
-        vtkDataSet* pds = cellToPoint->GetOutput();
-        vtkDataArray* pData = pds->GetPointData()->GetArray(scaleFieldNameChar);
+        // Need to convert CellData to PointData
+        needPointData = true;
 
-        // Store in main vtkPolyData
-        data->GetPointData()->AddArray(pData);
-
-        nComponents = pData->GetNumberOfComponents();
+        nComponents =
+            data->GetCellData()->GetArray(scaleFieldNameChar)
+                ->GetNumberOfComponents();
     }
     else
+    {
+        WarningInFunction
+            << "Cannot add glyphs. No such cell or point field: "
+            << scaleFieldName << endl;
+        return;
+    }
+
+
+    const bool ok = (nComponents == 1 || nComponents == 3);
+
+    if (!ok)
     {
         WarningInFunction
             << "Glyphs can only be added to scalar or vector data. "
             << "Unable to process field " << scaleFieldName << endl;
         return;
     }
+    else if (needPointData)
+    {
+        auto cellToPoint = vtkSmartPointer<vtkCellDataToPointData>::New();
+        cellToPoint->SetInputData(data);
+        cellToPoint->Update();
+        vtkDataSet* pds = cellToPoint->GetOutput();
+        vtkDataArray* pData = pds->GetPointData()->GetArray(scaleFieldNameChar);
+
+        // Store in main vtkPolyData
+        data->GetPointData()->AddArray(pData);
+    }
+
 
     if (nComponents == 1)
     {
@@ -367,18 +395,16 @@ void Foam::functionObjects::fieldVisualisationBase::addGlyphs
 
         if (maxGlyphLength > 0)
         {
-            double range[2];
+            // Can get range from point data:
 
-            // Can use values to find range
+            // double range[2];
             // vtkDataArray* values =
             //     data->GetPointData()->GetScalars(scaleFieldNameChar);
             // values->GetRange(range);
 
             // Set range according to user-supplied limits
-            range[0] = range_.first();
-            range[1] = range_.second();
             glyph->ClampingOn();
-            glyph->SetRange(range);
+            glyph->SetRange(range_.first(), range_.second());
 
             // If range[0] != min(value), maxGlyphLength behaviour will not
             // be correct...
@@ -450,15 +476,7 @@ void Foam::functionObjects::fieldVisualisationBase::addGlyphs
             scaleFieldNameChar
         );
     }
-    else
-    {
-        WarningInFunction
-            << "Glyphs can only be added to scalar and vector fields."
-            << " Field " << scaleFieldName << " has " << nComponents
-            << " components" << endl;
 
-        ok = false;
-    }
 
     if (ok)
     {
@@ -477,10 +495,11 @@ void Foam::functionObjects::fieldVisualisationBase::addGlyphs
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-Foam::functionObjects::fieldVisualisationBase::fieldVisualisationBase
+Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
+fieldVisualisationBase
 (
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours
+    const HashPtrTable<Function1<vector>>& colours
 )
 :
     colours_(colours),
@@ -504,16 +523,17 @@ Foam::functionObjects::fieldVisualisationBase::fieldVisualisationBase
 
             colourMapTypeNames.readIfPresent("colourMap", dict, colourMap_);
 
-            const dictionary& sbarDict = dict.subDict("scalarBar");
-            sbarDict.readEntry("visible", scalarBar_.visible_);
+            const dictionary& sbDict = dict.subDict("scalarBar");
+            sbDict.readEntry("visible", scalarBar_.visible_);
+
             if (scalarBar_.visible_)
             {
-                sbarDict.readEntry("vertical", scalarBar_.vertical_);
-                sbarDict.readEntry("position", scalarBar_.position_);
-                sbarDict.readEntry("title", scalarBar_.title_);
-                sbarDict.readEntry("fontSize", scalarBar_.fontSize_);
-                sbarDict.readEntry("labelFormat", scalarBar_.labelFormat_);
-                sbarDict.readEntry("numberOfLabels", scalarBar_.numberOfLabels_);
+                sbDict.readEntry("vertical", scalarBar_.vertical_);
+                sbDict.readEntry("position", scalarBar_.position_);
+                sbDict.readEntry("title", scalarBar_.title_);
+                sbDict.readEntry("fontSize", scalarBar_.fontSize_);
+                sbDict.readEntry("labelFormat", scalarBar_.labelFormat_);
+                sbDict.readEntry("numberOfLabels", scalarBar_.numberOfLabels_);
             }
             break;
         }
@@ -523,21 +543,23 @@ Foam::functionObjects::fieldVisualisationBase::fieldVisualisationBase
 
 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
 
-Foam::functionObjects::fieldVisualisationBase::~fieldVisualisationBase()
+Foam::functionObjects::runTimePostPro::fieldVisualisationBase::
+~fieldVisualisationBase()
 {}
 
 
 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
 
 const Foam::HashPtrTable<Foam::Function1<Foam::vector>, Foam::word>&
-Foam::functionObjects::fieldVisualisationBase::colours() const
+Foam::functionObjects::runTimePostPro::fieldVisualisationBase::colours() const
 {
     return colours_;
 }
 
 
 const Foam::word&
-Foam::functionObjects::fieldVisualisationBase::fieldName() const
+Foam::functionObjects::runTimePostPro::fieldVisualisationBase::fieldName()
+const
 {
     return fieldName_;
 }
diff --git a/src/functionObjects/graphics/runTimePostProcessing/fieldVisualisationBase.H b/src/functionObjects/graphics/runTimePostProcessing/fieldVisualisationBase.H
index 4f8341a6198..afc64771370 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/fieldVisualisationBase.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/fieldVisualisationBase.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -22,7 +22,7 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::functionObjects::fieldVisualisationBase
+    Foam::functionObjects::runTimePostPro::fieldVisualisationBase
 
 Description
     Base class for scene objects
@@ -42,26 +42,29 @@ SourceFiles
 #include "HashPtrTable.H"
 #include "Function1.H"
 
+// VTK includes
 #include "vtkSmartPointer.h"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+// Forward declarations
 class vtkActor;
 class vtkLookupTable;
+class vtkMapper;
 class vtkPolyData;
 class vtkPolyDataMapper;
 class vtkRenderer;
 
-
-class vtkMapper;
-
 namespace Foam
 {
 namespace functionObjects
 {
-
+// Forward declarations
 class runTimePostProcessing;
 
+namespace runTimePostPro
+{
+
 /*---------------------------------------------------------------------------*\
                    Class fieldVisualisationBase Declaration
 \*---------------------------------------------------------------------------*/
@@ -91,20 +94,9 @@ public:
         static const Enum<colourMapType> colourMapTypeNames;
 
 
-private:
-
-    // Private Member Functions
-
-        //- No copy construct
-        fieldVisualisationBase(const fieldVisualisationBase&) = delete;
-
-        //- No copy assignment
-        void operator=(const fieldVisualisationBase&) = delete;
-
-
 protected:
 
-    // Protected data
+    // Protected Data
 
         struct scalarBar
         {
@@ -118,7 +110,7 @@ protected:
         };
 
         //- Colours
-        const HashPtrTable<Function1<vector>, word>& colours_;
+        const HashPtrTable<Function1<vector>>& colours_;
 
         //- Field name
         word fieldName_;
@@ -171,6 +163,12 @@ protected:
             vtkRenderer* renderer
         ) const;
 
+        //- No copy construct
+        fieldVisualisationBase(const fieldVisualisationBase&) = delete;
+
+        //- No copy assignment
+        void operator=(const fieldVisualisationBase&) = delete;
+
 
 public:
 
@@ -180,7 +178,7 @@ public:
         fieldVisualisationBase
         (
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours
+            const HashPtrTable<Function1<vector>>& colours
         );
 
 
@@ -190,18 +188,19 @@ public:
 
     // Member Functions
 
-        // Access
+    // Access
 
-            //- Return the colours
-            const HashPtrTable<Function1<vector>, word>& colours() const;
+        //- Return the colours
+        const HashPtrTable<Function1<vector>>& colours() const;
 
-            //- Return the field name
-            const word& fieldName() const;
+        //- Return the field name
+        const word& fieldName() const;
 };
 
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+} // End namespace runTimePostPro
 } // End namespace functionObjects
 } // End namespace Foam
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.C b/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.C
index 11475a3b2a8..28d4fbffb3f 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.C
@@ -79,7 +79,7 @@ Foam::functionObjects::runTimePostPro::functionObjectBase::functionObjectBase
 (
     const stateFunctionObject& state,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours
+    const HashPtrTable<Function1<vector>>& colours
 )
 :
     fieldVisualisationBase(dict, colours),
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.H b/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.H
index 7515024521f..47647fc5e73 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.H
@@ -109,13 +109,13 @@ protected:
         //  \note does not change the stateFunctionObject
         bool removeFile(const word& keyword, const word& subDictName);
 
-
         //- No copy construct
         functionObjectBase(const functionObjectBase&) = delete;
 
         //- No copy assignment
         void operator=(const functionObjectBase&) = delete;
 
+
 public:
 
     //- Run-time type information
@@ -129,7 +129,7 @@ public:
         (
             const stateFunctionObject& state,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours
+            const HashPtrTable<Function1<vector>>& colours
         );
 
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.C b/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.C
index ce98b412267..e8645f118ba 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.C
@@ -35,10 +35,12 @@ License
 #include "vtkSmartPointer.h"
 #include "vtkPolyData.h"
 #include "vtkPolyDataMapper.h"
-#include "vtkXMLPolyDataReader.h"
-#include "vtkPolyDataReader.h"
 #include "vtkProperty.h"
 
+// VTK Readers
+#include "vtkPolyDataReader.h"
+#include "vtkXMLPolyDataReader.h"
+
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
 namespace Foam
@@ -60,7 +62,7 @@ Foam::functionObjects::runTimePostPro::functionObjectCloud::functionObjectCloud
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours
+    const HashPtrTable<Function1<vector>>& colours
 )
 :
     pointData(parent, dict, colours),
@@ -101,7 +103,6 @@ addGeometryToScene
     // containing all fields.
 
     inputFileName_ = getFileName("file", cloudName_);
-    inputFileName_.expand();
 
     if (inputFileName_.empty())
     {
@@ -113,6 +114,7 @@ addGeometryToScene
         return;
     }
 
+
     vtkSmartPointer<vtkPolyData> dataset;
 
     if (inputFileName_.hasExt("vtp"))
@@ -128,9 +130,17 @@ addGeometryToScene
         // Invalid name - ignore.
         // Don't support VTK legacy format at all - it is too wasteful
         // and cumbersome.
+
+        WarningInFunction
+            << "Could not read "<< inputFileName_ << nl
+            << "Only VTK (.vtp) files are supported"
+            << ". Cloud will not be processed"
+            << endl;
+
         inputFileName_.clear();
     }
 
+
     if (dataset)
     {
         auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.H b/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.H
index 74888b234d0..121e815a014 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.H
@@ -56,20 +56,9 @@ class functionObjectCloud
     public pointData,
     public functionObjectBase
 {
-private:
-
-    // Private Member Functions
-
-        //- No copy construct
-        functionObjectCloud(const functionObjectCloud&) = delete;
-
-        //- No copy assignment
-        void operator=(const functionObjectCloud&) = delete;
-
-
 protected:
 
-    // Protected data
+    // Protected Data
 
         //- Name of functionObjectCloud
         word cloudName_;
@@ -83,6 +72,16 @@ protected:
         //- Actor
         vtkSmartPointer<vtkActor> actor_;
 
+
+    // Protected Member Functions
+
+        //- No copy construct
+        functionObjectCloud(const functionObjectCloud&) = delete;
+
+        //- No copy assignment
+        void operator=(const functionObjectCloud&) = delete;
+
+
 public:
 
     //- Run-time type information
@@ -96,7 +95,7 @@ public:
         (
             const runTimePostProcessing& parent,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours
+            const HashPtrTable<Function1<vector>>& colours
         );
 
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectLine.C b/src/functionObjects/graphics/runTimePostProcessing/functionObjectLine.C
index ca0ba78ac8e..3eeffed2c61 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectLine.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectLine.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -30,11 +30,15 @@ License
 
 // VTK includes
 #include "vtkActor.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkProperty.h"
 #include "vtkRenderer.h"
 #include "vtkSmartPointer.h"
-#include "vtkPolyDataMapper.h"
+
+// VTK Readers
 #include "vtkPolyDataReader.h"
-#include "vtkProperty.h"
+#include "vtkXMLPolyDataReader.h"
 
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
@@ -51,13 +55,51 @@ namespace runTimePostPro
 }
 
 
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
+
+namespace
+{
+
+static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
+{
+    // Not extremely elegant...
+    vtkSmartPointer<vtkPolyData> dataset;
+
+    if (fName.ext() == "vtk")
+    {
+        auto reader = vtkSmartPointer<vtkPolyDataReader>::New();
+
+        reader->SetFileName(fName.c_str());
+        reader->Update();
+        dataset = reader->GetOutput();
+
+        return dataset;
+    }
+
+    if (fName.ext() == "vtp")
+    {
+        auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
+
+        reader->SetFileName(fName.c_str());
+        reader->Update();
+        dataset = reader->GetOutput();
+
+        return dataset;
+    }
+
+    return dataset;
+}
+
+} // End anonymous namespace
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::functionObjects::runTimePostPro::functionObjectLine::functionObjectLine
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours
+    const HashPtrTable<Function1<vector>>& colours
 )
 :
     pathline(parent, dict, colours),
@@ -99,21 +141,28 @@ addGeometryToScene
         return;
     }
 
-    if (fName.hasExt("vtk"))
+
+    auto polyData = getPolyDataFile(fName);
+
+    if (!polyData || polyData->GetNumberOfPoints() == 0)
     {
-        auto lines = vtkSmartPointer<vtkPolyDataReader>::New();
-        lines->SetFileName(fName.c_str());
-        lines->Update();
+        WarningInFunction
+            << "Could not read "<< fName << nl
+            << "Only VTK (.vtp, .vtk) files are supported"
+            << endl;
+        return;
+    }
 
-        auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
-        setField(position, fieldName_, mapper, renderer, lines->GetOutput());
 
-        actor_->SetMapper(mapper);
+    auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
 
-        addLines(position, actor_, lines->GetOutput());
+    setField(position, fieldName_, mapper, renderer, polyData);
 
-        renderer->AddActor(actor_);
-    }
+    actor_->SetMapper(mapper);
+
+    addLines(position, actor_, polyData);
+
+    renderer->AddActor(actor_);
 }
 
 
@@ -126,6 +175,7 @@ void Foam::functionObjects::runTimePostPro::functionObjectLine::updateActors
     actor_->GetProperty()->SetOpacity(opacity(position));
 }
 
+
 bool Foam::functionObjects::runTimePostPro::functionObjectLine::clear()
 {
     if (functionObjectBase::clear())
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectLine.H b/src/functionObjects/graphics/runTimePostProcessing/functionObjectLine.H
index f4e31d0d959..1d4b43d1c7a 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectLine.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectLine.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -56,9 +56,15 @@ class functionObjectLine
     public pathline,
     public functionObjectBase
 {
-private:
+protected:
+
+    // Protected Data
 
-    // Private Member Functions
+        //- Actor
+        vtkSmartPointer<vtkActor> actor_;
+
+
+    // Protected Member Functions
 
         //- No copy construct
         functionObjectLine(const functionObjectLine&) = delete;
@@ -67,14 +73,6 @@ private:
         void operator=(const functionObjectLine&) = delete;
 
 
-protected:
-
-    // Protected data
-
-        //- Actor
-        vtkSmartPointer<vtkActor> actor_;
-
-
 public:
 
     //- Run-time type information
@@ -88,7 +86,7 @@ public:
         (
             const runTimePostProcessing& parent,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours
+            const HashPtrTable<Function1<vector>>& colours
         );
 
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.C b/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.C
index 1d2e4d737a0..f7f694b50d9 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.C
@@ -30,12 +30,16 @@ License
 
 // VTK includes
 #include "vtkActor.h"
+#include "vtkPolyData.h"
 #include "vtkPolyDataMapper.h"
-#include "vtkPolyDataReader.h"
 #include "vtkProperty.h"
 #include "vtkRenderer.h"
 #include "vtkSmartPointer.h"
 
+// VTK Readers
+#include "vtkPolyDataReader.h"
+#include "vtkXMLPolyDataReader.h"
+
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
 namespace Foam
@@ -51,6 +55,44 @@ namespace runTimePostPro
 }
 
 
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
+
+namespace
+{
+
+static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
+{
+    // Not extremely elegant...
+    vtkSmartPointer<vtkPolyData> dataset;
+
+    if (fName.ext() == "vtk")
+    {
+        auto reader = vtkSmartPointer<vtkPolyDataReader>::New();
+
+        reader->SetFileName(fName.c_str());
+        reader->Update();
+        dataset = reader->GetOutput();
+
+        return dataset;
+    }
+
+    if (fName.ext() == "vtp")
+    {
+        auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
+
+        reader->SetFileName(fName.c_str());
+        reader->Update();
+        dataset = reader->GetOutput();
+
+        return dataset;
+    }
+
+    return dataset;
+}
+
+} // End anonymous namespace
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::functionObjects::runTimePostPro::functionObjectSurface::
@@ -58,7 +100,7 @@ functionObjectSurface
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours
+    const HashPtrTable<Function1<vector>>& colours
 )
 :
     geometrySurface(parent, dict, colours, List<fileName>()),
@@ -99,37 +141,38 @@ addGeometryToScene
     }
 
 
-    if (representation_ == rtGlyph)
+    auto polyData = getPolyDataFile(fName);
+
+    if (!polyData || polyData->GetNumberOfPoints() == 0)
     {
-        auto surf = vtkSmartPointer<vtkPolyDataReader>::New();
-        surf->SetFileName(fName.c_str());
-        surf->Update();
+        WarningInFunction
+            << "Could not read "<< fName << nl
+            << "Only VTK (.vtp, .vtk) files are supported"
+            << endl;
+        return;
+    }
 
+    if (representation_ == rtGlyph)
+    {
         addGlyphs
         (
             position,
             fieldName_,
             fieldName_,
             maxGlyphLength_,
-            surf->GetOutput(),
+            polyData,
             surfaceActor_,
             renderer
         );
-        return;
     }
-
-    if (fName.hasExt("vtk"))
+    else
     {
-        auto surf = vtkSmartPointer<vtkPolyDataReader>::New();
-        surf->SetFileName(fName.c_str());
-        surf->Update();
-
-        addFeatureEdges(renderer, surf->GetOutput());
+        addFeatureEdges(renderer, polyData);
 
         auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
-        mapper->SetInputConnection(surf->GetOutputPort());
+        mapper->SetInputData(polyData);
 
-        setField(position, fieldName_, mapper, renderer, surf->GetOutput());
+        setField(position, fieldName_, mapper, renderer, polyData);
 
         surfaceActor_->SetMapper(mapper);
 
@@ -137,12 +180,6 @@ addGeometryToScene
 
         renderer->AddActor(surfaceActor_);
     }
-    else
-    {
-        WarningInFunction
-            << "Only VTK file types are supported"
-            << endl;
-    }
 }
 
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.H b/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.H
index f8176288c0c..d7ee396eb07 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -56,10 +56,9 @@ class functionObjectSurface
     public geometrySurface,
     public functionObjectBase
 {
+protected:
 
-private:
-
-    // Private Member Functions
+    // Protected Member Functions
 
         //- No copy construct
         functionObjectSurface(const functionObjectSurface&) = delete;
@@ -81,7 +80,7 @@ public:
         (
             const runTimePostProcessing& parent,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours
+            const HashPtrTable<Function1<vector>>& colours
         );
 
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/geometryBase.C b/src/functionObjects/graphics/runTimePostProcessing/geometryBase.C
index 7edb7f1748d..299c2ee761d 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/geometryBase.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/geometryBase.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -27,6 +27,7 @@ License
 #include "runTimePostProcessing.H"
 #include "Constant.H"
 
+// VTK includes
 #include "vtkActor.h"
 #include "vtkProperty.h"
 
@@ -81,7 +82,7 @@ Foam::functionObjects::runTimePostPro::geometryBase::geometryBase
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours
+    const HashPtrTable<Function1<vector>>& colours
 )
 :
     parent_(parent),
@@ -96,7 +97,7 @@ Foam::functionObjects::runTimePostPro::geometryBase::geometryBase
 {
     if (dict.found("opacity"))
     {
-        opacity_.reset(Function1<scalar>::New("opacity", dict).ptr());
+        opacity_.reset(Function1<scalar>::New("opacity", dict));
     }
     else
     {
diff --git a/src/functionObjects/graphics/runTimePostProcessing/geometryBase.H b/src/functionObjects/graphics/runTimePostProcessing/geometryBase.H
index 2ed82fe9c9f..24ac7026f54 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/geometryBase.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/geometryBase.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -43,6 +43,7 @@ SourceFiles
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+// Forward declarations
 class vtkRenderer;
 class vtkActor;
 
@@ -51,6 +52,7 @@ namespace Foam
 namespace functionObjects
 {
 
+// Forward declarations
 class runTimePostProcessing;
 
 namespace runTimePostPro
@@ -78,17 +80,6 @@ public:
         static const Enum<renderModeType> renderModeTypeNames;
 
 
-private:
-
-    // Private Member Functions
-
-        //- No copy construct
-        geometryBase(const geometryBase&) = delete;
-
-        //- No copy assignment
-        void operator=(const geometryBase&) = delete;
-
-
 protected:
 
     // Protected data
@@ -109,7 +100,7 @@ protected:
         autoPtr<Function1<scalar>> opacity_;
 
         //- Reference to the colours
-        const HashPtrTable<Function1<vector>, word>& colours_;
+        const HashPtrTable<Function1<vector>>& colours_;
 
 
     // Protected functions
@@ -117,6 +108,12 @@ protected:
         //- Initialise actor
         void initialiseActor(vtkActor* actor) const;
 
+        //- No copy construct
+        geometryBase(const geometryBase&) = delete;
+
+        //- No copy assignment
+        void operator=(const geometryBase&) = delete;
+
 
 public:
 
@@ -127,7 +124,7 @@ public:
         (
             const runTimePostProcessing& parent_,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours
+            const HashPtrTable<Function1<vector>>& colours
         );
 
 
@@ -137,23 +134,25 @@ public:
 
     // Member Functions
 
-        // Access
+    // Access
+
+        //- Return the reference to the parent function object
+        const runTimePostProcessing& parent() const;
 
-            //- Return the reference to the parent function object
-            const runTimePostProcessing& parent() const;
+        //- Return the name
+        const word& name() const;
 
-            //- Return the name
-            const word& name() const;
+        //- Return the visible flag
+        bool visible() const;
 
-            //- Return the visible flag
-            bool visible() const;
+        //- Return the opacity
+        scalar opacity(const scalar position) const;
 
-            //- Return the opacity
-            scalar opacity(const scalar position) const;
+        //- Return reference to the colours
+        const HashPtrTable<Function1<vector>>& colours() const;
 
-            //- Return reference to the colours
-            const HashPtrTable<Function1<vector>, word>& colours() const;
 
+    // Scene interaction
 
         //- Add geometry to scene
         virtual void addGeometryToScene
diff --git a/src/functionObjects/graphics/runTimePostProcessing/geometrySurface.C b/src/functionObjects/graphics/runTimePostProcessing/geometrySurface.C
index 06cb8123bfa..583ec45fcd0 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/geometrySurface.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/geometrySurface.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -26,7 +26,8 @@ License
 // OpenFOAM includes
 #include "geometrySurface.H"
 #include "stringOps.H"
-#include "triSurface.H"
+#include "foamVtkTools.H"
+#include "MeshedSurfaces.H"
 #include "runTimePostProcessing.H"
 #include "addToRunTimeSelectionTable.H"
 
@@ -42,7 +43,12 @@ License
 #include "vtkProperty.h"
 #include "vtkRenderer.h"
 #include "vtkSmartPointer.h"
-#include "vtkTriangle.h"
+
+// VTK Readers
+#include "vtkOBJReader.h"
+#include "vtkSTLReader.h"
+#include "vtkPolyDataReader.h"
+#include "vtkXMLPolyDataReader.h"
 
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
@@ -58,6 +64,78 @@ namespace runTimePostPro
 }
 }
 
+
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
+
+namespace
+{
+
+static vtkSmartPointer<vtkPolyData> getPolyDataFile(const Foam::fileName& fName)
+{
+    // Not extremely elegant...
+    vtkSmartPointer<vtkPolyData> dataset;
+
+    if (fName.ext() == "vtk")
+    {
+        auto reader = vtkSmartPointer<vtkPolyDataReader>::New();
+
+        reader->SetFileName(fName.c_str());
+        reader->Update();
+        dataset = reader->GetOutput();
+
+        return dataset;
+    }
+
+    if (fName.ext() == "vtp")
+    {
+        auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
+
+        reader->SetFileName(fName.c_str());
+        reader->Update();
+        dataset = reader->GetOutput();
+
+        return dataset;
+    }
+
+    if (fName.ext() == "obj")
+    {
+        auto reader = vtkSmartPointer<vtkOBJReader>::New();
+
+        reader->SetFileName(fName.c_str());
+        reader->Update();
+        dataset = reader->GetOutput();
+
+        return dataset;
+    }
+
+    if (fName.ext() == "stl" || fName.ext() == "stlb")
+    {
+        auto reader = vtkSmartPointer<vtkSTLReader>::New();
+
+        reader->SetFileName(fName.c_str());
+        reader->Update();
+        dataset = reader->GetOutput();
+
+        return dataset;
+    }
+
+
+    // Fallback to using OpenFOAM to read the surface and convert afterwards
+    Foam::meshedSurface surf(fName);
+
+    dataset = Foam::vtk::Tools::Patch::mesh(surf);
+
+    dataset->GetCellData()->SetNormals
+    (
+        Foam::vtk::Tools::Patch::faceNormals(surf)
+    );
+
+    return dataset;
+}
+
+} // End anonymous namespace
+
+
 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
 
 void Foam::functionObjects::runTimePostPro::geometrySurface::addGeometryToScene
@@ -74,53 +152,22 @@ void Foam::functionObjects::runTimePostPro::geometrySurface::addGeometryToScene
             << " object" << exit(FatalError);
     }
 
-    triSurface surf(fName);
-
-    const Field<point>& surfPoints = surf.points();
-    const Field<vector>& surfFaceNormals = surf.faceNormals();
-
-    auto points = vtkSmartPointer<vtkPoints>::New();
-    auto triangles = vtkSmartPointer<vtkCellArray>::New();
-    auto faceNormals = vtkSmartPointer<vtkDoubleArray>::New();
-
-    faceNormals->SetNumberOfComponents(3);
-
-    forAll(surfPoints, i)
-    {
-        const point& pt = surfPoints[i];
-        points->InsertNextPoint(pt.x(), pt.y(), pt.z());
-    }
+    auto surf = getPolyDataFile(fName);
 
-    forAll(surf, i)
+    if (!surf || surf->GetNumberOfPoints() == 0)
     {
-        const Foam::face& f = surf[i];
-
-        auto triangle = vtkSmartPointer<vtkTriangle>::New();
-        triangle->GetPointIds()->SetId(0, f[0]);
-        triangle->GetPointIds()->SetId(1, f[1]);
-        triangle->GetPointIds()->SetId(2, f[2]);
-        triangles->InsertNextCell(triangle);
-
-        double n[3];
-        n[0] = surfFaceNormals[i].x();
-        n[1] = surfFaceNormals[i].y();
-        n[2] = surfFaceNormals[i].z();
-
-        faceNormals->InsertNextTuple(n);
+        FatalErrorInFunction
+            << "Could not read "<< fName << nl
+            << exit(FatalError);
     }
 
-    surf.clearOut();
-
-    auto polyData = vtkSmartPointer<vtkPolyData>::New();
-    polyData->SetPoints(points);
-    polyData->SetPolys(triangles);
-    polyData->GetCellData()->SetNormals(faceNormals);
-
     auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+
     mapper->ScalarVisibilityOff();
-    mapper->SetInputData(polyData);
 
-    addFeatureEdges(renderer, polyData);
+    mapper->SetInputData(surf);
+
+    addFeatureEdges(renderer, surf);
 
     surfaceActor_->SetMapper(mapper);
 
@@ -136,7 +183,7 @@ Foam::functionObjects::runTimePostPro::geometrySurface::geometrySurface
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours
+    const HashPtrTable<Function1<vector>>& colours
 )
 :
     surface(parent, dict, colours),
@@ -150,7 +197,7 @@ Foam::functionObjects::runTimePostPro::geometrySurface::geometrySurface
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours,
+    const HashPtrTable<Function1<vector>>& colours,
     const List<fileName>& fileNames
 )
 :
@@ -159,12 +206,6 @@ Foam::functionObjects::runTimePostPro::geometrySurface::geometrySurface
 {}
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::functionObjects::runTimePostPro::geometrySurface::~geometrySurface()
-{}
-
-
 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
 
 void Foam::functionObjects::runTimePostPro::geometrySurface::addGeometryToScene
@@ -178,10 +219,10 @@ void Foam::functionObjects::runTimePostPro::geometrySurface::addGeometryToScene
         return;
     }
 
-    forAll(fileNames_, i)
+    for (fileName f : fileNames_)  // Use a copy
     {
-        fileName fName = fileNames_[i].expand();
-        addGeometryToScene(position, renderer, fName);
+        f.expand();
+        addGeometryToScene(position, renderer, f);
     }
 }
 
@@ -210,8 +251,8 @@ void Foam::functionObjects::runTimePostPro::geometrySurface::updateActors
 
 bool Foam::functionObjects::runTimePostPro::geometrySurface::clear()
 {
-    // Note: not removing geometry files
-    // - these are usually static files that are used e.g. for meshing
+    // Note: do not remove geometry files
+    // - often static files used for other purposes as well (eg meshing)
 
     return true;
 }
diff --git a/src/functionObjects/graphics/runTimePostProcessing/geometrySurface.H b/src/functionObjects/graphics/runTimePostProcessing/geometrySurface.H
index 634a5e4877d..2f5cdacae8a 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/geometrySurface.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/geometrySurface.H
@@ -22,7 +22,7 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::geometrySurface
+    Foam::functionObjects::runTimePostPro::geometrySurface
 
 Description
     Visualisation of surface geometry data
@@ -39,6 +39,7 @@ SourceFiles
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+// Forward declarations
 class vtkPolyData;
 
 namespace Foam
@@ -56,17 +57,6 @@ class geometrySurface
 :
     public surface
 {
-private:
-
-    // Private Member Functions
-
-        //- No copy construct
-        geometrySurface(const geometrySurface&) = delete;
-
-        //- No copy assignment
-        void operator=(const geometrySurface&) = delete;
-
-
 protected:
 
     // Protected data
@@ -85,6 +75,12 @@ protected:
             const fileName& fName
         ) const;
 
+        //- No copy construct
+        geometrySurface(const geometrySurface&) = delete;
+
+        //- No copy assignment
+        void operator=(const geometrySurface&) = delete;
+
 
 public:
 
@@ -99,7 +95,7 @@ public:
         (
             const runTimePostProcessing& parent,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours
+            const HashPtrTable<Function1<vector>>& colours
         );
 
         //- Construct from components
@@ -107,18 +103,18 @@ public:
         (
             const runTimePostProcessing& parent,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours,
+            const HashPtrTable<Function1<vector>>& colours,
             const List<fileName>& fileNames
         );
 
 
     //- Destructor
-    virtual ~geometrySurface();
+    virtual ~geometrySurface() = default;
 
 
     // Member Functions
 
-        //- Add surface(s) to scene
+        //- Add geometry surface(s) to scene
         virtual void addGeometryToScene
         (
             const scalar position,
diff --git a/src/functionObjects/graphics/runTimePostProcessing/pathline.C b/src/functionObjects/graphics/runTimePostProcessing/pathline.C
index f85cbd8a2aa..ed6355728fd 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/pathline.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/pathline.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -78,7 +78,7 @@ void Foam::functionObjects::runTimePostPro::pathline::addLines
     actor->GetProperty()->SetColor(colour[0], colour[1], colour[2]);
 
     vtkPolyDataMapper* mapper =
-            vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
+        vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
 
     switch (representation_)
     {
@@ -123,7 +123,7 @@ Foam::functionObjects::runTimePostPro::pathline::pathline
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours
+    const HashPtrTable<Function1<vector>>& colours
 )
 :
     geometryBase(parent, dict, colours),
@@ -136,7 +136,7 @@ Foam::functionObjects::runTimePostPro::pathline::pathline
 {
     if (dict.found("lineColour"))
     {
-        lineColour_.reset(Function1<vector>::New("lineColour", dict).ptr());
+        lineColour_.reset(Function1<vector>::New("lineColour", dict));
     }
     else
     {
@@ -174,7 +174,7 @@ Foam::functionObjects::runTimePostPro::pathline::New
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours,
+    const HashPtrTable<Function1<vector>>& colours,
     const word& pathlineType
 )
 {
diff --git a/src/functionObjects/graphics/runTimePostProcessing/pathline.H b/src/functionObjects/graphics/runTimePostProcessing/pathline.H
index 7b452b48ebf..59f43c59112 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/pathline.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/pathline.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd
+     \\/     M anipulation  | Copyright (C) 2016-2018 OpenCFD Ltd
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -22,9 +22,10 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Class
-    Foam::pathline
+    Foam::functionObjects::runTimePostPro::pathline
 
 Description
+    Visualisation of line data (eg, streamlines)
 
 SourceFiles
     pathline.C
@@ -40,6 +41,7 @@ SourceFiles
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+// Forward declarations
 class vtkActor;
 class vtkPolyData;
 class vtkPolyDataMapper;
@@ -74,17 +76,6 @@ public:
         static const Enum<representationType> representationTypeNames;
 
 
-private:
-
-    // Private Member Functions
-
-        //- No copy construct
-        pathline(const pathline&) = delete;
-
-        //- No copy assignment
-        void operator=(const pathline&) = delete;
-
-
 protected:
 
     // Protected data
@@ -109,6 +100,12 @@ protected:
             vtkPolyData* data
         ) const;
 
+        //- No copy construct
+        pathline(const pathline&) = delete;
+
+        //- No copy assignment
+        void operator=(const pathline&) = delete;
+
 
 public:
 
@@ -126,7 +123,7 @@ public:
             (
                 const runTimePostProcessing& parent,
                 const dictionary& dict,
-                const HashPtrTable<Function1<vector>, word>& colours
+                const HashPtrTable<Function1<vector>>& colours
             ),
             (parent, dict, colours)
         );
@@ -139,7 +136,7 @@ public:
         (
             const runTimePostProcessing& parent,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours
+            const HashPtrTable<Function1<vector>>& colours
         );
 
 
@@ -150,7 +147,7 @@ public:
         (
             const runTimePostProcessing& parent,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours,
+            const HashPtrTable<Function1<vector>>& colours,
             const word& pathlineName
         );
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/pointData.C b/src/functionObjects/graphics/runTimePostProcessing/pointData.C
index ce4e9bd6924..112c115bc22 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/pointData.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/pointData.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -93,7 +93,7 @@ Foam::functionObjects::runTimePostPro::pointData::pointData
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours
+    const HashPtrTable<Function1<vector>>& colours
 )
 :
     geometryBase(parent, dict, colours),
@@ -106,7 +106,7 @@ Foam::functionObjects::runTimePostPro::pointData::pointData
 {
     if (dict.found("pointColour"))
     {
-        pointColour_.reset(Function1<vector>::New("pointColour", dict).ptr());
+        pointColour_.reset(Function1<vector>::New("pointColour", dict));
     }
     else
     {
@@ -135,7 +135,7 @@ Foam::functionObjects::runTimePostPro::pointData::New
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours,
+    const HashPtrTable<Function1<vector>>& colours,
     const word& pointDataType
 )
 {
diff --git a/src/functionObjects/graphics/runTimePostProcessing/pointData.H b/src/functionObjects/graphics/runTimePostProcessing/pointData.H
index 7d81b5cca37..595f48a976a 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/pointData.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/pointData.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015-2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -25,6 +25,7 @@ Class
     Foam::functionObjects::runTimePostPro::pointData
 
 Description
+    Visualisation of point data
 
 SourceFiles
     pointData.C
@@ -40,6 +41,7 @@ SourceFiles
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+// Forward declarations
 class vtkActor;
 class vtkPolyData;
 class vtkPolyDataMapper;
@@ -72,17 +74,6 @@ public:
         static const Enum<representationType> representationTypeNames;
 
 
-private:
-
-    // Private Member Functions
-
-        //- No copy construct
-        pointData(const pointData&) = delete;
-
-        //- No copy assignment
-        void operator=(const pointData&) = delete;
-
-
 protected:
 
     // Protected data
@@ -108,6 +99,12 @@ protected:
             vtkPolyData* data
         ) const;
 
+        //- No copy construct
+        pointData(const pointData&) = delete;
+
+        //- No copy assignment
+        void operator=(const pointData&) = delete;
+
 
 public:
 
@@ -125,7 +122,7 @@ public:
             (
                 const runTimePostProcessing& parent,
                 const dictionary& dict,
-                const HashPtrTable<Function1<vector>, word>& colours
+                const HashPtrTable<Function1<vector>>& colours
             ),
             (parent, dict, colours)
         );
@@ -138,7 +135,7 @@ public:
         (
             const runTimePostProcessing& parent,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours
+            const HashPtrTable<Function1<vector>>& colours
         );
 
 
@@ -149,7 +146,7 @@ public:
         (
             const runTimePostProcessing& parent,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours,
+            const HashPtrTable<Function1<vector>>& colours,
             const word& pointDataName
         );
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.C b/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.C
index 5aa639a049c..b90b7976e3c 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.C
@@ -39,7 +39,6 @@ License
 #include "vtkRenderer.h"
 #include "vtkRenderWindow.h"
 #include "vtkSmartPointer.h"
-
 #include "vtkLight.h"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@@ -60,6 +59,48 @@ namespace functionObjects
 }
 
 
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+template<class Type>
+static void addGeometryToScene
+(
+    PtrList<Type>& objects,
+    const scalar position,
+    vtkRenderer* renderer
+)
+{
+    for (Type& obj : objects)
+    {
+        obj.addGeometryToScene(position, renderer);
+    }
+}
+
+
+template<class Type>
+static void updateActors(PtrList<Type>& objects, const scalar position)
+{
+    for (Type& obj : objects)
+    {
+        obj.updateActors(position);
+    }
+}
+
+
+template<class Type>
+static void cleanup(PtrList<Type>& objects)
+{
+    for (Type& obj : objects)
+    {
+        obj.clear();
+    }
+}
+
+} // End namespace Foam
+
+
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
 Foam::functionObjects::runTimePostProcessing::runTimePostProcessing
@@ -95,7 +136,6 @@ bool Foam::functionObjects::runTimePostProcessing::read(const dictionary& dict)
     outputDict.readEntry("width", output_.width_);
     outputDict.readEntry("height", output_.height_);
 
-
     readObjects(dict.subOrEmptyDict("points"), points_);
     readObjects(dict.subOrEmptyDict("lines"), lines_);
     readObjects(dict.subOrEmptyDict("surfaces"), surfaces_);
@@ -107,16 +147,19 @@ bool Foam::functionObjects::runTimePostProcessing::read(const dictionary& dict)
         if (!dEntry.isDict())
         {
             FatalIOErrorInFunction(textDict)
+                << textDict.dictName()
                 << "text must be specified in dictionary format"
                 << exit(FatalIOError);
         }
 
+        const dictionary& objectDict = dEntry.dict();
+
         text_.append
         (
             new runTimePostPro::text
             (
                 *this,
-                dEntry.dict(),
+                objectDict,
                 scene_.colours()
             )
         );
@@ -167,76 +210,27 @@ bool Foam::functionObjects::runTimePostProcessing::write()
 
     renderWindow->AddRenderer(renderer);
 
-    // Add the points
-    forAll(points_, i)
-    {
-        points_[i].addGeometryToScene(0, renderer);
-    }
-
-    // Add the lines
-    forAll(lines_, i)
-    {
-        lines_[i].addGeometryToScene(0, renderer);
-    }
-
-    // Add the surfaces
-    forAll(surfaces_, i)
-    {
-        surfaces_[i].addGeometryToScene(0, renderer);
-    }
 
-    // Add the text
-    forAll(text_, i)
-    {
-        text_[i].addGeometryToScene(0, renderer);
-    }
+    addGeometryToScene(points_, 0, renderer);
+    addGeometryToScene(lines_, 0, renderer);
+    addGeometryToScene(surfaces_, 0, renderer);
+    addGeometryToScene(text_, 0, renderer);
 
     while (scene_.loop(renderer))
     {
-        scalar position = scene_.position();
-
-        // Update the text
-        forAll(text_, i)
-        {
-            text_[i].updateActors(position);
-        }
-
-        // Update the points
-        forAll(points_, i)
-        {
-            points_[i].updateActors(position);
-        }
-
-        // Update the lines
-        forAll(lines_, i)
-        {
-            lines_[i].updateActors(position);
-        }
+        const scalar position = scene_.position();
 
-        // Update the surfaces
-        forAll(surfaces_, i)
-        {
-            surfaces_[i].updateActors(position);
-        }
+        updateActors(text_, position);
+        updateActors(points_, position);
+        updateActors(lines_, position);
+        updateActors(surfaces_, position);
     }
 
-    // Clean up
-    forAll(text_, i)
-    {
-        text_[i].clear();
-    }
-    forAll(points_, i)
-    {
-        points_[i].clear();
-    }
-    forAll(lines_, i)
-    {
-        lines_[i].clear();
-    }
-    forAll(surfaces_, i)
-    {
-        surfaces_[i].clear();
-    }
+    // Cleanup
+    cleanup(text_);
+    cleanup(points_);
+    cleanup(lines_);
+    cleanup(surfaces_);
 
 
     // Instead of relying on the destructor, manually restore the previous
diff --git a/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.H b/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.H
index 8fd76343ba3..5fc14178e26 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessing.H
@@ -21,8 +21,15 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
+Namespace
+    Foam::functionObjects::runTimePostPro
+
+Description
+    Classes and objects used in the implementation of
+    Foam::functionObjects::runTimePostProcessing
+
 Class
-    Foam::functionObjects::runTimePostPro::runTimePostProcessing
+    Foam::functionObjects::runTimePostProcessing
 
 Group
     grpGraphicsFunctionObjects
@@ -34,9 +41,9 @@ Description
     which provide a broad set of functionality for scene composition and
     manipulation.
 
-    Images are generated using a combination of function object output, and
-    additional data e.gg triangulated surfaces and text.  Current capabilities
-    include support for:
+    Images are generated using a combination of function object output
+    and additional data - eg, surfaces and text.
+    Current capabilities include support for:
     - Camera
     - Objects
     - Points
@@ -45,6 +52,8 @@ Description
     - Scalar bars
     - Annotations
     - Selection of colour maps
+    .
+
     Scene configuration is performed using standard OpenFOAM dictionaries, using
     the main headings of: output=, camera, colours, points, lines,
     surfaces and text.
@@ -65,6 +74,7 @@ SourceFiles
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+// Forward declarations
 class vtkRenderer;
 class vtkRenderWindow;
 
@@ -74,10 +84,11 @@ namespace functionObjects
 {
 namespace runTimePostPro
 {
-    class pointData;
-    class pathline;
-    class surface;
-    class text;
+// Forward declarations
+class pointData;
+class pathline;
+class surface;
+class text;
 }
 
 /*---------------------------------------------------------------------------*\
diff --git a/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessingTemplates.C b/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessingTemplates.C
index 5651e8a3934..593fbe1c672 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessingTemplates.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/runTimePostProcessingTemplates.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2015 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2015-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
diff --git a/src/functionObjects/graphics/runTimePostProcessing/scene.C b/src/functionObjects/graphics/runTimePostProcessing/scene.C
index 63b4542113c..72cc6b402c6 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/scene.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/scene.C
@@ -38,7 +38,6 @@ License
 #include "vtkRenderWindow.h"
 #include "vtkWindowToImageFilter.h"
 
-
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
 void Foam::functionObjects::runTimePostPro::scene::readCamera
diff --git a/src/functionObjects/graphics/runTimePostProcessing/scene.H b/src/functionObjects/graphics/runTimePostProcessing/scene.H
index 713831bd099..48353f35e32 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/scene.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/scene.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -70,6 +70,7 @@ SourceFiles
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+// Forward declarations
 class vtkActor;
 class vtkRenderer;
 class vtkRenderWindow;
@@ -123,7 +124,7 @@ protected:
     // Protected data
 
         //- Colours
-        HashPtrTable<Function1<vector>, word> colours_;
+        HashPtrTable<Function1<vector>> colours_;
 
 
         // Camera settings
@@ -197,26 +198,27 @@ public:
 
     // Member Functions
 
-        // Access
+    // Access
 
-            //- Return the colours
-            const HashPtrTable<Function1<vector>, word>& colours() const;
+        //- Return the colours
+        const HashPtrTable<Function1<vector>>& colours() const;
 
-            //- Return the current frame index
-            label frameIndex() const;
+        //- Return the current frame index
+        label frameIndex() const;
 
-            //- Return the current position (in range 0-1)
-            scalar position() const;
+        //- Return the current position (in range 0-1)
+        scalar position() const;
 
-            void read(const dictionary& dict);
 
-            void initialise(vtkRenderer* renderer, const word& outputName);
+        void read(const dictionary& dict);
 
-            //- Main control loop
-            bool loop(vtkRenderer* renderer);
+        void initialise(vtkRenderer* renderer, const word& outputName);
 
-            //- Save image to file
-            void saveImage(vtkRenderWindow* renderWindow) const;
+        //- Main control loop
+        bool loop(vtkRenderer* renderer);
+
+        //- Save image to file
+        void saveImage(vtkRenderWindow* renderWindow) const;
 };
 
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/surface.C b/src/functionObjects/graphics/runTimePostProcessing/surface.C
index 8449b5f327a..0a170c95258 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/surface.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/surface.C
@@ -83,7 +83,7 @@ void Foam::functionObjects::runTimePostPro::surface::setRepresentation
         }
         case rtWireframe:
         {
-            // note: colour is set using general SetColour, not setEdgeColor
+            // note: colour is set using general SetColor, not SetEdgeColor
             actor->GetProperty()->SetRepresentationToWireframe();
             break;
         }
@@ -143,7 +143,7 @@ Foam::functionObjects::runTimePostPro::surface::surface
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours
+    const HashPtrTable<Function1<vector>>& colours
 )
 :
     geometryBase(parent, dict, colours),
@@ -163,10 +163,7 @@ Foam::functionObjects::runTimePostPro::surface::surface
 
     if (dict.found("surfaceColour"))
     {
-        surfaceColour_.reset
-        (
-            Function1<vector>::New("surfaceColour", dict).ptr()
-        );
+        surfaceColour_.reset(Function1<vector>::New("surfaceColour", dict));
     }
     else
     {
@@ -175,7 +172,7 @@ Foam::functionObjects::runTimePostPro::surface::surface
 
     if (dict.found("edgeColour"))
     {
-        edgeColour_.reset(Function1<vector>::New("edgeColour", dict).ptr());
+        edgeColour_.reset(Function1<vector>::New("edgeColour", dict));
     }
     else
     {
@@ -200,7 +197,7 @@ Foam::functionObjects::runTimePostPro::surface::New
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours,
+    const HashPtrTable<Function1<vector>>& colours,
     const word& surfaceType
 )
 {
diff --git a/src/functionObjects/graphics/runTimePostProcessing/surface.H b/src/functionObjects/graphics/runTimePostProcessing/surface.H
index ce988972502..d8eefe6ebeb 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/surface.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/surface.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -25,6 +25,7 @@ Class
     Foam::functionObjects::runTimePostPro::surface
 
 Description
+    Visualisation of surface data
 
 SourceFiles
     surface.C
@@ -37,11 +38,11 @@ SourceFiles
 #include "geometryBase.H"
 #include "Enum.H"
 #include "runTimeSelectionTables.H"
-
 #include "vtkSmartPointer.h"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+// Forward declarations
 class vtkActor;
 class vtkRenderer;
 class vtkPolyData;
@@ -77,17 +78,6 @@ public:
         static const Enum<representationType> representationTypeNames;
 
 
-private:
-
-    // Private Member Functions
-
-        //- No copy construct
-        surface(const surface&) = delete;
-
-        //- No copy assignment
-        void operator=(const surface&) = delete;
-
-
 protected:
 
     // Protected data
@@ -126,6 +116,12 @@ protected:
             vtkPolyData* data
         ) const;
 
+        //- No copy construct
+        surface(const surface&) = delete;
+
+        //- No copy assignment
+        void operator=(const surface&) = delete;
+
 
 public:
 
@@ -143,7 +139,7 @@ public:
             (
                 const runTimePostProcessing& parent,
                 const dictionary& dict,
-                const HashPtrTable<Function1<vector>, word>& colours
+                const HashPtrTable<Function1<vector>>& colours
             ),
             (parent, dict, colours)
         );
@@ -156,7 +152,7 @@ public:
         (
             const runTimePostProcessing& parent,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours
+            const HashPtrTable<Function1<vector>>& colours
         );
 
 
@@ -167,7 +163,7 @@ public:
         (
             const runTimePostProcessing& parent,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours,
+            const HashPtrTable<Function1<vector>>& colours,
             const word& surfaceName
         );
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/text.C b/src/functionObjects/graphics/runTimePostProcessing/text.C
index 160ec5be4fd..8c57916f5a3 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/text.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/text.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -40,7 +40,7 @@ Foam::functionObjects::runTimePostPro::text::text
 (
     const runTimePostProcessing& parent,
     const dictionary& dict,
-    const HashPtrTable<Function1<vector>, word>& colours
+    const HashPtrTable<Function1<vector>>& colours
 )
 :
     geometryBase(parent, dict, colours),
@@ -55,7 +55,7 @@ Foam::functionObjects::runTimePostPro::text::text
 
     if (dict.found("colour"))
     {
-        colour_.reset(Function1<vector>::New("colour", dict).ptr());
+        colour_.reset(Function1<vector>::New("colour", dict));
     }
     else
     {
diff --git a/src/functionObjects/graphics/runTimePostProcessing/text.H b/src/functionObjects/graphics/runTimePostProcessing/text.H
index 551fcf6b7c6..fd8835db52e 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/text.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/text.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2015 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2018 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -25,6 +25,8 @@ Class
     Foam::functionObjects::runTimePostPro::text
 
 Description
+    Define text element for runTimePostProcessing
+
     Example of text object specification:
     \verbatim
     text1
@@ -39,10 +41,22 @@ Description
         // colour    (0 1 1);
 
         // Optional entry
-        timeStamp   yes; //Append solution time to string
+        timeStamp   yes; // Append solution time to string
     }
     \endverbatim
 
+    Dictionary controls
+    \table
+        Property    | Description                          | Required | Default
+        visible     | Display the text                     | yes |
+        string      | Text to display                      | yes |
+        position    | The (x y) viewport position          | yes |
+        size        | The font size in points              | yes |
+        bold        | Use bold font                        | yes |
+        colour      | Override default text colour         | no  |
+        timeStamp   | Append solution timeName to string   | no  | false
+    \endtable
+
 SourceFiles
     text.C
 
@@ -56,6 +70,7 @@ SourceFiles
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+// Forward declarations
 class vtkRenderer;
 
 namespace Foam
@@ -73,20 +88,9 @@ class text
 :
     public geometryBase
 {
-private:
-
-    // Private Member Functions
-
-        //- No copy construct
-        text(const text&) = delete;
-
-        //- No copy assignment
-        void operator=(const text&) = delete;
-
-
 protected:
 
-    // Protected data
+    // Protected Data
 
         //- Text
         string string_;
@@ -107,6 +111,15 @@ protected:
         bool timeStamp_;
 
 
+    // Protected Member Functions
+
+        //- No copy construct
+        text(const text&) = delete;
+
+        //- No copy assignment
+        void operator=(const text&) = delete;
+
+
 public:
 
     // Constructors
@@ -116,7 +129,7 @@ public:
         (
             const runTimePostProcessing& parent,
             const dictionary& dict,
-            const HashPtrTable<Function1<vector>, word>& colours
+            const HashPtrTable<Function1<vector>>& colours
         );
 
 
diff --git a/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/Allclean b/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/Allclean
index e2f275d9fd6..08f9ce2fadd 100755
--- a/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/Allclean
+++ b/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/Allclean
@@ -4,4 +4,7 @@ cd ${0%/*} || exit 1                        # Run from this directory
 
 cleanCase0
 
+rm -f ppGeometry.vtp 2>/dev/null
+
+
 #------------------------------------------------------------------------------
diff --git a/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/Allrun.pre b/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/Allrun.pre
index f98d8e1402f..800108cf41a 100755
--- a/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/Allrun.pre
+++ b/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/Allrun.pre
@@ -19,6 +19,9 @@ runApplication topoSet
 
 runApplication createPatch -overwrite
 
+runApplication surfaceMeshTriangulate \
+    -patches hole ppGeometry.vtp -constant -time ''
+
 echo "End"
 
 #------------------------------------------------------------------------------
diff --git a/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/system/controlDict b/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/system/controlDict
index ba2cede19cc..091fdbca08a 100644
--- a/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/system/controlDict
+++ b/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/system/controlDict
@@ -15,6 +15,8 @@ FoamFile
 }
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+libs            ("libOpenFOAM.so" "libfieldFunctionObjects.so");
+
 application     pimpleFoam;
 
 startFrom       latestTime;
@@ -49,10 +51,10 @@ adjustTimeStep  yes;
 
 maxCo           0.2;
 
-
 functions
 {
     #include "sampling"
+    #include "streamLines"
     #include "runTimePostProcessing"
 }
 
diff --git a/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/system/runTimePostProcessing b/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/system/runTimePostProcessing
index b14879f52c1..47fd9e977ab 100644
--- a/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/system/runTimePostProcessing
+++ b/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/system/runTimePostProcessing
@@ -29,12 +29,12 @@ postPro1
         // Parallel projection flag
         parallelProjection  yes;
 
-        clipBox         (-0.2 -0.2 0)(1.65 0.2 1.25); // optional
+        // clipBox is optional
 
         position        (-2.28 1.28 2.24);
-        focalPoint      (0.003 0.008 0.024);
+        focalPoint      (0 0.008 0.024);
         up              (0.26 0.930 -0.266);
-        zoom    1.25;
+        zoom    1.75;
     }
 
     // Default colours
@@ -44,7 +44,7 @@ postPro1
     {
         background      (0.317647 0.341176 0.431373);
         background2     ${background};
-        text            (0 0 0);
+        text            (0.75 0.75 0.75);
         edge            (1 0 0);
         surface         (0.5 0.5 0.5);
         line            (1 0 0);
@@ -52,9 +52,24 @@ postPro1
 
     lines
     {
+        streamline
+        {
+            type            functionObjectLine;
+            functionObject  streamLines;
+            representation  tube;
+            visible         yes;
+            tubeRadius      0.0025;
+            colourBy        field;
+            field           U;
+            range           (0 10);
+            opacity         0.6;
+            scalarBar
+            {
+                visible     no;
+            }
+        }
     }
 
-
     _plane
     {
         type            functionObjectSurface;
@@ -77,6 +92,17 @@ postPro1
 
     surfaces
     {
+        geom
+        {
+            type            geometry;
+            files           ("<case>/ppGeometry.vtp");
+            renderMode      phong;
+            representation  surface;
+            edgeColour      (0.5 0.5 0.5);
+            visible         yes;
+            featureEdges    no;
+            opacity         0.8;
+        }
         plane0
         {
             ${_plane};
@@ -104,11 +130,11 @@ postPro1
     {
         text1
         {
-            string          "elipsekkLOmega";
-            position        (0.1 0.05);
-            size            24;
-            bold            no;
-            visible         yes;
+            string      "ellipse kkLOmega";
+            position    (0.6 0.05);
+            size        18;
+            bold        yes;
+            visible     yes;
         }
     }
 }
diff --git a/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/system/streamLines b/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/system/streamLines
new file mode 100644
index 00000000000..21bbef69bb4
--- /dev/null
+++ b/tutorials/incompressible/pimpleFoam/RAS/elipsekkLOmega/system/streamLines
@@ -0,0 +1,49 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  v1806                                 |
+|   \\  /    A nd           | Web:      www.OpenFOAM.com                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+
+streamLines
+{
+    type    streamLine;
+
+    writeControl    writeTime;
+
+    setFormat       vtk;
+
+    // Velocity field to use for tracking.
+    U               U;
+
+    // Tracked forwards (+U) or backwards (-U)
+    trackForward    true;
+
+    // Names of fields to sample. Should contain above velocity field!
+    fields          (p U);
+
+    // Steps particles can travel before being removed
+    lifeTime        10000;
+
+    // Number of steps per cell (estimate). Set to 1 to disable subcycling.
+    nSubCycle       5;
+
+    // Cloud name to use
+    cloud           particleTracks;
+
+    // Seeding method.
+    seedSampleSet
+    {
+        type        uniform;
+        axis        x;  //distance;
+
+        // Note: tracks slightly offset so as not to be on a face
+        start       (-0.70 -0.25 0.025);
+        end         (-0.70  0.25 0.025);
+        nPoints     20;
+    }
+}
+
+
+// ************************************************************************* //
-- 
GitLab