diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp index 86506dd53f..79dd39ac29 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp @@ -37,6 +37,7 @@ # include # include +# include # include # include @@ -623,13 +624,24 @@ void ViewProviderFemPostObject::updateData(const App::Property* p) { } } -bool ViewProviderFemPostObject::setupPipeline() { - +bool ViewProviderFemPostObject::setupPipeline() +{ vtkDataObject* data = static_cast(getObject())->Data.getValue(); if (!data) return false; + // check all fields if there is a real/imaginary one and if so + // add a field with an absolute value + vtkSmartPointer SPdata = data; + vtkDataSet* dset = vtkDataSet::SafeDownCast(SPdata); + std::string FieldName; + auto numFields = dset->GetPointData()->GetNumberOfArrays(); + for (int i = 0; i < numFields; ++i) { + FieldName = std::string(dset->GetPointData()->GetArrayName(i)); + addAbsoluteField(dset, FieldName); + } + m_outline->SetInputData(data); m_surface->SetInputData(data); m_wireframe->SetInputData(data); @@ -638,7 +650,6 @@ bool ViewProviderFemPostObject::setupPipeline() { return true; } - void ViewProviderFemPostObject::onChanged(const App::Property* prop) { if (m_blockPropertyChanges) @@ -685,7 +696,6 @@ bool ViewProviderFemPostObject::doubleClicked() { return true; } - bool ViewProviderFemPostObject::setEdit(int ModNum) { if (ModNum == ViewProvider::Default || ModNum == 1) { @@ -842,3 +852,70 @@ void ViewProviderFemPostObject::onSelectionChanged(const Gui::SelectionChanges & updateMaterial(); } } + +// if there is a real and an imaginary field, an absolute field is added +void ViewProviderFemPostObject::addAbsoluteField(vtkDataSet* dset, std::string FieldName) +{ + // real field names have the suffix " re", given by Elmer + // if the field does not have this suffix, we can return + auto suffix = FieldName.substr(FieldName.size() - 3, FieldName.size() - 1); + if (strcmp(suffix.c_str(), " re") != 0) + return; + + // absolute fields might have already been created, then do nothing + auto strAbsoluteFieldName = FieldName.substr(0, FieldName.size() - 2) + "abs"; + vtkDataArray* testArray = dset->GetPointData()->GetArray(strAbsoluteFieldName.c_str()); + if (testArray) + return; + + // safety check + vtkDataArray* realDdata = dset->GetPointData()->GetArray(FieldName.c_str()); + if (!realDdata) + return; + + // now check if the imaginary counterpart exists + auto strImaginaryFieldName = FieldName.substr(0, FieldName.size() - 2) + "im"; + vtkDataArray* imagDdata = dset->GetPointData()->GetArray(strImaginaryFieldName.c_str()); + if (!imagDdata) + return; + + // create a new array and copy over the real data + // since one cannot directly access the values of a vtkDataSet + // we need to copy them over in a loop + vtkSmartPointer absoluteData = vtkSmartPointer::New(); + absoluteData->SetNumberOfComponents(realDdata->GetNumberOfComponents()); + auto numTuples = realDdata->GetNumberOfTuples(); + absoluteData->SetNumberOfTuples(numTuples); + double tuple[] = {0, 0, 0}; + for (vtkIdType i = 0; i < numTuples; ++i) { + absoluteData->SetTuple(i, tuple); + } + // name the array + auto strAbsFieldName = FieldName.substr(0, FieldName.size() - 2) + "abs"; + absoluteData->SetName(strAbsFieldName.c_str()); + + // add array to data set + dset->GetPointData()->AddArray(absoluteData); + + // step through all mesh points and calculate them + double realValue = 0; + double imaginaryValue = 0; + double absoluteValue = 0; + for (int i = 0; i < dset->GetNumberOfPoints(); ++i) { + if (absoluteData->GetNumberOfComponents() == 1) { + realValue = realDdata->GetComponent(i, 0); + imaginaryValue = imagDdata->GetComponent(i, 0); + absoluteValue = sqrt(pow(realValue, 2) + pow(imaginaryValue, 2)); + absoluteData->SetComponent(i, 0, absoluteValue); + } + // if field is a vector + else { + for (int j = 0; j < absoluteData->GetNumberOfComponents(); ++j) { + realValue = realDdata->GetComponent(i, j); + imaginaryValue = imagDdata->GetComponent(i, j); + absoluteValue = sqrt(pow(realValue, 2) + pow(imaginaryValue, 2)); + absoluteData->SetComponent(i, j, absoluteValue); + } + } + } +} diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostObject.h b/src/Mod/Fem/Gui/ViewProviderFemPostObject.h index c573ebd7c2..15b56fce5d 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostObject.h +++ b/src/Mod/Fem/Gui/ViewProviderFemPostObject.h @@ -103,7 +103,7 @@ public: // handling when object is deleted bool onDelete(const std::vector&) override; bool canDelete(App::DocumentObject* obj) const override; - virtual void onSelectionChanged(const Gui::SelectionChanges &sel); + virtual void onSelectionChanged(const Gui::SelectionChanges& sel); /** @name Selection handling * This group of methods do the selection handling. @@ -156,6 +156,7 @@ private: vtkDataArray *tcoords); void WriteColorData(bool ResetColorBarRange); void WriteTransparency(); + void addAbsoluteField(vtkDataSet* dset, std::string FieldName); App::Enumeration m_coloringEnum, m_vectorEnum; bool m_blockPropertyChanges;