Commit 4d15bc6e authored by Mark Olesen's avatar Mark Olesen
Browse files

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
parent d18bdd8b
......@@ -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
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -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_;
}
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -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
......
......@@ -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),
......
......@@ -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
);
......
......@@ -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();
......
......@@ -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
);
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2015-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -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();