Files
create/src/Mod/Fem/App/FemPostPipeline.cpp
Benjamin Nauck 6f535f19fb Prefer to use BaseClass's isDerivedFrom<T> over non template or Base::Type's
Regex based changes, manually verified
2025-01-27 16:08:18 +01:00

254 lines
8.0 KiB
C++

/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <Python.h>
#include <vtkAppendFilter.h>
#include <vtkDataSetReader.h>
#include <vtkImageData.h>
#include <vtkRectilinearGrid.h>
#include <vtkStructuredGrid.h>
#include <vtkUnstructuredGrid.h>
#include <vtkXMLImageDataReader.h>
#include <vtkXMLPUnstructuredGridReader.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkXMLRectilinearGridReader.h>
#include <vtkXMLStructuredGridReader.h>
#include <vtkXMLUnstructuredGridReader.h>
#endif
#include <Base/Console.h>
#include "FemMesh.h"
#include "FemMeshObject.h"
#include "FemPostFilter.h"
#include "FemPostPipeline.h"
#include "FemPostPipelinePy.h"
#include "FemVTKTools.h"
using namespace Fem;
using namespace App;
PROPERTY_SOURCE(Fem::FemPostPipeline, Fem::FemPostObject)
const char* FemPostPipeline::ModeEnums[] = {"Serial", "Parallel", "Custom", nullptr};
FemPostPipeline::FemPostPipeline()
{
ADD_PROPERTY_TYPE(Filter,
(nullptr),
"Pipeline",
App::Prop_None,
"The filter used in this pipeline");
ADD_PROPERTY_TYPE(Functions,
(nullptr),
"Pipeline",
App::Prop_Hidden,
"The function provider which groups all pipeline functions");
ADD_PROPERTY_TYPE(Mode,
(long(2)),
"Pipeline",
App::Prop_None,
"Selects the pipeline data transition mode.\n"
"In serial, every filter gets the output of the previous one as input.\n"
"In parallel, every filter gets the pipeline source as input.\n"
"In custom, every filter keeps its input set by the user.");
Mode.setEnums(ModeEnums);
}
FemPostPipeline::~FemPostPipeline() = default;
short FemPostPipeline::mustExecute() const
{
if (Mode.isTouched()) {
return 1;
}
return FemPostObject::mustExecute();
}
DocumentObjectExecReturn* FemPostPipeline::execute()
{
return Fem::FemPostObject::execute();
}
bool FemPostPipeline::canRead(Base::FileInfo File)
{
// from FemResult only unstructural mesh is supported in femvtktoools.cpp
return File.hasExtension({"vtk", "vtp", "vts", "vtr", "vti", "vtu", "pvtu"});
}
void FemPostPipeline::read(Base::FileInfo File)
{
// checking on the file
if (!File.isReadable()) {
throw Base::FileException("File to load not existing or not readable", File);
}
if (File.hasExtension("vtu")) {
readXMLFile<vtkXMLUnstructuredGridReader>(File.filePath());
}
else if (File.hasExtension("pvtu")) {
readXMLFile<vtkXMLPUnstructuredGridReader>(File.filePath());
}
else if (File.hasExtension("vtp")) {
readXMLFile<vtkXMLPolyDataReader>(File.filePath());
}
else if (File.hasExtension("vts")) {
readXMLFile<vtkXMLStructuredGridReader>(File.filePath());
}
else if (File.hasExtension("vtr")) {
readXMLFile<vtkXMLRectilinearGridReader>(File.filePath());
}
else if (File.hasExtension("vti")) {
readXMLFile<vtkXMLImageDataReader>(File.filePath());
}
else if (File.hasExtension("vtk")) {
readXMLFile<vtkDataSetReader>(File.filePath());
}
else {
throw Base::FileException("Unknown extension");
}
}
void FemPostPipeline::scale(double s)
{
Data.scale(s);
}
void FemPostPipeline::onChanged(const Property* prop)
{
if (prop == &Filter || prop == &Mode) {
// if we are in custom mode the user is free to set the input
// thus nothing needs to be done here
if (Mode.getValue() == 2) { // custom
return;
}
// we check if all connections are right and add new ones if needed
std::vector<App::DocumentObject*> objs = Filter.getValues();
if (objs.empty()) {
return;
}
std::vector<App::DocumentObject*>::iterator it = objs.begin();
FemPostFilter* filter = static_cast<FemPostFilter*>(*it);
// the first filter must always grab the data
if (filter->Input.getValue()) {
filter->Input.setValue(nullptr);
}
// all the others need to be connected to the previous filter or grab the data,
// dependent on mode
++it;
for (; it != objs.end(); ++it) {
auto* nextFilter = static_cast<FemPostFilter*>(*it);
if (Mode.getValue() == 0) { // serial mode
if (nextFilter->Input.getValue() != filter) {
nextFilter->Input.setValue(filter);
}
}
else { // Parallel mode
if (nextFilter->Input.getValue()) {
nextFilter->Input.setValue(nullptr);
}
}
filter = nextFilter;
};
}
App::GeoFeature::onChanged(prop);
}
void FemPostPipeline::recomputeChildren()
{
for (const auto& obj : Filter.getValues()) {
obj->touch();
}
}
FemPostObject* FemPostPipeline::getLastPostObject()
{
if (Filter.getValues().empty()) {
return this;
}
return static_cast<FemPostObject*>(Filter.getValues().back());
}
bool FemPostPipeline::holdsPostObject(FemPostObject* obj)
{
std::vector<App::DocumentObject*>::const_iterator it = Filter.getValues().begin();
for (; it != Filter.getValues().end(); ++it) {
if (*it == obj) {
return true;
}
}
return false;
}
void FemPostPipeline::load(FemResultObject* res)
{
if (!res->Mesh.getValue()) {
Base::Console().Log("Result mesh object is empty.\n");
return;
}
if (!res->Mesh.getValue()->isDerivedFrom<Fem::FemMeshObject>()) {
Base::Console().Log("Result mesh object is not derived from Fem::FemMeshObject.\n");
return;
}
// first copy the mesh over
// ***************************
const FemMesh& mesh = static_cast<FemMeshObject*>(res->Mesh.getValue())->FemMesh.getValue();
vtkSmartPointer<vtkUnstructuredGrid> grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
FemVTKTools::exportVTKMesh(&mesh, grid);
// Now copy the point data over
// ***************************
FemVTKTools::exportFreeCADResult(res, grid);
Data.setValue(grid);
}
PyObject* FemPostPipeline::getPyObject()
{
if (PythonObject.is(Py::_None())) {
// ref counter is set to 1
PythonObject = Py::Object(new FemPostPipelinePy(this), true);
}
return Py::new_reference_to(PythonObject);
}