Fem: Remove dependency of the ViewProviderFemPostObject class on user parameters

This commit is contained in:
marioalexis
2025-09-10 13:38:38 -03:00
parent b9129f4453
commit 0c5746fe7a
7 changed files with 32 additions and 121 deletions

View File

@@ -73,10 +73,17 @@ FemPostPipeline::FemPostPipeline()
App::Prop_None,
"The frame used to calculate the data in the pipeline processing (read only, "
"set via pipeline object).");
ADD_PROPERTY_TYPE(MergeDuplicate,
(false),
"Pipeline",
App::Prop_None,
"Remove coindent elements.");
// create our source algorithm
m_source_algorithm = vtkSmartPointer<vtkFemFrameSourceAlgorithm>::New();
m_clean_filter = vtkSmartPointer<vtkCleanUnstructuredGrid>::New();
m_clean_filter->SetPointDataWeighingStrategy(vtkCleanUnstructuredGrid::AVERAGING);
m_transform_filter->SetInputConnection(m_source_algorithm->GetOutputPort(0));
}
@@ -276,6 +283,19 @@ void FemPostPipeline::onChanged(const Property* prop)
recomputeChildren();
}
if (prop == &MergeDuplicate) {
if (MergeDuplicate.getValue()) {
m_clean_filter->SetInputConnection(m_source_algorithm->GetOutputPort(0));
m_transform_filter->SetInputConnection(m_clean_filter->GetOutputPort(0));
}
else {
m_transform_filter->SetInputConnection(m_source_algorithm->GetOutputPort(0));
}
m_transform_filter->Update();
updateData();
recomputeChildren();
}
// use the correct data as source
if (prop == &Data && !m_block_property) {
m_source_algorithm->setDataObject(Data.getValue());

View File

@@ -32,6 +32,11 @@
#include "FemResultObject.h"
#include "VTKExtensions/vtkFemFrameSourceAlgorithm.h"
#if VTK_VERSION_NUMBER < VTK_VERSION_CHECK(9, 3, 0)
#include "VTKExtensions/vtkCleanUnstructuredGrid.h"
#else
#include <vtkCleanUnstructuredGrid.h>
#endif
#include <vtkSmartPointer.h>
@@ -47,7 +52,7 @@ public:
FemPostPipeline();
App::PropertyEnumeration Frame;
App::PropertyBool MergeDuplicate;
virtual vtkDataSet* getDataSet() override;
Fem::FemPostFunctionProvider* getFunctionProvider();
@@ -108,6 +113,7 @@ private:
App::Enumeration m_frameEnum;
vtkSmartPointer<vtkFemFrameSourceAlgorithm> m_source_algorithm;
vtkSmartPointer<vtkCleanUnstructuredGrid> m_clean_filter;
bool m_block_property = false;
bool m_data_updated = false;

View File

@@ -15,7 +15,7 @@
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QGroupBox" name="gb_gmsh_param">
<widget class="QGroupBox" name="gb_elmer_param">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
@@ -169,25 +169,6 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="Gui::PrefCheckBox" name="cb_filtering">
<property name="toolTip">
<string>Merge mesh volume regions processed by each CPU core to make boundaries invisible.</string>
</property>
<property name="text">
<string>Filter results</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>FilterMultiCPUResults</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/Elmer</cstring>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View File

@@ -59,7 +59,6 @@ void DlgSettingsFemElmerImp::saveSettings()
ui->sb_num_processes->onSave();
ui->cb_filtering->onSave();
ui->ckb_binary_format->onSave();
ui->ckb_geom_id->onSave();
}
@@ -71,7 +70,6 @@ void DlgSettingsFemElmerImp::loadSettings()
ui->sb_num_processes->onRestore();
ui->cb_filtering->onRestore();
ui->ckb_binary_format->onRestore();
ui->ckb_geom_id->onRestore();
}

View File

@@ -515,7 +515,6 @@ void ViewProviderFemPostObject::updateProperties()
void ViewProviderFemPostObject::update3D()
{
vtkPolyData* pd = m_currentAlgorithm->GetOutput();
vtkPointData* pntData;
@@ -802,79 +801,6 @@ void ViewProviderFemPostObject::updateData(const App::Property* p)
}
}
void ViewProviderFemPostObject::filterArtifacts(vtkDataSet* dset)
{
// The problem is that in the surface view the boundary regions of the volumes
// calculated by the different CPU cores is always visible, independent of the
// transparency setting. Elmer is not to blame because this is a property of the
// partial VTK file reader. So this can happen with various inputs
// since FreeCAD can also be used to view VTK files without the need to perform
// an analysis. Therefore it is impossible to know in advance when a filter
// is necessary or not.
// Only for pure CCX analyses we know that no filtering is necessary. However,
// the effort to catch this case is not worth it since the filtering is
// only as time-consuming as enabling the surface filter. In fact, it is like
// performing the surface filter twice.
// We need to set the filter clipping plane below the z-minimum of the data.
// We can either do this by checking the VTK data or by getting the info from
// the 3D view. We use here the latter because this is much faster.
// since we will set the filter according to the visible bounding box
// assure the object is visible
bool visibility = this->Visibility.getValue();
if (!visibility) {
this->Visibility.setValue(true);
}
m_blockPropertyChanges = true;
Gui::Document* doc = this->getDocument();
Gui::View3DInventor* view =
qobject_cast<Gui::View3DInventor*>(doc->getViewOfViewProvider(this));
if (view) {
Gui::View3DInventorViewer* viewer = view->getViewer();
SbBox3f boundingBox;
boundingBox = viewer->getBoundingBox();
if (boundingBox.hasVolume()) {
// setup
vtkSmartPointer<vtkImplicitFunction> m_implicit;
auto m_plane = vtkSmartPointer<vtkPlane>::New();
m_implicit = m_plane;
m_plane->SetNormal(0., 0., 1.);
auto extractor = vtkSmartPointer<vtkTableBasedClipDataSet>::New();
float dx, dy, dz;
boundingBox.getSize(dx, dy, dz);
// Set plane below the minimum to assure there are
// no boundary cells (touching the function) and for Warp filters
// the user might change the warp factor a lot. Thus set
// 10 times dz to be safe even for unrealistic warp deformations
m_plane->SetOrigin(0., 0., -10 * dz);
extractor->SetClipFunction(m_implicit);
extractor->SetInputData(dset);
extractor->Update();
auto extractorResult = extractor->GetOutputDataObject(0);
if (extractorResult) {
m_surface->SetInputData(extractorResult);
}
else {
m_surface->SetInputData(dset);
}
}
else {
// for the case that there are only 2D objects
m_surface->SetInputData(dset);
}
}
m_blockPropertyChanges = false;
// restore initial vsibility
if (!visibility) {
this->Visibility.setValue(visibility);
}
}
bool ViewProviderFemPostObject::setupPipeline()
{
if (m_blockPropertyChanges) {
@@ -882,9 +808,6 @@ bool ViewProviderFemPostObject::setupPipeline()
}
auto postObject = getObject<Fem::FemPostObject>();
// check all fields if there is a real/imaginary one and if so
// add a field with an absolute value
vtkDataSet* dset = postObject->getDataSet();
if (!dset) {
return false;
@@ -893,26 +816,7 @@ bool ViewProviderFemPostObject::setupPipeline()
m_outline->SetInputData(dset);
m_points->SetInputData(dset);
m_wireframe->SetInputData(dset);
// Filtering artifacts is necessary for partial VTU files (*.pvtu) independent of the
// current Elmer CPU core settings because the user might load an external file.
// It is only necessary for the surface filter.
// The problem is that when opening an existing FreeCAD file, we get no information how the
// Data of the postObject was once created. The vtkDataObject type does not provide this info.
// Therefore the only way is the hack to filter only if the used Elmer CPU cores are > 1.
auto hGrp = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Mod/Fem/Elmer");
bool FilterMultiCPUResults = hGrp->GetBool("FilterMultiCPUResults", true);
int UseNumberOfCores = hGrp->GetInt("UseNumberOfCores", 1);
// filtering is only necessary for pipelines and warp filters
if (FilterMultiCPUResults && (UseNumberOfCores > 1)
&& ((postObject->getTypeId() == Base::Type::fromName("Fem::FemPostPipeline"))
|| (postObject->getTypeId() == Base::Type::fromName("Fem::FemPostWarpVectorFilter")))) {
filterArtifacts(dset);
}
else {
m_surface->SetInputData(dset);
}
m_surface->SetInputData(dset);
return true;
}

View File

@@ -155,7 +155,6 @@ protected:
vtkSmartPointer<vtkVertexGlyphFilter> m_points, m_pointsSurface;
private:
void filterArtifacts(vtkDataSet* data);
void updateProperties();
void update3D();
void WritePointData(vtkPoints* points, vtkDataArray* normals, vtkDataArray* tcoords);

View File

@@ -63,6 +63,9 @@ void ViewProviderFemPostPipeline::updateData(const App::Property* prop)
updateFunctionSize();
updateColorBars();
}
else if (prop == &pipeline->MergeDuplicate) {
updateVtk();
}
}
void ViewProviderFemPostPipeline::updateFunctionSize()