diff --git a/src/functionObjects/graphics/runTimePostProcessing/CMakeLists-Common.txt b/src/functionObjects/graphics/runTimePostProcessing/CMakeLists-Common.txt
index 9dc15138fde6a5ef2052b653cf5f4c77502d47e0..55effddcd5fc858546342eeefb97d8f08f8e5585 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/CMakeLists-Common.txt
+++ b/src/functionObjects/graphics/runTimePostProcessing/CMakeLists-Common.txt
@@ -15,6 +15,7 @@ include_directories(
     $ENV{WM_PROJECT_DIR}/src/OSspecific/$ENV{WM_OSTYPE}/lnInclude
     $ENV{WM_PROJECT_DIR}/src/surfMesh/lnInclude
     $ENV{WM_PROJECT_DIR}/src/finiteVolume/lnInclude
+    $ENV{WM_PROJECT_DIR}/src/conversion/lnInclude
     ${CMAKE_CURRENT_SOURCE_DIR}
     ${CMAKE_CURRENT_BINARY_DIR}
 )
@@ -58,6 +59,7 @@ file(GLOB SOURCE_FILES
     functionObjectLine.C
     functionObjectSurface.C
     geometryBase.C
+    geometryPatches.C
     geometrySurface.C
     pathline.C
     pointData.C
@@ -72,6 +74,7 @@ set(OPENFOAM_LIBRARIES
     OpenFOAM
     surfMesh
     finiteVolume
+    conversion
 )
 
 add_library(
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.C b/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.C
index df8fb3383a14a6fe7f1e782fd714951457487513..5ca9cac31d6801ed881e2bb7de4bd5e95d413bc6 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.C
@@ -44,11 +44,11 @@ namespace runTimePostPro
 bool Foam::functionObjects::runTimePostPro::functionObjectBase::removeFile
 (
     const word& keyword,
-    const word& fieldName
+    const word& subDictName
 )
 {
     dictionary dict;
-    state_.getObjectDict(functionObjectName_, fieldName, dict);
+    state_.getObjectDict(functionObjectName_, subDictName, dict);
 
     fileName fName;
     if (dict.readIfPresent(keyword, fName))
@@ -65,15 +65,13 @@ Foam::fileName
 Foam::functionObjects::runTimePostPro::functionObjectBase::getFileName
 (
     const word& keyword,
-    const word& fieldName
+    const word& subDictName
 ) const
 {
     dictionary dict;
-    state_.getObjectDict(functionObjectName_, fieldName, dict);
+    state_.getObjectDict(functionObjectName_, subDictName, dict);
 
-    fileName fName(dict.lookupOrDefault(keyword, fileName::null));
-
-    return fName;
+    return dict.lookupOrDefault<fileName>(keyword, fileName::null);
 }
 
 
@@ -88,11 +86,9 @@ Foam::functionObjects::runTimePostPro::functionObjectBase::functionObjectBase
 :
     fieldVisualisationBase(dict, colours),
     state_(state),
-    functionObjectName_(""),
+    functionObjectName_(dict.lookup("functionObject")),
     clearObjects_(dict.lookupOrDefault("clearObjects", false))
-{
-    dict.lookup("functionObject") >> functionObjectName_;
-}
+{}
 
 
 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.H b/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.H
index b04e44bb9bc49ff8a6bbab5d197ea81a7b4e6a95..042873e40a45687a0458b1fcde707dd772937504 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectBase.H
@@ -27,6 +27,13 @@ Class
 Description
     Base class for function object visualisation
 
+    Dictionary controls
+    \table
+        Property     | Description                      | Required    | Default
+        functionObject | The data source                | yes         |
+        clearObjects  | Remove file after use           | no          | no
+    \endtable
+
 SourceFiles
     functionObjectBase.C
 
@@ -73,7 +80,7 @@ protected:
         //- Reference to the state
         const stateFunctionObject& state_;
 
-        //- Function object name
+        //- The function object name which provides the source data
         word functionObjectName_;
 
         //- Flag to indicate that source data should be cleared after use
@@ -82,11 +89,36 @@ protected:
 
     // Protected Member Functions
 
-        //- Retrieve file used to create the scene object
-        fileName getFileName(const word& keyword, const word& fieldName) const;
-
-        //- Remove file used to create the scene object
-        bool removeFile(const word& keyword, const word& fieldName);
+        //- Retrieve the filename used to create the scene object
+        //- using information stored via the stateFunctionObject.
+        //
+        //  \param keyword is normally "file"
+        //  \param subDictName is the sub-dictionary name, which is often
+        //     the fieldName when one file is used per field.
+        //
+        //  Eg,
+        //  \verbatim
+        //      T
+        //      {
+        //          file    "path/T_object.vtk";
+        //      }
+        //      defaultCloud
+        //      {
+        //          file    "path/cloud_0001.vtp";
+        //          fields  (T U);
+        //      }
+        //  \endverbatim
+        fileName getFileName
+        (
+            const word& keyword,
+            const word& subDictName
+        ) const;
+
+        //- Remove file used to create the scene object.
+        //  Same naming semantics as getFileName.
+        //
+        //  \note does not change the stateFunctionObject
+        bool removeFile(const word& keyword, const word& subDictName);
 
 
 public:
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.C b/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.C
index f4fe22be99e03b169322697010f59dfd735b73a3..06c6e2114be9b11619bdc72cbd83f30741f9ce8a 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.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.
@@ -28,12 +28,15 @@ License
 #include "fvMesh.H"
 #include "runTimePostProcessing.H"
 #include "addToRunTimeSelectionTable.H"
+#include "stringOps.H"
 
 // VTK includes
 #include "vtkActor.h"
 #include "vtkRenderer.h"
 #include "vtkSmartPointer.h"
+#include "vtkPolyData.h"
 #include "vtkPolyDataMapper.h"
+#include "vtkXMLPolyDataReader.h"
 #include "vtkPolyDataReader.h"
 #include "vtkProperty.h"
 
@@ -64,6 +67,7 @@ Foam::functionObjects::runTimePostPro::functionObjectCloud::functionObjectCloud
     pointData(parent, dict, colours),
     functionObjectBase(parent, dict, colours),
     cloudName_(dict.lookup("cloud")),
+    inputFileName_(),
     colourFieldName_(dict.lookup("colourField")),
     actor_()
 {
@@ -92,23 +96,42 @@ addGeometryToScene
         return;
     }
 
+    inputFileName_.clear();
+
+    // The CloudToVTK functionObject from
+    //
+    //   lagrangian/intermediate/submodels/CloudFunctionObjects/
+    //
+    // stores file state on cloud OutputProperties itself,
+    //
+    // whereas the vtkCloud functionObject treats it like other
+    // output and stores via the stateFunctionObject.
+    // Since it uses VTP format, there is only a single file with all fields
+    // - lookup by cloudName.
+
     const dictionary& cloudDict =
         geometryBase::parent_.mesh().lookupObject<IOdictionary>
         (
             cloudName_ + "OutputProperties"
         );
 
-    fileName fName;
-    if (cloudDict.found("functionObjectCloud"))
+    if (cloudDict.found("cloudFunctionObject"))
     {
         const dictionary& foDict = cloudDict.subDict("cloudFunctionObject");
         if (foDict.found(functionObjectName_))
         {
-            foDict.subDict(functionObjectName_).readIfPresent("file", fName);
+            foDict.subDict(functionObjectName_)
+                .readIfPresent("file", inputFileName_);
         }
     }
+    else
+    {
+        inputFileName_ = getFileName("file", cloudName_);
+    }
 
-    if (fName.empty())
+
+    stringOps::inplaceExpand(inputFileName_);
+    if (inputFileName_.empty())
     {
         WarningInFunction
             << "Unable to find function object " << functionObjectName_
@@ -118,12 +141,32 @@ addGeometryToScene
         return;
     }
 
-    if (fName.ext() == "vtk")
+    vtkSmartPointer<vtkPolyData> dataset;
+
+    if (inputFileName_.hasExt("vtp"))
     {
-        auto points = vtkSmartPointer<vtkPolyDataReader>::New();
-        points->SetFileName(fName.c_str());
-        points->Update();
+        auto reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
+        reader->SetFileName(inputFileName_.c_str());
+        reader->Update();
 
+        dataset = reader->GetOutput();
+    }
+    else if (inputFileName_.hasExt("vtk"))
+    {
+        auto reader = vtkSmartPointer<vtkPolyDataReader>::New();
+        reader->SetFileName(inputFileName_.c_str());
+        reader->Update();
+
+        dataset = reader->GetOutput();
+    }
+    else
+    {
+        // Invalid name - ignore
+        inputFileName_.clear();
+    }
+
+    if (dataset)
+    {
         auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
 
         actor_->SetMapper(mapper);
@@ -134,7 +177,7 @@ addGeometryToScene
             fieldName_,
             colourFieldName_,
             maxGlyphLength_,
-            points->GetOutput(),
+            dataset,
             actor_,
             renderer
         );
@@ -160,27 +203,10 @@ bool Foam::functionObjects::runTimePostPro::functionObjectCloud::clear()
 {
     if (functionObjectBase::clear())
     {
-        const dictionary& cloudDict =
-            geometryBase::parent_.mesh().lookupObject<IOdictionary>
-            (
-                cloudName_ & "OutputProperties"
-            );
-
-        if (cloudDict.found("functionObjectCloud"))
+        if (inputFileName_.size() && Foam::rm(inputFileName_))
         {
-            const dictionary& foDict = cloudDict.subDict("functionObjectCloud");
-            if (foDict.found(functionObjectName_))
-            {
-                const dictionary& functionDict =
-                    foDict.subDict(functionObjectName_);
-
-                fileName fName;
-                if (functionDict.readIfPresent("file", fName))
-                {
-                    Foam::rm(fName);
-                    return true;
-                }
-            }
+            inputFileName_.clear();
+            return true;
         }
     }
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.H b/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.H
index e40489ef143d22aaa6373ed60de5880ea6928de0..74888b234d0b006de4e8dc0082c96891ac9c6e10 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.H
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectCloud.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.
@@ -74,13 +74,15 @@ protected:
         //- Name of functionObjectCloud
         word cloudName_;
 
+        //- The input filename used
+        fileName inputFileName_;
+
         //- Name of field to colour by
         word colourFieldName_;
 
         //- Actor
         vtkSmartPointer<vtkActor> actor_;
 
-
 public:
 
     //- Run-time type information
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectLine.C b/src/functionObjects/graphics/runTimePostProcessing/functionObjectLine.C
index 2d7fc46940061554aa6a782089bfef9a8ee7a686..ca0ba78ac8ecce5e8d11b2e3f06fb22effa8f3d2 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectLine.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectLine.C
@@ -99,7 +99,7 @@ addGeometryToScene
         return;
     }
 
-    if (fName.ext() == "vtk")
+    if (fName.hasExt("vtk"))
     {
         auto lines = vtkSmartPointer<vtkPolyDataReader>::New();
         lines->SetFileName(fName.c_str());
diff --git a/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.C b/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.C
index 22b9c7570e500c4cfcdefac2f2bbe8ea4d5b6446..1d2e4d737a08025601b1fa318bd939281d2f6f41 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/functionObjectSurface.C
@@ -115,34 +115,33 @@ addGeometryToScene
             surfaceActor_,
             renderer
         );
+        return;
     }
-    else
+
+    if (fName.hasExt("vtk"))
     {
-        if (fName.ext() == "vtk")
-        {
-            auto surf = vtkSmartPointer<vtkPolyDataReader>::New();
-            surf->SetFileName(fName.c_str());
-            surf->Update();
+        auto surf = vtkSmartPointer<vtkPolyDataReader>::New();
+        surf->SetFileName(fName.c_str());
+        surf->Update();
 
-            addFeatureEdges(renderer, surf->GetOutput());
+        addFeatureEdges(renderer, surf->GetOutput());
 
-            auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
-            mapper->SetInputConnection(surf->GetOutputPort());
+        auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
+        mapper->SetInputConnection(surf->GetOutputPort());
 
-            setField(position, fieldName_, mapper, renderer, surf->GetOutput());
+        setField(position, fieldName_, mapper, renderer, surf->GetOutput());
 
-            surfaceActor_->SetMapper(mapper);
+        surfaceActor_->SetMapper(mapper);
 
-            setRepresentation(surfaceActor_);
+        setRepresentation(surfaceActor_);
 
-            renderer->AddActor(surfaceActor_);
-        }
-        else
-        {
-            WarningInFunction
-                << "Only VTK file types are supported"
-                << endl;
-        }
+        renderer->AddActor(surfaceActor_);
+    }
+    else
+    {
+        WarningInFunction
+            << "Only VTK file types are supported"
+            << endl;
     }
 }
 
diff --git a/src/functionObjects/graphics/runTimePostProcessing/geometrySurface.C b/src/functionObjects/graphics/runTimePostProcessing/geometrySurface.C
index 7c6889322210aa3fc00c94e1f9a73699a3acf943..8c890980dc55c36ec6ba4ad28dacef4a99025840 100644
--- a/src/functionObjects/graphics/runTimePostProcessing/geometrySurface.C
+++ b/src/functionObjects/graphics/runTimePostProcessing/geometrySurface.C
@@ -71,7 +71,7 @@ void Foam::functionObjects::runTimePostPro::geometrySurface::addGeometryToScene
     {
         FatalErrorInFunction
             << "Glyph representation not available for " << typeName
-            << "object" << exit(FatalError);
+            << " object" << exit(FatalError);
     }
 
     triSurface surf(fName);