Fem: Export PostObject data to VTK - fixes #5816

This commit is contained in:
marioalexis
2024-03-16 01:25:52 -03:00
committed by Chris Hennes
parent 01877fd196
commit f4bbfed153
9 changed files with 189 additions and 10 deletions

View File

@@ -51,7 +51,6 @@ endif()
generate_from_xml(FemMeshPy)
generate_from_xml(FemPostPipelinePy)
SET(Python_SRCS
@@ -65,9 +64,13 @@ SET(Python_SRCS
if(BUILD_FEM_VTK)
SET(Python_SRCS
${Python_SRCS}
FemPostObjectPy.xml
FemPostObjectPyImp.cpp
FemPostPipelinePy.xml
FemPostPipelinePyImp.cpp
)
generate_from_xml(FemPostObjectPy)
generate_from_xml(FemPostPipelinePy)
endif(BUILD_FEM_VTK)
SOURCE_GROUP("Python" FILES ${Python_SRCS})

View File

@@ -24,9 +24,13 @@
#ifndef _PreComp_
#include <vtkDataSet.h>
#include <vtkXMLDataSetWriter.h>
#endif
#include <Base/Exception.h>
#include "FemPostObject.h"
#include "FemPostObjectPy.h"
using namespace Fem;
@@ -56,3 +60,80 @@ vtkBoundingBox FemPostObject::getBoundingBox()
return box;
}
PyObject* FemPostObject::getPyObject()
{
if (PythonObject.is(Py::_None())) {
// ref counter is set to 1
PythonObject = Py::Object(new FemPostObjectPy(this), true);
}
return Py::new_reference_to(PythonObject);
}
namespace
{
template<typename T>
void vtkWriter(const char* filename, const vtkSmartPointer<vtkDataObject>& dataObject)
{
if (vtkDataSet::SafeDownCast(dataObject)->GetNumberOfPoints() <= 0) {
throw Base::ValueError("Empty data object");
}
vtkSmartPointer<T> writer = vtkSmartPointer<T>::New();
writer->SetFileName(filename);
writer->SetDataModeToBinary();
writer->SetInputDataObject(dataObject);
writer->Write();
}
std::string vtkWriterExtension(const vtkSmartPointer<vtkDataObject>& dataObject)
{
std::string extension;
switch (dataObject->GetDataObjectType()) {
case VTK_POLY_DATA:
extension = "vtp";
break;
case VTK_STRUCTURED_GRID:
extension = "vts";
break;
case VTK_RECTILINEAR_GRID:
extension = "vtr";
break;
case VTK_UNSTRUCTURED_GRID:
extension = "vtu";
break;
case VTK_UNIFORM_GRID:
extension = "vti";
break;
default:
break;
}
return extension;
}
} // namespace
void FemPostObject::writeVTK(const char* filename)
{
const vtkSmartPointer<vtkDataObject>& data = Data.getValue();
// set appropriate filename extension
std::string name(filename);
std::string extension = vtkWriterExtension(data);
if (extension.empty()) {
throw Base::TypeError("Unsupported data type");
}
std::string::size_type pos = name.find_last_of(".");
if (pos != std::string::npos) {
name = name.substr(0, pos + 1).append(extension);
}
else {
name = name.append(".").append(extension);
}
vtkWriter<vtkXMLDataSetWriter>(name.c_str(), data);
}

View File

@@ -45,7 +45,10 @@ public:
Fem::PropertyPostDataObject Data;
PyObject* getPyObject() override;
vtkBoundingBox getBoundingBox();
void writeVTK(const char* filename);
};
} // namespace Fem

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="GeoFeaturePy"
Name="FemPostObjectPy"
Twin="FemPostObject"
TwinPointer="FemPostObject"
Include="Mod/Fem/App/FemPostObject.h"
Namespace="Fem"
FatherInclude="App/GeoFeaturePy.h"
FatherNamespace="App">
<Documentation>
<Author Licence="LGPL" Name="Mario Passaglia" EMail="mpassaglia@cbc.uba.ar" />
<UserDocu>The FemPostObject class.</UserDocu>
</Documentation>
<Methode Name="writeVTK">
<Documentation>
<UserDocu>writeVTK(filename) -> None
Write data object to VTK file.
filename: str
File extension is automatically detected from data type.</UserDocu>
</Documentation>
</Methode>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,66 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2024 Mario Passaglia <mpassaglia[at]cbc.uba.ar> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
**************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <Python.h>
#endif
#include "FemPostObjectPy.h"
#include "FemPostObjectPy.cpp"
using namespace Fem;
// returns a string which represent the object e.g. when printed in python
std::string FemPostObjectPy::representation() const
{
std::stringstream str;
str << "<FemPostObject object at " << getFemPostObjectPtr() << ">";
return str.str();
}
PyObject* FemPostObjectPy::writeVTK(PyObject* args)
{
char* filename;
if (!PyArg_ParseTuple(args, "et", "utf-8", &filename)) {
return nullptr;
}
std::string utf8Name(filename);
PyMem_Free(filename);
getFemPostObjectPtr()->writeVTK(utf8Name.c_str());
Py_Return;
}
PyObject* FemPostObjectPy::getCustomAttributes(const char* /*attr*/) const
{
return nullptr;
}
int FemPostObjectPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="GeoFeaturePy"
Father="FemPostObjectPy"
Name="FemPostPipelinePy"
Twin="FemPostPipeline"
TwinPointer="FemPostPipeline"
Include="Mod/Fem/App/FemPostPipeline.h"
Namespace="Fem"
FatherInclude="App/GeoFeaturePy.h"
FatherNamespace="App">
FatherInclude="Mod/Fem/App/FemPostObjectPy.h"
FatherNamespace="Fem">
<Documentation>
<Author Licence="LGPL" Name="Werner Mayer" EMail="wmayer@users.sourceforge.net" />
<UserDocu>The FemPostPipeline class.</UserDocu>

View File

@@ -10,7 +10,7 @@
FatherInclude="Gui/ViewProviderDocumentObjectPy.h"
FatherNamespace="Gui">
<Documentation>
<Author Licence="LGPL" Name="Mario Passaglia" EMail="mpassaglia@cbc.ub.ar" />
<Author Licence="LGPL" Name="Mario Passaglia" EMail="mpassaglia@cbc.uba.ar" />
<UserDocu>This is the ViewProviderFemConstraint class</UserDocu>
</Documentation>
<Attribute Name="SymbolNode" ReadOnly="true">

View File

@@ -90,4 +90,4 @@ FreeCAD.addImportType("FEM result Z88 displacements (*o2.txt *O2.TXT)", "feminou
if "BUILD_FEM_VTK" in FreeCAD.__cmake__:
FreeCAD.addImportType("FEM result VTK (*.vtk *.VTK *.vtu *.VTU *.pvtu *.PVTU)", "feminout.importVTKResults")
FreeCAD.addExportType("FEM result VTK (*.vtk *.vtu)", "feminout.importVTKResults")
FreeCAD.addExportType("FEM result VTK (*.vtu *.vtp *.vts *.vtr *.vti)", "feminout.importVTKResults")

View File

@@ -75,10 +75,8 @@ def export(
return
obj = objectslist[0]
if obj.isDerivedFrom("Fem::FemPostPipeline"):
Console.PrintError(
"Export of a VTK post object to vtk is not yet implemented!\n"
)
if obj.isDerivedFrom("Fem::FemPostObject"):
obj.writeVTK(filename)
return
elif obj.isDerivedFrom("Fem::FemMeshObject"):
Console.PrintError(