Fem: Add box filter function

This commit is contained in:
marioalexis
2023-03-10 12:41:27 -03:00
committed by Uwe
parent ca5d7a7eae
commit b51eec232f
9 changed files with 567 additions and 0 deletions

View File

@@ -187,6 +187,7 @@ PyMOD_INIT_FUNC(Fem)
Fem::FemPostFunction ::init();
Fem::FemPostFunctionProvider ::init();
Fem::FemPostBoxFunction ::init();
Fem::FemPostCylinderFunction ::init();
Fem::FemPostPlaneFunction ::init();
Fem::FemPostSphereFunction ::init();

View File

@@ -59,6 +59,51 @@ DocumentObjectExecReturn* FemPostFunction::execute() {
return DocumentObject::StdReturn;
}
// ***************************************************************************
// box function
PROPERTY_SOURCE(Fem::FemPostBoxFunction, Fem::FemPostFunction)
FemPostBoxFunction::FemPostBoxFunction()
: FemPostFunction()
{
ADD_PROPERTY(Center, (Base::Vector3d(0.0, 0.0, 0.0)));
ADD_PROPERTY(Length, (10.0));
ADD_PROPERTY(Width, (10.0));
ADD_PROPERTY(Height, (10.0));
m_box = vtkSmartPointer<vtkBox>::New();
m_implicit = m_box;
m_box->SetBounds(-5.0, 5.0, -5.0, 5.0, -5.0, 5.0);
}
FemPostBoxFunction::~FemPostBoxFunction()
{
}
void FemPostBoxFunction::onChanged(const Property* prop)
{
if (prop == &Center || prop == &Length || prop == &Width || prop == &Height) {
const Base::Vector3d& vec = Center.getValue();
float l = Length.getValue();
float w = Width.getValue();
float h = Height.getValue();
m_box->SetBounds(
vec[0] - l/2, vec[0] + l/2,
vec[1] - w/2, vec[1] + w/2,
vec[2] - h/2, vec[2] + h/2);
}
Fem::FemPostFunction::onChanged(prop);
}
void FemPostBoxFunction::onDocumentRestored()
{
// This is to notify the view provider that the document has been fully restored
Center.touch();
}
// ***************************************************************************
// cylinder function
PROPERTY_SOURCE(Fem::FemPostCylinderFunction, Fem::FemPostFunction)

View File

@@ -24,6 +24,7 @@
#define Fem_FemPostFunction_H
#include <vtkBoundingBox.h>
#include <vtkBox.h>
#include <vtkCylinder.h>
#include <vtkImplicitFunction.h>
#include <vtkPlane.h>
@@ -84,6 +85,34 @@ protected:
// ---------------------------------------------------------------------------
class FemExport FemPostBoxFunction : public FemPostFunction
{
PROPERTY_HEADER_WITH_OVERRIDE(Fem::FemPostBoxFunction);
public:
FemPostBoxFunction();
~FemPostBoxFunction() override;
App::PropertyVectorDistance Center;
App::PropertyDistance Length;
App::PropertyDistance Width;
App::PropertyDistance Height;
const char* getViewProviderName() const override {
return "FemGui::ViewProviderFemPostBoxFunction";
}
protected:
void onChanged(const App::Property* prop) override;
/// get called after a document has been fully restored
void onDocumentRestored() override;
vtkSmartPointer<vtkBox> m_box;
};
// ---------------------------------------------------------------------------
class FemExport FemPostCylinderFunction : public FemPostFunction
{
PROPERTY_HEADER_WITH_OVERRIDE(Fem::FemPostCylinderFunction);

View File

@@ -161,6 +161,7 @@ PyMOD_INIT_FUNC(FemGui)
FemGui::ViewProviderFemPostFunction ::init();
FemGui::ViewProviderFemPostFunctionProvider ::init();
FemGui::ViewProviderFemPostBoxFunction ::init();
FemGui::ViewProviderFemPostCylinderFunction ::init();
FemGui::ViewProviderFemPostPlaneFunction ::init();
FemGui::ViewProviderFemPostSphereFunction ::init();

View File

@@ -0,0 +1,197 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BoxWidget</class>
<widget class="QWidget" name="BoxWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>280</width>
<height>85</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QLabel" name="label_7">
<property name="text">
<string>x</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_8">
<property name="text">
<string>y</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label_9">
<property name="text">
<string>z</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Center</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="Gui::PrefQuantitySpinBox" name="centerX">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="Gui::PrefQuantitySpinBox" name="centerY">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="Gui::PrefQuantitySpinBox" name="centerZ">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Length</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Gui::PrefQuantitySpinBox" name="length">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Width</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="Gui::PrefQuantitySpinBox" name="width">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Height</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="Gui::PrefQuantitySpinBox" name="height">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Gui::QuantitySpinBox</class>
<extends>QWidget</extends>
<header>Gui/QuantitySpinBox.h</header>
</customwidget>
<customwidget>
<class>Gui::PrefQuantitySpinBox</class>
<extends>Gui::QuantitySpinBox</extends>
<header>Gui/PrefWidgets.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -91,6 +91,7 @@ set(FemGui_UIC_SRCS
if(BUILD_FEM_VTK)
set(FemGui_UIC_SRCS
${FemGui_UIC_SRCS}
BoxWidget.ui
CylinderWidget.ui
PlaneWidget.ui
SphereWidget.ui
@@ -270,6 +271,7 @@ SET(FemGui_SRCS_TaskBoxes
if(BUILD_FEM_VTK)
SET(FemGui_SRCS_TaskBoxes
${FemGui_SRCS_TaskBoxes}
BoxWidget.ui
CylinderWidget.ui
PlaneWidget.ui
SphereWidget.ui

View File

@@ -2106,6 +2106,8 @@ void CmdFemPostFunctions::activated(int iMsg)
name = "Sphere";
else if (iMsg == 2)
name = "Cylinder";
else if (iMsg == 3)
name = "Box";
else
return;
@@ -2184,6 +2186,26 @@ void CmdFemPostFunctions::activated(int iMsg)
FeatName.c_str(),
box.GetDiagonalLength() / 3.6); // make cylinder a bit higher than the box
}
else if (iMsg == 3) {
doCommand(Doc,
"App.ActiveDocument.%s.Center = App.Vector(%f, %f, %f)",
FeatName.c_str(),
center[0],
center[1] + box.GetLength(1) / 2,
center[2] + box.GetLength(2) / 2);
doCommand(Doc,
"App.ActiveDocument.%s.Length = %f",
FeatName.c_str(),
box.GetLength(0));
doCommand(Doc,
"App.ActiveDocument.%s.Width = %f",
FeatName.c_str(),
box.GetLength(1));
doCommand(Doc,
"App.ActiveDocument.%s.Height = %f",
FeatName.c_str(),
box.GetLength(2));
}
this->updateActive();
//most of the times functions are added inside of a filter, make sure this still works
@@ -2220,6 +2242,9 @@ Gui::Action* CmdFemPostFunctions::createAction()
QAction* cmd2 = pcAction->addAction(QString());
cmd2->setIcon(Gui::BitmapFactory().iconFromTheme("fem-post-geo-cylinder"));
QAction* cmd3 = pcAction->addAction(QString());
cmd3->setIcon(Gui::BitmapFactory().iconFromTheme("fem-post-geo-box"));
_pcAction = pcAction;
languageChange();
@@ -2256,6 +2281,12 @@ void CmdFemPostFunctions::languageChange()
cmd->setToolTip(QApplication::translate(
"FEM_PostCreateFunctions", "Create a cylinder function, defined by its center, axis and radius"));
cmd->setStatusTip(cmd->toolTip());
cmd = a[3];
cmd->setText(QApplication::translate("CmdFemPostFunctions", "Box"));
cmd->setToolTip(QApplication::translate(
"FEM_PostCreateFunctions", "Create a box function, defined by its center, length, width and height"));
cmd->setStatusTip(cmd->toolTip());
}
bool CmdFemPostFunctions::isActive()

View File

@@ -57,6 +57,7 @@
#include "FemSettings.h"
#include "TaskPostBoxes.h"
#include "ui_BoxWidget.h"
#include "ui_CylinderWidget.h"
#include "ui_PlaneWidget.h"
#include "ui_SphereWidget.h"
@@ -379,6 +380,183 @@ void ViewProviderFemPostFunction::onChanged(const App::Property* prop) {
}
// ***************************************************************************
PROPERTY_SOURCE(FemGui::ViewProviderFemPostBoxFunction, FemGui::ViewProviderFemPostFunction)
ViewProviderFemPostBoxFunction::ViewProviderFemPostBoxFunction()
{
sPixmap = "fem-post-geo-box";
setAutoScale(false);
// setup the visualisation geometry
getGeometryNode()->addChild(ShapeNodes::postBox());
}
ViewProviderFemPostBoxFunction::~ViewProviderFemPostBoxFunction()
{
}
void ViewProviderFemPostBoxFunction::draggerUpdate(SoDragger* m)
{
Fem::FemPostBoxFunction* func = static_cast<Fem::FemPostBoxFunction*>(getObject());
SoHandleBoxDragger* dragger = static_cast<SoHandleBoxDragger*>(m);
const SbVec3f& center = dragger->translation.getValue();
SbVec3f scale = dragger->scaleFactor.getValue();
func->Center.setValue(center[0], center[1], center[2]);
func->Length.setValue(scale[0]);
func->Width.setValue(scale[1]);
func->Height.setValue(scale[2]);
}
void ViewProviderFemPostBoxFunction::updateData(const App::Property* p)
{
Fem::FemPostBoxFunction* func = static_cast<Fem::FemPostBoxFunction*>(getObject());
if (!isDragging() &&
(p == &func->Center || p == &func->Length || p == &func->Width || p == &func->Height)) {
const Base::Vector3d& center = func->Center.getValue();
float l = func->Length.getValue();
float w = func->Width.getValue();
float h = func->Height.getValue();
SbMatrix s, t;
s.setScale(SbVec3f(l, w, h));
t.setTranslate(SbVec3f(center.x, center.y, center.z));
s.multRight(t);
getManipulator()->setMatrix(s);
}
Gui::ViewProviderDocumentObject::updateData(p);
}
SoTransformManip* ViewProviderFemPostBoxFunction::setupManipulator()
{
return new SoHandleBoxManip;
}
FunctionWidget* ViewProviderFemPostBoxFunction::createControlWidget()
{
return new BoxWidget();
}
BoxWidget::BoxWidget()
{
ui = new Ui_BoxWidget();
ui->setupUi(this);
QSize size = ui->centerX->sizeForText(QStringLiteral("000000000000"));
ui->centerX->setMinimumWidth(size.width());
ui->centerY->setMinimumWidth(size.width());
ui->centerZ->setMinimumWidth(size.width());
ui->length->setMinimumWidth(size.width());
ui->width->setMinimumWidth(size.width());
ui->height->setMinimumWidth(size.width());
int UserDecimals = Base::UnitsApi::getDecimals();
ui->centerX->setDecimals(UserDecimals);
ui->centerY->setDecimals(UserDecimals);
ui->centerZ->setDecimals(UserDecimals);
ui->length->setDecimals(UserDecimals);
ui->width->setDecimals(UserDecimals);
ui->height->setDecimals(UserDecimals);
connect(ui->centerX, qOverload<double>(&Gui::QuantitySpinBox::valueChanged), this, &BoxWidget::centerChanged);
connect(ui->centerY, qOverload<double>(&Gui::QuantitySpinBox::valueChanged), this, &BoxWidget::centerChanged);
connect(ui->centerZ, qOverload<double>(&Gui::QuantitySpinBox::valueChanged), this, &BoxWidget::centerChanged);
connect(ui->length, qOverload<double>(&Gui::QuantitySpinBox::valueChanged), this, &BoxWidget::lengthChanged);
connect(ui->width, qOverload<double>(&Gui::QuantitySpinBox::valueChanged), this, &BoxWidget::widthChanged);
connect(ui->height, qOverload<double>(&Gui::QuantitySpinBox::valueChanged), this, &BoxWidget::heightChanged);
}
BoxWidget::~BoxWidget()
{
}
void BoxWidget::applyPythonCode()
{
}
void BoxWidget::setViewProvider(ViewProviderFemPostFunction* view)
{
FemGui::FunctionWidget::setViewProvider(view);
setBlockObjectUpdates(true);
Base::Unit unit = static_cast<Fem::FemPostBoxFunction*>(getObject())->Center.getUnit();
ui->centerX->setUnit(unit);
ui->centerY->setUnit(unit);
ui->centerZ->setUnit(unit);
unit = static_cast<Fem::FemPostBoxFunction*>(getObject())->Length.getUnit();
ui->length->setUnit(unit);
unit = static_cast<Fem::FemPostBoxFunction*>(getObject())->Width.getUnit();
ui->width->setUnit(unit);
unit = static_cast<Fem::FemPostBoxFunction*>(getObject())->Height.getUnit();
ui->height->setUnit(unit);
setBlockObjectUpdates(false);
onChange(static_cast<Fem::FemPostBoxFunction*>(getObject())->Center);
onChange(static_cast<Fem::FemPostBoxFunction*>(getObject())->Length);
onChange(static_cast<Fem::FemPostBoxFunction*>(getObject())->Width);
onChange(static_cast<Fem::FemPostBoxFunction*>(getObject())->Height);
}
void BoxWidget::onChange(const App::Property& p)
{
setBlockObjectUpdates(true);
Fem::FemPostBoxFunction* func = static_cast<Fem::FemPostBoxFunction*>(getObject());
if (&p == &func->Center) {
const Base::Vector3d& vec = static_cast<const App::PropertyVector*>(&p)->getValue();
ui->centerX->setValue(vec.x);
ui->centerY->setValue(vec.y);
ui->centerZ->setValue(vec.z);
}
else if (&p == &func->Length) {
double l = static_cast<const App::PropertyDistance*>(&p)->getValue();
ui->length->setValue(l);
}
else if (&p == &func->Width) {
double w = static_cast<const App::PropertyDistance*>(&p)->getValue();
ui->width->setValue(w);
}
else if (&p == &func->Height) {
double h = static_cast<const App::PropertyDistance*>(&p)->getValue();
ui->height->setValue(h);
}
setBlockObjectUpdates(false);
}
void BoxWidget::centerChanged(double) {
if (!blockObjectUpdates()) {
Base::Vector3d vec(ui->centerX->value().getValue(), ui->centerY->value().getValue(),
ui->centerZ->value().getValue());
static_cast<Fem::FemPostBoxFunction*>(getObject())->Center.setValue(vec);
}
}
void BoxWidget::lengthChanged(double)
{
if (!blockObjectUpdates()) {
double l = ui->length->value().getValue();
static_cast<Fem::FemPostBoxFunction*>(getObject())->Length.setValue(l);
}
}
void BoxWidget::widthChanged(double)
{
if (!blockObjectUpdates()) {
double w = ui->width->value().getValue();
static_cast<Fem::FemPostBoxFunction*>(getObject())->Width.setValue(w);
}
}
void BoxWidget::heightChanged(double)
{
if (!blockObjectUpdates()) {
double h = ui->height->value().getValue();
static_cast<Fem::FemPostBoxFunction*>(getObject())->Height.setValue(h);
}
}
// ***************************************************************************
PROPERTY_SOURCE(FemGui::ViewProviderFemPostCylinderFunction, FemGui::ViewProviderFemPostFunction)
@@ -882,6 +1060,48 @@ namespace FemGui
namespace ShapeNodes
{
SoGroup* postBox()
{
SoCoordinate3* points = new SoCoordinate3();
points->point.setNum(18);
points->point.set1Value(0, -0.5, -0.5, -0.5);
points->point.set1Value(1, 0.5, -0.5, -0.5);
points->point.set1Value(2, 0.5, 0.5, -0.5);
points->point.set1Value(3, -0.5, 0.5, -0.5);
points->point.set1Value(4, -0.5, -0.5, -0.5);
points->point.set1Value(5, -0.5, -0.5, 0.5);
points->point.set1Value(6, 0.5, -0.5, 0.5);
points->point.set1Value(7, 0.5, 0.5, 0.5);
points->point.set1Value(8, -0.5, 0.5, 0.5);
points->point.set1Value(9, -0.5, -0.5, 0.5);
points->point.set1Value(10, -0.5, -0.5, -0.5);
points->point.set1Value(11, -0.5, -0.5, 0.5);
points->point.set1Value(12, 0.5, -0.5, -0.5);
points->point.set1Value(13, 0.5, -0.5, 0.5);
points->point.set1Value(14, 0.5, 0.5, -0.5);
points->point.set1Value(15, 0.5, 0.5, 0.5);
points->point.set1Value(16, -0.5, 0.5, -0.5);
points->point.set1Value(17, -0.5, 0.5, 0.5);
int vert[6];
vert[0] = 5;
vert[1] = 5;
vert[2] = 2;
vert[3] = 2;
vert[4] = 2;
vert[5] = 2;
SoGroup* group = new SoGroup();
SoLineSet* line = new SoLineSet();
line->numVertices.setValues(0, 6, vert);
group->addChild(points);
group->addChild(line);
return group;
}
SoGroup* postCylinder()
{
SoCoordinate3* points = new SoCoordinate3();

View File

@@ -39,6 +39,7 @@ class SoScale;
class SoSphere;
class SoSurroundScale;
class SoTransformManip;
class Ui_BoxWidget;
class Ui_CylinderWidget;
class Ui_PlaneWidget;
class Ui_SphereWidget;
@@ -153,6 +154,45 @@ private:
bool m_autoscale, m_isDragging, m_autoRecompute;
};
// ***************************************************************************
class FemGuiExport BoxWidget : public FunctionWidget {
Q_OBJECT
public:
BoxWidget();
~BoxWidget() override;
void applyPythonCode() override;
void onChange(const App::Property& p) override;
void setViewProvider(ViewProviderFemPostFunction* view) override;
private Q_SLOTS:
void centerChanged(double);
void lengthChanged(double);
void widthChanged(double);
void heightChanged(double);
private:
Ui_BoxWidget* ui;
};
class FemGuiExport ViewProviderFemPostBoxFunction : public ViewProviderFemPostFunction
{
PROPERTY_HEADER_WITH_OVERRIDE(FemGui::ViewProviderFemPostBoxFunction);
public:
ViewProviderFemPostBoxFunction();
~ViewProviderFemPostBoxFunction() override;
SoTransformManip* setupManipulator() override;
FunctionWidget* createControlWidget() override;
protected:
void draggerUpdate(SoDragger* mat) override;
void updateData(const App::Property*) override;
};
// ***************************************************************************
class FemGuiExport CylinderWidget : public FunctionWidget {
@@ -273,6 +313,7 @@ protected:
namespace ShapeNodes
{
SoGroup* postBox();
SoGroup* postCylinder();
SoGroup* postPlane();
SoGroup* postSphere();