Fem: Add smoothing filter extension to contours filter (#18088)
* Fem: Add smoothing filter extension to contours filter
This commit is contained in:
@@ -181,6 +181,8 @@ PyMOD_INIT_FUNC(Fem)
|
||||
Fem::FemSolverObjectPython ::init();
|
||||
|
||||
#ifdef FC_USE_VTK
|
||||
Fem::FemPostSmoothFilterExtension ::init();
|
||||
|
||||
Fem::FemPostObject ::init();
|
||||
Fem::FemPostPipeline ::init();
|
||||
Fem::FemPostFilter ::init();
|
||||
|
||||
@@ -515,6 +515,104 @@ DocumentObjectExecReturn* FemPostClipFilter::execute()
|
||||
return Fem::FemPostFilter::execute();
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// smoothing filter extension
|
||||
const App::PropertyQuantityConstraint::Constraints FemPostSmoothFilterExtension::angleRange = {
|
||||
0.0,
|
||||
180.0,
|
||||
1.0};
|
||||
const App::PropertyIntegerConstraint::Constraints FemPostSmoothFilterExtension::iterationRange = {
|
||||
0,
|
||||
VTK_INT_MAX,
|
||||
1};
|
||||
const App::PropertyFloatConstraint::Constraints FemPostSmoothFilterExtension::relaxationRange = {
|
||||
0,
|
||||
1.0,
|
||||
0.01};
|
||||
|
||||
EXTENSION_PROPERTY_SOURCE(Fem::FemPostSmoothFilterExtension, App::DocumentObjectExtension)
|
||||
|
||||
FemPostSmoothFilterExtension::FemPostSmoothFilterExtension()
|
||||
{
|
||||
EXTENSION_ADD_PROPERTY_TYPE(BoundarySmoothing,
|
||||
(true),
|
||||
"Smoothing",
|
||||
App::Prop_None,
|
||||
"Smooth vertices on the boundary");
|
||||
EXTENSION_ADD_PROPERTY_TYPE(EdgeAngle,
|
||||
(15),
|
||||
"Smoothing",
|
||||
App::Prop_None,
|
||||
"Angle to control smoothing along edges");
|
||||
EXTENSION_ADD_PROPERTY_TYPE(EnableSmoothing,
|
||||
(false),
|
||||
"Smoothing",
|
||||
App::Prop_None,
|
||||
"Enable Laplacian smoothing");
|
||||
EXTENSION_ADD_PROPERTY_TYPE(FeatureAngle,
|
||||
(45),
|
||||
"Smoothing",
|
||||
App::Prop_None,
|
||||
"Angle for sharp edge identification");
|
||||
EXTENSION_ADD_PROPERTY_TYPE(EdgeSmoothing,
|
||||
(false),
|
||||
"Smoothing",
|
||||
App::Prop_None,
|
||||
"Smooth align sharp interior edges");
|
||||
EXTENSION_ADD_PROPERTY_TYPE(RelaxationFactor,
|
||||
(0.05),
|
||||
"Smoothing",
|
||||
App::Prop_None,
|
||||
"Factor to control vertex displacement");
|
||||
EXTENSION_ADD_PROPERTY_TYPE(Iterations,
|
||||
(20),
|
||||
"Smoothing",
|
||||
App::Prop_None,
|
||||
"Number of smoothing iterations");
|
||||
|
||||
EdgeAngle.setConstraints(&angleRange);
|
||||
FeatureAngle.setConstraints(&angleRange);
|
||||
Iterations.setConstraints(&iterationRange);
|
||||
RelaxationFactor.setConstraints(&relaxationRange);
|
||||
|
||||
m_smooth = vtkSmartPointer<vtkSmoothPolyDataFilter>::New();
|
||||
// override default VTK values
|
||||
m_smooth->SetNumberOfIterations(EnableSmoothing.getValue() ? Iterations.getValue() : 0);
|
||||
m_smooth->SetBoundarySmoothing(BoundarySmoothing.getValue());
|
||||
m_smooth->SetEdgeAngle(EdgeAngle.getValue());
|
||||
m_smooth->SetFeatureAngle(FeatureAngle.getValue());
|
||||
m_smooth->SetFeatureEdgeSmoothing(EdgeSmoothing.getValue());
|
||||
m_smooth->SetRelaxationFactor(RelaxationFactor.getValue());
|
||||
|
||||
initExtensionType(FemPostSmoothFilterExtension::getExtensionClassTypeId());
|
||||
}
|
||||
|
||||
void FemPostSmoothFilterExtension::extensionOnChanged(const App::Property* prop)
|
||||
{
|
||||
if (prop == &EnableSmoothing || prop == &Iterations) {
|
||||
// if disabled, set iterations to zero to do nothing
|
||||
m_smooth->SetNumberOfIterations(EnableSmoothing.getValue() ? Iterations.getValue() : 0);
|
||||
}
|
||||
else if (prop == &BoundarySmoothing) {
|
||||
m_smooth->SetBoundarySmoothing(static_cast<const App::PropertyBool*>(prop)->getValue());
|
||||
}
|
||||
else if (prop == &EdgeAngle) {
|
||||
m_smooth->SetEdgeAngle(static_cast<const App::PropertyAngle*>(prop)->getValue());
|
||||
}
|
||||
else if (prop == &FeatureAngle) {
|
||||
m_smooth->SetFeatureAngle(static_cast<const App::PropertyAngle*>(prop)->getValue());
|
||||
}
|
||||
else if (prop == &EdgeSmoothing) {
|
||||
m_smooth->SetFeatureEdgeSmoothing(static_cast<const App::PropertyBool*>(prop)->getValue());
|
||||
}
|
||||
else if (prop == &RelaxationFactor) {
|
||||
m_smooth->SetRelaxationFactor(static_cast<const App::PropertyFloat*>(prop)->getValue());
|
||||
}
|
||||
else {
|
||||
DocumentObjectExtension::extensionOnChanged(prop);
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// contours filter
|
||||
PROPERTY_SOURCE(Fem::FemPostContoursFilter, Fem::FemPostFilter)
|
||||
@@ -543,10 +641,13 @@ FemPostContoursFilter::FemPostContoursFilter()
|
||||
FilterPipeline contours;
|
||||
m_contours = vtkSmartPointer<vtkContourFilter>::New();
|
||||
m_contours->ComputeScalarsOn();
|
||||
smoothExtension.getFilter()->SetInputConnection(m_contours->GetOutputPort());
|
||||
contours.source = m_contours;
|
||||
contours.target = m_contours;
|
||||
contours.target = smoothExtension.getFilter();
|
||||
addFilterPipeline(contours, "contours");
|
||||
setActiveFilterPipeline("contours");
|
||||
|
||||
smoothExtension.initExtension(this);
|
||||
}
|
||||
|
||||
FemPostContoursFilter::~FemPostContoursFilter() = default;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define Fem_FemPostFilter_H
|
||||
|
||||
#include <vtkContourFilter.h>
|
||||
#include <vtkSmoothPolyDataFilter.h>
|
||||
#include <vtkCutter.h>
|
||||
#include <vtkExtractGeometry.h>
|
||||
#include <vtkExtractVectorComponents.h>
|
||||
@@ -36,6 +37,7 @@
|
||||
#include <vtkWarpVector.h>
|
||||
|
||||
#include <App/PropertyUnits.h>
|
||||
#include <App/DocumentObjectExtension.h>
|
||||
|
||||
#include "FemPostObject.h"
|
||||
|
||||
@@ -77,6 +79,37 @@ private:
|
||||
std::string m_activePipeline;
|
||||
};
|
||||
|
||||
class FemExport FemPostSmoothFilterExtension: public App::DocumentObjectExtension
|
||||
{
|
||||
EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(Fem::FemPostSmoothFilterExtension);
|
||||
|
||||
public:
|
||||
FemPostSmoothFilterExtension();
|
||||
~FemPostSmoothFilterExtension() override = default;
|
||||
|
||||
App::PropertyBool BoundarySmoothing;
|
||||
App::PropertyAngle EdgeAngle;
|
||||
App::PropertyBool EdgeSmoothing;
|
||||
App::PropertyBool EnableSmoothing;
|
||||
App::PropertyAngle FeatureAngle;
|
||||
App::PropertyIntegerConstraint Iterations;
|
||||
App::PropertyFloatConstraint RelaxationFactor;
|
||||
|
||||
vtkSmartPointer<vtkSmoothPolyDataFilter> getFilter() const
|
||||
{
|
||||
return m_smooth;
|
||||
}
|
||||
|
||||
protected:
|
||||
void extensionOnChanged(const App::Property* prop) override;
|
||||
|
||||
private:
|
||||
vtkSmartPointer<vtkSmoothPolyDataFilter> m_smooth;
|
||||
static const App::PropertyQuantityConstraint::Constraints angleRange;
|
||||
static const App::PropertyIntegerConstraint::Constraints iterationRange;
|
||||
static const App::PropertyFloatConstraint::Constraints relaxationRange;
|
||||
};
|
||||
|
||||
// ***************************************************************************
|
||||
// in the following, the different filters sorted alphabetically
|
||||
// ***************************************************************************
|
||||
@@ -210,11 +243,14 @@ public:
|
||||
protected:
|
||||
App::DocumentObjectExecReturn* execute() override;
|
||||
void onChanged(const App::Property* prop) override;
|
||||
|
||||
void recalculateContours(double min, double max);
|
||||
void refreshFields();
|
||||
void refreshVectors();
|
||||
bool m_blockPropertyChanges = false;
|
||||
|
||||
std::string contourFieldName;
|
||||
FemPostSmoothFilterExtension smoothExtension;
|
||||
|
||||
private:
|
||||
vtkSmartPointer<vtkContourFilter> m_contours;
|
||||
|
||||
@@ -1437,19 +1437,25 @@ TaskPostContours::TaskPostContours(ViewProviderFemPostContours* view, QWidget* p
|
||||
QMetaObject::connectSlotsByName(this);
|
||||
this->groupLayout()->addWidget(proxy);
|
||||
|
||||
auto obj = getObject<Fem::FemPostContoursFilter>();
|
||||
|
||||
// load filter settings
|
||||
updateEnumerationList(getTypedObject<Fem::FemPostContoursFilter>()->Field, ui->fieldsCB);
|
||||
updateEnumerationList(getTypedObject<Fem::FemPostContoursFilter>()->VectorMode, ui->vectorsCB);
|
||||
updateEnumerationList(obj->Field, ui->fieldsCB);
|
||||
updateEnumerationList(obj->VectorMode, ui->vectorsCB);
|
||||
// for a new filter, initialize the coloring
|
||||
auto colorState = getObject<Fem::FemPostContoursFilter>()->NoColor.getValue();
|
||||
auto colorState = obj->NoColor.getValue();
|
||||
if (!colorState && getTypedView<ViewProviderFemPostObject>()->Field.getValue() == 0) {
|
||||
getTypedView<ViewProviderFemPostObject>()->Field.setValue(1);
|
||||
}
|
||||
|
||||
ui->numberContoursSB->setValue(
|
||||
getObject<Fem::FemPostContoursFilter>()->NumberOfContours.getValue());
|
||||
ui->numberContoursSB->setValue(obj->NumberOfContours.getValue());
|
||||
ui->noColorCB->setChecked(colorState);
|
||||
|
||||
auto ext = obj->getExtension<Fem::FemPostSmoothFilterExtension>();
|
||||
ui->ckb_smoothing->setChecked(ext->EnableSmoothing.getValue());
|
||||
ui->dsb_relaxation->setValue(ext->RelaxationFactor.getValue());
|
||||
ui->dsb_relaxation->setEnabled(ext->EnableSmoothing.getValue());
|
||||
|
||||
// connect
|
||||
connect(ui->fieldsCB,
|
||||
qOverload<int>(&QComboBox::currentIndexChanged),
|
||||
@@ -1464,6 +1470,11 @@ TaskPostContours::TaskPostContours(ViewProviderFemPostContours* view, QWidget* p
|
||||
this,
|
||||
&TaskPostContours::onNumberOfContoursChanged);
|
||||
connect(ui->noColorCB, &QCheckBox::toggled, this, &TaskPostContours::onNoColorChanged);
|
||||
connect(ui->ckb_smoothing, &QCheckBox::toggled, this, &TaskPostContours::onSmoothingChanged);
|
||||
connect(ui->dsb_relaxation,
|
||||
qOverload<double>(&QDoubleSpinBox::valueChanged),
|
||||
this,
|
||||
&TaskPostContours::onRelaxationChanged);
|
||||
}
|
||||
|
||||
TaskPostContours::~TaskPostContours() = default;
|
||||
@@ -1549,6 +1560,22 @@ void TaskPostContours::onNoColorChanged(bool state)
|
||||
recompute();
|
||||
}
|
||||
|
||||
void TaskPostContours::onSmoothingChanged(bool state)
|
||||
{
|
||||
auto ext = static_cast<Fem::FemPostContoursFilter*>(getObject())
|
||||
->getExtension<Fem::FemPostSmoothFilterExtension>();
|
||||
ext->EnableSmoothing.setValue(state);
|
||||
ui->dsb_relaxation->setEnabled(state);
|
||||
recompute();
|
||||
}
|
||||
|
||||
void TaskPostContours::onRelaxationChanged(double value)
|
||||
{
|
||||
auto ext = static_cast<Fem::FemPostContoursFilter*>(getObject())
|
||||
->getExtension<Fem::FemPostSmoothFilterExtension>();
|
||||
ext->RelaxationFactor.setValue(value);
|
||||
recompute();
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// cut filter
|
||||
|
||||
@@ -412,6 +412,8 @@ private:
|
||||
void onVectorModeChanged(int idx);
|
||||
void onNumberOfContoursChanged(int number);
|
||||
void onNoColorChanged(bool state);
|
||||
void onSmoothingChanged(bool state);
|
||||
void onRelaxationChanged(double v);
|
||||
|
||||
private:
|
||||
QWidget* proxy;
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
<set>Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="keyboardTracking">
|
||||
<bool>false</bool>
|
||||
@@ -71,18 +71,54 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="ckb_smoothing">
|
||||
<property name="toolTip">
|
||||
<string>Enable Laplacian smoothing</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Smoothing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="lbl_relaxation">
|
||||
<property name="text">
|
||||
<string notr="true">Relaxation Factor:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QDoubleSpinBox" name="dsb_relaxation">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Factor to control vertex displacement</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.00000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.00000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.01000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="noColorCB">
|
||||
<property name="toolTip">
|
||||
<string>Contour lines will not be colored</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No Color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="noColorCB">
|
||||
<property name="toolTip">
|
||||
<string>Contour lines will not be colored</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
||||
Reference in New Issue
Block a user