Fem: Add calculator filter
This commit is contained in:
@@ -189,6 +189,7 @@ PyMOD_INIT_FUNC(Fem)
|
||||
Fem::FemPostPipeline ::init();
|
||||
Fem::FemPostFilter ::init();
|
||||
Fem::FemPostBranchFilter ::init();
|
||||
Fem::FemPostCalculatorFilter ::init();
|
||||
Fem::FemPostClipFilter ::init();
|
||||
Fem::FemPostContoursFilter ::init();
|
||||
Fem::FemPostCutFilter ::init();
|
||||
|
||||
@@ -1297,3 +1297,132 @@ short int FemPostWarpVectorFilter::mustExecute() const
|
||||
return App::DocumentObject::mustExecute();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// calculator filter
|
||||
PROPERTY_SOURCE(Fem::FemPostCalculatorFilter, Fem::FemPostFilter)
|
||||
|
||||
FemPostCalculatorFilter::FemPostCalculatorFilter()
|
||||
: FemPostFilter()
|
||||
{
|
||||
ADD_PROPERTY_TYPE(FieldName,
|
||||
("Calculator"),
|
||||
"Calculator",
|
||||
App::Prop_None,
|
||||
"Name of the calculated field");
|
||||
ADD_PROPERTY_TYPE(Function,
|
||||
(""),
|
||||
"Calculator",
|
||||
App::Prop_None,
|
||||
"Expression of the unction to evaluate");
|
||||
ADD_PROPERTY_TYPE(ReplacementValue,
|
||||
(0.0f),
|
||||
"Calculator",
|
||||
App::Prop_None,
|
||||
"Value used to replace invalid operations");
|
||||
ADD_PROPERTY_TYPE(ReplaceInvalid,
|
||||
(false),
|
||||
"Calculator",
|
||||
App::Prop_None,
|
||||
"Replace invalid values");
|
||||
|
||||
FilterPipeline calculator;
|
||||
m_calculator = vtkSmartPointer<vtkArrayCalculator>::New();
|
||||
m_calculator->SetResultArrayName(FieldName.getValue());
|
||||
calculator.source = m_calculator;
|
||||
calculator.target = m_calculator;
|
||||
addFilterPipeline(calculator, "calculator");
|
||||
setActiveFilterPipeline("calculator");
|
||||
}
|
||||
|
||||
FemPostCalculatorFilter::~FemPostCalculatorFilter() = default;
|
||||
|
||||
DocumentObjectExecReturn* FemPostCalculatorFilter::execute()
|
||||
{
|
||||
updateAvailableFields();
|
||||
|
||||
return FemPostFilter::execute();
|
||||
}
|
||||
|
||||
void FemPostCalculatorFilter::onChanged(const Property* prop)
|
||||
{
|
||||
if (prop == &Function) {
|
||||
m_calculator->SetFunction(Function.getValue());
|
||||
}
|
||||
else if (prop == &FieldName) {
|
||||
m_calculator->SetResultArrayName(FieldName.getValue());
|
||||
}
|
||||
else if (prop == &ReplaceInvalid) {
|
||||
m_calculator->SetReplaceInvalidValues(ReplaceInvalid.getValue());
|
||||
}
|
||||
else if (prop == &ReplacementValue) {
|
||||
m_calculator->SetReplacementValue(ReplacementValue.getValue());
|
||||
}
|
||||
else if (prop == &Data) {
|
||||
updateAvailableFields();
|
||||
}
|
||||
Fem::FemPostFilter::onChanged(prop);
|
||||
}
|
||||
|
||||
short int FemPostCalculatorFilter::mustExecute() const
|
||||
{
|
||||
if (Function.isTouched() || FieldName.isTouched()) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return FemPostFilter::mustExecute();
|
||||
}
|
||||
}
|
||||
|
||||
void FemPostCalculatorFilter::updateAvailableFields()
|
||||
{
|
||||
// clear all variables
|
||||
m_calculator->RemoveAllVariables();
|
||||
m_calculator->AddCoordinateScalarVariable("coordsX", 0);
|
||||
m_calculator->AddCoordinateScalarVariable("coordsY", 1);
|
||||
m_calculator->AddCoordinateScalarVariable("coordsZ", 2);
|
||||
m_calculator->AddCoordinateVectorVariable("coords");
|
||||
|
||||
std::vector<std::string> scalars;
|
||||
std::vector<std::string> vectors;
|
||||
// std::vector<std::string> tensors;
|
||||
|
||||
vtkSmartPointer<vtkDataObject> data = getInputData();
|
||||
vtkDataSet* dset = vtkDataSet::SafeDownCast(data);
|
||||
if (!dset) {
|
||||
return;
|
||||
}
|
||||
vtkPointData* pd = dset->GetPointData();
|
||||
|
||||
// get all vector fields
|
||||
for (int i = 0; i < pd->GetNumberOfArrays(); ++i) {
|
||||
std::string name1 = pd->GetArrayName(i);
|
||||
std::string name2 = name1;
|
||||
std::replace(name2.begin(), name2.end(), ' ', '_');
|
||||
if (pd->GetArray(i)->GetNumberOfComponents() == 3) {
|
||||
m_calculator->AddVectorVariable(name2.c_str(), name1.c_str());
|
||||
// add components as scalar variable
|
||||
m_calculator->AddScalarVariable((name2 + "_X").c_str(), name1.c_str(), 0);
|
||||
m_calculator->AddScalarVariable((name2 + "_Y").c_str(), name1.c_str(), 1);
|
||||
m_calculator->AddScalarVariable((name2 + "_Z").c_str(), name1.c_str(), 2);
|
||||
}
|
||||
else if (pd->GetArray(i)->GetNumberOfComponents() == 1) {
|
||||
m_calculator->AddScalarVariable(name2.c_str(), name1.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<std::string> FemPostCalculatorFilter::getScalarVariables()
|
||||
{
|
||||
std::vector<std::string> scalars = m_calculator->GetScalarVariableNames();
|
||||
scalars.insert(scalars.begin(), {"coordsX", "coordsY", "coordsZ"});
|
||||
return scalars;
|
||||
}
|
||||
|
||||
const std::vector<std::string> FemPostCalculatorFilter::getVectorVariables()
|
||||
{
|
||||
std::vector<std::string> vectors = m_calculator->GetVectorVariableNames();
|
||||
vectors.insert(vectors.begin(), "coords");
|
||||
return vectors;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#ifndef Fem_FemPostFilter_H
|
||||
#define Fem_FemPostFilter_H
|
||||
|
||||
#include <vtkArrayCalculator.h>
|
||||
#include <vtkContourFilter.h>
|
||||
#include <vtkSmoothPolyDataFilter.h>
|
||||
#include <vtkCutter.h>
|
||||
@@ -372,6 +373,41 @@ private:
|
||||
App::Enumeration m_vectorFields;
|
||||
};
|
||||
|
||||
// ***************************************************************************
|
||||
// calculator filter
|
||||
class FemExport FemPostCalculatorFilter: public FemPostFilter
|
||||
{
|
||||
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(Fem::FemPostCalculatorFilter);
|
||||
|
||||
public:
|
||||
FemPostCalculatorFilter();
|
||||
~FemPostCalculatorFilter() override;
|
||||
|
||||
App::PropertyString FieldName;
|
||||
App::PropertyString Function;
|
||||
App::PropertyFloat ReplacementValue;
|
||||
App::PropertyBool ReplaceInvalid;
|
||||
|
||||
const char* getViewProviderName() const override
|
||||
{
|
||||
return "FemGui::ViewProviderFemPostCalculator";
|
||||
}
|
||||
short int mustExecute() const override;
|
||||
|
||||
const std::vector<std::string> getScalarVariables();
|
||||
const std::vector<std::string> getVectorVariables();
|
||||
|
||||
protected:
|
||||
App::DocumentObjectExecReturn* execute() override;
|
||||
void onChanged(const App::Property* prop) override;
|
||||
|
||||
void updateAvailableFields();
|
||||
|
||||
private:
|
||||
vtkSmartPointer<vtkArrayCalculator> m_calculator;
|
||||
};
|
||||
|
||||
} // namespace Fem
|
||||
|
||||
|
||||
|
||||
@@ -155,6 +155,7 @@
|
||||
// VTK
|
||||
#include <vtkAlgorithmOutput.h>
|
||||
#include <vtkAppendFilter.h>
|
||||
#include <vtkArrayCalculator.h>
|
||||
#include <vtkCellArray.h>
|
||||
#include <vtkCompositeDataSet.h>
|
||||
#include <vtkDataArray.h>
|
||||
|
||||
@@ -162,6 +162,7 @@ PyMOD_INIT_FUNC(FemGui)
|
||||
FemGui::ViewProviderFemPostObject ::init();
|
||||
FemGui::ViewProviderFemPostPipeline ::init();
|
||||
FemGui::ViewProviderFemPostBranchFilter ::init();
|
||||
FemGui::ViewProviderFemPostCalculator ::init();
|
||||
FemGui::ViewProviderFemPostClip ::init();
|
||||
FemGui::ViewProviderFemPostContours ::init();
|
||||
FemGui::ViewProviderFemPostCut ::init();
|
||||
|
||||
@@ -87,6 +87,7 @@ if(BUILD_FEM_VTK)
|
||||
CylinderWidget.ui
|
||||
PlaneWidget.ui
|
||||
SphereWidget.ui
|
||||
TaskPostCalculator.ui
|
||||
TaskPostClip.ui
|
||||
TaskPostContours.ui
|
||||
TaskPostCut.ui
|
||||
@@ -281,6 +282,7 @@ if(BUILD_FEM_VTK)
|
||||
SphereWidget.ui
|
||||
TaskPostBoxes.h
|
||||
TaskPostBoxes.cpp
|
||||
TaskPostCalculator.ui
|
||||
TaskPostClip.ui
|
||||
TaskPostContours.ui
|
||||
TaskPostCut.ui
|
||||
|
||||
@@ -2338,6 +2338,42 @@ bool CmdFemPostContoursFilter::isActive()
|
||||
}
|
||||
|
||||
|
||||
//================================================================================================
|
||||
DEF_STD_CMD_A(CmdFemPostCalculatorFilter)
|
||||
|
||||
CmdFemPostCalculatorFilter::CmdFemPostCalculatorFilter()
|
||||
: Command("FEM_PostFilterCalculator")
|
||||
{
|
||||
sAppModule = "Fem";
|
||||
sGroup = QT_TR_NOOP("Fem");
|
||||
sMenuText = QT_TR_NOOP("Calculator filter");
|
||||
sToolTipText = QT_TR_NOOP("Create new fields from current data");
|
||||
sWhatsThis = "FEM_PostFilterCalculator";
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "FEM_PostFilterCalculator";
|
||||
}
|
||||
|
||||
void CmdFemPostCalculatorFilter::activated(int)
|
||||
{
|
||||
setupFilter(this, "Calculator");
|
||||
}
|
||||
|
||||
bool CmdFemPostCalculatorFilter::isActive()
|
||||
{
|
||||
// only allow one object
|
||||
auto selection = getSelection().getSelection();
|
||||
if (selection.size() > 1) {
|
||||
return false;
|
||||
}
|
||||
for (auto obj : selection) {
|
||||
if (obj.pObject->isDerivedFrom<Fem::FemPostObject>()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//================================================================================================
|
||||
DEF_STD_CMD_ACL(CmdFemPostFunctions)
|
||||
|
||||
@@ -2783,6 +2819,7 @@ void CreateFemCommands()
|
||||
// vtk post processing
|
||||
#ifdef FC_USE_VTK
|
||||
rcCmdMgr.addCommand(new CmdFemPostApllyChanges);
|
||||
rcCmdMgr.addCommand(new CmdFemPostCalculatorFilter);
|
||||
rcCmdMgr.addCommand(new CmdFemPostClipFilter);
|
||||
rcCmdMgr.addCommand(new CmdFemPostContoursFilter);
|
||||
rcCmdMgr.addCommand(new CmdFemPostCutFilter);
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
#include <QSlider>
|
||||
#include <QStackedWidget>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTextCharFormat>
|
||||
#include <QTextStream>
|
||||
#include <QThread>
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
<file>icons/FEM_MaterialSolid.svg</file>
|
||||
|
||||
<!-- gui command icons: post processing -->
|
||||
<file>icons/FEM_PostFilterCalculator.svg</file>
|
||||
<file>icons/FEM_PostFilterClipRegion.svg</file>
|
||||
<file>icons/FEM_PostFilterClipScalar.svg</file>
|
||||
<file>icons/FEM_PostFilterContours.svg</file>
|
||||
|
||||
324
src/Mod/Fem/Gui/Resources/icons/FEM_PostFilterCalculator.svg
Normal file
324
src/Mod/Fem/Gui/Resources/icons/FEM_PostFilterCalculator.svg
Normal file
@@ -0,0 +1,324 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
id="svg5816"
|
||||
version="1.1"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs3">
|
||||
<linearGradient
|
||||
id="linearGradient6">
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6" />
|
||||
<stop
|
||||
style="stop-color:#204a87;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop7" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4">
|
||||
<stop
|
||||
style="stop-color:#eeeeec;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4" />
|
||||
<stop
|
||||
style="stop-color:#888a85;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop5" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient13">
|
||||
<stop
|
||||
style="stop-color:#4e9a06;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop13" />
|
||||
<stop
|
||||
style="stop-color:#172a04;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop14" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5048">
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="0"
|
||||
id="stop5050" />
|
||||
<stop
|
||||
id="stop5056"
|
||||
offset="0.5"
|
||||
style="stop-color:black;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5052" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient30695">
|
||||
<stop
|
||||
style="stop-color:#b8babc;stop-opacity:1.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop30697" />
|
||||
<stop
|
||||
id="stop30703"
|
||||
offset="0.37383178"
|
||||
style="stop-color:#5d6062;stop-opacity:1.0000000;" />
|
||||
<stop
|
||||
style="stop-color:#585b5d;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop30699" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient30685">
|
||||
<stop
|
||||
style="stop-color:#8d8d8d;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop30687" />
|
||||
<stop
|
||||
style="stop-color:#747474;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop30689" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient30649">
|
||||
<stop
|
||||
style="stop-color:#858585;stop-opacity:1.0000000;"
|
||||
offset="0.0000000"
|
||||
id="stop30651" />
|
||||
<stop
|
||||
style="stop-color:#5f5f5f;stop-opacity:1.0000000;"
|
||||
offset="1.0000000"
|
||||
id="stop30653" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient30518">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop30520" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.78698224;"
|
||||
offset="1.0000000"
|
||||
id="stop30522" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient30505">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop30507" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop30509" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
xlink:href="#linearGradient30505"
|
||||
id="radialGradient30511"
|
||||
cx="25.375"
|
||||
cy="43.375"
|
||||
fx="25.375"
|
||||
fy="43.375"
|
||||
r="17.125"
|
||||
gradientTransform="matrix(1,0,0,0.343066,0,28.49453)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient13"
|
||||
id="linearGradient14"
|
||||
x1="14.194713"
|
||||
y1="14.959513"
|
||||
x2="50.307402"
|
||||
y2="14.959513"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.94136107,0,0,0.80047803,1.6398337,2.9844794)" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient4"
|
||||
id="linearGradient5"
|
||||
x1="13.925462"
|
||||
y1="28.767968"
|
||||
x2="23.993155"
|
||||
y2="28.767968"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient6"
|
||||
id="linearGradient7"
|
||||
x1="14.345589"
|
||||
y1="45.668344"
|
||||
x2="23.573026"
|
||||
y2="45.668344"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>calc</rdf:li>
|
||||
<rdf:li>calculator</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer2"
|
||||
style="display:inline"
|
||||
transform="matrix(0.99687962,0,0,0.99742739,0.09985202,0.07897114)">
|
||||
<rect
|
||||
style="display:inline;fill:#888a85;fill-opacity:1;stroke:#2e3436;stroke-width:2.00570932;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect1"
|
||||
width="46.144329"
|
||||
height="58.148834"
|
||||
x="8.9278355"
|
||||
y="2.9289429"
|
||||
rx="2.0969498"
|
||||
ry="2.0765483" />
|
||||
<path
|
||||
style="font-variation-settings:normal;display:inline;opacity:1;vector-effect:none;fill:#888a85;fill-opacity:1;stroke:#d3d7cf;stroke-width:2.00573;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;-inkscape-stroke:none;stop-color:#000000;stop-opacity:1"
|
||||
id="rect4"
|
||||
width="46"
|
||||
height="58"
|
||||
x="9"
|
||||
y="3"
|
||||
rx="2.0903912"
|
||||
ry="2.0712333"
|
||||
d="M 10.934001,4.9340059 H 53.066 V 59.072716 H 10.934001 Z" />
|
||||
<path
|
||||
style="display:inline;fill:url(#linearGradient14);fill-opacity:1;stroke:#2e3436;stroke-width:2.00563;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="rect3"
|
||||
width="32"
|
||||
height="8"
|
||||
x="16"
|
||||
y="11"
|
||||
rx="1.9157546"
|
||||
ry="1.6495458"
|
||||
d="m 17.8516,10.949162 h 28.29625 c 1.053857,0 1.902269,0.715397 1.902269,1.60403 v 4.812098 c 0,0.888633 -0.848412,1.604033 -1.902269,1.604033 H 17.8516 c -1.053858,0 -1.902269,-0.7154 -1.902269,-1.604033 v -4.812098 c 0,-0.888633 0.848411,-1.60403 1.902269,-1.60403 z" />
|
||||
<g
|
||||
id="g18"
|
||||
transform="translate(0.01819536,-1.7775041)">
|
||||
<rect
|
||||
style="font-variation-settings:normal;opacity:1;fill:#babdb6;fill-opacity:1;stroke:#2e3436;stroke-width:2.00589;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||
id="rect14"
|
||||
width="8.0254087"
|
||||
height="8.0199003"
|
||||
x="14.928866"
|
||||
y="24.758476"
|
||||
rx="1.0018098"
|
||||
ry="1.0005703" />
|
||||
<rect
|
||||
style="font-variation-settings:normal;opacity:1;fill:#babdb6;fill-opacity:1;stroke:#2e3436;stroke-width:2.00589;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||
id="rect16"
|
||||
width="8.0254192"
|
||||
height="8.019906"
|
||||
x="14.92884"
|
||||
y="35.786819"
|
||||
rx="1.0018109"
|
||||
ry="1.0005711" />
|
||||
<rect
|
||||
style="font-variation-settings:normal;opacity:1;fill:#babdb6;fill-opacity:1;stroke:#2e3436;stroke-width:2.00589;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||
id="rect17"
|
||||
width="8.0254192"
|
||||
height="8.019906"
|
||||
x="14.928837"
|
||||
y="46.815189"
|
||||
rx="1.001811"
|
||||
ry="1.0005711" />
|
||||
</g>
|
||||
<g
|
||||
id="g20"
|
||||
transform="translate(13.058887,-1.7775041)">
|
||||
<rect
|
||||
style="font-variation-settings:normal;opacity:1;fill:#babdb6;fill-opacity:1;stroke:#2e3436;stroke-width:2.00589;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||
id="rect18"
|
||||
width="8.0254192"
|
||||
height="8.019906"
|
||||
x="14.92884"
|
||||
y="24.75845"
|
||||
rx="1.0018109"
|
||||
ry="1.0005711" />
|
||||
<rect
|
||||
style="font-variation-settings:normal;opacity:1;fill:#babdb6;fill-opacity:1;stroke:#2e3436;stroke-width:2.00589;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||
id="rect19"
|
||||
width="8.0254087"
|
||||
height="8.0199003"
|
||||
x="14.928866"
|
||||
y="35.78685"
|
||||
rx="1.0063162"
|
||||
ry="1.0050732" />
|
||||
<rect
|
||||
style="font-variation-settings:normal;opacity:1;fill:#babdb6;fill-opacity:1;stroke:#2e3436;stroke-width:2.00570932;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||
id="rect20"
|
||||
width="8.0246763"
|
||||
height="8.019165"
|
||||
x="14.928775"
|
||||
y="46.815128"
|
||||
rx="1.0062244"
|
||||
ry="1.004981" />
|
||||
</g>
|
||||
<g
|
||||
id="g24"
|
||||
transform="translate(26.099579,-1.7775041)"
|
||||
style="display:inline;stroke-width:2.00571;stroke-dasharray:none">
|
||||
<rect
|
||||
style="font-variation-settings:normal;display:inline;opacity:1;fill:#babdb6;fill-opacity:1;stroke:#2e3436;stroke-width:2.00658;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||
id="rect22"
|
||||
width="8.0247221"
|
||||
height="8.0192175"
|
||||
x="14.928753"
|
||||
y="24.758362"
|
||||
rx="1.0017239"
|
||||
ry="1.0004852" />
|
||||
<rect
|
||||
style="font-variation-settings:normal;display:inline;opacity:1;fill:#729fcf;stroke:#2e3436;stroke-width:2.00557;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
|
||||
id="rect23"
|
||||
width="8.0257349"
|
||||
height="18.046019"
|
||||
x="14.927776"
|
||||
y="36.788338"
|
||||
rx="1.1226069"
|
||||
ry="0.9708975" />
|
||||
</g>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:oblique;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:5.66667px;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Bold Oblique';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:start;writing-mode:lr-tb;direction:ltr;text-anchor:start;fill:#babdb6;fill-opacity:1;stroke:#2e3436;stroke-width:0.3;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="27.29318"
|
||||
y="16.778864"
|
||||
id="text1"><tspan
|
||||
id="tspan1"
|
||||
x="27.29318"
|
||||
y="16.778864">f(x)</tspan></text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
@@ -52,6 +52,7 @@
|
||||
#include <Mod/Fem/App/FemPostBranchFilter.h>
|
||||
#include <Mod/Fem/App/FemPostPipeline.h>
|
||||
|
||||
#include "ui_TaskPostCalculator.h"
|
||||
#include "ui_TaskPostClip.h"
|
||||
#include "ui_TaskPostContours.h"
|
||||
#include "ui_TaskPostCut.h"
|
||||
@@ -323,6 +324,9 @@ void TaskDlgPost::open()
|
||||
void TaskDlgPost::clicked(int button)
|
||||
{
|
||||
if (button == QDialogButtonBox::Apply) {
|
||||
for (auto box : m_boxes) {
|
||||
box->apply();
|
||||
}
|
||||
recompute();
|
||||
}
|
||||
}
|
||||
@@ -2123,4 +2127,130 @@ void TaskPostWarpVector::onMinValueChanged(double)
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// calculator filter
|
||||
static const std::vector<std::string> calculatorOperators = {
|
||||
"+", "-", "*", "/", "-", "^", "abs", "cos", "sin", "tan", "exp",
|
||||
"log", "pow", "sqrt", "iHat", "jHat", "kHat", "cross", "dot", "mag", "norm"};
|
||||
|
||||
TaskPostCalculator::TaskPostCalculator(ViewProviderFemPostCalculator* view, QWidget* parent)
|
||||
: TaskPostBox(view,
|
||||
Gui::BitmapFactory().pixmap("FEM_PostFilterCalculator"),
|
||||
tr("Calculator options"),
|
||||
parent)
|
||||
, ui(new Ui_TaskPostCalculator)
|
||||
{
|
||||
// we load the views widget
|
||||
proxy = new QWidget(this);
|
||||
ui->setupUi(proxy);
|
||||
setupConnections();
|
||||
this->groupLayout()->addWidget(proxy);
|
||||
|
||||
// load the default values
|
||||
auto obj = getObject<Fem::FemPostCalculatorFilter>();
|
||||
ui->let_field_name->blockSignals(true);
|
||||
ui->let_field_name->setText(QString::fromUtf8(obj->FieldName.getValue()));
|
||||
ui->let_field_name->blockSignals(false);
|
||||
|
||||
ui->let_function->blockSignals(true);
|
||||
ui->let_function->setText(QString::fromUtf8(obj->Function.getValue()));
|
||||
ui->let_function->blockSignals(false);
|
||||
|
||||
ui->ckb_replace_invalid->setChecked(obj->ReplaceInvalid.getValue());
|
||||
ui->dsb_replacement_value->setEnabled(obj->ReplaceInvalid.getValue());
|
||||
ui->dsb_replacement_value->setValue(obj->ReplacementValue.getValue());
|
||||
ui->dsb_replacement_value->setMaximum(std::numeric_limits<double>::max());
|
||||
ui->dsb_replacement_value->setMinimum(std::numeric_limits<double>::lowest());
|
||||
|
||||
// fill available fields
|
||||
for (const auto& f : obj->getScalarVariables()) {
|
||||
ui->cb_scalars->addItem(QString::fromStdString(f));
|
||||
}
|
||||
for (const auto& f : obj->getVectorVariables()) {
|
||||
ui->cb_vectors->addItem(QString::fromStdString(f));
|
||||
}
|
||||
|
||||
QStringList qOperators;
|
||||
for (const auto& o : calculatorOperators) {
|
||||
qOperators << QString::fromStdString(o);
|
||||
}
|
||||
ui->cb_operators->addItems(qOperators);
|
||||
|
||||
ui->cb_scalars->setCurrentIndex(-1);
|
||||
ui->cb_vectors->setCurrentIndex(-1);
|
||||
ui->cb_operators->setCurrentIndex(-1);
|
||||
}
|
||||
|
||||
TaskPostCalculator::~TaskPostCalculator() = default;
|
||||
|
||||
void TaskPostCalculator::setupConnections()
|
||||
{
|
||||
connect(ui->dsb_replacement_value,
|
||||
qOverload<double>(&QDoubleSpinBox::valueChanged),
|
||||
this,
|
||||
&TaskPostCalculator::onReplacementValueChanged);
|
||||
connect(ui->ckb_replace_invalid,
|
||||
&QCheckBox::toggled,
|
||||
this,
|
||||
&TaskPostCalculator::onReplaceInvalidChanged);
|
||||
connect(ui->cb_scalars,
|
||||
qOverload<int>(&QComboBox::activated),
|
||||
this,
|
||||
&TaskPostCalculator::onScalarsActivated);
|
||||
connect(ui->cb_vectors,
|
||||
qOverload<int>(&QComboBox::activated),
|
||||
this,
|
||||
&TaskPostCalculator::onVectorsActivated);
|
||||
connect(ui->cb_operators,
|
||||
qOverload<int>(&QComboBox::activated),
|
||||
this,
|
||||
&TaskPostCalculator::onOperatorsActivated);
|
||||
}
|
||||
|
||||
void TaskPostCalculator::onReplaceInvalidChanged(bool state)
|
||||
{
|
||||
auto obj = static_cast<Fem::FemPostCalculatorFilter*>(getObject());
|
||||
obj->ReplaceInvalid.setValue(state);
|
||||
ui->dsb_replacement_value->setEnabled(state);
|
||||
recompute();
|
||||
}
|
||||
|
||||
void TaskPostCalculator::onReplacementValueChanged(double value)
|
||||
{
|
||||
auto obj = static_cast<Fem::FemPostCalculatorFilter*>(getObject());
|
||||
obj->ReplacementValue.setValue(value);
|
||||
recompute();
|
||||
}
|
||||
|
||||
void TaskPostCalculator::onScalarsActivated(int index)
|
||||
{
|
||||
QString item = ui->cb_scalars->itemText(index);
|
||||
ui->let_function->insert(item);
|
||||
}
|
||||
|
||||
void TaskPostCalculator::onVectorsActivated(int index)
|
||||
{
|
||||
QString item = ui->cb_vectors->itemText(index);
|
||||
ui->let_function->insert(item);
|
||||
}
|
||||
|
||||
void TaskPostCalculator::onOperatorsActivated(int index)
|
||||
{
|
||||
QString item = ui->cb_operators->itemText(index);
|
||||
ui->let_function->insert(item);
|
||||
}
|
||||
|
||||
void TaskPostCalculator::apply()
|
||||
{
|
||||
auto obj = getObject<Fem::FemPostCalculatorFilter>();
|
||||
std::string function = ui->let_function->text().toStdString();
|
||||
std::string name = ui->let_field_name->text().toStdString();
|
||||
obj->Function.setValue(function);
|
||||
obj->FieldName.setValue(name);
|
||||
recompute();
|
||||
|
||||
auto view = getTypedView<ViewProviderFemPostCalculator>();
|
||||
view->Field.setValue(obj->FieldName.getValue());
|
||||
}
|
||||
|
||||
#include "moc_TaskPostBoxes.cpp"
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
class QComboBox;
|
||||
class Ui_TaskPostDisplay;
|
||||
class Ui_TaskPostCalculator;
|
||||
class Ui_TaskPostClip;
|
||||
class Ui_TaskPostContours;
|
||||
class Ui_TaskPostDataAlongLine;
|
||||
@@ -141,12 +142,15 @@ public:
|
||||
QWidget* parent = nullptr);
|
||||
~TaskPostBox() override;
|
||||
|
||||
virtual void applyPythonCode() = 0;
|
||||
virtual void applyPythonCode() {};
|
||||
virtual bool isGuiTaskOnly()
|
||||
{
|
||||
return false;
|
||||
} // return true if only gui properties are manipulated
|
||||
|
||||
// executed when the apply button is pressed in the task dialog
|
||||
virtual void apply() {};
|
||||
|
||||
protected:
|
||||
App::DocumentObject* getObject() const
|
||||
{
|
||||
@@ -555,6 +559,35 @@ private:
|
||||
std::unique_ptr<Ui_TaskPostWarpVector> ui;
|
||||
};
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// calculator filter
|
||||
class ViewProviderFemPostCalculator;
|
||||
|
||||
class TaskPostCalculator: public TaskPostBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TaskPostCalculator(ViewProviderFemPostCalculator* view, QWidget* parent = nullptr);
|
||||
~TaskPostCalculator() override;
|
||||
|
||||
protected:
|
||||
void apply() override;
|
||||
|
||||
private:
|
||||
void setupConnections();
|
||||
void onReplaceInvalidChanged(bool state);
|
||||
void onReplacementValueChanged(double value);
|
||||
void onScalarsActivated(int index);
|
||||
void onVectorsActivated(int index);
|
||||
void onOperatorsActivated(int index);
|
||||
|
||||
private:
|
||||
QWidget* proxy;
|
||||
std::unique_ptr<Ui_TaskPostCalculator> ui;
|
||||
};
|
||||
|
||||
} // namespace FemGui
|
||||
|
||||
#endif // GUI_TASKVIEW_TaskPostDisplay_H
|
||||
|
||||
127
src/Mod/Fem/Gui/TaskPostCalculator.ui
Normal file
127
src/Mod/Fem/Gui/TaskPostCalculator.ui
Normal file
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TaskPostCalculator</class>
|
||||
<widget class="QWidget" name="TaskPostCalculator">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>250</width>
|
||||
<height>115</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vertica_layout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gpb_function">
|
||||
<property name="title">
|
||||
<string></string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vbl_function">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="form_layout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lbl_field_name">
|
||||
<property name="text">
|
||||
<string>Field Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="let_field_name">
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="let_function">
|
||||
<property name="toolTip">
|
||||
<string>Mathematical expression</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gpb_fields">
|
||||
<property name="title">
|
||||
<string></string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Available fields</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vbl_fields">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="fl_fields">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lbl_scalars">
|
||||
<property name="text">
|
||||
<string>Scalars:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="cb_scalars"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lbl_vectors">
|
||||
<property name="text">
|
||||
<string>Vectors:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cb_vectors"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="lbl_operators">
|
||||
<property name="text">
|
||||
<string>Operators:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="cb_operators"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gpb_replacement">
|
||||
<layout class="QVBoxLayout" name="vbl_replacement">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="fl_replacement">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="ckb_replace_invalid">
|
||||
<property name="text">
|
||||
<string>Replace invalid data:</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Replacement value for invalid operations</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Gui::DoubleSpinBox" name="dsb_replacement_value">
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::DoubleSpinBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Gui/SpinBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
</ui>
|
||||
@@ -215,3 +215,38 @@ void ViewProviderFemPostWarpVector::setupTaskDialog(TaskDlgPost* dlg)
|
||||
// add the display options
|
||||
FemGui::ViewProviderFemPostObject::setupTaskDialog(dlg);
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// calculator filter
|
||||
PROPERTY_SOURCE(FemGui::ViewProviderFemPostCalculator, FemGui::ViewProviderFemPostObject)
|
||||
|
||||
ViewProviderFemPostCalculator::ViewProviderFemPostCalculator()
|
||||
{
|
||||
sPixmap = "FEM_PostFilterCalculator";
|
||||
}
|
||||
|
||||
ViewProviderFemPostCalculator::~ViewProviderFemPostCalculator() = default;
|
||||
|
||||
void ViewProviderFemPostCalculator::updateData(const App::Property* prop)
|
||||
{
|
||||
auto obj = getObject<Fem::FemPostCalculatorFilter>();
|
||||
if (prop == &obj->Data) {
|
||||
// update color bar
|
||||
ViewProviderFemPostObject::updateData(prop);
|
||||
updateMaterial();
|
||||
}
|
||||
else {
|
||||
return ViewProviderFemPostObject::updateData(prop);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewProviderFemPostCalculator::setupTaskDialog(TaskDlgPost* dlg)
|
||||
{
|
||||
// add the function box
|
||||
assert(dlg->getView() == this);
|
||||
dlg->appendBox(new TaskPostCalculator(this));
|
||||
|
||||
// add the display options
|
||||
FemGui::ViewProviderFemPostObject::setupTaskDialog(dlg);
|
||||
}
|
||||
|
||||
@@ -154,6 +154,24 @@ protected:
|
||||
void setupTaskDialog(TaskDlgPost* dlg) override;
|
||||
};
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// calculator filter
|
||||
class FemGuiExport ViewProviderFemPostCalculator: public ViewProviderFemPostObject
|
||||
{
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(FemGui::ViewProviderFemPostCalculator);
|
||||
|
||||
public:
|
||||
/// constructor.
|
||||
ViewProviderFemPostCalculator();
|
||||
~ViewProviderFemPostCalculator() override;
|
||||
|
||||
void updateData(const App::Property* prop) override;
|
||||
|
||||
protected:
|
||||
void setupTaskDialog(TaskDlgPost* dlg) override;
|
||||
};
|
||||
|
||||
} // namespace FemGui
|
||||
|
||||
|
||||
|
||||
@@ -209,6 +209,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
||||
<< "FEM_PostFilterDataAlongLine"
|
||||
<< "FEM_PostFilterLinearizedStresses"
|
||||
<< "FEM_PostFilterDataAtPoint"
|
||||
<< "FEM_PostFilterCalculator"
|
||||
<< "Separator"
|
||||
<< "FEM_PostCreateFunctions";
|
||||
#endif
|
||||
@@ -356,6 +357,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
<< "FEM_PostFilterDataAlongLine"
|
||||
<< "FEM_PostFilterLinearizedStresses"
|
||||
<< "FEM_PostFilterDataAtPoint"
|
||||
<< "FEM_PostFilterCalculator"
|
||||
<< "Separator"
|
||||
<< "FEM_PostCreateFunctions";
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user