FEM: Switch post groups to extension based system

This commit is contained in:
Stefan Tröger
2024-12-21 20:02:07 +01:00
committed by Benjamin Nauck
parent a4558f31b4
commit a5e66bf542
19 changed files with 350 additions and 268 deletions

View File

@@ -40,7 +40,7 @@ EXTENSION_PROPERTY_SOURCE(App::OriginGroupExtension, App::GeoFeatureGroupExtensi
OriginGroupExtension::OriginGroupExtension()
{
Base::Console().Message("Extension type: %s\n", OriginGroupExtension::getExtensionClassTypeId().getName());
initExtensionType(OriginGroupExtension::getExtensionClassTypeId());
EXTENSION_ADD_PROPERTY_TYPE(Origin,

View File

@@ -184,6 +184,7 @@ PyMOD_INIT_FUNC(Fem)
Fem::FemPostSmoothFilterExtension ::init();
Fem::FemPostObject ::init();
Fem::FemPostGroupExtension ::init();
Fem::FemPostPipeline ::init();
Fem::FemPostFilter ::init();
Fem::FemPostClipFilter ::init();

View File

@@ -83,6 +83,8 @@ if(BUILD_FEM_VTK)
PropertyPostDataObject.cpp
FemPostObject.h
FemPostObject.cpp
FemPostGroupExtension.h
FemPostGroupExtension.cpp
FemPostPipeline.h
FemPostPipeline.cpp
FemPostBranch.h

View File

@@ -41,7 +41,6 @@
#include "FemMesh.h"
#include "FemMeshObject.h"
#include "FemPostPipeline.h"
#include "FemPostBranch.h"
#include "FemPostBranchPy.h"
#include "FemVTKTools.h"
@@ -50,30 +49,22 @@
using namespace Fem;
using namespace App;
PROPERTY_SOURCE(Fem::FemPostBranch, Fem::FemPostFilter)
const char* FemPostBranch::ModeEnums[] = {"Serial", "Parallel", nullptr};
PROPERTY_SOURCE_WITH_EXTENSIONS(Fem::FemPostBranch, Fem::FemPostFilter);
const char* FemPostBranch::OutputEnums[] = {"Passthrough", "Append", nullptr};
FemPostBranch::FemPostBranch() : Fem::FemPostFilter(), App::GroupExtension()
FemPostBranch::FemPostBranch() : Fem::FemPostFilter(), Fem::FemPostGroupExtension()
{
GroupExtension::initExtension(this);
FemPostGroupExtension::initExtension(this);
ADD_PROPERTY_TYPE(Mode,
(long(0)),
"Branch",
App::Prop_None,
"Selects which input the child filters of the branch receive\n"
"In serial the first filter receives the branch input, and the concecitive ones get the prior filter output.\n"
"In parallel, every filter receives the branch input.");
ADD_PROPERTY_TYPE(Output,
(long(0)),
"Branch",
"Pipeline",
App::Prop_None,
"Selects what the output of the branch itself is\n"
"In passthrough the branchs output is equal its imput.\n"
"In append, all filters outputs gets appended as the branches output");
"In append, all child filter outputs gets appended as the branches output");
Mode.setEnums(ModeEnums);
Output.setEnums(OutputEnums);
/* We always have a passthrough filter. This allows to connect our children
@@ -211,58 +202,24 @@ void FemPostBranch::filterChanged(FemPostFilter* filter)
// if we append as output, we need to inform the parent object that we are isTouched
if (Output.getValue() == 1) {
//make sure we inform our parent object that we changed, it then can inform others if needed
App::DocumentObject* group = App::GroupExtension::getGroupOfObject(this);
App::DocumentObject* group = FemPostGroupExtension::getGroupOfObject(this);
if (!group) {
return;
}
if (group->isDerivedFrom(Fem::FemPostPipeline::getClassTypeId())) {
auto pipe = dynamic_cast<Fem::FemPostPipeline*>(group);
pipe->filterChanged(this);
}
else if (group->isDerivedFrom(Fem::FemPostBranch::getClassTypeId())) {
auto branch = dynamic_cast<Fem::FemPostBranch*>(group);
branch->filterChanged(this);
if (group->hasExtension(FemPostGroupExtension::getExtensionClassTypeId())) {
auto postgroup = group->getExtensionByType<FemPostGroupExtension>();
postgroup->filterChanged(this);
}
}
}
void FemPostBranch::pipelineChanged(FemPostFilter* filter) {
void FemPostBranch::filterPipelineChanged(FemPostFilter*) {
// one of our filters has changed its active pipeline. We need to reconnect it properly.
// As we are cheap we just reconnect everything
// TODO: Do more efficiently
onChanged(&Group);
}
void FemPostBranch::recomputeChildren()
{
for (const auto& obj : Group.getValues()) {
obj->touch();
}
}
FemPostObject* FemPostBranch::getLastPostObject()
{
if (Group.getValues().empty()) {
return this;
}
return static_cast<FemPostObject*>(Group.getValues().back());
}
bool FemPostBranch::holdsPostObject(FemPostObject* obj)
{
std::vector<App::DocumentObject*>::const_iterator it = Group.getValues().begin();
for (; it != Group.getValues().end(); ++it) {
if (*it == obj) {
return true;
}
}
return false;
}
PyObject* FemPostBranch::getPyObject()
{

View File

@@ -23,12 +23,9 @@
#ifndef Fem_FemPostBranch_H
#define Fem_FemPostBranch_H
#include "App/GroupExtension.h"
#include "FemPostFilter.h"
#include "FemPostFunction.h"
#include "FemPostObject.h"
#include "FemResultObject.h"
#include "FemPostGroupExtension.h"
#include <vtkSmartPointer.h>
#include <vtkAppendFilter.h>
@@ -38,7 +35,7 @@
namespace Fem
{
class FemExport FemPostBranch: public Fem::FemPostFilter, public App::GroupExtension
class FemExport FemPostBranch: public Fem::FemPostFilter, public FemPostGroupExtension
{
PROPERTY_HEADER_WITH_EXTENSIONS(Fem::FemPostBranch);
@@ -59,40 +56,18 @@ public:
return "FemGui::ViewProviderFemPostBranch";
}
// load data from files
static bool canRead(Base::FileInfo file);
void read(Base::FileInfo file);
void scale(double s);
// load from results
void load(FemResultObject* res);
// Branch handling
void filterChanged(FemPostFilter* filter);
void pipelineChanged(FemPostFilter* filter);
void recomputeChildren();
FemPostObject* getLastPostObject();
bool holdsPostObject(FemPostObject* obj);
void filterChanged(FemPostFilter* filter) override;
void filterPipelineChanged(FemPostFilter* filter) override;
protected:
void onChanged(const App::Property* prop) override;
private:
static const char* ModeEnums[];
static const char* OutputEnums[];
vtkSmartPointer<vtkAppendFilter> m_append;
vtkSmartPointer<vtkPassThrough> m_passthrough;
template<class TReader>
void readXMLFile(std::string file)
{
vtkSmartPointer<TReader> reader = vtkSmartPointer<TReader>::New();
reader->SetFileName(file.c_str());
reader->Update();
Data.setValue(reader->GetOutput());
}
};
} // namespace Fem

View File

@@ -78,19 +78,14 @@ void FemPostFilter::setActiveFilterPipeline(std::string name)
//set the new pipeline active
m_activePipeline = name;
//inform our parent, that we need to be connected a new
App::DocumentObject* group = App::GroupExtension::getGroupOfObject(this);
//inform our parent, that we need to be reconnected
App::DocumentObject* group = FemPostGroupExtension::getGroupOfObject(this);
if (!group) {
return;
}
if (group->isDerivedFrom(Fem::FemPostPipeline::getClassTypeId())) {
auto pipe = dynamic_cast<Fem::FemPostPipeline*>(group);
pipe->pipelineChanged(this);
}
else if (group->isDerivedFrom(Fem::FemPostBranch::getClassTypeId())) {
auto branch = dynamic_cast<Fem::FemPostBranch*>(group);
branch->pipelineChanged(this);
if (group->hasExtension(FemPostGroupExtension::getExtensionClassTypeId())) {
auto postgroup = group->getExtensionByType<FemPostGroupExtension>();
postgroup->filterPipelineChanged(this);
}
}
}
@@ -103,18 +98,15 @@ FemPostFilter::FilterPipeline& FemPostFilter::getActiveFilterPipeline()
void FemPostFilter::onChanged(const App::Property* prop)
{
//make sure we inform our parent object that we changed, it then can inform others if needed
App::DocumentObject* group = App::GroupExtension::getGroupOfObject(this);
if (!group) {
return FemPostObject::onChanged(prop);
}
if (group->isDerivedFrom(Fem::FemPostPipeline::getClassTypeId())) {
auto pipe = dynamic_cast<Fem::FemPostPipeline*>(group);
pipe->filterChanged(this);
}
else if (group->isDerivedFrom(Fem::FemPostBranch::getClassTypeId())) {
auto branch = dynamic_cast<Fem::FemPostBranch*>(group);
branch->filterChanged(this);
if(prop != &Data) {
App::DocumentObject* group = FemPostGroupExtension::getGroupOfObject(this);
if (!group) {
return;
}
if (group->hasExtension(FemPostGroupExtension::getExtensionClassTypeId())) {
auto postgroup = group->getExtensionByType<FemPostGroupExtension>();
postgroup->filterChanged(this);
}
}
return FemPostObject::onChanged(prop);
@@ -1162,7 +1154,6 @@ FemPostWarpVectorFilter::~FemPostWarpVectorFilter() = default;
DocumentObjectExecReturn* FemPostWarpVectorFilter::execute()
{
Base::Console().Message("Warp Execute\n");
std::string val;
if (Vector.getValue() >= 0) {

View File

@@ -23,6 +23,7 @@
#include "PreCompiled.h"
#include "FemPostFunction.h"
#include <App/Document.h>
using namespace Fem;
@@ -31,19 +32,26 @@ using namespace App;
PROPERTY_SOURCE(Fem::FemPostFunctionProvider, App::DocumentObject)
FemPostFunctionProvider::FemPostFunctionProvider()
: DocumentObject()
: DocumentObjectGroup()
{
ADD_PROPERTY(Functions, (nullptr));
}
FemPostFunctionProvider::~FemPostFunctionProvider() = default;
void FemPostFunctionProvider::onChanged(const Property* prop)
bool FemPostFunctionProvider::allowObject(App::DocumentObject* obj)
{
App::DocumentObject::onChanged(prop);
return obj->isDerivedFrom(FemPostFunction::getClassTypeId());
}
void FemPostFunctionProvider::unsetupObject()
{
// remove all children!
auto document = getExtendedObject()->getDocument();
for (const auto& obj : Group.getValues()) {
document->removeObject(obj->getNameInDocument());
}
}
PROPERTY_SOURCE(Fem::FemPostFunction, App::DocumentObject)

View File

@@ -32,6 +32,7 @@
#include <vtkSphere.h>
#include <App/PropertyUnits.h>
#include <App/DocumentObjectGroup.h>
#include "FemPostObject.h"
@@ -72,7 +73,7 @@ protected:
vtkBoundingBox m_boundingBox;
};
class FemExport FemPostFunctionProvider: public App::DocumentObject
class FemExport FemPostFunctionProvider: public App::DocumentObjectGroup
{
PROPERTY_HEADER_WITH_OVERRIDE(Fem::FemPostFunctionProvider);
@@ -86,10 +87,9 @@ public:
return "FemGui::ViewProviderFemPostFunctionProvider";
}
App::PropertyLinkList Functions;
protected:
void onChanged(const App::Property* prop) override;
bool allowObject(App::DocumentObject* obj) override;
void unsetupObject() override;
};
// ---------------------------------------------------------------------------

View File

@@ -0,0 +1,163 @@
/***************************************************************************
* Copyright (c) 2024 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"
#include "FemPostGroupExtension.h"
#include <App/Document.h>
using namespace Fem;
EXTENSION_PROPERTY_SOURCE(Fem::FemPostGroupExtension, App::GroupExtension);
const char* FemPostGroupExtension::ModeEnums[] = {"Serial", "Parallel", nullptr};
FemPostGroupExtension::FemPostGroupExtension() : App::GroupExtension() {
initExtensionType(Fem::FemPostGroupExtension::getExtensionClassTypeId());
EXTENSION_ADD_PROPERTY_TYPE(Mode,
(long(0)),
"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");
EXTENSION_ADD_PROPERTY_TYPE(Filter,
(nullptr),
"Pipeline",
App::Prop_Transient,
"List of all filters");
Mode.setEnums(ModeEnums);
}
FemPostGroupExtension::~FemPostGroupExtension() {
}
void FemPostGroupExtension::initExtension(App::ExtensionContainer* obj)
{
if (!obj->isDerivedFrom(Fem::FemPostObject::getClassTypeId())) {
throw Base::RuntimeError("FemPostGroupExtension can only be applied to FemPostObject");
}
App::GroupExtension::initExtension(obj);
}
void FemPostGroupExtension::extensionOnChanged(const App::Property* p)
{
if(p == &Group) {
if (!m_blockChange) {
// make sure filter property holds all our filters (and non filters are in front)
std::vector<App::DocumentObject*> filters;
for(auto obj : Group.getValues()) {
if(obj->isDerivedFrom(FemPostFilter::getClassTypeId())) {
filters.push_back(obj);
}
}
// sort the group, so that non filter objects are always on top
auto objs = Group.getValues();
std::sort( objs.begin( ), objs.end( ), [ ]( const App::DocumentObject* lhs, const App::DocumentObject* rhs ){
int l = lhs->isDerivedFrom(FemPostFilter::getClassTypeId()) ? 0 : 1;
int r = rhs->isDerivedFrom(FemPostFilter::getClassTypeId()) ? 0 : 1;
return r<l;
});
m_blockChange = true;
Group.setValue(objs);
Filter.setValue(filters);
m_blockChange = false;
}
}
else if (p == &Filter) {
if (!m_blockChange) {
// someone external changed filter, make sure group represents this
// collect all filters
std::vector<App::DocumentObject*> filters;
for (auto obj : Filter.getValues()) {
if (obj->isDerivedFrom(Fem::FemPostFilter::getClassTypeId())) {
filters.push_back(obj);
}
}
//collect all other items that are not filters
std::vector<App::DocumentObject*> objs;
for (auto obj : Group.getValues()) {
if (!obj->isDerivedFrom(Fem::FemPostFilter::getClassTypeId())) {
objs.push_back(obj);
}
}
// set the properties correctly
m_blockChange = true;
objs.insert( objs.end(), filters.begin(), filters.end() );
Filter.setValue(filters);
Group.setValue(objs);
m_blockChange = false;
}
}
GroupExtension::extensionOnChanged(p);
}
void FemPostGroupExtension::onExtendedUnsetupObject()
{
// remove all children!
auto document = getExtendedObject()->getDocument();
for (const auto& obj : Group.getValues()) {
document->removeObject(obj->getNameInDocument());
}
}
void FemPostGroupExtension::recomputeChildren()
{
for (const auto& obj : Group.getValues()) {
obj->touch();
}
}
FemPostObject* FemPostGroupExtension::getLastPostObject()
{
if (Group.getValues().empty()) {
return static_cast<FemPostObject*>(this->getExtendedObject());
}
return static_cast<FemPostObject*>(Group.getValues().back());
}
bool FemPostGroupExtension::holdsPostObject(FemPostObject* obj)
{
std::vector<App::DocumentObject*>::const_iterator it = Group.getValues().begin();
for (; it != Group.getValues().end(); ++it) {
if (*it == obj) {
return true;
}
}
return false;
}

View File

@@ -0,0 +1,68 @@
/***************************************************************************
* Copyright (c) 2024 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 *
* *
***************************************************************************/
#ifndef Fem_FemPostGroup_H
#define Fem_FemPostGroup_H
#include "Base/Unit.h"
#include "App/GroupExtension.h"
#include "FemPostFilter.h"
namespace Fem
{
// object grouping FEM filters and building the structure of the pipeline
class FemExport FemPostGroupExtension : public App::GroupExtension {
using inherited = App::GroupExtension;
EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(Fem::FemPostGroupExtension);
public:
/// Constructor
FemPostGroupExtension();
~FemPostGroupExtension() override;
void initExtension(App::ExtensionContainer* obj) override;
App::PropertyEnumeration Mode;
App::PropertyLinkList Filter;
// Pipeline handling
virtual void filterChanged(FemPostFilter*) {}; // settings change in filter
virtual void filterPipelineChanged(FemPostFilter*) {}; // pipeline change in filter
virtual void recomputeChildren();
virtual FemPostObject* getLastPostObject();
virtual bool holdsPostObject(FemPostObject* obj);
protected:
void extensionOnChanged(const App::Property* p) override;
void onExtendedUnsetupObject() override;
private:
bool m_blockChange = false;
static const char* ModeEnums[];
};
} // namespace Fem
#endif // Fem_FemPostGroup_H

View File

@@ -151,7 +151,7 @@ int FemFrameSourceAlgorithm::RequestInformation(vtkInformation*reqInfo, vtkInfor
return 1;
}
int FemFrameSourceAlgorithm::RequestData(vtkInformation* reqInfo, vtkInformationVector** inVector, vtkInformationVector* outVector)
int FemFrameSourceAlgorithm::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector* outVector)
{
std::stringstream strstm;
@@ -192,34 +192,19 @@ int FemFrameSourceAlgorithm::RequestData(vtkInformation* reqInfo, vtkInformation
}
PROPERTY_SOURCE_WITH_EXTENSIONS(Fem::FemPostPipeline, Fem::FemPostObject)
PROPERTY_SOURCE(Fem::FemPostPipeline, Fem::FemPostObject)
const char* FemPostPipeline::ModeEnums[] = {"Serial", "Parallel", nullptr};
FemPostPipeline::FemPostPipeline() : Fem::FemPostObject(), App::GroupExtension()
FemPostPipeline::FemPostPipeline() : FemPostObject(), FemPostGroupExtension()
{
GroupExtension::initExtension(this);
ADD_PROPERTY_TYPE(Functions,
(nullptr),
"Pipeline",
App::Prop_Hidden,
"The function provider which groups all pipeline functions");
ADD_PROPERTY_TYPE(Mode,
(long(0)),
"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");
FemPostGroupExtension::initExtension(this);
ADD_PROPERTY_TYPE(Frame,
(long(0)),
"Pipeline",
App::Prop_None,
"The frame used to calculate the data in the pipeline processing (read only, set via pipeline object).");
Mode.setEnums(ModeEnums);
// create our source algorithm
m_source_algorithm = vtkSmartPointer<FemFrameSourceAlgorithm>::New();
}
@@ -249,6 +234,17 @@ vtkDataSet* FemPostPipeline::getDataSet() {
return nullptr;
}
Fem::FemPostFunctionProvider* FemPostPipeline::getFunctionProvider() {
// see if we have one
for (auto obj : Group.getValues()){
if(obj->isDerivedFrom(FemPostFunctionProvider::getClassTypeId())) {
return static_cast<FemPostFunctionProvider*>(obj);
}
}
return nullptr;
}
bool FemPostPipeline::canRead(Base::FileInfo File)
{
@@ -305,6 +301,7 @@ void FemPostPipeline::onChanged(const Property* prop)
* of our child filters correctly according to the new settings
*/
FemPostObject::onChanged(prop);
// use the correct data as source
if (prop == &Data) {
@@ -360,10 +357,10 @@ void FemPostPipeline::onChanged(const Property* prop)
// connect all filters correctly to the source
if (prop == &Group || prop == &Mode) {
if (prop == &Filter || prop == &Mode) {
// we check if all connections are right and add new ones if needed
std::vector<App::DocumentObject*> objs = Group.getValues();
std::vector<App::DocumentObject*> objs = Filter.getValues();
if (objs.empty()) {
return;
@@ -398,9 +395,6 @@ void FemPostPipeline::onChanged(const Property* prop)
filter = nextFilter;
};
}
FemPostObject::onChanged(prop);
}
void FemPostPipeline::filterChanged(FemPostFilter* filter)
@@ -428,7 +422,7 @@ void FemPostPipeline::filterChanged(FemPostFilter* filter)
}
}
void FemPostPipeline::pipelineChanged(FemPostFilter* filter) {
void FemPostPipeline::filterPipelineChanged(FemPostFilter*) {
// one of our filters has changed its active pipeline. We need to reconnect it properly.
// As we are cheap we just reconnect everything
// TODO: Do more efficiently
@@ -441,7 +435,7 @@ void FemPostPipeline::recomputeChildren()
double frame = 0;
auto frames = getFrameValues();
if (!frames.empty() &&
Frame.getValue() < frames.size()) {
Frame.getValue() < long(frames.size())) {
frame = frames[Frame.getValue()];
}
@@ -455,30 +449,6 @@ void FemPostPipeline::recomputeChildren()
}
}
FemPostObject* FemPostPipeline::getLastPostObject()
{
if (Group.getValues().empty()) {
return this;
}
return static_cast<FemPostObject*>(Group.getValues().back());
}
bool FemPostPipeline::holdsPostObject(FemPostObject* obj)
{
std::vector<App::DocumentObject*>::const_iterator it = Group.getValues().begin();
for (; it != Group.getValues().end(); ++it) {
if (*it == obj) {
return true;
}
}
return false;
}
bool FemPostPipeline::hasFrames()
{

View File

@@ -23,12 +23,8 @@
#ifndef Fem_FemPostPipeline_H
#define Fem_FemPostPipeline_H
<<<<<<< HEAD
=======
#include "Base/Unit.h"
>>>>>>> 782848c556 (FEM: Make multistep work for eigenmodes)
#include "App/GroupExtension.h"
#include "FemPostGroupExtension.h"
#include "FemPostFilter.h"
#include "FemPostFunction.h"
@@ -66,7 +62,7 @@ protected:
};
class FemExport FemPostPipeline: public Fem::FemPostObject, public App::GroupExtension
class FemExport FemPostPipeline: public Fem::FemPostObject, public Fem::FemPostGroupExtension
{
PROPERTY_HEADER_WITH_EXTENSIONS(Fem::FemPostPipeline);
@@ -75,12 +71,11 @@ public:
FemPostPipeline();
~FemPostPipeline() override;
App::PropertyLink Functions;
App::PropertyEnumeration Mode;
App::PropertyEnumeration Frame;
virtual vtkDataSet* getDataSet() override;
Fem::FemPostFunctionProvider* getFunctionProvider();
short mustExecute() const override;
PyObject* getPyObject() override;
@@ -99,12 +94,10 @@ public:
void load(FemResultObject* res);
void load(std::vector<FemResultObject*> res, std::vector<double> values, Base::Unit unit, std::string frame_type);
// Pipeline handling
void filterChanged(FemPostFilter* filter);
void pipelineChanged(FemPostFilter* filter);
void recomputeChildren();
FemPostObject* getLastPostObject();
bool holdsPostObject(FemPostObject* obj);
// Group pipeline handling
void filterChanged(FemPostFilter* filter) override;
void filterPipelineChanged(FemPostFilter* filter) override;
void recomputeChildren() override;
// frame handling
bool hasFrames();
@@ -117,7 +110,6 @@ protected:
void onChanged(const App::Property* prop) override;
private:
static const char* ModeEnums[];
App::Enumeration m_frameEnum;
vtkSmartPointer<FemFrameSourceAlgorithm> m_source_algorithm;

View File

@@ -2479,23 +2479,17 @@ void CmdFemPostFunctions::activated(int iMsg)
openCommand(QT_TRANSLATE_NOOP("Command", "Create function"));
// check if the pipeline has a filter provider and add one if needed
Fem::FemPostFunctionProvider* provider;
if (!pipeline->Functions.getValue()
|| pipeline->Functions.getValue()->getTypeId()
!= Fem::FemPostFunctionProvider::getClassTypeId()) {
Fem::FemPostFunctionProvider* provider = pipeline->getFunctionProvider();
if (!provider) {
std::string FuncName = getUniqueObjectName("Functions");
doCommand(Doc,
"App.ActiveDocument.addObject('Fem::FemPostFunctionProvider','%s')",
FuncName.c_str());
doCommand(Doc,
"App.ActiveDocument.%s.Functions = App.ActiveDocument.%s",
"App.ActiveDocument.%s.addObject(App.ActiveDocument.%s)",
pipeline->getNameInDocument(),
FuncName.c_str());
provider = static_cast<Fem::FemPostFunctionProvider*>(
getDocument()->getObject(FuncName.c_str()));
}
else {
provider = static_cast<Fem::FemPostFunctionProvider*>(pipeline->Functions.getValue());
provider = pipeline->getFunctionProvider();
}
// build the object
@@ -2504,10 +2498,9 @@ void CmdFemPostFunctions::activated(int iMsg)
"App.activeDocument().addObject('Fem::FemPost%sFunction','%s')",
name.c_str(),
FeatName.c_str());
doCommand(Doc, "__list__ = App.ActiveDocument.%s.Functions", provider->getNameInDocument());
doCommand(Doc, "__list__.append(App.ActiveDocument.%s)", FeatName.c_str());
doCommand(Doc, "App.ActiveDocument.%s.Functions = __list__", provider->getNameInDocument());
doCommand(Doc, "del __list__");
doCommand(Doc, "App.ActiveDocument.%s.addObject(App.ActiveDocument.%s)",
provider->getNameInDocument(),
FeatName.c_str());
// set the default values, for this get the bounding box
vtkBoundingBox box = pipeline->getBoundingBox();

View File

@@ -1385,17 +1385,15 @@ void TaskPostClip::collectImplicitFunctions()
pipelines = getDocument()->getObjectsOfType<Fem::FemPostPipeline>();
if (!pipelines.empty()) {
Fem::FemPostPipeline* pipeline = pipelines.front();
if (pipeline->Functions.getValue()
&& pipeline->Functions.getValue()->is<Fem::FemPostFunctionProvider>()) {
Fem::FemPostFunctionProvider* provider = pipeline->getFunctionProvider();
if (provider) {
ui->FunctionBox->clear();
QStringList items;
std::size_t currentItem = 0;
App::DocumentObject* currentFunction =
getObject<Fem::FemPostClipFilter>()->Function.getValue();
const std::vector<App::DocumentObject*>& funcs =
static_cast<Fem::FemPostFunctionProvider*>(pipeline->Functions.getValue())
->Functions.getValues();
const std::vector<App::DocumentObject*>& funcs = provider->Group.getValues();
for (std::size_t i = 0; i < funcs.size(); ++i) {
items.push_back(QString::fromLatin1(funcs[i]->getNameInDocument()));
if (currentFunction == funcs[i]) {
@@ -1435,12 +1433,10 @@ void TaskPostClip::onFunctionBoxCurrentIndexChanged(int idx)
pipelines = getDocument()->getObjectsOfType<Fem::FemPostPipeline>();
if (!pipelines.empty()) {
Fem::FemPostPipeline* pipeline = pipelines.front();
if (pipeline->Functions.getValue()
&& pipeline->Functions.getValue()->is<Fem::FemPostFunctionProvider>()) {
Fem::FemPostFunctionProvider* provider = pipeline->getFunctionProvider();
if (provider) {
const std::vector<App::DocumentObject*>& funcs =
static_cast<Fem::FemPostFunctionProvider*>(pipeline->Functions.getValue())
->Functions.getValues();
const std::vector<App::DocumentObject*>& funcs = provider->Group.getValues();
if (idx >= 0) {
getObject<Fem::FemPostClipFilter>()->Function.setValue(funcs[idx]);
}
@@ -1695,17 +1691,15 @@ void TaskPostCut::collectImplicitFunctions()
pipelines = getDocument()->getObjectsOfType<Fem::FemPostPipeline>();
if (!pipelines.empty()) {
Fem::FemPostPipeline* pipeline = pipelines.front();
if (pipeline->Functions.getValue()
&& pipeline->Functions.getValue()->is<Fem::FemPostFunctionProvider>()) {
Fem::FemPostFunctionProvider* provider = pipeline->getFunctionProvider();
if (provider) {
ui->FunctionBox->clear();
QStringList items;
std::size_t currentItem = 0;
App::DocumentObject* currentFunction =
getObject<Fem::FemPostCutFilter>()->Function.getValue();
const std::vector<App::DocumentObject*>& funcs =
static_cast<Fem::FemPostFunctionProvider*>(pipeline->Functions.getValue())
->Functions.getValues();
const std::vector<App::DocumentObject*>& funcs = provider->Group.getValues();
for (std::size_t i = 0; i < funcs.size(); ++i) {
items.push_back(QString::fromLatin1(funcs[i]->getNameInDocument()));
if (currentFunction == funcs[i]) {
@@ -1745,12 +1739,10 @@ void TaskPostCut::onFunctionBoxCurrentIndexChanged(int idx)
pipelines = getDocument()->getObjectsOfType<Fem::FemPostPipeline>();
if (!pipelines.empty()) {
Fem::FemPostPipeline* pipeline = pipelines.front();
if (pipeline->Functions.getValue()
&& pipeline->Functions.getValue()->is<Fem::FemPostFunctionProvider>()) {
Fem::FemPostFunctionProvider* provider = pipeline->getFunctionProvider();
if (provider) {
const std::vector<App::DocumentObject*>& funcs =
static_cast<Fem::FemPostFunctionProvider*>(pipeline->Functions.getValue())
->Functions.getValues();
const std::vector<App::DocumentObject*>& funcs = provider->Group.getValues();
if (idx >= 0) {
getObject<Fem::FemPostCutFilter>()->Function.setValue(funcs[idx]);
}

View File

@@ -92,16 +92,6 @@ ViewProviderFemPostFunctionProvider::ViewProviderFemPostFunctionProvider() = def
ViewProviderFemPostFunctionProvider::~ViewProviderFemPostFunctionProvider() = default;
std::vector<App::DocumentObject*> ViewProviderFemPostFunctionProvider::claimChildren() const
{
return getObject<Fem::FemPostFunctionProvider>()->Functions.getValues();
}
std::vector<App::DocumentObject*> ViewProviderFemPostFunctionProvider::claimChildren3D() const
{
return claimChildren();
}
void ViewProviderFemPostFunctionProvider::onChanged(const App::Property* prop)
{
Gui::ViewProviderDocumentObject::onChanged(prop);
@@ -113,7 +103,7 @@ void ViewProviderFemPostFunctionProvider::updateData(const App::Property* prop)
{
Gui::ViewProviderDocumentObject::updateData(prop);
Fem::FemPostFunctionProvider* obj = getObject<Fem::FemPostFunctionProvider>();
if (prop == &obj->Functions) {
if (prop == &obj->Group) {
updateSize();
}
}
@@ -139,8 +129,9 @@ bool ViewProviderFemPostFunctionProvider::onDelete(const std::vector<std::string
// warn the user if the object has unselected children
auto objs = claimChildren();
return ViewProviderFemAnalysis::checkSelectedChildren(objs,
this->getDocument(),
"functions list");
this->getDocument(),
"functions list");
}
bool ViewProviderFemPostFunctionProvider::canDelete(App::DocumentObject* obj) const

View File

@@ -27,7 +27,7 @@
#include <QWidget>
#include <boost/signals2.hpp>
#include <Gui/ViewProviderDocumentObject.h>
#include <Gui/ViewProviderDocumentObjectGroup.h>
#include <Mod/Fem/App/FemPostFunction.h>
@@ -93,7 +93,7 @@ private:
boost::signals2::scoped_connection m_connection;
};
class FemGuiExport ViewProviderFemPostFunctionProvider: public Gui::ViewProviderDocumentObject
class FemGuiExport ViewProviderFemPostFunctionProvider: public Gui::ViewProviderDocumentObjectGroup
{
PROPERTY_HEADER_WITH_OVERRIDE(FemGui::ViewProviderFemPostFunctionProvider);
@@ -111,8 +111,6 @@ public:
bool canDelete(App::DocumentObject* obj) const override;
protected:
std::vector<App::DocumentObject*> claimChildren() const override;
std::vector<App::DocumentObject*> claimChildren3D() const override;
void onChanged(const App::Property* prop) override;
void updateData(const App::Property*) override;

View File

@@ -1067,7 +1067,15 @@ bool ViewProviderFemPostObject::onDelete(const std::vector<std::string>&)
{
// warn the user if the object has unselected children
auto objs = claimChildren();
return ViewProviderFemAnalysis::checkSelectedChildren(objs, this->getDocument(), "pipeline");
if (!ViewProviderFemAnalysis::checkSelectedChildren(objs, this->getDocument(), "pipeline")) {
return false;
};
// delete all subelements
for(auto obj : objs) {
getObject()->getDocument()->removeObject(obj->getNameInDocument());
}
return true;
}
bool ViewProviderFemPostObject::canDelete(App::DocumentObject* obj) const

View File

@@ -52,59 +52,34 @@ ViewProviderFemPostPipeline::ViewProviderFemPostPipeline()
ViewProviderFemPostPipeline::~ViewProviderFemPostPipeline() = default;
std::vector<App::DocumentObject*> ViewProviderFemPostPipeline::claimChildren() const
{
Fem::FemPostPipeline* pipeline = getObject<Fem::FemPostPipeline>();
std::vector<App::DocumentObject*> children = FemGui::ViewProviderFemPostObject::claimChildren();
if (pipeline->Functions.getValue()) {
children.insert(children.begin(), pipeline->Functions.getValue());
}
return children;
}
std::vector<App::DocumentObject*> ViewProviderFemPostPipeline::claimChildren3D() const
{
return claimChildren();
}
void ViewProviderFemPostPipeline::updateData(const App::Property* prop)
{
FemGui::ViewProviderFemPostObject::updateData(prop);
<<<<<<< HEAD
Fem::FemPostPipeline* pipeline = getObject<Fem::FemPostPipeline>();
=======
Fem::FemPostPipeline* pipeline = static_cast<Fem::FemPostPipeline*>(getObject());
>>>>>>> 782848c556 (FEM: Make multistep work for eigenmodes)
if (prop == &pipeline->Functions) {
updateFunctionSize();
}
if (prop == &pipeline->Frame) {
// Frame is pipeline property, not post object, parent updateData does not catch it for update
updateVtk();
}
else if ((prop == &pipeline->Data) ||
(prop == &pipeline->Group)) {
updateFunctionSize();
}
}
void ViewProviderFemPostPipeline::updateFunctionSize()
{
// we need to get the bounding box and set the function provider size
Fem::FemPostPipeline* obj = getObject<Fem::FemPostPipeline>();
if (!obj->Functions.getValue()
|| !obj->Functions.getValue()->isDerivedFrom(
Fem::FemPostFunctionProvider::getClassTypeId())) {
Fem::FemPostFunctionProvider* fp = obj->getFunctionProvider();
if (!fp) {
return;
}
// get the function provider
FemGui::ViewProviderFemPostFunctionProvider* vp =
static_cast<FemGui::ViewProviderFemPostFunctionProvider*>(
Gui::Application::Instance->getViewProvider(obj->Functions.getValue()));
Gui::Application::Instance->getViewProvider(fp));
if (obj->Data.getValue() && obj->Data.getValue()->IsA("vtkDataSet")) {
vtkBoundingBox box = obj->getBoundingBox();

View File

@@ -43,8 +43,6 @@ public:
ViewProviderFemPostPipeline();
~ViewProviderFemPostPipeline() override;
std::vector<App::DocumentObject*> claimChildren() const override;
std::vector<App::DocumentObject*> claimChildren3D() const override;
void updateData(const App::Property* prop) override;
bool onDelete(const std::vector<std::string>& objs) override;
void onSelectionChanged(const Gui::SelectionChanges& sel) override;