FEM: Backward compatibility for post pipeline and multiple fixes
This commit is contained in:
committed by
Benjamin Nauck
parent
53a7e5ab34
commit
c8a4ff0a70
@@ -13,6 +13,11 @@
|
||||
<Author Licence="LGPL" Name="Werner Mayer" EMail="wmayer@users.sourceforge.net" />
|
||||
<UserDocu>The FemPostBranch class.</UserDocu>
|
||||
</Documentation>
|
||||
<Methode Name="getFilter">
|
||||
<Documentation>
|
||||
<UserDocu>Returns all filters, that this pipeline uses (non recursive, result does not contain branch child filters)</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="recomputeChildren">
|
||||
<Documentation>
|
||||
<UserDocu>Recomputes all children of the pipeline</UserDocu>
|
||||
|
||||
@@ -42,6 +42,20 @@ std::string FemPostBranchFilterPy::representation() const
|
||||
return {"<FemPostBranchFilter object>"};
|
||||
}
|
||||
|
||||
PyObject* FemPostBranchFilterPy::getFilter(PyObject* args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto filters = getFemPostBranchFilterPtr()->getFilter();
|
||||
Py::List sequence;
|
||||
for (auto filter : filters) {
|
||||
sequence.append(Py::asObject(filter->getPyObject()));
|
||||
}
|
||||
|
||||
return Py::new_reference_to(sequence);
|
||||
}
|
||||
|
||||
PyObject* FemPostBranchFilterPy::recomputeChildren(PyObject* args)
|
||||
{
|
||||
|
||||
@@ -98,15 +98,13 @@ 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
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
@@ -44,7 +44,7 @@ bool FemPostFunctionProvider::allowObject(App::DocumentObject* obj)
|
||||
return obj->isDerivedFrom(FemPostFunction::getClassTypeId());
|
||||
}
|
||||
|
||||
void FemPostFunctionProvider::unsetupObject()
|
||||
void FemPostFunctionProvider::unsetupObject()
|
||||
{
|
||||
// remove all children!
|
||||
auto document = getExtendedObject()->getDocument();
|
||||
@@ -53,6 +53,24 @@ void FemPostFunctionProvider::unsetupObject()
|
||||
}
|
||||
}
|
||||
|
||||
void FemPostFunctionProvider::handleChangedPropertyName(Base::XMLReader& reader,
|
||||
const char* typeName,
|
||||
const char* propName)
|
||||
{
|
||||
if (strcmp(propName, "Functions") == 0
|
||||
&& Base::Type::fromName(typeName) == App::PropertyLinkList::getClassTypeId()) {
|
||||
|
||||
// add the formerly Functions values to the group
|
||||
App::PropertyLinkList functions;
|
||||
functions.setContainer(this);
|
||||
functions.Restore(reader);
|
||||
Group.setValues(functions.getValues());
|
||||
}
|
||||
else {
|
||||
App::DocumentObject::handleChangedPropertyName(reader, typeName, propName);
|
||||
}
|
||||
}
|
||||
|
||||
PROPERTY_SOURCE(Fem::FemPostFunction, App::DocumentObject)
|
||||
|
||||
FemPostFunction::FemPostFunction() = default;
|
||||
|
||||
@@ -90,6 +90,9 @@ public:
|
||||
protected:
|
||||
bool allowObject(App::DocumentObject* obj) override;
|
||||
void unsetupObject() override;
|
||||
|
||||
// update documents
|
||||
void handleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName) override;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -42,12 +42,6 @@ FemPostGroupExtension::FemPostGroupExtension() : App::GroupExtension() {
|
||||
"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);
|
||||
}
|
||||
|
||||
@@ -70,15 +64,7 @@ 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
|
||||
// sort the group, so that non filter objects are always on top (in case any object using this extension allows those)
|
||||
auto objs = Group.getValues();
|
||||
std::sort( objs.begin( ), objs.end( ), [ ]( const App::DocumentObject* lhs, const App::DocumentObject* rhs ){
|
||||
|
||||
@@ -88,41 +74,24 @@ void FemPostGroupExtension::extensionOnChanged(const App::Property* p)
|
||||
});
|
||||
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);
|
||||
}
|
||||
|
||||
std::vector<Fem::FemPostFilter*> FemPostGroupExtension::getFilter()
|
||||
{
|
||||
//collect all other items that are not filters
|
||||
std::vector<Fem::FemPostFilter*> filters;
|
||||
for (auto obj : Group.getValues()) {
|
||||
if (obj->isDerivedFrom(Fem::FemPostFilter::getClassTypeId())) {
|
||||
filters.push_back(static_cast<FemPostFilter*>(obj));
|
||||
}
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
App::DocumentObject* FemPostGroupExtension::getGroupOfObject(const App::DocumentObject* obj)
|
||||
{
|
||||
for (auto o : obj->getInList()) {
|
||||
|
||||
@@ -44,7 +44,6 @@ public:
|
||||
void initExtension(App::ExtensionContainer* obj) override;
|
||||
|
||||
App::PropertyEnumeration Mode;
|
||||
App::PropertyLinkList Filter;
|
||||
|
||||
// Pipeline handling
|
||||
virtual void filterChanged(FemPostFilter*) {}; // settings change in filter
|
||||
@@ -54,6 +53,7 @@ public:
|
||||
virtual bool holdsPostObject(FemPostObject* obj);
|
||||
|
||||
// general
|
||||
std::vector<Fem::FemPostFilter*> getFilter();
|
||||
static App::DocumentObject* getGroupOfObject(const App::DocumentObject* obj);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -71,10 +71,10 @@ FemFrameSourceAlgorithm::FemFrameSourceAlgorithm::FemFrameSourceAlgorithm()
|
||||
|
||||
|
||||
FemFrameSourceAlgorithm::FemFrameSourceAlgorithm::~FemFrameSourceAlgorithm()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void FemFrameSourceAlgorithm::setDataObject(vtkSmartPointer<vtkDataObject> data ) {
|
||||
void FemFrameSourceAlgorithm::setDataObject(vtkSmartPointer<vtkDataObject> data)
|
||||
{
|
||||
m_data = data;
|
||||
Update();
|
||||
}
|
||||
@@ -94,7 +94,7 @@ std::vector<double> FemFrameSourceAlgorithm::getFrameValues()
|
||||
unsigned long nblocks = multiblock->GetNumberOfBlocks();
|
||||
std::vector<double> tFrames(nblocks);
|
||||
|
||||
for (unsigned long i=0; i<nblocks; i++) {
|
||||
for (unsigned long i = 0; i < nblocks; i++) {
|
||||
|
||||
vtkDataObject* block = multiblock->GetBlock(i);
|
||||
// check if the TimeValue field is available
|
||||
@@ -102,10 +102,9 @@ std::vector<double> FemFrameSourceAlgorithm::getFrameValues()
|
||||
break;
|
||||
}
|
||||
|
||||
//store the time value!
|
||||
// store the time value!
|
||||
vtkDataArray* TimeValue = block->GetFieldData()->GetArray("TimeValue");
|
||||
if (!TimeValue->IsA("vtkFloatArray") ||
|
||||
TimeValue->GetNumberOfTuples() < 1) {
|
||||
if (!TimeValue->IsA("vtkFloatArray") || TimeValue->GetNumberOfTuples() < 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -120,11 +119,12 @@ std::vector<double> FemFrameSourceAlgorithm::getFrameValues()
|
||||
return tFrames;
|
||||
}
|
||||
|
||||
int FemFrameSourceAlgorithm::RequestInformation(vtkInformation*reqInfo, vtkInformationVector **inVector, vtkInformationVector* outVector)
|
||||
int FemFrameSourceAlgorithm::RequestInformation(vtkInformation* reqInfo,
|
||||
vtkInformationVector** inVector,
|
||||
vtkInformationVector* outVector)
|
||||
{
|
||||
|
||||
if (!this->Superclass::RequestInformation(reqInfo, inVector, outVector))
|
||||
{
|
||||
if (!this->Superclass::RequestInformation(reqInfo, inVector, outVector)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -151,14 +151,17 @@ int FemFrameSourceAlgorithm::RequestInformation(vtkInformation*reqInfo, vtkInfor
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FemFrameSourceAlgorithm::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector* outVector)
|
||||
int FemFrameSourceAlgorithm::RequestData(vtkInformation*,
|
||||
vtkInformationVector**,
|
||||
vtkInformationVector* outVector)
|
||||
{
|
||||
|
||||
std::stringstream strstm;
|
||||
outVector->Print(strstm);
|
||||
|
||||
vtkInformation* outInfo = outVector->GetInformationObject(0);
|
||||
vtkUnstructuredGrid* output = vtkUnstructuredGrid::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
||||
vtkUnstructuredGrid* output =
|
||||
vtkUnstructuredGrid::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
||||
|
||||
if (!output || !m_data) {
|
||||
return 0;
|
||||
@@ -173,14 +176,15 @@ int FemFrameSourceAlgorithm::RequestData(vtkInformation*, vtkInformationVector**
|
||||
vtkSmartPointer<vtkMultiBlockDataSet> multiblock = vtkMultiBlockDataSet::SafeDownCast(m_data);
|
||||
// find the block asked for (lazy implementation)
|
||||
unsigned long idx = 0;
|
||||
if (outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()))
|
||||
{
|
||||
if (outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP())) {
|
||||
auto time = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
|
||||
auto frames = getFrameValues();
|
||||
|
||||
// we have float values, so be aware of roundign erros. lets subtract the searched time and then use the smalles value
|
||||
for(auto& frame : frames)
|
||||
frame = std::abs(frame-time);
|
||||
// we have float values, so be aware of roundign erros. lets subtract the searched time and
|
||||
// then use the smalles value
|
||||
for (auto& frame : frames) {
|
||||
frame = std::abs(frame - time);
|
||||
}
|
||||
|
||||
auto it = std::min_element(std::begin(frames), std::end(frames));
|
||||
idx = std::distance(std::begin(frames), it);
|
||||
@@ -194,7 +198,9 @@ int FemFrameSourceAlgorithm::RequestData(vtkInformation*, vtkInformationVector**
|
||||
|
||||
PROPERTY_SOURCE_WITH_EXTENSIONS(Fem::FemPostPipeline, Fem::FemPostObject)
|
||||
|
||||
FemPostPipeline::FemPostPipeline() : FemPostObject(), FemPostGroupExtension()
|
||||
FemPostPipeline::FemPostPipeline()
|
||||
: FemPostObject()
|
||||
, FemPostGroupExtension()
|
||||
{
|
||||
|
||||
FemPostGroupExtension::initExtension(this);
|
||||
@@ -203,7 +209,8 @@ FemPostPipeline::FemPostPipeline() : FemPostObject(), FemPostGroupExtension()
|
||||
(long(0)),
|
||||
"Pipeline",
|
||||
App::Prop_None,
|
||||
"The frame used to calculate the data in the pipeline processing (read only, set via pipeline object).");
|
||||
"The frame used to calculate the data in the pipeline processing (read only, "
|
||||
"set via pipeline object).");
|
||||
|
||||
// create our source algorithm
|
||||
m_source_algorithm = vtkSmartPointer<FemFrameSourceAlgorithm>::New();
|
||||
@@ -213,14 +220,15 @@ FemPostPipeline::~FemPostPipeline() = default;
|
||||
|
||||
short FemPostPipeline::mustExecute() const
|
||||
{
|
||||
if (Mode.isTouched() ) {
|
||||
if (Mode.isTouched()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FemPostObject::mustExecute();
|
||||
}
|
||||
|
||||
vtkDataSet* FemPostPipeline::getDataSet() {
|
||||
vtkDataSet* FemPostPipeline::getDataSet()
|
||||
{
|
||||
|
||||
vtkDataObject* data = m_source_algorithm->GetOutputDataObject(0);
|
||||
if (!data) {
|
||||
@@ -234,11 +242,12 @@ vtkDataSet* FemPostPipeline::getDataSet() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Fem::FemPostFunctionProvider* FemPostPipeline::getFunctionProvider() {
|
||||
Fem::FemPostFunctionProvider* FemPostPipeline::getFunctionProvider()
|
||||
{
|
||||
|
||||
// see if we have one
|
||||
for (auto obj : Group.getValues()){
|
||||
if(obj->isDerivedFrom(FemPostFunctionProvider::getClassTypeId())) {
|
||||
for (auto obj : Group.getValues()) {
|
||||
if (obj->isDerivedFrom(FemPostFunctionProvider::getClassTypeId())) {
|
||||
return static_cast<FemPostFunctionProvider*>(obj);
|
||||
}
|
||||
}
|
||||
@@ -309,7 +318,7 @@ void FemPostPipeline::scale(double s)
|
||||
|
||||
void FemPostPipeline::onChanged(const Property* prop)
|
||||
{
|
||||
/* onChanged handles the Pipeline setup: we connect the inputs and outputs
|
||||
/* onChanged handles the Pipeline setup: we connect the inputs and outputs
|
||||
* of our child filters correctly according to the new settings
|
||||
*/
|
||||
|
||||
@@ -334,7 +343,7 @@ void FemPostPipeline::onChanged(const Property* prop)
|
||||
auto unit = getFrameUnit();
|
||||
for (const double& frame : frames) {
|
||||
auto quantity = Base::Quantity(frame, unit);
|
||||
frame_values.push_back(quantity.getUserString().toStdString());
|
||||
frame_values.push_back(quantity.getUserString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,7 +352,8 @@ void FemPostPipeline::onChanged(const Property* prop)
|
||||
m_frameEnum.setEnums(frame_values);
|
||||
Frame.setValue(m_frameEnum);
|
||||
|
||||
std::vector<std::string>::iterator it = std::find(frame_values.begin(), frame_values.end(), val);
|
||||
std::vector<std::string>::iterator it =
|
||||
std::find(frame_values.begin(), frame_values.end(), val);
|
||||
if (!val.empty() && it != frame_values.end()) {
|
||||
Frame.setValue(val.c_str());
|
||||
}
|
||||
@@ -356,8 +366,7 @@ void FemPostPipeline::onChanged(const Property* prop)
|
||||
|
||||
// update the algorithm for the visulization
|
||||
auto frames = getFrameValues();
|
||||
if (!frames.empty() &&
|
||||
Frame.getValue() < long(frames.size())) {
|
||||
if (!frames.empty() && Frame.getValue() < long(frames.size())) {
|
||||
|
||||
double time = frames[Frame.getValue()];
|
||||
m_source_algorithm->UpdateTimeStep(time);
|
||||
@@ -369,39 +378,40 @@ void FemPostPipeline::onChanged(const Property* prop)
|
||||
|
||||
|
||||
// connect all filters correctly to the source
|
||||
if (prop == &Filter || prop == &Mode) {
|
||||
if (prop == &Group || prop == &Mode) {
|
||||
|
||||
// we check if all connections are right and add new ones if needed
|
||||
std::vector<App::DocumentObject*> objs = Filter.getValues();
|
||||
std::vector<FemPostFilter*> objs = getFilter();
|
||||
|
||||
if (objs.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FemPostFilter* filter = NULL;
|
||||
std::vector<App::DocumentObject*>::iterator it = objs.begin();
|
||||
std::vector<FemPostFilter*>::iterator it = objs.begin();
|
||||
for (; it != objs.end(); ++it) {
|
||||
|
||||
// prepare the filter: make all connections new
|
||||
FemPostFilter* nextFilter = static_cast<FemPostFilter*>(*it);
|
||||
FemPostFilter* nextFilter = *it;
|
||||
nextFilter->getActiveFilterPipeline().source->RemoveAllInputConnections(0);
|
||||
|
||||
// handle input modes
|
||||
if (Mode.getValue() == 0) {
|
||||
// serial: the next filter gets the previous output, the first one gets our input
|
||||
if (filter == NULL) {
|
||||
nextFilter->getActiveFilterPipeline().source->SetInputConnection(m_source_algorithm->GetOutputPort(0));
|
||||
} else {
|
||||
nextFilter->getActiveFilterPipeline().source->SetInputConnection(filter->getActiveFilterPipeline().target->GetOutputPort());
|
||||
}
|
||||
|
||||
}
|
||||
else if (Mode.getValue() == 1) {
|
||||
// handle input modes (Parallel is seperated, alll other settings are serial, just in
|
||||
// case an old document is loaded with "custom" mode, idx 2)
|
||||
if (Mode.getValue() == 1) {
|
||||
// parallel: all filters get out input
|
||||
nextFilter->getActiveFilterPipeline().source->SetInputConnection(m_source_algorithm->GetOutputPort(0));
|
||||
nextFilter->getActiveFilterPipeline().source->SetInputConnection(
|
||||
m_source_algorithm->GetOutputPort(0));
|
||||
}
|
||||
else {
|
||||
throw Base::ValueError("Unknown Mode set for Pipeline");
|
||||
// serial: the next filter gets the previous output, the first one gets our input
|
||||
if (filter == NULL) {
|
||||
nextFilter->getActiveFilterPipeline().source->SetInputConnection(
|
||||
m_source_algorithm->GetOutputPort(0));
|
||||
}
|
||||
else {
|
||||
nextFilter->getActiveFilterPipeline().source->SetInputConnection(
|
||||
filter->getActiveFilterPipeline().target->GetOutputPort());
|
||||
}
|
||||
}
|
||||
|
||||
filter = nextFilter;
|
||||
@@ -411,7 +421,7 @@ void FemPostPipeline::onChanged(const Property* prop)
|
||||
|
||||
void FemPostPipeline::filterChanged(FemPostFilter* filter)
|
||||
{
|
||||
//we only need to update the following children if we are in serial mode
|
||||
// we only need to update the following children if we are in serial mode
|
||||
if (Mode.getValue() == 0) {
|
||||
|
||||
std::vector<App::DocumentObject*> objs = Group.getValues();
|
||||
@@ -434,7 +444,8 @@ void FemPostPipeline::filterChanged(FemPostFilter* filter)
|
||||
}
|
||||
}
|
||||
|
||||
void FemPostPipeline::filterPipelineChanged(FemPostFilter*) {
|
||||
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
|
||||
@@ -446,8 +457,7 @@ void FemPostPipeline::recomputeChildren()
|
||||
// get the frame we use
|
||||
double frame = 0;
|
||||
auto frames = getFrameValues();
|
||||
if (!frames.empty() &&
|
||||
Frame.getValue() < long(frames.size())) {
|
||||
if (!frames.empty() && Frame.getValue() < long(frames.size())) {
|
||||
|
||||
frame = frames[Frame.getValue()];
|
||||
}
|
||||
@@ -484,9 +494,7 @@ std::string FemPostPipeline::getFrameType()
|
||||
}
|
||||
|
||||
vtkAbstractArray* TimeInfo = multiblock->GetFieldData()->GetAbstractArray("TimeInfo");
|
||||
if (!TimeInfo ||
|
||||
!TimeInfo->IsA("vtkStringArray") ||
|
||||
TimeInfo->GetNumberOfTuples() < 2) {
|
||||
if (!TimeInfo || !TimeInfo->IsA("vtkStringArray") || TimeInfo->GetNumberOfTuples() < 2) {
|
||||
|
||||
return std::string("unknown");
|
||||
}
|
||||
@@ -512,14 +520,13 @@ Base::Unit FemPostPipeline::getFrameUnit()
|
||||
}
|
||||
|
||||
vtkAbstractArray* TimeInfo = multiblock->GetFieldData()->GetAbstractArray("TimeInfo");
|
||||
if (!TimeInfo->IsA("vtkStringArray") ||
|
||||
TimeInfo->GetNumberOfTuples() < 2) {
|
||||
if (!TimeInfo->IsA("vtkStringArray") || TimeInfo->GetNumberOfTuples() < 2) {
|
||||
|
||||
// units cannot be undefined, so use time
|
||||
return Base::Unit::TimeSpan;
|
||||
}
|
||||
|
||||
return Base::Unit(QString::fromStdString(vtkStringArray::SafeDownCast(TimeInfo)->GetValue(1)));
|
||||
return Base::Unit(vtkStringArray::SafeDownCast(TimeInfo)->GetValue(1));
|
||||
}
|
||||
|
||||
std::vector<double> FemPostPipeline::getFrameValues()
|
||||
@@ -560,21 +567,25 @@ void FemPostPipeline::load(FemResultObject* res)
|
||||
// set multiple result objects as frames for one pipeline
|
||||
// Notes:
|
||||
// 1. values vector must contain growing value, smallest first
|
||||
void FemPostPipeline::load(std::vector<FemResultObject*> res, std::vector<double> values, Base::Unit unit, std::string frame_type) {
|
||||
void FemPostPipeline::load(std::vector<FemResultObject*> res,
|
||||
std::vector<double> values,
|
||||
Base::Unit unit,
|
||||
std::string frame_type)
|
||||
{
|
||||
|
||||
if (res.size() != values.size() ) {
|
||||
if (res.size() != values.size()) {
|
||||
Base::Console().Error("Result values and frame values have different length.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// setup the time information for the multiblock
|
||||
// setup the time information for the multiblock
|
||||
vtkStringArray* TimeInfo = vtkStringArray::New();
|
||||
TimeInfo->SetName("TimeInfo");
|
||||
TimeInfo->InsertNextValue(frame_type);
|
||||
TimeInfo->InsertNextValue(unit.getString().toStdString());
|
||||
TimeInfo->InsertNextValue(unit.getString());
|
||||
|
||||
auto multiblock = vtkSmartPointer<vtkMultiBlockDataSet>::New();
|
||||
for (ulong i=0; i<res.size(); i++) {
|
||||
for (ulong i = 0; i < res.size(); i++) {
|
||||
|
||||
if (!res[i]->Mesh.getValue()->isDerivedFrom(Fem::FemMeshObject::getClassTypeId())) {
|
||||
Base::Console().Error("Result mesh object is not derived from Fem::FemMeshObject.\n");
|
||||
@@ -582,7 +593,8 @@ void FemPostPipeline::load(std::vector<FemResultObject*> res, std::vector<double
|
||||
}
|
||||
|
||||
// first copy the mesh over
|
||||
const FemMesh& mesh = static_cast<FemMeshObject*>(res[i]->Mesh.getValue())->FemMesh.getValue();
|
||||
const FemMesh& mesh =
|
||||
static_cast<FemMeshObject*>(res[i]->Mesh.getValue())->FemMesh.getValue();
|
||||
vtkSmartPointer<vtkUnstructuredGrid> grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
|
||||
FemVTKTools::exportVTKMesh(&mesh, grid);
|
||||
|
||||
@@ -604,6 +616,49 @@ void FemPostPipeline::load(std::vector<FemResultObject*> res, std::vector<double
|
||||
Data.setValue(multiblock);
|
||||
}
|
||||
|
||||
void FemPostPipeline::handleChangedPropertyName(Base::XMLReader& reader,
|
||||
const char* typeName,
|
||||
const char* propName)
|
||||
{
|
||||
if (strcmp(propName, "Filter") == 0
|
||||
&& Base::Type::fromName(typeName) == App::PropertyLinkList::getClassTypeId()) {
|
||||
|
||||
// add the formerly filter values to the group
|
||||
App::PropertyLinkList filter;
|
||||
filter.setContainer(this);
|
||||
filter.Restore(reader);
|
||||
auto group_filter = filter.getValues();
|
||||
auto group = Group.getValues();
|
||||
group.insert(group.end(), group_filter.begin(), group_filter.end());
|
||||
Group.setValues(group);
|
||||
}
|
||||
else if (strcmp(propName, "Functions") == 0
|
||||
&& Base::Type::fromName(typeName) == App::PropertyLink::getClassTypeId()) {
|
||||
|
||||
// add the formerly Functions values to the group
|
||||
App::PropertyLink functions;
|
||||
functions.setContainer(this);
|
||||
functions.Restore(reader);
|
||||
if (functions.getValue()) {
|
||||
auto group = Group.getValues();
|
||||
group.push_back(functions.getValue());
|
||||
Group.setValues(group);
|
||||
}
|
||||
}
|
||||
else {
|
||||
FemPostObject::handleChangedPropertyName(reader, typeName, propName);
|
||||
}
|
||||
}
|
||||
|
||||
void FemPostPipeline::onDocumentRestored()
|
||||
{
|
||||
// if a old document was loaded with "custom" mode setting, the current value
|
||||
// would be out of range. Reset it to "serial"
|
||||
if (Mode.getValue() > 1 || Mode.getValue() < 0) {
|
||||
Mode.setValue(long(0));
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* FemPostPipeline::getPyObject()
|
||||
{
|
||||
if (PythonObject.is(Py::_None())) {
|
||||
|
||||
@@ -110,6 +110,10 @@ protected:
|
||||
void onChanged(const App::Property* prop) override;
|
||||
bool allowObject(App::DocumentObject* obj) override;
|
||||
|
||||
// update documents
|
||||
void handleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName) override;
|
||||
void onDocumentRestored() override;
|
||||
|
||||
private:
|
||||
App::Enumeration m_frameEnum;
|
||||
vtkSmartPointer<FemFrameSourceAlgorithm> m_source_algorithm;
|
||||
|
||||
@@ -28,6 +28,11 @@
|
||||
<UserDocu>Load a single result object or create a multiframe result by loading multiple result frames. If multistep is wanted, 4 argumenhts are needed: 1. List of result object each being one frame, 2. List of values valid for each frame (e.g. [s] if time data), 3. the unit of the value, 4. the Description of the frames</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getFilter">
|
||||
<Documentation>
|
||||
<UserDocu>Returns all filters, that this pipeline uses (non recursive, result does not contain branch child filters)</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="recomputeChildren">
|
||||
<Documentation>
|
||||
<UserDocu>Recomputes all children of the pipeline</UserDocu>
|
||||
|
||||
@@ -150,6 +150,22 @@ PyObject* FemPostPipelinePy::load(PyObject* args)
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
|
||||
PyObject* FemPostPipelinePy::getFilter(PyObject* args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto filters = getFemPostPipelinePtr()->getFilter();
|
||||
Py::List sequence;
|
||||
for (auto filter : filters) {
|
||||
sequence.append(Py::asObject(filter->getPyObject()));
|
||||
}
|
||||
|
||||
return Py::new_reference_to(sequence);
|
||||
}
|
||||
|
||||
PyObject* FemPostPipelinePy::recomputeChildren(PyObject* args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) {
|
||||
|
||||
@@ -481,10 +481,8 @@ void TaskPostFunction::applyPythonCode()
|
||||
// ***************************************************************************
|
||||
// Frames
|
||||
TaskPostFrames::TaskPostFrames(ViewProviderFemPostObject* view, QWidget* parent)
|
||||
: TaskPostBox(view,
|
||||
Gui::BitmapFactory().pixmap("FEM_PostFrames"),
|
||||
tr("Result Frames"),
|
||||
parent), ui(new Ui_TaskPostFrames)
|
||||
: TaskPostBox(view, Gui::BitmapFactory().pixmap("FEM_PostFrames"), tr("Result Frames"), parent)
|
||||
, ui(new Ui_TaskPostFrames)
|
||||
{
|
||||
// we load the views widget
|
||||
proxy = new QWidget(this);
|
||||
@@ -498,12 +496,13 @@ TaskPostFrames::TaskPostFrames(ViewProviderFemPostObject* view, QWidget* parent)
|
||||
|
||||
auto unit = pipeline->getFrameUnit();
|
||||
auto steps = pipeline->getFrameValues();
|
||||
for (unsigned long i=0; i<steps.size(); i++) {
|
||||
QTableWidgetItem *idx = new QTableWidgetItem(QString::number(i));
|
||||
QTableWidgetItem *value = new QTableWidgetItem(Base::Quantity(steps[i], unit).getUserString());
|
||||
for (unsigned long i = 0; i < steps.size(); i++) {
|
||||
QTableWidgetItem* idx = new QTableWidgetItem(QString::number(i));
|
||||
QTableWidgetItem* value = new QTableWidgetItem(
|
||||
QString::fromStdString(Base::Quantity(steps[i], unit).getUserString()));
|
||||
|
||||
int rowIdx = ui->FrameTable->rowCount();
|
||||
ui->FrameTable->insertRow (rowIdx);
|
||||
ui->FrameTable->insertRow(rowIdx);
|
||||
ui->FrameTable->setItem(rowIdx, 0, idx);
|
||||
ui->FrameTable->setItem(rowIdx, 1, value);
|
||||
}
|
||||
@@ -530,14 +529,12 @@ void TaskPostFrames::onSelectionChanged()
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TaskPostFrames::applyPythonCode()
|
||||
{
|
||||
// we apply the views widgets python code
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// in the following, the different filters sorted alphabetically
|
||||
// ***************************************************************************
|
||||
@@ -549,7 +546,8 @@ TaskPostBranch::TaskPostBranch(ViewProviderFemPostBranchFilter* view, QWidget* p
|
||||
: TaskPostBox(view,
|
||||
Gui::BitmapFactory().pixmap("FEM_PostBranchFilter"),
|
||||
tr("Branch behaviour"),
|
||||
parent), ui(new Ui_TaskPostBranch)
|
||||
parent)
|
||||
, ui(new Ui_TaskPostBranch)
|
||||
{
|
||||
// we load the views widget
|
||||
proxy = new QWidget(this);
|
||||
@@ -590,14 +588,12 @@ void TaskPostBranch::onOutputIndexChanged(int idx)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TaskPostBranch::applyPythonCode()
|
||||
{
|
||||
// we apply the views widgets python code
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// data along line filter
|
||||
TaskPostDataAlongLine::TaskPostDataAlongLine(ViewProviderFemPostDataAlongLine* view,
|
||||
|
||||
@@ -56,7 +56,7 @@ bool ViewProviderFemPostBranchFilter::acceptReorderingObjects() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ViewProviderFemPostBranchFilter::canDragObjectToTarget(App::DocumentObject* obj, App::DocumentObject* target) const {
|
||||
bool ViewProviderFemPostBranchFilter::canDragObjectToTarget(App::DocumentObject*, App::DocumentObject* target) const {
|
||||
|
||||
// allow drag only to other post groups
|
||||
if (target) {
|
||||
|
||||
@@ -233,7 +233,7 @@ bool ViewProviderFemPostPipeline::acceptReorderingObjects() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ViewProviderFemPostPipeline::canDragObjectToTarget(App::DocumentObject* obj, App::DocumentObject* target) const {
|
||||
bool ViewProviderFemPostPipeline::canDragObjectToTarget(App::DocumentObject*, App::DocumentObject* target) const {
|
||||
|
||||
// allow drag only to other post groups
|
||||
if (target) {
|
||||
|
||||
@@ -51,6 +51,10 @@ public:
|
||||
void scaleField(vtkDataSet* dset, vtkDataArray* pdata, double FieldFactor);
|
||||
PyObject* getPyObject() override;
|
||||
|
||||
// override, to not show/hide children as the parent is shown/hidden like normal groups
|
||||
void extensionHide() override {};
|
||||
void extensionShow() override {};
|
||||
|
||||
protected:
|
||||
void updateFunctionSize();
|
||||
virtual void setupTaskDialog(TaskDlgPost* dlg) override;
|
||||
|
||||
@@ -71,10 +71,7 @@ def purge_results(analysis):
|
||||
# result pipeline and filter
|
||||
for m in analysis.Group:
|
||||
if is_of_type(m, "Fem::FemPostPipeline"):
|
||||
# delete associated filters
|
||||
for filter_obj in m.Filter:
|
||||
analysis.Document.removeObject(filter_obj.Name)
|
||||
# delete the pipeline itself
|
||||
# delete the pipeline itself (it removes all fiters itself)
|
||||
analysis.Document.removeObject(m.Name)
|
||||
analysis.Document.recompute()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user