From cefbb17c1775fc0d52727c51bab880cb7dc9fb55 Mon Sep 17 00:00:00 2001 From: Ajinkya Dahale Date: Sat, 29 Oct 2022 18:57:17 +0530 Subject: [PATCH 01/13] [FEM] Add rigid body constraint --- src/Mod/Fem/App/AppFem.cpp | 2 + src/Mod/Fem/App/CMakeLists.txt | 2 + src/Mod/Fem/App/FemConstraintRigidBody.cpp | 82 +++++ src/Mod/Fem/App/FemConstraintRigidBody.h | 77 +++++ src/Mod/Fem/Gui/AppFemGui.cpp | 2 + src/Mod/Fem/Gui/CMakeLists.txt | 6 + src/Mod/Fem/Gui/Command.cpp | 43 +++ .../Fem/Gui/TaskFemConstraintRigidBody.cpp | 310 +++++++++++++++++ src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h | 73 ++++ src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui | 317 ++++++++++++++++++ .../ViewProviderFemConstraintRigidBody.cpp | 167 +++++++++ .../Gui/ViewProviderFemConstraintRigidBody.h | 50 +++ src/Mod/Fem/Gui/Workbench.cpp | 2 + 13 files changed, 1133 insertions(+) create mode 100644 src/Mod/Fem/App/FemConstraintRigidBody.cpp create mode 100644 src/Mod/Fem/App/FemConstraintRigidBody.h create mode 100644 src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp create mode 100644 src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h create mode 100644 src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui create mode 100644 src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.cpp create mode 100644 src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.h diff --git a/src/Mod/Fem/App/AppFem.cpp b/src/Mod/Fem/App/AppFem.cpp index c37cb4f535..7649fc53fe 100644 --- a/src/Mod/Fem/App/AppFem.cpp +++ b/src/Mod/Fem/App/AppFem.cpp @@ -41,6 +41,7 @@ #include "FemConstraintPlaneRotation.h" #include "FemConstraintPressure.h" #include "FemConstraintPulley.h" +#include "FemConstraintRigidBody.h" #include "FemConstraintSpring.h" #include "FemConstraintTemperature.h" #include "FemConstraintTransform.h" @@ -142,6 +143,7 @@ PyMOD_INIT_FUNC(Fem) Fem::ConstraintContact ::init(); Fem::ConstraintDisplacement ::init(); Fem::ConstraintFixed ::init(); + Fem::ConstraintRigidBody ::init(); Fem::ConstraintFluidBoundary ::init(); Fem::ConstraintForce ::init(); Fem::ConstraintGear ::init(); diff --git a/src/Mod/Fem/App/CMakeLists.txt b/src/Mod/Fem/App/CMakeLists.txt index dd9250a00c..ab96acb6ed 100644 --- a/src/Mod/Fem/App/CMakeLists.txt +++ b/src/Mod/Fem/App/CMakeLists.txt @@ -148,6 +148,8 @@ SET(FemConstraints_SRCS FemConstraintBearing.cpp FemConstraintFixed.cpp FemConstraintFixed.h + FemConstraintRigidBody.cpp + FemConstraintRigidBody.h FemConstraintForce.cpp FemConstraintForce.h FemConstraintFluidBoundary.cpp diff --git a/src/Mod/Fem/App/FemConstraintRigidBody.cpp b/src/Mod/Fem/App/FemConstraintRigidBody.cpp new file mode 100644 index 0000000000..b2c2dc2d10 --- /dev/null +++ b/src/Mod/Fem/App/FemConstraintRigidBody.cpp @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (c) 2022 Ajinkya Dahale * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#include "FemConstraintRigidBody.h" + + +using namespace Fem; + +PROPERTY_SOURCE(Fem::ConstraintRigidBody, Fem::Constraint) + +ConstraintRigidBody::ConstraintRigidBody() +{ + ADD_PROPERTY(xRefNode,(0.0)); + ADD_PROPERTY(yRefNode,(0.0)); + ADD_PROPERTY(zRefNode,(0.0)); + ADD_PROPERTY(xDisplacement,(0.0)); + ADD_PROPERTY(yDisplacement,(0.0)); + ADD_PROPERTY(zDisplacement,(0.0)); + ADD_PROPERTY(xRotation,(0.0)); + ADD_PROPERTY(yRotation,(0.0)); + ADD_PROPERTY(zRotation,(0.0)); + ADD_PROPERTY(xLoad,(0.0)); + ADD_PROPERTY(yLoad,(0.0)); + ADD_PROPERTY(zLoad,(0.0)); + ADD_PROPERTY(xMoment,(0.0)); + ADD_PROPERTY(yMoment,(0.0)); + ADD_PROPERTY(zMoment,(0.0)); + ADD_PROPERTY(DefineRefNode,(1)); + + // For drawing the icons + ADD_PROPERTY_TYPE(Points,(Base::Vector3d()),"ConstraintRigidBody",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output), + "Points where symbols are drawn"); + ADD_PROPERTY_TYPE(Normals,(Base::Vector3d()),"ConstraintRigidBody",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output), + "Normals where symbols are drawn"); + Points.setValues(std::vector()); + Normals.setValues(std::vector()); +} + +App::DocumentObjectExecReturn *ConstraintRigidBody::execute() +{ + return Constraint::execute(); +} + +void ConstraintRigidBody::onChanged(const App::Property* prop) +{ + // Note: If we call this at the end, then the symbols are not oriented correctly initially + // because the NormalDirection has not been calculated yet + Constraint::onChanged(prop); + + if (prop == &References) { + std::vector points; + std::vector normals; + int scale = 1; //OvG: Enforce use of scale + if (getPoints(points, normals, &scale)) { + Points.setValues(points); + Normals.setValues(normals); + Scale.setValue(scale); //OvG: Scale + Points.touch(); // This triggers ViewProvider::updateData() + } + } +} diff --git a/src/Mod/Fem/App/FemConstraintRigidBody.h b/src/Mod/Fem/App/FemConstraintRigidBody.h new file mode 100644 index 0000000000..970bce23f2 --- /dev/null +++ b/src/Mod/Fem/App/FemConstraintRigidBody.h @@ -0,0 +1,77 @@ +/*************************************************************************** + * Copyright (c) 2022 Ajinkya Dahale * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef FEM_CONSTRAINTRIGIDBODY_H +#define FEM_CONSTRAINTRIGIDBODY_H + +#include "FemConstraint.h" + + +namespace Fem +{ + +class FemExport ConstraintRigidBody : public Fem::Constraint +{ + PROPERTY_HEADER_WITH_OVERRIDE(Fem::ConstraintRigidBody); + +public: + /// Constructor + ConstraintRigidBody(); + + // Read-only (calculated values). These trigger changes in the ViewProvider + App::PropertyVectorList Points; + App::PropertyVectorList Normals; + + // Rigid Body parameters + App::PropertyFloat xRefNode; + App::PropertyFloat yRefNode; + App::PropertyFloat zRefNode; + App::PropertyFloat xDisplacement; + App::PropertyFloat yDisplacement; + App::PropertyFloat zDisplacement; + App::PropertyFloat xRotation; + App::PropertyFloat yRotation; + App::PropertyFloat zRotation; + App::PropertyFloat xLoad; + App::PropertyFloat yLoad; + App::PropertyFloat zLoad; + App::PropertyFloat xMoment; + App::PropertyFloat yMoment; + App::PropertyFloat zMoment; + App::PropertyBool DefineRefNode; + + /// recalculate the object + App::DocumentObjectExecReturn *execute() override; + + /// returns the type name of the ViewProvider + const char* getViewProviderName() const override { + return "FemGui::ViewProviderFemConstraintRigidBody"; + } + +protected: + void onChanged(const App::Property* prop) override; +}; + +} // namespace Fem + + +#endif // FEM_CONSTRAINTRIGIDBODY_H diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index c4f36d46a2..23151146da 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -51,6 +51,7 @@ #include "ViewProviderFemConstraintContact.h" #include "ViewProviderFemConstraintDisplacement.h" #include "ViewProviderFemConstraintFixed.h" +#include "ViewProviderFemConstraintRigidBody.h" #include "ViewProviderFemConstraintForce.h" #include "ViewProviderFemConstraintFluidBoundary.h" #include "ViewProviderFemConstraintGear.h" @@ -120,6 +121,7 @@ PyMOD_INIT_FUNC(FemGui) FemGui::ViewProviderFemConstraintContact ::init(); FemGui::ViewProviderFemConstraintDisplacement ::init(); FemGui::ViewProviderFemConstraintFixed ::init(); + FemGui::ViewProviderFemConstraintRigidBody ::init(); FemGui::ViewProviderFemConstraintFluidBoundary ::init(); FemGui::ViewProviderFemConstraintForce ::init(); FemGui::ViewProviderFemConstraintGear ::init(); diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index 1d07f4e4f3..2842895ba4 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -63,6 +63,7 @@ set(FemGui_UIC_SRCS TaskFemConstraint.ui TaskFemConstraintBearing.ui TaskFemConstraintFixed.ui + TaskFemConstraintRigidBody.ui TaskFemConstraintForce.ui TaskFemConstraintFluidBoundary.ui TaskFemConstraintPressure.ui @@ -134,6 +135,9 @@ SET(FemGui_DLG_SRCS TaskFemConstraintFixed.ui TaskFemConstraintFixed.cpp TaskFemConstraintFixed.h + TaskFemConstraintRigidBody.ui + TaskFemConstraintRigidBody.cpp + TaskFemConstraintRigidBody.h TaskFemConstraintForce.ui TaskFemConstraintForce.cpp TaskFemConstraintForce.h @@ -210,6 +214,8 @@ SET(FemGui_SRCS_ViewProvider ViewProviderFemConstraintBearing.h ViewProviderFemConstraintFixed.cpp ViewProviderFemConstraintFixed.h + ViewProviderFemConstraintRigidBody.cpp + ViewProviderFemConstraintRigidBody.h ViewProviderFemConstraintForce.cpp ViewProviderFemConstraintForce.h ViewProviderFemConstraintFluidBoundary.cpp diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index 9c4c8a7732..501a7afb3e 100644 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -387,6 +387,48 @@ bool CmdFemConstraintFixed::isActive() } +//================================================================================================ +DEF_STD_CMD_A(CmdFemConstraintRigidBody) + +CmdFemConstraintRigidBody::CmdFemConstraintRigidBody() + : Command("FEM_ConstraintRigidBody") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Constraint rigid body"); + sToolTipText = QT_TR_NOOP("Creates a FEM constraint for a rigid body"); + sWhatsThis = "FEM_ConstraintRigidBody"; + sStatusTip = sToolTipText; + sPixmap = "FEM_ConstraintRigidBody"; +} + +void CmdFemConstraintRigidBody::activated(int) +{ + Fem::FemAnalysis* Analysis; + + if (getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("ConstraintRigidBody"); + + openCommand(QT_TRANSLATE_NOOP("Command", "Make FEM constraint fixed geometry")); + doCommand(Doc, "App.activeDocument().addObject(\"Fem::ConstraintRigidBody\",\"%s\")", FeatName.c_str()); + doCommand(Doc, "App.activeDocument().%s.Scale = 1", FeatName.c_str()); //OvG: set initial scale to 1 + doCommand(Doc, "App.activeDocument().%s.addObject(App.activeDocument().%s)", Analysis->getNameInDocument(), FeatName.c_str()); + + doCommand(Doc, "%s", gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui, "Gui.activeDocument().setEdit('%s')", FeatName.c_str()); +} + +bool CmdFemConstraintRigidBody::isActive() +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + + //================================================================================================ DEF_STD_CMD_A(CmdFemConstraintFluidBoundary) @@ -2625,6 +2667,7 @@ void CreateFemCommands() rcCmdMgr.addCommand(new CmdFemConstraintContact()); rcCmdMgr.addCommand(new CmdFemConstraintDisplacement()); rcCmdMgr.addCommand(new CmdFemConstraintFixed()); + rcCmdMgr.addCommand(new CmdFemConstraintRigidBody()); rcCmdMgr.addCommand(new CmdFemConstraintFluidBoundary()); rcCmdMgr.addCommand(new CmdFemConstraintForce()); rcCmdMgr.addCommand(new CmdFemConstraintGear()); diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp new file mode 100644 index 0000000000..fc4c234280 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp @@ -0,0 +1,310 @@ +/*************************************************************************** + * Copyright (c) 2022 Ajinkya Dahale * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +# include +#endif + +#include +#include +#include +#include + +#include "TaskFemConstraintRigidBody.h" +#include "ui_TaskFemConstraintRigidBody.h" + + +using namespace FemGui; +using namespace Gui; + +/* TRANSLATOR FemGui::TaskFemConstraintRigidBody */ + +TaskFemConstraintRigidBody::TaskFemConstraintRigidBody(ViewProviderFemConstraintRigidBody* ConstraintView, QWidget* parent) + : TaskFemConstraintOnBoundary(ConstraintView, parent, "FEM_ConstraintRigidBody") +{ //Note change "RigidBody" in line above to new constraint name + proxy = new QWidget(this); + ui = new Ui_TaskFemConstraintRigidBody(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + + // create a context menu for the listview of the references + createDeleteAction(ui->lw_references); + deleteAction->connect(deleteAction, &QAction::triggered, + this, &TaskFemConstraintRigidBody::onReferenceDeleted); + + connect(ui->lw_references, &QListWidget::currentItemChanged, + this, &TaskFemConstraintRigidBody::setSelection); + connect(ui->lw_references, &QListWidget::itemClicked, + this, &TaskFemConstraintRigidBody::setSelection); + + // TODO: Relate inputs to property + + this->groupLayout()->addWidget(proxy); + + /* Note: */ + // Get the feature data + Fem::ConstraintRigidBody* pcConstraint = static_cast(ConstraintView->getObject()); + double fStates[15]; + fStates[0] = pcConstraint->xRefNode.getValue(); + fStates[1] = pcConstraint->yRefNode.getValue(); + fStates[2] = pcConstraint->zRefNode.getValue(); + fStates[3] = pcConstraint->xDisplacement.getValue(); + fStates[4] = pcConstraint->yDisplacement.getValue(); + fStates[5] = pcConstraint->zDisplacement.getValue(); + fStates[6] = pcConstraint->xRotation.getValue(); + fStates[7] = pcConstraint->yRotation.getValue(); + fStates[8] = pcConstraint->zRotation.getValue(); + fStates[9] = pcConstraint->xLoad.getValue(); + fStates[10] = pcConstraint->yLoad.getValue(); + fStates[11] = pcConstraint->zLoad.getValue(); + fStates[12] = pcConstraint->xMoment.getValue(); + fStates[13] = pcConstraint->yMoment.getValue(); + fStates[14] = pcConstraint->zMoment.getValue(); + + std::vector Objects = pcConstraint->References.getValues(); + std::vector SubElements = pcConstraint->References.getSubValues(); + + // Fill data into dialog elements + ui->if_ref_node_x->setValue(fStates[0]); + ui->if_ref_node_y->setValue(fStates[1]); + ui->if_ref_node_z->setValue(fStates[2]); + ui->if_ref_load_x->setValue(fStates[9]); + ui->if_ref_load_y->setValue(fStates[10]); + ui->if_ref_load_z->setValue(fStates[11]); + ui->if_rot_load_x->setValue(fStates[12]); + ui->if_rot_load_y->setValue(fStates[13]); + ui->if_rot_load_z->setValue(fStates[14]); + + ui->lw_references->clear(); + for (std::size_t i = 0; i < Objects.size(); i++) { + ui->lw_references->addItem(makeRefText(Objects[i], SubElements[i])); + } + if (!Objects.empty()) { + ui->lw_references->setCurrentRow(0, QItemSelectionModel::ClearAndSelect); + } + + //Selection buttons + buttonGroup->addButton(ui->btnAdd, (int)SelectionChangeModes::refAdd); + buttonGroup->addButton(ui->btnRemove, (int)SelectionChangeModes::refRemove); + + updateUI(); +} + +TaskFemConstraintRigidBody::~TaskFemConstraintRigidBody() +{ + delete ui; +} + +void TaskFemConstraintRigidBody::updateUI() +{ + if (ui->lw_references->model()->rowCount() == 0) { + // Go into reference selection mode if no reference has been selected yet + onButtonReference(true); + return; + } +} + +void TaskFemConstraintRigidBody::addToSelection() +{ + std::vector selection = Gui::Selection().getSelectionEx(); //gets vector of selected objects of active document + if (selection.empty()) { + QMessageBox::warning(this, tr("Selection error"), tr("Nothing selected!")); + return; + } + Fem::ConstraintRigidBody* pcConstraint = static_cast(ConstraintView->getObject()); + std::vector Objects = pcConstraint->References.getValues(); + std::vector SubElements = pcConstraint->References.getSubValues(); + + for (std::vector::iterator it = selection.begin(); it != selection.end(); ++it) {//for every selected object + if (!it->isObjectTypeOf(Part::Feature::getClassTypeId())) { + QMessageBox::warning(this, tr("Selection error"), tr("Selected object is not a part!")); + return; + } + std::vector subNames = it->getSubNames(); + App::DocumentObject* obj = ConstraintView->getObject()->getDocument()->getObject(it->getFeatName()); + for (size_t subIt = 0; subIt < (subNames.size()); ++subIt) {// for every selected sub element + bool addMe = true; + for (std::vector::iterator itr = std::find(SubElements.begin(), SubElements.end(), subNames[subIt]); + itr != SubElements.end(); + itr = std::find(++itr, SubElements.end(), subNames[subIt])) + {// for every sub element in selection that matches one in old list + if (obj == Objects[std::distance(SubElements.begin(), itr)]) {//if selected sub element's object equals the one in old list then it was added before so don't add + addMe = false; + } + } + // limit constraint such that only vertexes or faces or edges can be used depending on what was selected first + std::string searchStr; + if (subNames[subIt].find("Vertex") != std::string::npos) + searchStr = "Vertex"; + else if (subNames[subIt].find("Edge") != std::string::npos) + searchStr = "Edge"; + else + searchStr = "Face"; + for (size_t iStr = 0; iStr < (SubElements.size()); ++iStr) { + if (SubElements[iStr].find(searchStr) == std::string::npos) { + QString msg = tr("Only one type of selection (vertex,face or edge) per constraint allowed!"); + QMessageBox::warning(this, tr("Selection error"), msg); + addMe = false; + break; + } + } + if (addMe) { + QSignalBlocker block(ui->lw_references); + Objects.push_back(obj); + SubElements.push_back(subNames[subIt]); + ui->lw_references->addItem(makeRefText(obj, subNames[subIt])); + } + } + } + //Update UI + pcConstraint->References.setValues(Objects, SubElements); + updateUI(); +} + +void TaskFemConstraintRigidBody::removeFromSelection() +{ + std::vector selection = Gui::Selection().getSelectionEx(); //gets vector of selected objects of active document + if (selection.empty()) { + QMessageBox::warning(this, tr("Selection error"), tr("Nothing selected!")); + return; + } + Fem::ConstraintRigidBody* pcConstraint = static_cast(ConstraintView->getObject()); + std::vector Objects = pcConstraint->References.getValues(); + std::vector SubElements = pcConstraint->References.getSubValues(); + std::vector itemsToDel; + for (std::vector::iterator it = selection.begin(); it != selection.end(); ++it) {//for every selected object + if (!it->isObjectTypeOf(Part::Feature::getClassTypeId())) { + QMessageBox::warning(this, tr("Selection error"), tr("Selected object is not a part!")); + return; + } + const std::vector& subNames = it->getSubNames(); + App::DocumentObject* obj = it->getObject(); + + for (size_t subIt = 0; subIt < (subNames.size()); ++subIt) {// for every selected sub element + for (std::vector::iterator itr = std::find(SubElements.begin(), SubElements.end(), subNames[subIt]); + itr != SubElements.end(); + itr = std::find(++itr, SubElements.end(), subNames[subIt])) + {// for every sub element in selection that matches one in old list + if (obj == Objects[std::distance(SubElements.begin(), itr)]) {//if selected sub element's object equals the one in old list then it was added before so mark for deletion + itemsToDel.push_back(std::distance(SubElements.begin(), itr)); + } + } + } + } + std::sort(itemsToDel.begin(), itemsToDel.end()); + while (!itemsToDel.empty()) { + Objects.erase(Objects.begin() + itemsToDel.back()); + SubElements.erase(SubElements.begin() + itemsToDel.back()); + itemsToDel.pop_back(); + } + //Update UI + { + QSignalBlocker block(ui->lw_references); + ui->lw_references->clear(); + for (unsigned int j = 0; j < Objects.size(); j++) { + ui->lw_references->addItem(makeRefText(Objects[j], SubElements[j])); + } + } + pcConstraint->References.setValues(Objects, SubElements); + updateUI(); +} + +void TaskFemConstraintRigidBody::onReferenceDeleted() { + TaskFemConstraintRigidBody::removeFromSelection(); +} + +const std::string TaskFemConstraintRigidBody::getReferences() const +{ + int rows = ui->lw_references->model()->rowCount(); + std::vector items; + for (int r = 0; r < rows; r++) { + items.push_back(ui->lw_references->item(r)->text().toStdString()); + } + return TaskFemConstraint::getReferences(items); +} + +bool TaskFemConstraintRigidBody::event(QEvent* e) +{ + return TaskFemConstraint::KeyEvent(e); +} + +void TaskFemConstraintRigidBody::changeEvent(QEvent*) +{ +} + +void TaskFemConstraintRigidBody::clearButtons(const SelectionChangeModes notThis) +{ + if (notThis != SelectionChangeModes::refAdd) + ui->btnAdd->setChecked(false); + if (notThis != SelectionChangeModes::refRemove) + ui->btnRemove->setChecked(false); +} + +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgFemConstraintRigidBody::TaskDlgFemConstraintRigidBody(ViewProviderFemConstraintRigidBody* ConstraintView) +{ + this->ConstraintView = ConstraintView; + assert(ConstraintView); + this->parameter = new TaskFemConstraintRigidBody(ConstraintView); + + Content.push_back(parameter); +} + +//==== calls from the TaskView =============================================================== + +void TaskDlgFemConstraintRigidBody::open() +{ + // a transaction is already open at creation time of the panel + if (!Gui::Command::hasPendingCommand()) { + QString msg = QObject::tr("Constraint RigidBody"); + Gui::Command::openCommand((const char*)msg.toUtf8()); + ConstraintView->setVisible(true); + Gui::Command::doCommand(Gui::Command::Doc, ViewProviderFemConstraint::gethideMeshShowPartStr((static_cast(ConstraintView->getObject()))->getNameInDocument()).c_str()); //OvG: Hide meshes and show parts + } +} + +bool TaskDlgFemConstraintRigidBody::accept() +{ + std::string name = ConstraintView->getObject()->getNameInDocument(); + const TaskFemConstraintRigidBody* parameters = static_cast(parameter); + std::string scale = parameters->getScale(); //OvG: determine modified scale + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.Scale = %s", name.c_str(), scale.c_str()); //OvG: implement modified scale + return TaskDlgFemConstraint::accept(); +} + +bool TaskDlgFemConstraintRigidBody::reject() +{ + Gui::Command::abortCommand(); + Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeDocument().resetEdit()"); + Gui::Command::updateActive(); + + return true; +} + +#include "moc_TaskFemConstraintRigidBody.cpp" diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h new file mode 100644 index 0000000000..dca5bf7c49 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (c) 2022 Ajinkya Dahale * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef GUI_TASKVIEW_TaskFemConstraintRigidBody_H +#define GUI_TASKVIEW_TaskFemConstraintRigidBody_H + +#include + +#include "TaskFemConstraintOnBoundary.h" +#include "ViewProviderFemConstraintRigidBody.h" + + +class Ui_TaskFemConstraintRigidBody; + +namespace FemGui { +class TaskFemConstraintRigidBody : public TaskFemConstraintOnBoundary +{ + Q_OBJECT + +public: + explicit TaskFemConstraintRigidBody(ViewProviderFemConstraintRigidBody *ConstraintView,QWidget *parent = nullptr); + ~TaskFemConstraintRigidBody() override; + const std::string getReferences() const override; + +private Q_SLOTS: + void onReferenceDeleted(); + void addToSelection() override; + void removeFromSelection() override; + +protected: + bool event(QEvent *e) override; + void changeEvent(QEvent *e) override; + void clearButtons(const SelectionChangeModes notThis) override; + +private: + void updateUI(); + Ui_TaskFemConstraintRigidBody* ui; + +}; + +class TaskDlgFemConstraintRigidBody : public TaskDlgFemConstraint +{ + Q_OBJECT + +public: + explicit TaskDlgFemConstraintRigidBody(ViewProviderFemConstraintRigidBody *ConstraintView); + void open() override; + bool accept() override; + bool reject() override; +}; + +} //namespace FemGui + +#endif // GUI_TASKVIEW_TaskFemConstraintRigidBody_H diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui new file mode 100644 index 0000000000..2ea39976dd --- /dev/null +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui @@ -0,0 +1,317 @@ + + + TaskFemConstraintRigidBody + + + + 0 + 0 + 296 + 587 + + + + Form + + + + + + Select multiple face(s), click Add or Remove + + + + + + + + + + 0 + 0 + + + + Add + + + true + + + + + + + + 0 + 0 + + + + Remove + + + true + + + + + + + + + + + + + + Reference Node + + + + + + + + + X: + + + + + + + 0 mm + + + mm + + + 0.000000000000000 + + + + + + + Y: + + + + + + + 0 mm + + + mm + + + 0.000000000000000 + + + + + + + Z: + + + + + + + 0 mm + + + mm + + + 0.000000000000000 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Load on Reference Node + + + + + + + + + X: + + + + + + + 0 N + + + N + + + 0.000000000000000 + + + + + + + Y: + + + + + + + 0 N + + + N + + + 0.000000000000000 + + + + + + + Z: + + + + + + + 0 N + + + N + + + 0.000000000000000 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Moment on Rotation Node + + + + + + + + + X: + + + + + + + 0 N mm + + + N mm + + + 0.000000000000000 + + + + + + + Y: + + + + + + + 0 N mm + + + N mm + + + 0.000000000000000 + + + + + + + Z: + + + + + + + 0 N mm + + + N mm + + + 0.000000000000000 + + + + + + + + + + + + Gui::InputField + QLineEdit +
Gui/InputField.h
+
+
+ + +
diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.cpp new file mode 100644 index 0000000000..0d11bacdac --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.cpp @@ -0,0 +1,167 @@ +/*************************************************************************** + * Copyright (c) 2022 Ajinkya Dahale * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +# include +# include +# include +#endif + +#include +#include "Gui/Control.h" + +#include "ViewProviderFemConstraintRigidBody.h" +#include "TaskFemConstraintRigidBody.h" + + +using namespace FemGui; + +PROPERTY_SOURCE(FemGui::ViewProviderFemConstraintRigidBody, FemGui::ViewProviderFemConstraintOnBoundary) + + +ViewProviderFemConstraintRigidBody::ViewProviderFemConstraintRigidBody() +{ + sPixmap = "FEM_ConstraintRigidBody"; +} + +ViewProviderFemConstraintRigidBody::~ViewProviderFemConstraintRigidBody() +{ +} + +bool ViewProviderFemConstraintRigidBody::setEdit(int ModNum) +{ + if (ModNum == ViewProvider::Default ) { + // When double-clicking on the item for this constraint the + // object unsets and sets its edit mode without closing + // the task panel + Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog(); + TaskDlgFemConstraintRigidBody *constrDlg = qobject_cast(dlg); + if (constrDlg && constrDlg->getConstraintView() != this) + constrDlg = nullptr; // another constraint left open its task panel + if (dlg && !constrDlg) { + // This case will occur in the ShaftWizard application + checkForWizard(); + if (!wizardWidget || !wizardSubLayout) { + // No shaft wizard is running + QMessageBox msgBox; + msgBox.setText(QObject::tr("A dialog is already open in the task panel")); + msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + Gui::Control().reject(); + else + return false; + } else if (constraintDialog) { + // Another FemConstraint* dialog is already open inside the Shaft Wizard + // Ignore the request to open another dialog + return false; + } else { + constraintDialog = new TaskFemConstraintRigidBody(this); + return true; + } + } + + // clear the selection (convenience) + Gui::Selection().clearSelection(); + + // start the edit dialog + if (constrDlg) + Gui::Control().showDialog(constrDlg); + else + Gui::Control().showDialog(new TaskDlgFemConstraintRigidBody(this)); + + return true; + } else { + return ViewProviderDocumentObject::setEdit(ModNum); // clazy:exclude=skipped-base-method + } +} + +#define WIDTH (2) +#define HEIGHT (1) +//#define USE_MULTIPLE_COPY //OvG: MULTICOPY fails to update scaled display on initial drawing - so disable + +void ViewProviderFemConstraintRigidBody::updateData(const App::Property* prop) +{ + // Gets called whenever a property of the attached object changes + Fem::ConstraintRigidBody *pcConstraint = static_cast(this->getObject()); + float scaledwidth = WIDTH * pcConstraint->Scale.getValue(); //OvG: Calculate scaled values once only + float scaledheight = HEIGHT * pcConstraint->Scale.getValue(); + +#ifdef USE_MULTIPLE_COPY + //OvG: always need access to cp for scaling + SoMultipleCopy* cp = new SoMultipleCopy(); + if (pShapeSep->getNumChildren() == 0) { + // Set up the nodes + cp->matrix.setNum(0); + cp->addChild((SoNode*)createRigidBody(scaledheight, scaledwidth)); //OvG: Scaling + pShapeSep->addChild(cp); + } +#endif + + if (strcmp(prop->getName(),"Points") == 0) { + const std::vector& points = pcConstraint->Points.getValues(); + const std::vector& normals = pcConstraint->Normals.getValues(); + if (points.size() != normals.size()) + return; + std::vector::const_iterator n = normals.begin(); + +#ifdef USE_MULTIPLE_COPY + cp = static_cast(pShapeSep->getChild(0)); + cp->matrix.setNum(points.size()); + SbMatrix* matrices = cp->matrix.startEditing(); + int idx = 0; +#else + // Note: Points and Normals are always updated together + Gui::coinRemoveAllChildren(pShapeSep); +#endif + + for (std::vector::const_iterator p = points.begin(); p != points.end(); + p++) { + SbVec3f base(p->x, p->y, p->z); + SbVec3f dir(n->x, n->y, n->z); + SbRotation rot(SbVec3f(0, -1, 0), dir); +#ifdef USE_MULTIPLE_COPY + SbMatrix m; + m.setTransform(base, rot, SbVec3f(1, 1, 1)); + matrices[idx] = m; + idx++; +#else + SoSeparator* sep = new SoSeparator(); + createPlacement(sep, base, rot); + createFixed(sep, scaledheight, scaledwidth); //OvG: Scaling + pShapeSep->addChild(sep); +#endif + n++; + } +#ifdef USE_MULTIPLE_COPY + cp->matrix.finishEditing(); +#endif + } + + ViewProviderFemConstraint::updateData(prop); +} diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.h b/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.h new file mode 100644 index 0000000000..956e8513c9 --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (c) 2022 Ajinkya Dahale * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef GUI_VIEWPROVIDERFEMCONSTRAINTRIGIDBODY_H +#define GUI_VIEWPROVIDERFEMCONSTRAINTRIGIDBODY_H + +#include "ViewProviderFemConstraintOnBoundary.h" + +namespace FemGui +{ + +class FemGuiExport ViewProviderFemConstraintRigidBody : public FemGui::ViewProviderFemConstraintOnBoundary +{ + PROPERTY_HEADER_WITH_OVERRIDE(FemGui::ViewProviderFemConstraintRigidBody); + +public: + /// Constructor + ViewProviderFemConstraintRigidBody(); + ~ViewProviderFemConstraintRigidBody() override; + + void updateData(const App::Property*) override; + +protected: + bool setEdit(int ModNum) override; +}; + +} //namespace FemGui + + +#endif // GUI_VIEWPROVIDERFEMCONSTRAINTRIGIDBODY_H diff --git a/src/Mod/Fem/Gui/Workbench.cpp b/src/Mod/Fem/Gui/Workbench.cpp index eccc5ed9e7..d146a0887f 100644 --- a/src/Mod/Fem/Gui/Workbench.cpp +++ b/src/Mod/Fem/Gui/Workbench.cpp @@ -132,6 +132,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const Gui::ToolBarItem* mech = new Gui::ToolBarItem(root); mech->setCommand("Mechanical boundary conditions and loads"); *mech << "FEM_ConstraintFixed" + << "FEM_ConstraintRigidBody" << "FEM_ConstraintDisplacement" << "FEM_ConstraintContact" << "FEM_ConstraintTie" @@ -263,6 +264,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const Gui::MenuItem* mech = new Gui::MenuItem; mech->setCommand("&Mechanical boundary conditions and loads"); *mech << "FEM_ConstraintFixed" + << "FEM_ConstraintRigidBody" << "FEM_ConstraintDisplacement" << "FEM_ConstraintContact" << "FEM_ConstraintTie" From 5ae3c93fc3f3ce593fcb63583a977b5c4bde24ae Mon Sep 17 00:00:00 2001 From: Ajinkya Dahale Date: Wed, 2 Nov 2022 00:16:58 +0530 Subject: [PATCH 02/13] FEM: Make connections with rigid body gui and app --- .../Fem/Gui/TaskFemConstraintRigidBody.cpp | 33 +++++++++++++++++-- src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h | 10 ++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp index fc4c234280..e108d498e9 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp @@ -246,6 +246,18 @@ const std::string TaskFemConstraintRigidBody::getReferences() const return TaskFemConstraint::getReferences(items); } +double TaskFemConstraintRigidBody::get_xRefNode() const { return ui->if_ref_node_x->rawValue(); } +double TaskFemConstraintRigidBody::get_yRefNode() const { return ui->if_ref_node_y->rawValue(); } +double TaskFemConstraintRigidBody::get_zRefNode() const { return ui->if_ref_node_z->rawValue(); } +double TaskFemConstraintRigidBody::get_xLoad() const { return ui->if_ref_load_x->rawValue(); } +double TaskFemConstraintRigidBody::get_yLoad() const { return ui->if_ref_load_y->rawValue(); } +double TaskFemConstraintRigidBody::get_zLoad() const { return ui->if_ref_load_z->rawValue(); } +double TaskFemConstraintRigidBody::get_xMoment() const { return ui->if_rot_load_x->rawValue(); } +double TaskFemConstraintRigidBody::get_yMoment() const { return ui->if_rot_load_y->rawValue(); } +double TaskFemConstraintRigidBody::get_zMoment() const { return ui->if_rot_load_z->rawValue(); } +// TODO: This needs to be implemented +bool TaskFemConstraintRigidBody::get_DefineRefNode() const { return true; } + bool TaskFemConstraintRigidBody::event(QEvent* e) { return TaskFemConstraint::KeyEvent(e); @@ -293,8 +305,25 @@ bool TaskDlgFemConstraintRigidBody::accept() { std::string name = ConstraintView->getObject()->getNameInDocument(); const TaskFemConstraintRigidBody* parameters = static_cast(parameter); - std::string scale = parameters->getScale(); //OvG: determine modified scale - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.Scale = %s", name.c_str(), scale.c_str()); //OvG: implement modified scale + try { + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.xRefNode = %f", name.c_str(), parameters->get_xRefNode()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.yRefNode = %f", name.c_str(), parameters->get_yRefNode()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.zRefNode = %f", name.c_str(), parameters->get_zRefNode()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.xLoad = %f", name.c_str(), parameters->get_xLoad()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.yLoad = %f", name.c_str(), parameters->get_yLoad()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.zLoad = %f", name.c_str(), parameters->get_zLoad()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.xMoment = %f", name.c_str(), parameters->get_xMoment()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.yMoment = %f", name.c_str(), parameters->get_yMoment()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.zMoment = %f", name.c_str(), parameters->get_zMoment()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.DefineRefNode = %s", name.c_str(), parameters->get_DefineRefNode() ? "True" : "False"); + + std::string scale = parameters->getScale(); //OvG: determine modified scale + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.Scale = %s", name.c_str(), scale.c_str()); //OvG: implement modified scale + } + catch (const Base::Exception& e) { + QMessageBox::warning(parameter, tr("Input error"), QString::fromLatin1(e.what())); + return false; + } return TaskDlgFemConstraint::accept(); } diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h index dca5bf7c49..fc8df9f372 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h @@ -40,6 +40,16 @@ public: explicit TaskFemConstraintRigidBody(ViewProviderFemConstraintRigidBody *ConstraintView,QWidget *parent = nullptr); ~TaskFemConstraintRigidBody() override; const std::string getReferences() const override; + double get_xRefNode() const; + double get_yRefNode() const; + double get_zRefNode() const; + double get_xLoad() const; + double get_yLoad() const; + double get_zLoad() const; + double get_xMoment() const; + double get_yMoment() const; + double get_zMoment() const; + bool get_DefineRefNode() const; private Q_SLOTS: void onReferenceDeleted(); From cc6e59eaccb9839a3505bc103be1f91d787ac93d Mon Sep 17 00:00:00 2001 From: Ajinkya Dahale Date: Wed, 2 Nov 2022 17:20:07 +0530 Subject: [PATCH 03/13] FEM: Add rigid body constraint to ccx writer --- src/Mod/Fem/CMakeLists.txt | 1 + src/Mod/Fem/ObjectsFem.py | 10 ++ src/Mod/Fem/femmesh/meshsetsgetter.py | 16 +++ .../calculix/write_constraint_rigidbody.py | 105 ++++++++++++++++++ src/Mod/Fem/femsolver/calculix/writer.py | 3 + src/Mod/Fem/femtools/membertools.py | 7 ++ 6 files changed, 142 insertions(+) create mode 100644 src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody.py diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 91ed22746b..365e208dc7 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -231,6 +231,7 @@ SET(FemSolverCalculix_SRCS femsolver/calculix/write_constraint_initialtemperature.py femsolver/calculix/write_constraint_planerotation.py femsolver/calculix/write_constraint_pressure.py + femsolver/calculix/write_constraint_rigidbody.py femsolver/calculix/write_constraint_sectionprint.py femsolver/calculix/write_constraint_selfweight.py femsolver/calculix/write_constraint_temperature.py diff --git a/src/Mod/Fem/ObjectsFem.py b/src/Mod/Fem/ObjectsFem.py index c1e6deb951..40f73d3945 100644 --- a/src/Mod/Fem/ObjectsFem.py +++ b/src/Mod/Fem/ObjectsFem.py @@ -173,6 +173,16 @@ def makeConstraintFixed( return obj +def makeConstraintRigidBody( + doc, + name="ConstraintRigidBody" +): + """makeConstraintRigidBody(document, [name]): + makes a Fem ConstraintRigidBody object""" + obj = doc.addObject("Fem::ConstraintRigidBody", name) + return obj + + def makeConstraintFlowVelocity( doc, name="ConstraintFlowVelocity" diff --git a/src/Mod/Fem/femmesh/meshsetsgetter.py b/src/Mod/Fem/femmesh/meshsetsgetter.py index 4ef2b31702..c84b2b31b0 100644 --- a/src/Mod/Fem/femmesh/meshsetsgetter.py +++ b/src/Mod/Fem/femmesh/meshsetsgetter.py @@ -139,6 +139,7 @@ class MeshSetsGetter(): # constraints node sets getter self.get_constraints_fixed_nodes() self.get_constraints_displacement_nodes() + self.get_constraints_rigidbody_nodes() self.get_constraints_planerotation_nodes() # constraints surface sets getter @@ -205,6 +206,21 @@ class MeshSetsGetter(): femobj["NodesSolid"] = set(nds_solid) femobj["NodesFaceEdge"] = set(nds_faceedge) + def get_constraints_rigidbody_nodes(self): + if not self.member.cons_rigidbody: + return + # get nodes + for femobj in self.member.cons_rigidbody: + # femobj --> dict, FreeCAD document object is femobj["Object"] + print_obj_info(femobj["Object"]) + femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references( + self.femmesh, + femobj + ) + # add nodes to constraint_conflict_nodes, needed by constraint plane rotation + for node in femobj["Nodes"]: + self.constraint_conflict_nodes.append(node) + def get_constraints_displacement_nodes(self): if not self.member.cons_displacement: return diff --git a/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody.py b/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody.py new file mode 100644 index 0000000000..26169e4098 --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody.py @@ -0,0 +1,105 @@ +# *************************************************************************** +# * Copyright (c) 2022 Ajinkya Dahale * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint rigid body" +__author__ = "Ajinkya Dahale" +__url__ = "https://www.freecadweb.org" + + +def get_analysis_types(): + return "all" # write for all analysis types + + +def get_sets_name(): + return "constraints_rigidbody_node_sets" + + +def get_constraint_title(): + return "Rigid Body Constraints" + + +def get_before_write_meshdata_constraint(): + return "" + + +def get_after_write_meshdata_constraint(): + return "" + + +def get_before_write_constraint(): + return "" + + +def get_after_write_constraint(): + return "" + + +def write_meshdata_constraint(f, femobj, rb_obj, ccxwriter): + f.write("*NSET,NSET=" + rb_obj.Name + "\n") + for n in femobj["Nodes"]: + f.write("{},\n".format(n)) + + +def write_constraint(f, femobj, rb_obj, ccxwriter): + + # floats read from ccx should use {:.13G}, see comment in writer module + is_ref_bc_defined = any((rb_obj.xDisplacement, + rb_obj.yDisplacement, + rb_obj.zDisplacement, + rb_obj.xLoad, + rb_obj.yLoad, + rb_obj.zLoad)) + + is_rot_bc_defined = any((rb_obj.xRotation, + rb_obj.yRotation, + rb_obj.zRotation, + rb_obj.xMoment, + rb_obj.yMoment, + rb_obj.zMoment)) + + # FIXME: This needs to be implemented + ref_node_idx = -1 + rot_node_idx = -1 + + kw_line = "*RIGID BODY,NSET={}".format(rb_obj.Name) + + if is_ref_bc_defined: + kw_line = kw_line + ",REF NODE={}".format(ref_node_idx) + + if is_rot_bc_defined: + kw_line = kw_line + ",ROT NODE={}".format(rot_node_idx) + + f.write(kw_line + "\n") + + # TODO: Displacement definitions need fixing + if is_ref_bc_defined: + f.write("*CLOAD\n") + f.write("{},1,{}\n".format(ref_node_idx, rb_obj.xLoad)) + f.write("{},2,{}\n".format(ref_node_idx, rb_obj.yLoad)) + f.write("{},3,{}\n".format(ref_node_idx, rb_obj.zLoad)) + + if is_rot_bc_defined: + f.write("*CLOAD\n") + f.write("{},1,{}\n".format(rot_node_idx, rb_obj.xMoment)) + f.write("{},2,{}\n".format(rot_node_idx, rb_obj.yMoment)) + f.write("{},3,{}\n".format(rot_node_idx, rb_obj.zMoment)) diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py index bf61f35baa..25225bc9c5 100644 --- a/src/Mod/Fem/femsolver/calculix/writer.py +++ b/src/Mod/Fem/femsolver/calculix/writer.py @@ -45,6 +45,7 @@ from . import write_constraint_heatflux as con_heatflux from . import write_constraint_initialtemperature as con_itemp from . import write_constraint_planerotation as con_planerotation from . import write_constraint_pressure as con_pressure +from . import write_constraint_rigidbody as con_rigidbody from . import write_constraint_sectionprint as con_sectionprint from . import write_constraint_selfweight as con_selfweight from . import write_constraint_temperature as con_temperature @@ -161,6 +162,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # node sets self.write_constraints_meshsets(inpfile, self.member.cons_fixed, con_fixed) + self.write_constraints_meshsets(inpfile, self.member.cons_rigidbody, con_rigidbody) self.write_constraints_meshsets(inpfile, self.member.cons_displacement, con_displacement) self.write_constraints_meshsets(inpfile, self.member.cons_planerotation, con_planerotation) self.write_constraints_meshsets(inpfile, self.member.cons_transform, con_transform) @@ -181,6 +183,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): self.write_constraints_propdata(inpfile, self.member.cons_contact, con_contact) self.write_constraints_propdata(inpfile, self.member.cons_tie, con_tie) self.write_constraints_propdata(inpfile, self.member.cons_transform, con_transform) + self.write_constraints_propdata(inpfile, self.member.cons_rigidbody, con_rigidbody) # step equation write_step_equation.write_step_equation(inpfile, self) diff --git a/src/Mod/Fem/femtools/membertools.py b/src/Mod/Fem/femtools/membertools.py index e75ce7d593..705885b0a6 100644 --- a/src/Mod/Fem/femtools/membertools.py +++ b/src/Mod/Fem/femtools/membertools.py @@ -207,6 +207,10 @@ class AnalysisMember(): list of fixed constraints from the analysis. [{"Object":fixed_obj, "NodeSupports":bool}, {}, ...] + constraints_rigidbody : list of dictionaries + list of displacements for the analysis. + [{"Object":rigidbody_obj, "xxxxxxxx":value}, {}, ...] + constraints_force : list of dictionaries list of force constraints from the analysis. [{"Object":force_obj, "NodeLoad":value}, {}, ... @@ -294,6 +298,9 @@ class AnalysisMember(): self.cons_fixed = self.get_several_member( "Fem::ConstraintFixed" ) + self.cons_rigidbody = self.get_several_member( + "Fem::ConstraintRigidBody" + ) self.cons_force = self.get_several_member( "Fem::ConstraintForce" ) From 4feb519bc94448f63dc556eea57463f2dfbb4900 Mon Sep 17 00:00:00 2001 From: Ajinkya Dahale Date: Sat, 5 Nov 2022 16:39:27 +0530 Subject: [PATCH 04/13] FEM: Add unit test for new `ConstraintRigidBody` object --- src/Mod/Fem/App/FemConstraintRigidBody.cpp | 50 ++-- src/Mod/Fem/App/FemConstraintRigidBody.h | 11 +- src/Mod/Fem/Gui/Command.cpp | 34 ++- .../Fem/Gui/TaskFemConstraintRigidBody.cpp | 246 +++++++++++++----- src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h | 21 +- .../ViewProviderFemConstraintRigidBody.cpp | 71 ++--- .../Gui/ViewProviderFemConstraintRigidBody.h | 7 +- src/Mod/Fem/femtest/app/test_object.py | 28 ++ 8 files changed, 318 insertions(+), 150 deletions(-) diff --git a/src/Mod/Fem/App/FemConstraintRigidBody.cpp b/src/Mod/Fem/App/FemConstraintRigidBody.cpp index b2c2dc2d10..0d55192806 100644 --- a/src/Mod/Fem/App/FemConstraintRigidBody.cpp +++ b/src/Mod/Fem/App/FemConstraintRigidBody.cpp @@ -31,33 +31,39 @@ PROPERTY_SOURCE(Fem::ConstraintRigidBody, Fem::Constraint) ConstraintRigidBody::ConstraintRigidBody() { - ADD_PROPERTY(xRefNode,(0.0)); - ADD_PROPERTY(yRefNode,(0.0)); - ADD_PROPERTY(zRefNode,(0.0)); - ADD_PROPERTY(xDisplacement,(0.0)); - ADD_PROPERTY(yDisplacement,(0.0)); - ADD_PROPERTY(zDisplacement,(0.0)); - ADD_PROPERTY(xRotation,(0.0)); - ADD_PROPERTY(yRotation,(0.0)); - ADD_PROPERTY(zRotation,(0.0)); - ADD_PROPERTY(xLoad,(0.0)); - ADD_PROPERTY(yLoad,(0.0)); - ADD_PROPERTY(zLoad,(0.0)); - ADD_PROPERTY(xMoment,(0.0)); - ADD_PROPERTY(yMoment,(0.0)); - ADD_PROPERTY(zMoment,(0.0)); - ADD_PROPERTY(DefineRefNode,(1)); + ADD_PROPERTY(xRefNode, (0.0)); + ADD_PROPERTY(yRefNode, (0.0)); + ADD_PROPERTY(zRefNode, (0.0)); + ADD_PROPERTY(xDisplacement, (0.0)); + ADD_PROPERTY(yDisplacement, (0.0)); + ADD_PROPERTY(zDisplacement, (0.0)); + ADD_PROPERTY(xRotation, (0.0)); + ADD_PROPERTY(yRotation, (0.0)); + ADD_PROPERTY(zRotation, (0.0)); + ADD_PROPERTY(xLoad, (0.0)); + ADD_PROPERTY(yLoad, (0.0)); + ADD_PROPERTY(zLoad, (0.0)); + ADD_PROPERTY(xMoment, (0.0)); + ADD_PROPERTY(yMoment, (0.0)); + ADD_PROPERTY(zMoment, (0.0)); + ADD_PROPERTY(DefineRefNode, (1)); // For drawing the icons - ADD_PROPERTY_TYPE(Points,(Base::Vector3d()),"ConstraintRigidBody",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output), + ADD_PROPERTY_TYPE(Points, + (Base::Vector3d()), + "ConstraintRigidBody", + App::PropertyType(App::Prop_ReadOnly | App::Prop_Output), "Points where symbols are drawn"); - ADD_PROPERTY_TYPE(Normals,(Base::Vector3d()),"ConstraintRigidBody",App::PropertyType(App::Prop_ReadOnly|App::Prop_Output), + ADD_PROPERTY_TYPE(Normals, + (Base::Vector3d()), + "ConstraintRigidBody", + App::PropertyType(App::Prop_ReadOnly | App::Prop_Output), "Normals where symbols are drawn"); Points.setValues(std::vector()); Normals.setValues(std::vector()); } -App::DocumentObjectExecReturn *ConstraintRigidBody::execute() +App::DocumentObjectExecReturn* ConstraintRigidBody::execute() { return Constraint::execute(); } @@ -71,12 +77,12 @@ void ConstraintRigidBody::onChanged(const App::Property* prop) if (prop == &References) { std::vector points; std::vector normals; - int scale = 1; //OvG: Enforce use of scale + int scale = 1; // OvG: Enforce use of scale if (getPoints(points, normals, &scale)) { Points.setValues(points); Normals.setValues(normals); - Scale.setValue(scale); //OvG: Scale - Points.touch(); // This triggers ViewProvider::updateData() + Scale.setValue(scale); // OvG: Scale + Points.touch(); // This triggers ViewProvider::updateData() } } } diff --git a/src/Mod/Fem/App/FemConstraintRigidBody.h b/src/Mod/Fem/App/FemConstraintRigidBody.h index 970bce23f2..3f3b0a795a 100644 --- a/src/Mod/Fem/App/FemConstraintRigidBody.h +++ b/src/Mod/Fem/App/FemConstraintRigidBody.h @@ -29,7 +29,7 @@ namespace Fem { -class FemExport ConstraintRigidBody : public Fem::Constraint +class FemExport ConstraintRigidBody: public Fem::Constraint { PROPERTY_HEADER_WITH_OVERRIDE(Fem::ConstraintRigidBody); @@ -60,10 +60,11 @@ public: App::PropertyBool DefineRefNode; /// recalculate the object - App::DocumentObjectExecReturn *execute() override; + App::DocumentObjectExecReturn* execute() override; /// returns the type name of the ViewProvider - const char* getViewProviderName() const override { + const char* getViewProviderName() const override + { return "FemGui::ViewProviderFemConstraintRigidBody"; } @@ -71,7 +72,7 @@ protected: void onChanged(const App::Property* prop) override; }; -} // namespace Fem +} // namespace Fem -#endif // FEM_CONSTRAINTRIGIDBODY_H +#endif // FEM_CONSTRAINTRIGIDBODY_H diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index 501a7afb3e..31d85d49a6 100644 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -393,30 +393,40 @@ DEF_STD_CMD_A(CmdFemConstraintRigidBody) CmdFemConstraintRigidBody::CmdFemConstraintRigidBody() : Command("FEM_ConstraintRigidBody") { - sAppModule = "Fem"; - sGroup = QT_TR_NOOP("Fem"); - sMenuText = QT_TR_NOOP("Constraint rigid body"); - sToolTipText = QT_TR_NOOP("Creates a FEM constraint for a rigid body"); - sWhatsThis = "FEM_ConstraintRigidBody"; - sStatusTip = sToolTipText; - sPixmap = "FEM_ConstraintRigidBody"; + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Constraint rigid body"); + sToolTipText = QT_TR_NOOP("Creates a FEM constraint for a rigid body"); + sWhatsThis = "FEM_ConstraintRigidBody"; + sStatusTip = sToolTipText; + sPixmap = "FEM_ConstraintRigidBody"; } void CmdFemConstraintRigidBody::activated(int) { Fem::FemAnalysis* Analysis; - if (getConstraintPrerequisits(&Analysis)) + if (getConstraintPrerequisits(&Analysis)) { return; + } std::string FeatName = getUniqueObjectName("ConstraintRigidBody"); openCommand(QT_TRANSLATE_NOOP("Command", "Make FEM constraint fixed geometry")); - doCommand(Doc, "App.activeDocument().addObject(\"Fem::ConstraintRigidBody\",\"%s\")", FeatName.c_str()); - doCommand(Doc, "App.activeDocument().%s.Scale = 1", FeatName.c_str()); //OvG: set initial scale to 1 - doCommand(Doc, "App.activeDocument().%s.addObject(App.activeDocument().%s)", Analysis->getNameInDocument(), FeatName.c_str()); + doCommand(Doc, + "App.activeDocument().addObject(\"Fem::ConstraintRigidBody\",\"%s\")", + FeatName.c_str()); + doCommand(Doc, + "App.activeDocument().%s.Scale = 1", + FeatName.c_str()); // OvG: set initial scale to 1 + doCommand(Doc, + "App.activeDocument().%s.addObject(App.activeDocument().%s)", + Analysis->getNameInDocument(), + FeatName.c_str()); - doCommand(Doc, "%s", gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + doCommand(Doc, + "%s", + gethideMeshShowPartStr(FeatName).c_str()); // OvG: Hide meshes and show parts updateActive(); diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp index e108d498e9..d86b879530 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp @@ -23,9 +23,9 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include -# include +#include +#include +#include #endif #include @@ -42,9 +42,11 @@ using namespace Gui; /* TRANSLATOR FemGui::TaskFemConstraintRigidBody */ -TaskFemConstraintRigidBody::TaskFemConstraintRigidBody(ViewProviderFemConstraintRigidBody* ConstraintView, QWidget* parent) +TaskFemConstraintRigidBody::TaskFemConstraintRigidBody( + ViewProviderFemConstraintRigidBody* ConstraintView, + QWidget* parent) : TaskFemConstraintOnBoundary(ConstraintView, parent, "FEM_ConstraintRigidBody") -{ //Note change "RigidBody" in line above to new constraint name +{ // Note change "RigidBody" in line above to new constraint name proxy = new QWidget(this); ui = new Ui_TaskFemConstraintRigidBody(); ui->setupUi(proxy); @@ -52,13 +54,19 @@ TaskFemConstraintRigidBody::TaskFemConstraintRigidBody(ViewProviderFemConstraint // create a context menu for the listview of the references createDeleteAction(ui->lw_references); - deleteAction->connect(deleteAction, &QAction::triggered, - this, &TaskFemConstraintRigidBody::onReferenceDeleted); + deleteAction->connect(deleteAction, + &QAction::triggered, + this, + &TaskFemConstraintRigidBody::onReferenceDeleted); - connect(ui->lw_references, &QListWidget::currentItemChanged, - this, &TaskFemConstraintRigidBody::setSelection); - connect(ui->lw_references, &QListWidget::itemClicked, - this, &TaskFemConstraintRigidBody::setSelection); + connect(ui->lw_references, + &QListWidget::currentItemChanged, + this, + &TaskFemConstraintRigidBody::setSelection); + connect(ui->lw_references, + &QListWidget::itemClicked, + this, + &TaskFemConstraintRigidBody::setSelection); // TODO: Relate inputs to property @@ -66,7 +74,8 @@ TaskFemConstraintRigidBody::TaskFemConstraintRigidBody(ViewProviderFemConstraint /* Note: */ // Get the feature data - Fem::ConstraintRigidBody* pcConstraint = static_cast(ConstraintView->getObject()); + Fem::ConstraintRigidBody* pcConstraint = + static_cast(ConstraintView->getObject()); double fStates[15]; fStates[0] = pcConstraint->xRefNode.getValue(); fStates[1] = pcConstraint->yRefNode.getValue(); @@ -106,7 +115,7 @@ TaskFemConstraintRigidBody::TaskFemConstraintRigidBody(ViewProviderFemConstraint ui->lw_references->setCurrentRow(0, QItemSelectionModel::ClearAndSelect); } - //Selection buttons + // Selection buttons buttonGroup->addButton(ui->btnAdd, (int)SelectionChangeModes::refAdd); buttonGroup->addButton(ui->btnRemove, (int)SelectionChangeModes::refRemove); @@ -129,43 +138,60 @@ void TaskFemConstraintRigidBody::updateUI() void TaskFemConstraintRigidBody::addToSelection() { - std::vector selection = Gui::Selection().getSelectionEx(); //gets vector of selected objects of active document + std::vector selection = + Gui::Selection().getSelectionEx(); // gets vector of selected objects of active document if (selection.empty()) { QMessageBox::warning(this, tr("Selection error"), tr("Nothing selected!")); return; } - Fem::ConstraintRigidBody* pcConstraint = static_cast(ConstraintView->getObject()); + Fem::ConstraintRigidBody* pcConstraint = + static_cast(ConstraintView->getObject()); std::vector Objects = pcConstraint->References.getValues(); std::vector SubElements = pcConstraint->References.getSubValues(); - for (std::vector::iterator it = selection.begin(); it != selection.end(); ++it) {//for every selected object + for (std::vector::iterator it = selection.begin(); it != selection.end(); + ++it) { // for every selected object if (!it->isObjectTypeOf(Part::Feature::getClassTypeId())) { QMessageBox::warning(this, tr("Selection error"), tr("Selected object is not a part!")); return; } std::vector subNames = it->getSubNames(); - App::DocumentObject* obj = ConstraintView->getObject()->getDocument()->getObject(it->getFeatName()); - for (size_t subIt = 0; subIt < (subNames.size()); ++subIt) {// for every selected sub element + App::DocumentObject* obj = + ConstraintView->getObject()->getDocument()->getObject(it->getFeatName()); + for (size_t subIt = 0; subIt < (subNames.size()); + ++subIt) { // for every selected sub element bool addMe = true; - for (std::vector::iterator itr = std::find(SubElements.begin(), SubElements.end(), subNames[subIt]); - itr != SubElements.end(); - itr = std::find(++itr, SubElements.end(), subNames[subIt])) - {// for every sub element in selection that matches one in old list - if (obj == Objects[std::distance(SubElements.begin(), itr)]) {//if selected sub element's object equals the one in old list then it was added before so don't add + for (std::vector::iterator itr = + std::find(SubElements.begin(), SubElements.end(), subNames[subIt]); + itr != SubElements.end(); + itr = std::find(++itr, + SubElements.end(), + subNames[subIt])) { // for every sub element in selection that + // matches one in old list + if (obj + == Objects[std::distance( + SubElements.begin(), + itr)]) { // if selected sub element's object equals the one in old list + // then it was added before so don't add addMe = false; } } - // limit constraint such that only vertexes or faces or edges can be used depending on what was selected first + // limit constraint such that only vertexes or faces or edges can be used depending on + // what was selected first std::string searchStr; - if (subNames[subIt].find("Vertex") != std::string::npos) + if (subNames[subIt].find("Vertex") != std::string::npos) { searchStr = "Vertex"; - else if (subNames[subIt].find("Edge") != std::string::npos) + } + else if (subNames[subIt].find("Edge") != std::string::npos) { searchStr = "Edge"; - else + } + else { searchStr = "Face"; + } for (size_t iStr = 0; iStr < (SubElements.size()); ++iStr) { if (SubElements[iStr].find(searchStr) == std::string::npos) { - QString msg = tr("Only one type of selection (vertex,face or edge) per constraint allowed!"); + QString msg = tr( + "Only one type of selection (vertex,face or edge) per constraint allowed!"); QMessageBox::warning(this, tr("Selection error"), msg); addMe = false; break; @@ -179,23 +205,26 @@ void TaskFemConstraintRigidBody::addToSelection() } } } - //Update UI + // Update UI pcConstraint->References.setValues(Objects, SubElements); updateUI(); } void TaskFemConstraintRigidBody::removeFromSelection() { - std::vector selection = Gui::Selection().getSelectionEx(); //gets vector of selected objects of active document + std::vector selection = + Gui::Selection().getSelectionEx(); // gets vector of selected objects of active document if (selection.empty()) { QMessageBox::warning(this, tr("Selection error"), tr("Nothing selected!")); return; } - Fem::ConstraintRigidBody* pcConstraint = static_cast(ConstraintView->getObject()); + Fem::ConstraintRigidBody* pcConstraint = + static_cast(ConstraintView->getObject()); std::vector Objects = pcConstraint->References.getValues(); std::vector SubElements = pcConstraint->References.getSubValues(); std::vector itemsToDel; - for (std::vector::iterator it = selection.begin(); it != selection.end(); ++it) {//for every selected object + for (std::vector::iterator it = selection.begin(); it != selection.end(); + ++it) { // for every selected object if (!it->isObjectTypeOf(Part::Feature::getClassTypeId())) { QMessageBox::warning(this, tr("Selection error"), tr("Selected object is not a part!")); return; @@ -203,12 +232,20 @@ void TaskFemConstraintRigidBody::removeFromSelection() const std::vector& subNames = it->getSubNames(); App::DocumentObject* obj = it->getObject(); - for (size_t subIt = 0; subIt < (subNames.size()); ++subIt) {// for every selected sub element - for (std::vector::iterator itr = std::find(SubElements.begin(), SubElements.end(), subNames[subIt]); - itr != SubElements.end(); - itr = std::find(++itr, SubElements.end(), subNames[subIt])) - {// for every sub element in selection that matches one in old list - if (obj == Objects[std::distance(SubElements.begin(), itr)]) {//if selected sub element's object equals the one in old list then it was added before so mark for deletion + for (size_t subIt = 0; subIt < (subNames.size()); + ++subIt) { // for every selected sub element + for (std::vector::iterator itr = + std::find(SubElements.begin(), SubElements.end(), subNames[subIt]); + itr != SubElements.end(); + itr = std::find(++itr, + SubElements.end(), + subNames[subIt])) { // for every sub element in selection that + // matches one in old list + if (obj + == Objects[std::distance( + SubElements.begin(), + itr)]) { // if selected sub element's object equals the one in old list + // then it was added before so mark for deletion itemsToDel.push_back(std::distance(SubElements.begin(), itr)); } } @@ -220,7 +257,7 @@ void TaskFemConstraintRigidBody::removeFromSelection() SubElements.erase(SubElements.begin() + itemsToDel.back()); itemsToDel.pop_back(); } - //Update UI + // Update UI { QSignalBlocker block(ui->lw_references); ui->lw_references->clear(); @@ -232,7 +269,8 @@ void TaskFemConstraintRigidBody::removeFromSelection() updateUI(); } -void TaskFemConstraintRigidBody::onReferenceDeleted() { +void TaskFemConstraintRigidBody::onReferenceDeleted() +{ TaskFemConstraintRigidBody::removeFromSelection(); } @@ -246,17 +284,47 @@ const std::string TaskFemConstraintRigidBody::getReferences() const return TaskFemConstraint::getReferences(items); } -double TaskFemConstraintRigidBody::get_xRefNode() const { return ui->if_ref_node_x->rawValue(); } -double TaskFemConstraintRigidBody::get_yRefNode() const { return ui->if_ref_node_y->rawValue(); } -double TaskFemConstraintRigidBody::get_zRefNode() const { return ui->if_ref_node_z->rawValue(); } -double TaskFemConstraintRigidBody::get_xLoad() const { return ui->if_ref_load_x->rawValue(); } -double TaskFemConstraintRigidBody::get_yLoad() const { return ui->if_ref_load_y->rawValue(); } -double TaskFemConstraintRigidBody::get_zLoad() const { return ui->if_ref_load_z->rawValue(); } -double TaskFemConstraintRigidBody::get_xMoment() const { return ui->if_rot_load_x->rawValue(); } -double TaskFemConstraintRigidBody::get_yMoment() const { return ui->if_rot_load_y->rawValue(); } -double TaskFemConstraintRigidBody::get_zMoment() const { return ui->if_rot_load_z->rawValue(); } +double TaskFemConstraintRigidBody::get_xRefNode() const +{ + return ui->if_ref_node_x->rawValue(); +} +double TaskFemConstraintRigidBody::get_yRefNode() const +{ + return ui->if_ref_node_y->rawValue(); +} +double TaskFemConstraintRigidBody::get_zRefNode() const +{ + return ui->if_ref_node_z->rawValue(); +} +double TaskFemConstraintRigidBody::get_xLoad() const +{ + return ui->if_ref_load_x->rawValue(); +} +double TaskFemConstraintRigidBody::get_yLoad() const +{ + return ui->if_ref_load_y->rawValue(); +} +double TaskFemConstraintRigidBody::get_zLoad() const +{ + return ui->if_ref_load_z->rawValue(); +} +double TaskFemConstraintRigidBody::get_xMoment() const +{ + return ui->if_rot_load_x->rawValue(); +} +double TaskFemConstraintRigidBody::get_yMoment() const +{ + return ui->if_rot_load_y->rawValue(); +} +double TaskFemConstraintRigidBody::get_zMoment() const +{ + return ui->if_rot_load_z->rawValue(); +} // TODO: This needs to be implemented -bool TaskFemConstraintRigidBody::get_DefineRefNode() const { return true; } +bool TaskFemConstraintRigidBody::get_DefineRefNode() const +{ + return true; +} bool TaskFemConstraintRigidBody::event(QEvent* e) { @@ -264,22 +332,24 @@ bool TaskFemConstraintRigidBody::event(QEvent* e) } void TaskFemConstraintRigidBody::changeEvent(QEvent*) -{ -} +{} void TaskFemConstraintRigidBody::clearButtons(const SelectionChangeModes notThis) { - if (notThis != SelectionChangeModes::refAdd) + if (notThis != SelectionChangeModes::refAdd) { ui->btnAdd->setChecked(false); - if (notThis != SelectionChangeModes::refRemove) + } + if (notThis != SelectionChangeModes::refRemove) { ui->btnRemove->setChecked(false); + } } //************************************************************************** // TaskDialog //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TaskDlgFemConstraintRigidBody::TaskDlgFemConstraintRigidBody(ViewProviderFemConstraintRigidBody* ConstraintView) +TaskDlgFemConstraintRigidBody::TaskDlgFemConstraintRigidBody( + ViewProviderFemConstraintRigidBody* ConstraintView) { this->ConstraintView = ConstraintView; assert(ConstraintView); @@ -297,28 +367,66 @@ void TaskDlgFemConstraintRigidBody::open() QString msg = QObject::tr("Constraint RigidBody"); Gui::Command::openCommand((const char*)msg.toUtf8()); ConstraintView->setVisible(true); - Gui::Command::doCommand(Gui::Command::Doc, ViewProviderFemConstraint::gethideMeshShowPartStr((static_cast(ConstraintView->getObject()))->getNameInDocument()).c_str()); //OvG: Hide meshes and show parts + Gui::Command::doCommand( + Gui::Command::Doc, + ViewProviderFemConstraint::gethideMeshShowPartStr( + (static_cast(ConstraintView->getObject()))->getNameInDocument()) + .c_str()); // OvG: Hide meshes and show parts } } bool TaskDlgFemConstraintRigidBody::accept() { std::string name = ConstraintView->getObject()->getNameInDocument(); - const TaskFemConstraintRigidBody* parameters = static_cast(parameter); + const TaskFemConstraintRigidBody* parameters = + static_cast(parameter); try { - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.xRefNode = %f", name.c_str(), parameters->get_xRefNode()); - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.yRefNode = %f", name.c_str(), parameters->get_yRefNode()); - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.zRefNode = %f", name.c_str(), parameters->get_zRefNode()); - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.xLoad = %f", name.c_str(), parameters->get_xLoad()); - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.yLoad = %f", name.c_str(), parameters->get_yLoad()); - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.zLoad = %f", name.c_str(), parameters->get_zLoad()); - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.xMoment = %f", name.c_str(), parameters->get_xMoment()); - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.yMoment = %f", name.c_str(), parameters->get_yMoment()); - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.zMoment = %f", name.c_str(), parameters->get_zMoment()); - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.DefineRefNode = %s", name.c_str(), parameters->get_DefineRefNode() ? "True" : "False"); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.xRefNode = %f", + name.c_str(), + parameters->get_xRefNode()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.yRefNode = %f", + name.c_str(), + parameters->get_yRefNode()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.zRefNode = %f", + name.c_str(), + parameters->get_zRefNode()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.xLoad = %f", + name.c_str(), + parameters->get_xLoad()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.yLoad = %f", + name.c_str(), + parameters->get_yLoad()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.zLoad = %f", + name.c_str(), + parameters->get_zLoad()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.xMoment = %f", + name.c_str(), + parameters->get_xMoment()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.yMoment = %f", + name.c_str(), + parameters->get_yMoment()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.zMoment = %f", + name.c_str(), + parameters->get_zMoment()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.DefineRefNode = %s", + name.c_str(), + parameters->get_DefineRefNode() ? "True" : "False"); - std::string scale = parameters->getScale(); //OvG: determine modified scale - Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.Scale = %s", name.c_str(), scale.c_str()); //OvG: implement modified scale + std::string scale = parameters->getScale(); // OvG: determine modified scale + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.Scale = %s", + name.c_str(), + scale.c_str()); // OvG: implement modified scale } catch (const Base::Exception& e) { QMessageBox::warning(parameter, tr("Input error"), QString::fromLatin1(e.what())); diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h index fc8df9f372..1c94bcc11b 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h @@ -31,13 +31,15 @@ class Ui_TaskFemConstraintRigidBody; -namespace FemGui { -class TaskFemConstraintRigidBody : public TaskFemConstraintOnBoundary +namespace FemGui +{ +class TaskFemConstraintRigidBody: public TaskFemConstraintOnBoundary { Q_OBJECT public: - explicit TaskFemConstraintRigidBody(ViewProviderFemConstraintRigidBody *ConstraintView,QWidget *parent = nullptr); + explicit TaskFemConstraintRigidBody(ViewProviderFemConstraintRigidBody* ConstraintView, + QWidget* parent = nullptr); ~TaskFemConstraintRigidBody() override; const std::string getReferences() const override; double get_xRefNode() const; @@ -57,27 +59,26 @@ private Q_SLOTS: void removeFromSelection() override; protected: - bool event(QEvent *e) override; - void changeEvent(QEvent *e) override; + bool event(QEvent* e) override; + void changeEvent(QEvent* e) override; void clearButtons(const SelectionChangeModes notThis) override; private: void updateUI(); Ui_TaskFemConstraintRigidBody* ui; - }; -class TaskDlgFemConstraintRigidBody : public TaskDlgFemConstraint +class TaskDlgFemConstraintRigidBody: public TaskDlgFemConstraint { Q_OBJECT public: - explicit TaskDlgFemConstraintRigidBody(ViewProviderFemConstraintRigidBody *ConstraintView); + explicit TaskDlgFemConstraintRigidBody(ViewProviderFemConstraintRigidBody* ConstraintView); void open() override; bool accept() override; bool reject() override; }; -} //namespace FemGui +} // namespace FemGui -#endif // GUI_TASKVIEW_TaskFemConstraintRigidBody_H +#endif // GUI_TASKVIEW_TaskFemConstraintRigidBody_H diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.cpp index 0d11bacdac..d7a7f23430 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.cpp @@ -23,11 +23,11 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include #endif #include @@ -39,7 +39,8 @@ using namespace FemGui; -PROPERTY_SOURCE(FemGui::ViewProviderFemConstraintRigidBody, FemGui::ViewProviderFemConstraintOnBoundary) +PROPERTY_SOURCE(FemGui::ViewProviderFemConstraintRigidBody, + FemGui::ViewProviderFemConstraintOnBoundary) ViewProviderFemConstraintRigidBody::ViewProviderFemConstraintRigidBody() @@ -48,19 +49,20 @@ ViewProviderFemConstraintRigidBody::ViewProviderFemConstraintRigidBody() } ViewProviderFemConstraintRigidBody::~ViewProviderFemConstraintRigidBody() -{ -} +{} bool ViewProviderFemConstraintRigidBody::setEdit(int ModNum) { - if (ModNum == ViewProvider::Default ) { + if (ModNum == ViewProvider::Default) { // When double-clicking on the item for this constraint the // object unsets and sets its edit mode without closing // the task panel - Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog(); - TaskDlgFemConstraintRigidBody *constrDlg = qobject_cast(dlg); - if (constrDlg && constrDlg->getConstraintView() != this) - constrDlg = nullptr; // another constraint left open its task panel + Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); + TaskDlgFemConstraintRigidBody* constrDlg = + qobject_cast(dlg); + if (constrDlg && constrDlg->getConstraintView() != this) { + constrDlg = nullptr; // another constraint left open its task panel + } if (dlg && !constrDlg) { // This case will occur in the ShaftWizard application checkForWizard(); @@ -72,15 +74,19 @@ bool ViewProviderFemConstraintRigidBody::setEdit(int ModNum) msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::Yes); int ret = msgBox.exec(); - if (ret == QMessageBox::Yes) + if (ret == QMessageBox::Yes) { Gui::Control().reject(); - else + } + else { return false; - } else if (constraintDialog) { + } + } + else if (constraintDialog) { // Another FemConstraint* dialog is already open inside the Shaft Wizard // Ignore the request to open another dialog return false; - } else { + } + else { constraintDialog = new TaskFemConstraintRigidBody(this); return true; } @@ -90,44 +96,51 @@ bool ViewProviderFemConstraintRigidBody::setEdit(int ModNum) Gui::Selection().clearSelection(); // start the edit dialog - if (constrDlg) + if (constrDlg) { Gui::Control().showDialog(constrDlg); - else + } + else { Gui::Control().showDialog(new TaskDlgFemConstraintRigidBody(this)); + } return true; - } else { - return ViewProviderDocumentObject::setEdit(ModNum); // clazy:exclude=skipped-base-method + } + else { + return ViewProviderDocumentObject::setEdit(ModNum); // clazy:exclude=skipped-base-method } } #define WIDTH (2) #define HEIGHT (1) -//#define USE_MULTIPLE_COPY //OvG: MULTICOPY fails to update scaled display on initial drawing - so disable +// #define USE_MULTIPLE_COPY //OvG: MULTICOPY fails to update scaled display on initial drawing - +// so disable void ViewProviderFemConstraintRigidBody::updateData(const App::Property* prop) { // Gets called whenever a property of the attached object changes - Fem::ConstraintRigidBody *pcConstraint = static_cast(this->getObject()); - float scaledwidth = WIDTH * pcConstraint->Scale.getValue(); //OvG: Calculate scaled values once only + Fem::ConstraintRigidBody* pcConstraint = + static_cast(this->getObject()); + float scaledwidth = + WIDTH * pcConstraint->Scale.getValue(); // OvG: Calculate scaled values once only float scaledheight = HEIGHT * pcConstraint->Scale.getValue(); #ifdef USE_MULTIPLE_COPY - //OvG: always need access to cp for scaling + // OvG: always need access to cp for scaling SoMultipleCopy* cp = new SoMultipleCopy(); if (pShapeSep->getNumChildren() == 0) { // Set up the nodes cp->matrix.setNum(0); - cp->addChild((SoNode*)createRigidBody(scaledheight, scaledwidth)); //OvG: Scaling + cp->addChild((SoNode*)createRigidBody(scaledheight, scaledwidth)); // OvG: Scaling pShapeSep->addChild(cp); } #endif - if (strcmp(prop->getName(),"Points") == 0) { + if (strcmp(prop->getName(), "Points") == 0) { const std::vector& points = pcConstraint->Points.getValues(); const std::vector& normals = pcConstraint->Normals.getValues(); - if (points.size() != normals.size()) + if (points.size() != normals.size()) { return; + } std::vector::const_iterator n = normals.begin(); #ifdef USE_MULTIPLE_COPY @@ -153,7 +166,7 @@ void ViewProviderFemConstraintRigidBody::updateData(const App::Property* prop) #else SoSeparator* sep = new SoSeparator(); createPlacement(sep, base, rot); - createFixed(sep, scaledheight, scaledwidth); //OvG: Scaling + createFixed(sep, scaledheight, scaledwidth); // OvG: Scaling pShapeSep->addChild(sep); #endif n++; diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.h b/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.h index 956e8513c9..19008b3c15 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.h +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.h @@ -29,7 +29,8 @@ namespace FemGui { -class FemGuiExport ViewProviderFemConstraintRigidBody : public FemGui::ViewProviderFemConstraintOnBoundary +class FemGuiExport ViewProviderFemConstraintRigidBody + : public FemGui::ViewProviderFemConstraintOnBoundary { PROPERTY_HEADER_WITH_OVERRIDE(FemGui::ViewProviderFemConstraintRigidBody); @@ -44,7 +45,7 @@ protected: bool setEdit(int ModNum) override; }; -} //namespace FemGui +} // namespace FemGui -#endif // GUI_VIEWPROVIDERFEMCONSTRAINTRIGIDBODY_H +#endif // GUI_VIEWPROVIDERFEMCONSTRAINTRIGIDBODY_H diff --git a/src/Mod/Fem/femtest/app/test_object.py b/src/Mod/Fem/femtest/app/test_object.py index a435674e4b..dc5d64d62c 100644 --- a/src/Mod/Fem/femtest/app/test_object.py +++ b/src/Mod/Fem/femtest/app/test_object.py @@ -189,6 +189,10 @@ class TestObjectType(unittest.TestCase): "Fem::ConstraintFixed", type_of_obj(ObjectsFem.makeConstraintFixed(doc)) ) + self.assertEqual( + "Fem::ConstraintRigidBody", + type_of_obj(ObjectsFem.makeConstraintRigidBody(doc)) + ) self.assertEqual( "Fem::ConstraintFlowVelocity", type_of_obj(ObjectsFem.makeConstraintFlowVelocity(doc)) @@ -434,6 +438,10 @@ class TestObjectType(unittest.TestCase): ObjectsFem.makeConstraintFixed(doc), "Fem::ConstraintFixed" )) + self.assertTrue(is_of_type( + ObjectsFem.makeConstraintRigidBody(doc), + "Fem::ConstraintRigidBody" + )) self.assertTrue(is_of_type( ObjectsFem.makeConstraintFlowVelocity(doc), "Fem::ConstraintFlowVelocity" @@ -778,6 +786,21 @@ class TestObjectType(unittest.TestCase): "Fem::ConstraintFixed" )) + # ConstraintRigidBody + constraint_rigidbody = ObjectsFem.makeConstraintRigidBody(doc) + self.assertTrue(is_derived_from( + constraint_rigidbody, + "App::DocumentObject" + )) + self.assertTrue(is_derived_from( + constraint_rigidbody, + "Fem::Constraint" + )) + self.assertTrue(is_derived_from( + constraint_rigidbody, + "Fem::ConstraintRigidBody" + )) + # ConstraintFlowVelocity constraint_flow_velocity = ObjectsFem.makeConstraintFlowVelocity(doc) self.assertTrue(is_derived_from( @@ -1573,6 +1596,10 @@ class TestObjectType(unittest.TestCase): ObjectsFem.makeConstraintFixed( doc).isDerivedFrom("Fem::ConstraintFixed") ) + self.assertTrue( + ObjectsFem.makeConstraintRigidBody( + doc).isDerivedFrom("Fem::ConstraintRigidBody") + ) self.assertTrue( ObjectsFem.makeConstraintFlowVelocity( doc).isDerivedFrom("Fem::ConstraintPython") @@ -1844,6 +1871,7 @@ def create_all_fem_objects_doc( analysis.addObject(ObjectsFem.makeConstraintDisplacement(doc)) analysis.addObject(ObjectsFem.makeConstraintElectrostaticPotential(doc)) analysis.addObject(ObjectsFem.makeConstraintFixed(doc)) + analysis.addObject(ObjectsFem.makeConstraintRigidBody(doc)) analysis.addObject(ObjectsFem.makeConstraintFlowVelocity(doc)) analysis.addObject(ObjectsFem.makeConstraintFluidBoundary(doc)) analysis.addObject(ObjectsFem.makeConstraintSpring(doc)) From ab6afeb2612ba85361fd5503d18f935f2182130d Mon Sep 17 00:00:00 2001 From: FEA-eng <59876896+FEA-eng@users.noreply.github.com> Date: Fri, 15 Mar 2024 18:54:10 +0100 Subject: [PATCH 05/13] Fem: Update properties of ConstraintRigidBody --- src/Mod/Fem/App/FemConstraintRigidBody.cpp | 6 +-- src/Mod/Fem/App/FemConstraintRigidBody.h | 6 +-- .../Fem/Gui/TaskFemConstraintRigidBody.cpp | 48 +++++++++---------- src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h | 6 +-- src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui | 46 +++++++++--------- 5 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/Mod/Fem/App/FemConstraintRigidBody.cpp b/src/Mod/Fem/App/FemConstraintRigidBody.cpp index 0d55192806..dd7a5bd194 100644 --- a/src/Mod/Fem/App/FemConstraintRigidBody.cpp +++ b/src/Mod/Fem/App/FemConstraintRigidBody.cpp @@ -40,9 +40,9 @@ ConstraintRigidBody::ConstraintRigidBody() ADD_PROPERTY(xRotation, (0.0)); ADD_PROPERTY(yRotation, (0.0)); ADD_PROPERTY(zRotation, (0.0)); - ADD_PROPERTY(xLoad, (0.0)); - ADD_PROPERTY(yLoad, (0.0)); - ADD_PROPERTY(zLoad, (0.0)); + ADD_PROPERTY(xForce, (0.0)); + ADD_PROPERTY(yForce, (0.0)); + ADD_PROPERTY(zForce, (0.0)); ADD_PROPERTY(xMoment, (0.0)); ADD_PROPERTY(yMoment, (0.0)); ADD_PROPERTY(zMoment, (0.0)); diff --git a/src/Mod/Fem/App/FemConstraintRigidBody.h b/src/Mod/Fem/App/FemConstraintRigidBody.h index 3f3b0a795a..73b15ca90a 100644 --- a/src/Mod/Fem/App/FemConstraintRigidBody.h +++ b/src/Mod/Fem/App/FemConstraintRigidBody.h @@ -51,9 +51,9 @@ public: App::PropertyFloat xRotation; App::PropertyFloat yRotation; App::PropertyFloat zRotation; - App::PropertyFloat xLoad; - App::PropertyFloat yLoad; - App::PropertyFloat zLoad; + App::PropertyFloat xForce; + App::PropertyFloat yForce; + App::PropertyFloat zForce; App::PropertyFloat xMoment; App::PropertyFloat yMoment; App::PropertyFloat zMoment; diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp index d86b879530..73025f46e6 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp @@ -86,9 +86,9 @@ TaskFemConstraintRigidBody::TaskFemConstraintRigidBody( fStates[6] = pcConstraint->xRotation.getValue(); fStates[7] = pcConstraint->yRotation.getValue(); fStates[8] = pcConstraint->zRotation.getValue(); - fStates[9] = pcConstraint->xLoad.getValue(); - fStates[10] = pcConstraint->yLoad.getValue(); - fStates[11] = pcConstraint->zLoad.getValue(); + fStates[9] = pcConstraint->xForce.getValue(); + fStates[10] = pcConstraint->yForce.getValue(); + fStates[11] = pcConstraint->zForce.getValue(); fStates[12] = pcConstraint->xMoment.getValue(); fStates[13] = pcConstraint->yMoment.getValue(); fStates[14] = pcConstraint->zMoment.getValue(); @@ -100,12 +100,12 @@ TaskFemConstraintRigidBody::TaskFemConstraintRigidBody( ui->if_ref_node_x->setValue(fStates[0]); ui->if_ref_node_y->setValue(fStates[1]); ui->if_ref_node_z->setValue(fStates[2]); - ui->if_ref_load_x->setValue(fStates[9]); - ui->if_ref_load_y->setValue(fStates[10]); - ui->if_ref_load_z->setValue(fStates[11]); - ui->if_rot_load_x->setValue(fStates[12]); - ui->if_rot_load_y->setValue(fStates[13]); - ui->if_rot_load_z->setValue(fStates[14]); + ui->if_ref_force_x->setValue(fStates[9]); + ui->if_ref_force_y->setValue(fStates[10]); + ui->if_ref_force_z->setValue(fStates[11]); + ui->if_rot_force_x->setValue(fStates[12]); + ui->if_rot_force_y->setValue(fStates[13]); + ui->if_rot_force_z->setValue(fStates[14]); ui->lw_references->clear(); for (std::size_t i = 0; i < Objects.size(); i++) { @@ -296,29 +296,29 @@ double TaskFemConstraintRigidBody::get_zRefNode() const { return ui->if_ref_node_z->rawValue(); } -double TaskFemConstraintRigidBody::get_xLoad() const +double TaskFemConstraintRigidBody::get_xForce() const { - return ui->if_ref_load_x->rawValue(); + return ui->if_ref_force_x->rawValue(); } -double TaskFemConstraintRigidBody::get_yLoad() const +double TaskFemConstraintRigidBody::get_yForce() const { - return ui->if_ref_load_y->rawValue(); + return ui->if_ref_force_y->rawValue(); } -double TaskFemConstraintRigidBody::get_zLoad() const +double TaskFemConstraintRigidBody::get_zForce() const { - return ui->if_ref_load_z->rawValue(); + return ui->if_ref_force_z->rawValue(); } double TaskFemConstraintRigidBody::get_xMoment() const { - return ui->if_rot_load_x->rawValue(); + return ui->if_rot_force_x->rawValue(); } double TaskFemConstraintRigidBody::get_yMoment() const { - return ui->if_rot_load_y->rawValue(); + return ui->if_rot_force_y->rawValue(); } double TaskFemConstraintRigidBody::get_zMoment() const { - return ui->if_rot_load_z->rawValue(); + return ui->if_rot_force_z->rawValue(); } // TODO: This needs to be implemented bool TaskFemConstraintRigidBody::get_DefineRefNode() const @@ -394,17 +394,17 @@ bool TaskDlgFemConstraintRigidBody::accept() name.c_str(), parameters->get_zRefNode()); Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.xLoad = %f", + "App.ActiveDocument.%s.xForce = %f", name.c_str(), - parameters->get_xLoad()); + parameters->get_xForce()); Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.yLoad = %f", + "App.ActiveDocument.%s.yForce = %f", name.c_str(), - parameters->get_yLoad()); + parameters->get_yForce()); Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.zLoad = %f", + "App.ActiveDocument.%s.zForce = %f", name.c_str(), - parameters->get_zLoad()); + parameters->get_zForce()); Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.xMoment = %f", name.c_str(), diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h index 1c94bcc11b..24642d2f93 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h @@ -45,9 +45,9 @@ public: double get_xRefNode() const; double get_yRefNode() const; double get_zRefNode() const; - double get_xLoad() const; - double get_yLoad() const; - double get_zLoad() const; + double get_xForce() const; + double get_yForce() const; + double get_zForce() const; double get_xMoment() const; double get_yMoment() const; double get_zMoment() const; diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui index 2ea39976dd..7aa6cec178 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui @@ -147,23 +147,23 @@ - + - Load on Reference Node + Force on Reference Node - + - + X: - + 0 N @@ -176,14 +176,14 @@ - + Y: - + 0 N @@ -196,14 +196,14 @@ - + Z: - + 0 N @@ -231,28 +231,28 @@ - + Moment on Rotation Node - + - + X: - + - 0 N mm + 0 N*m - N mm + N*m 0.000000000000000 @@ -260,19 +260,19 @@ - + Y: - + - 0 N mm + 0 N*m - N mm + N*m 0.000000000000000 @@ -280,19 +280,19 @@ - + Z: - + - 0 N mm + 0 N*m - N mm + N*m 0.000000000000000 From 3739d065280e8b5ecd145c77c198cd0a7b709efb Mon Sep 17 00:00:00 2001 From: FEA-eng <59876896+FEA-eng@users.noreply.github.com> Date: Fri, 15 Mar 2024 19:12:12 +0100 Subject: [PATCH 06/13] Fem: Update writer of the constraint rigid body --- src/Mod/Fem/App/FemConstraintRigidBody.cpp | 2 +- src/Mod/Fem/CMakeLists.txt | 1 + .../calculix/write_constraint_rigidbody.py | 28 +++--- .../write_constraint_rigidbody_step.py | 88 +++++++++++++++++++ src/Mod/Fem/femsolver/calculix/writer.py | 2 + src/Mod/Fem/femtools/membertools.py | 3 + 6 files changed, 105 insertions(+), 19 deletions(-) create mode 100644 src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody_step.py diff --git a/src/Mod/Fem/App/FemConstraintRigidBody.cpp b/src/Mod/Fem/App/FemConstraintRigidBody.cpp index dd7a5bd194..cb57e9cdca 100644 --- a/src/Mod/Fem/App/FemConstraintRigidBody.cpp +++ b/src/Mod/Fem/App/FemConstraintRigidBody.cpp @@ -77,7 +77,7 @@ void ConstraintRigidBody::onChanged(const App::Property* prop) if (prop == &References) { std::vector points; std::vector normals; - int scale = 1; // OvG: Enforce use of scale + double scale = 1; // OvG: Enforce use of scale if (getPoints(points, normals, &scale)) { Points.setValues(points); Normals.setValues(normals); diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 365e208dc7..97a64ed510 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -232,6 +232,7 @@ SET(FemSolverCalculix_SRCS femsolver/calculix/write_constraint_planerotation.py femsolver/calculix/write_constraint_pressure.py femsolver/calculix/write_constraint_rigidbody.py + femsolver/calculix/write_constraint_rigidbody_step.py femsolver/calculix/write_constraint_sectionprint.py femsolver/calculix/write_constraint_selfweight.py femsolver/calculix/write_constraint_temperature.py diff --git a/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody.py b/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody.py index 26169e4098..0ea4566e80 100644 --- a/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody.py +++ b/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody.py @@ -66,9 +66,9 @@ def write_constraint(f, femobj, rb_obj, ccxwriter): is_ref_bc_defined = any((rb_obj.xDisplacement, rb_obj.yDisplacement, rb_obj.zDisplacement, - rb_obj.xLoad, - rb_obj.yLoad, - rb_obj.zLoad)) + rb_obj.xForce, + rb_obj.yForce, + rb_obj.zForce)) is_rot_bc_defined = any((rb_obj.xRotation, rb_obj.yRotation, @@ -78,10 +78,14 @@ def write_constraint(f, femobj, rb_obj, ccxwriter): rb_obj.zMoment)) # FIXME: This needs to be implemented - ref_node_idx = -1 - rot_node_idx = -1 + ref_node_idx = 10000000 + rot_node_idx = 20000000 - kw_line = "*RIGID BODY,NSET={}".format(rb_obj.Name) + f.write("*NODE\n") + f.write("{},{},{},{}\n".format(ref_node_idx, rb_obj.xRefNode, rb_obj.yRefNode, rb_obj.zRefNode)) + f.write("{},{},{},{}\n".format(rot_node_idx, rb_obj.xRefNode, rb_obj.yRefNode, rb_obj.zRefNode)) + + kw_line = "*RIGID BODY, NSET={}, REF NODE={}, ROT NODE={}".format(rb_obj.Name, ref_node_idx, rot_node_idx) if is_ref_bc_defined: kw_line = kw_line + ",REF NODE={}".format(ref_node_idx) @@ -91,15 +95,3 @@ def write_constraint(f, femobj, rb_obj, ccxwriter): f.write(kw_line + "\n") - # TODO: Displacement definitions need fixing - if is_ref_bc_defined: - f.write("*CLOAD\n") - f.write("{},1,{}\n".format(ref_node_idx, rb_obj.xLoad)) - f.write("{},2,{}\n".format(ref_node_idx, rb_obj.yLoad)) - f.write("{},3,{}\n".format(ref_node_idx, rb_obj.zLoad)) - - if is_rot_bc_defined: - f.write("*CLOAD\n") - f.write("{},1,{}\n".format(rot_node_idx, rb_obj.xMoment)) - f.write("{},2,{}\n".format(rot_node_idx, rb_obj.yMoment)) - f.write("{},3,{}\n".format(rot_node_idx, rb_obj.zMoment)) diff --git a/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody_step.py b/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody_step.py new file mode 100644 index 0000000000..4b026675d3 --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody_step.py @@ -0,0 +1,88 @@ +# *************************************************************************** +# * Copyright (c) 2022 Ajinkya Dahale * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint rigid body" +__author__ = "Ajinkya Dahale" +__url__ = "https://www.freecadweb.org" + + +def get_analysis_types(): + return "all" # write for all analysis types + + +def get_sets_name(): + return "constraints_rigidbody_node_sets" + + +def get_constraint_title(): + return "Rigid Body Constraints" + + +def get_before_write_meshdata_constraint(): + return "" + + +def get_after_write_meshdata_constraint(): + return "" + + +def get_before_write_constraint(): + return "" + + +def get_after_write_constraint(): + return "" + + +def write_constraint(f, femobj, rb_obj, ccxwriter): + + # floats read from ccx should use {:.13G}, see comment in writer module + is_ref_bc_defined = any((rb_obj.xDisplacement, + rb_obj.yDisplacement, + rb_obj.zDisplacement, + rb_obj.xForce, + rb_obj.yForce, + rb_obj.zForce)) + + is_rot_bc_defined = any((rb_obj.xRotation, + rb_obj.yRotation, + rb_obj.zRotation, + rb_obj.xMoment, + rb_obj.yMoment, + rb_obj.zMoment)) + + # FIXME: This needs to be implemented + ref_node_idx = 10000000 + rot_node_idx = 20000000 + + + # TODO: Displacement definitions need fixing + f.write("*CLOAD\n") + f.write("{},1,{}\n".format(ref_node_idx, rb_obj.xForce)) + f.write("{},2,{}\n".format(ref_node_idx, rb_obj.yForce)) + f.write("{},3,{}\n".format(ref_node_idx, rb_obj.zForce)) + + f.write("*CLOAD\n") + f.write("{},1,{}\n".format(rot_node_idx, rb_obj.xMoment)) + f.write("{},2,{}\n".format(rot_node_idx, rb_obj.yMoment)) + f.write("{},3,{}\n".format(rot_node_idx, rb_obj.zMoment)) diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py index 25225bc9c5..bee4afb173 100644 --- a/src/Mod/Fem/femsolver/calculix/writer.py +++ b/src/Mod/Fem/femsolver/calculix/writer.py @@ -46,6 +46,7 @@ from . import write_constraint_initialtemperature as con_itemp from . import write_constraint_planerotation as con_planerotation from . import write_constraint_pressure as con_pressure from . import write_constraint_rigidbody as con_rigidbody +from . import write_constraint_rigidbody_step as con_rigidbody_step from . import write_constraint_sectionprint as con_sectionprint from . import write_constraint_selfweight as con_selfweight from . import write_constraint_temperature as con_temperature @@ -190,6 +191,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # constraints dependent from steps self.write_constraints_propdata(inpfile, self.member.cons_fixed, con_fixed) + self.write_constraints_propdata(inpfile, self.member.cons_rigidbody_step, con_rigidbody_step) self.write_constraints_propdata(inpfile, self.member.cons_displacement, con_displacement) self.write_constraints_propdata(inpfile, self.member.cons_sectionprint, con_sectionprint) self.write_constraints_propdata(inpfile, self.member.cons_selfweight, con_selfweight) diff --git a/src/Mod/Fem/femtools/membertools.py b/src/Mod/Fem/femtools/membertools.py index 705885b0a6..058ca710d5 100644 --- a/src/Mod/Fem/femtools/membertools.py +++ b/src/Mod/Fem/femtools/membertools.py @@ -301,6 +301,9 @@ class AnalysisMember(): self.cons_rigidbody = self.get_several_member( "Fem::ConstraintRigidBody" ) + self.cons_rigidbody_step = self.get_several_member( + "Fem::ConstraintRigidBody" + ) self.cons_force = self.get_several_member( "Fem::ConstraintForce" ) From 4c0ae6122fa9378f401bf8aa4198b8642d73af1e Mon Sep 17 00:00:00 2001 From: FEA-eng <59876896+FEA-eng@users.noreply.github.com> Date: Fri, 15 Mar 2024 19:36:48 +0100 Subject: [PATCH 07/13] Base: Add moment unit --- src/App/Application.cpp | 1 + src/App/PropertyUnits.cpp | 11 +++++++++++ src/App/PropertyUnits.h | 13 +++++++++++++ src/Base/Unit.cpp | 4 ++++ src/Base/Unit.h | 1 + src/Base/UnitsSchemaInternal.cpp | 18 ++++++++++++++++++ src/Base/UnitsSchemaMKS.cpp | 18 ++++++++++++++++++ 7 files changed, 66 insertions(+) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 0e86aa9bdb..11b078c97a 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -2027,6 +2027,7 @@ void Application::initTypes() App::PropertyMagneticFluxDensity ::init(); App::PropertyMagnetization ::init(); App::PropertyMass ::init(); + App::PropertyMoment ::init(); App::PropertyPressure ::init(); App::PropertyPower ::init(); App::PropertyShearModulus ::init(); diff --git a/src/App/PropertyUnits.cpp b/src/App/PropertyUnits.cpp index 6c0f60f8a8..867555456c 100644 --- a/src/App/PropertyUnits.cpp +++ b/src/App/PropertyUnits.cpp @@ -555,6 +555,17 @@ PropertyMass::PropertyMass() setUnit(Base::Unit::Mass); } +//************************************************************************** +// PropertyMoment +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPESYSTEM_SOURCE(App::PropertyMoment, App::PropertyQuantity) + +PropertyMoment::PropertyMoment() +{ + setUnit(Base::Unit::Moment); +} + //************************************************************************** // PropertyPressure //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/src/App/PropertyUnits.h b/src/App/PropertyUnits.h index fc32e080b1..c0854e47c1 100644 --- a/src/App/PropertyUnits.h +++ b/src/App/PropertyUnits.h @@ -540,6 +540,19 @@ public: ~PropertyMass() override = default; }; +/** Moment property + * This is a property for representing moment. It is basically a float + * property. On the Gui it has a quantity like N*m. + */ +class AppExport PropertyMoment: public PropertyQuantity +{ + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + +public: + PropertyMoment(); + ~PropertyMoment() override = default; +}; + /** Pressure property * This is a property for representing pressure. It basically a float * property. On the Gui it has a quantity like Pa. diff --git a/src/Base/Unit.cpp b/src/Base/Unit.cpp index 7aa14c7526..46a5dbe3ef 100644 --- a/src/Base/Unit.cpp +++ b/src/Base/Unit.cpp @@ -623,6 +623,9 @@ QString Unit::getTypeString() const if (*this == Unit::YoungsModulus) { return QString::fromLatin1("YoungsModulus"); } + if (*this == Unit::Moment) { + return QString::fromLatin1("Moment"); + } return {}; } @@ -664,6 +667,7 @@ const Unit Unit::MagneticFieldStrength (-1,0,0,1); const Unit Unit::MagneticFlux (2,1,-2,-1); const Unit Unit::MagneticFluxDensity (0,1,-2,-1); const Unit Unit::Magnetization (-1,0,0,1); +const Unit Unit::Moment (2, 1, -2); const Unit Unit::Pressure (-1,1,-2); const Unit Unit::Power (2, 1, -3); const Unit Unit::ShearModulus (-1,1,-2); diff --git a/src/Base/Unit.h b/src/Base/Unit.h index 77b325a784..5e957a97a7 100644 --- a/src/Base/Unit.h +++ b/src/Base/Unit.h @@ -155,6 +155,7 @@ public: static const Unit Force; static const Unit Work; static const Unit Power; + static const Unit Moment; static const Unit SpecificEnergy; static const Unit ThermalConductivity; diff --git a/src/Base/UnitsSchemaInternal.cpp b/src/Base/UnitsSchemaInternal.cpp index 355e8307c7..4b141fd247 100644 --- a/src/Base/UnitsSchemaInternal.cpp +++ b/src/Base/UnitsSchemaInternal.cpp @@ -272,6 +272,24 @@ UnitsSchemaInternal::schemaTranslate(const Quantity& quant, double& factor, QStr factor = 1e9; } } + // else if (unit == Unit::Moment) { + // if (UnitValue < 1e6) { + // unitString = QString::fromLatin1("mNm"); + // factor = 1e3; + // } + // else if (UnitValue < 1e9) { + // unitString = QString::fromLatin1("Nm"); + // factor = 1e6; + // } + // else if (UnitValue < 1e12) { + // unitString = QString::fromLatin1("kNm"); + // factor = 1e9; + // } + // else { + // unitString = QString::fromLatin1("MNm"); + // factor = 1e12; + // } + // } else if (unit == Unit::Power) { if (UnitValue < 1e6) { unitString = QString::fromLatin1("mW"); diff --git a/src/Base/UnitsSchemaMKS.cpp b/src/Base/UnitsSchemaMKS.cpp index aba27295ab..96034a9495 100644 --- a/src/Base/UnitsSchemaMKS.cpp +++ b/src/Base/UnitsSchemaMKS.cpp @@ -261,6 +261,24 @@ QString UnitsSchemaMKS::schemaTranslate(const Quantity& quant, double& factor, Q factor = 1e9; } } + // else if (unit == Unit::Moment) { + // if (UnitValue < 1e6) { + // unitString = QString::fromLatin1("mNm"); + // factor = 1e3; + // } + // else if (UnitValue < 1e9) { + // unitString = QString::fromLatin1("Nm"); + // factor = 1e6; + // } + // else if (UnitValue < 1e12) { + // unitString = QString::fromLatin1("kNm"); + // factor = 1e9; + // } + // else { + // unitString = QString::fromLatin1("MNm"); + // factor = 1e12; + // } + // } else if (unit == Unit::Power) { if (UnitValue < 1e6) { unitString = QString::fromLatin1("mW"); From f1547eaff4079132d81076700881ae5008b3b662 Mon Sep 17 00:00:00 2001 From: FEA-eng <59876896+FEA-eng@users.noreply.github.com> Date: Fri, 15 Mar 2024 19:55:58 +0100 Subject: [PATCH 08/13] Fem: Add ConstraintRigidBody icon --- src/Mod/Fem/Gui/Resources/Fem.qrc | 1 + .../icons/FEM_ConstraintRigidBody.svg | 300 ++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 src/Mod/Fem/Gui/Resources/icons/FEM_ConstraintRigidBody.svg diff --git a/src/Mod/Fem/Gui/Resources/Fem.qrc b/src/Mod/Fem/Gui/Resources/Fem.qrc index 9fda988706..4ad05ea761 100755 --- a/src/Mod/Fem/Gui/Resources/Fem.qrc +++ b/src/Mod/Fem/Gui/Resources/Fem.qrc @@ -29,6 +29,7 @@ icons/FEM_ConstraintPlaneRotation.svg icons/FEM_ConstraintPressure.svg icons/FEM_ConstraintPulley.svg + icons/FEM_ConstraintRigidBody.svg icons/FEM_ConstraintSectionPrint.svg icons/FEM_ConstraintSelfWeight.svg icons/FEM_ConstraintSpring.svg diff --git a/src/Mod/Fem/Gui/Resources/icons/FEM_ConstraintRigidBody.svg b/src/Mod/Fem/Gui/Resources/icons/FEM_ConstraintRigidBody.svg new file mode 100644 index 0000000000..c35f004947 --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/icons/FEM_ConstraintRigidBody.svg @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [vdwalts] + + + 2016-08-01 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/ + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 505579dd8db97038277a9824b4e622cd220144e2 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Sun, 12 May 2024 21:04:58 -0300 Subject: [PATCH 09/13] Fem: Add transform for extra symbol in constraints --- src/Mod/Fem/Gui/ViewProviderFemConstraint.cpp | 19 +++++++++++++++++++ src/Mod/Fem/Gui/ViewProviderFemConstraint.h | 9 +++++++++ 2 files changed, 28 insertions(+) diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraint.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraint.cpp index b0cc44ed82..cf567600c3 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraint.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraint.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,7 @@ ViewProviderFemConstraint::ViewProviderFemConstraint() : rotateSymbol(true) , pSymbol(nullptr) , pExtraSymbol(nullptr) + , pExtraTrans(nullptr) , ivFile(nullptr) , wizardWidget(nullptr) , wizardSubLayout(nullptr) @@ -70,6 +72,8 @@ ViewProviderFemConstraint::ViewProviderFemConstraint() pShapeSep->ref(); pMultCopy = new SoMultipleCopy(); pMultCopy->ref(); + pExtraTrans = new SoTransform(); + pExtraTrans->ref(); ShapeAppearance.setDiffuseColor(1.0f, 0.0f, 0.2f); ShapeAppearance.setSpecularColor(0.0f, 0.0f, 0.0f); @@ -80,6 +84,7 @@ ViewProviderFemConstraint::ViewProviderFemConstraint() ViewProviderFemConstraint::~ViewProviderFemConstraint() { pMultCopy->unref(); + pExtraTrans->unref(); pShapeSep->unref(); } @@ -129,6 +134,7 @@ void ViewProviderFemConstraint::loadSymbol(const char* fileName) if (nodes->getNumChildren() == 2) { pExtraSymbol = dynamic_cast(nodes->getChild(1)); if (pExtraSymbol) { + pShapeSep->addChild(pExtraTrans); pShapeSep->addChild(pExtraSymbol); } } @@ -221,6 +227,8 @@ void ViewProviderFemConstraint::updateSymbol() } pMultCopy->matrix.finishEditing(); + + transformExtraSymbol(); } void ViewProviderFemConstraint::transformSymbol(const Base::Vector3d& point, @@ -239,6 +247,17 @@ void ViewProviderFemConstraint::transformSymbol(const Base::Vector3d& point, mat.setTransform(tra, rot, scale); } +void ViewProviderFemConstraint::transformExtraSymbol() const +{ + if (pExtraTrans) { + auto obj = static_cast(this->getObject()); + float s = obj->getScaleFactor(); + SbMatrix mat; + mat.setScale(s); + pExtraTrans->setMatrix(mat); + } +} + // OvG: Visibility automation show parts and hide meshes on activation of a constraint std::string ViewProviderFemConstraint::gethideMeshShowPartStr(const std::string showConstr) diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraint.h b/src/Mod/Fem/Gui/ViewProviderFemConstraint.h index e32d8f0c63..e887981291 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraint.h +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraint.h @@ -36,6 +36,7 @@ class SbRotation; class SoMultipleCopy; +class SoTransform; namespace FemGui { @@ -68,6 +69,7 @@ public: SoSeparator* getSymbolSeparator() const; SoSeparator* getExtraSymbolSeparator() const; + SoTransform* getExtraSymbolTransform() const; // Apply rotation on copies of the constraint symbol void setRotateSymbol(bool rotate); bool getRotateSymbol() const; @@ -94,6 +96,7 @@ protected: void updateSymbol(); virtual void transformSymbol(const Base::Vector3d& point, const Base::Vector3d& normal, SbMatrix& mat) const; + virtual void transformExtraSymbol() const; static void createPlacement(SoSeparator* sep, const SbVec3f& base, const SbRotation& r); static void updatePlacement(const SoSeparator* sep, @@ -163,6 +166,7 @@ protected: SoSeparator* pShapeSep; SoSeparator* pSymbol; SoSeparator* pExtraSymbol; + SoTransform* pExtraTrans; SoMultipleCopy* pMultCopy; const char* ivFile; @@ -190,6 +194,11 @@ inline SoSeparator* ViewProviderFemConstraint::getExtraSymbolSeparator() const return pExtraSymbol; } +inline SoTransform* ViewProviderFemConstraint::getExtraSymbolTransform() const +{ + return pExtraTrans; +} + inline bool ViewProviderFemConstraint::getRotateSymbol() const { return rotateSymbol; From b799b390b9895279f8478813de98aed0f3ca27ef Mon Sep 17 00:00:00 2001 From: marioalexis Date: Wed, 8 May 2024 10:10:52 -0300 Subject: [PATCH 10/13] Fem: Change properties of the rigid body constraint --- src/Mod/Fem/App/FemConstraintRigidBody.cpp | 126 ++++++++++++++------- src/Mod/Fem/App/FemConstraintRigidBody.h | 38 +++---- 2 files changed, 101 insertions(+), 63 deletions(-) diff --git a/src/Mod/Fem/App/FemConstraintRigidBody.cpp b/src/Mod/Fem/App/FemConstraintRigidBody.cpp index cb57e9cdca..8a10cf1315 100644 --- a/src/Mod/Fem/App/FemConstraintRigidBody.cpp +++ b/src/Mod/Fem/App/FemConstraintRigidBody.cpp @@ -29,38 +29,92 @@ using namespace Fem; PROPERTY_SOURCE(Fem::ConstraintRigidBody, Fem::Constraint) +const char* ConstraintRigidBody::boundaryModeEnum[] = {"Free", "Constraint", "Load", nullptr}; + ConstraintRigidBody::ConstraintRigidBody() { - ADD_PROPERTY(xRefNode, (0.0)); - ADD_PROPERTY(yRefNode, (0.0)); - ADD_PROPERTY(zRefNode, (0.0)); - ADD_PROPERTY(xDisplacement, (0.0)); - ADD_PROPERTY(yDisplacement, (0.0)); - ADD_PROPERTY(zDisplacement, (0.0)); - ADD_PROPERTY(xRotation, (0.0)); - ADD_PROPERTY(yRotation, (0.0)); - ADD_PROPERTY(zRotation, (0.0)); - ADD_PROPERTY(xForce, (0.0)); - ADD_PROPERTY(yForce, (0.0)); - ADD_PROPERTY(zForce, (0.0)); - ADD_PROPERTY(xMoment, (0.0)); - ADD_PROPERTY(yMoment, (0.0)); - ADD_PROPERTY(zMoment, (0.0)); - ADD_PROPERTY(DefineRefNode, (1)); + ADD_PROPERTY_TYPE(ReferenceNode, + (0.0, 0.0, 0.0), + "ConstraintRigidBody", + App::Prop_Output, + "Reference node position"); + ADD_PROPERTY_TYPE(Displacement, + (0.0, 0.0, 0.0), + "ConstraintRigidBody", + App::Prop_Output, + "Reference node displacement"); + ADD_PROPERTY_TYPE(Rotation, + (Base::Rotation(0.0, 0.0, 0.0, 1.0)), + "ConstraintRigidBody", + App::Prop_Output, + "Reference node rotation"); + ADD_PROPERTY_TYPE(ForceX, + (0.0), + "ConstraintRigidBody", + App::Prop_Output, + "Applied force in X direction"); + ADD_PROPERTY_TYPE(ForceY, + (0.0), + "ConstraintRigidBody", + App::Prop_Output, + "Applied force in Y direction"); + ADD_PROPERTY_TYPE(ForceZ, + (0.0), + "ConstraintRigidBody", + App::Prop_Output, + "Applied force in Z direction"); + ADD_PROPERTY_TYPE(MomentX, + (0.0), + "ConstraintRigidBody", + App::Prop_Output, + "Applied moment in X direction"); + ADD_PROPERTY_TYPE(MomentY, + (0.0), + "ConstraintRigidBody", + App::Prop_Output, + "Applied moment in Y direction"); + ADD_PROPERTY_TYPE(MomentZ, + (0.0), + "ConstraintRigidBody", + App::Prop_Output, + "Applied moment in Z direction"); + ADD_PROPERTY_TYPE(TranslationalModeX, + ("Free"), + "ConstraintRigidBody", + App::Prop_Output, + "X-direction displacement/force mode"); + ADD_PROPERTY_TYPE(TranslationalModeY, + ("Free"), + "ConstraintRigidBody", + App::Prop_Output, + "Y-direction displacement/force mode"); + ADD_PROPERTY_TYPE(TranslationalModeZ, + ("Free"), + "ConstraintRigidBody", + App::Prop_Output, + "Z-direction displacement/force mode"); + ADD_PROPERTY_TYPE(RotationalModeX, + ("None"), + "ConstraintRigidBody", + App::Prop_Output, + "X-direction rotation/moment mode"); + ADD_PROPERTY_TYPE(RotationalModeY, + ("None"), + "ConstraintRigidBody", + App::Prop_Output, + "Y-direction rotation/moment mode"); + ADD_PROPERTY_TYPE(RotationalModeZ, + ("None"), + "ConstraintRigidBody", + App::Prop_Output, + "Z-direction rotation/moment mode"); - // For drawing the icons - ADD_PROPERTY_TYPE(Points, - (Base::Vector3d()), - "ConstraintRigidBody", - App::PropertyType(App::Prop_ReadOnly | App::Prop_Output), - "Points where symbols are drawn"); - ADD_PROPERTY_TYPE(Normals, - (Base::Vector3d()), - "ConstraintRigidBody", - App::PropertyType(App::Prop_ReadOnly | App::Prop_Output), - "Normals where symbols are drawn"); - Points.setValues(std::vector()); - Normals.setValues(std::vector()); + TranslationalModeX.setEnums(boundaryModeEnum); + TranslationalModeY.setEnums(boundaryModeEnum); + TranslationalModeZ.setEnums(boundaryModeEnum); + RotationalModeX.setEnums(boundaryModeEnum); + RotationalModeY.setEnums(boundaryModeEnum); + RotationalModeZ.setEnums(boundaryModeEnum); } App::DocumentObjectExecReturn* ConstraintRigidBody::execute() @@ -70,19 +124,5 @@ App::DocumentObjectExecReturn* ConstraintRigidBody::execute() void ConstraintRigidBody::onChanged(const App::Property* prop) { - // Note: If we call this at the end, then the symbols are not oriented correctly initially - // because the NormalDirection has not been calculated yet Constraint::onChanged(prop); - - if (prop == &References) { - std::vector points; - std::vector normals; - double scale = 1; // OvG: Enforce use of scale - if (getPoints(points, normals, &scale)) { - Points.setValues(points); - Normals.setValues(normals); - Scale.setValue(scale); // OvG: Scale - Points.touch(); // This triggers ViewProvider::updateData() - } - } } diff --git a/src/Mod/Fem/App/FemConstraintRigidBody.h b/src/Mod/Fem/App/FemConstraintRigidBody.h index 73b15ca90a..28ff18229a 100644 --- a/src/Mod/Fem/App/FemConstraintRigidBody.h +++ b/src/Mod/Fem/App/FemConstraintRigidBody.h @@ -37,27 +37,22 @@ public: /// Constructor ConstraintRigidBody(); - // Read-only (calculated values). These trigger changes in the ViewProvider - App::PropertyVectorList Points; - App::PropertyVectorList Normals; - // Rigid Body parameters - App::PropertyFloat xRefNode; - App::PropertyFloat yRefNode; - App::PropertyFloat zRefNode; - App::PropertyFloat xDisplacement; - App::PropertyFloat yDisplacement; - App::PropertyFloat zDisplacement; - App::PropertyFloat xRotation; - App::PropertyFloat yRotation; - App::PropertyFloat zRotation; - App::PropertyFloat xForce; - App::PropertyFloat yForce; - App::PropertyFloat zForce; - App::PropertyFloat xMoment; - App::PropertyFloat yMoment; - App::PropertyFloat zMoment; - App::PropertyBool DefineRefNode; + App::PropertyPosition ReferenceNode; + App::PropertyPosition Displacement; + App::PropertyRotation Rotation; + App::PropertyForce ForceX; + App::PropertyForce ForceY; + App::PropertyForce ForceZ; + App::PropertyMoment MomentX; + App::PropertyMoment MomentY; + App::PropertyMoment MomentZ; + App::PropertyEnumeration TranslationalModeX; + App::PropertyEnumeration TranslationalModeY; + App::PropertyEnumeration TranslationalModeZ; + App::PropertyEnumeration RotationalModeX; + App::PropertyEnumeration RotationalModeY; + App::PropertyEnumeration RotationalModeZ; /// recalculate the object App::DocumentObjectExecReturn* execute() override; @@ -70,6 +65,9 @@ public: protected: void onChanged(const App::Property* prop) override; + +private: + static const char* boundaryModeEnum[]; }; } // namespace Fem From 03dc23497088091ffc1159c3815f52291fddec1c Mon Sep 17 00:00:00 2001 From: marioalexis Date: Wed, 8 May 2024 10:13:26 -0300 Subject: [PATCH 11/13] Fem: Update view provider of the rigid body constraint --- src/Mod/Fem/Gui/CMakeLists.txt | 1 + .../Resources/symbols/ConstraintRigidBody.iv | 32 +++++++ .../ViewProviderFemConstraintRigidBody.cpp | 96 ++++++------------- .../Gui/ViewProviderFemConstraintRigidBody.h | 2 + 4 files changed, 62 insertions(+), 69 deletions(-) create mode 100644 src/Mod/Fem/Gui/Resources/symbols/ConstraintRigidBody.iv diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index 2842895ba4..65d871e137 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -360,6 +360,7 @@ SET(FemGuiSymbol_IV Resources/symbols/ConstraintHeatFlux.iv Resources/symbols/ConstraintPlaneRotation.iv Resources/symbols/ConstraintPressure.iv + Resources/symbols/ConstraintRigidBody.iv Resources/symbols/ConstraintSpring.iv Resources/symbols/ConstraintTemperature.iv Resources/symbols/ConstraintTie.iv diff --git a/src/Mod/Fem/Gui/Resources/symbols/ConstraintRigidBody.iv b/src/Mod/Fem/Gui/Resources/symbols/ConstraintRigidBody.iv new file mode 100644 index 0000000000..66d3d0fc8b --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/symbols/ConstraintRigidBody.iv @@ -0,0 +1,32 @@ +#Inventor V2.1 ascii + + +Separator { + + Separator { + + Translation { + translation 0 2.5 0 + } + Sphere { + radius 0.5 + + } + Translation { + translation 0 -1.25 0 + + } + Cylinder { + radius 0.25 + height 2.5 + + } + } + Separator { + + Sphere { + radius 0.25 + + } + } +} diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.cpp b/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.cpp index d7a7f23430..0364b65b12 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.cpp @@ -24,17 +24,14 @@ #ifndef _PreComp_ #include -#include -#include -#include -#include +#include #endif -#include #include "Gui/Control.h" +#include -#include "ViewProviderFemConstraintRigidBody.h" #include "TaskFemConstraintRigidBody.h" +#include "ViewProviderFemConstraintRigidBody.h" using namespace FemGui; @@ -46,10 +43,11 @@ PROPERTY_SOURCE(FemGui::ViewProviderFemConstraintRigidBody, ViewProviderFemConstraintRigidBody::ViewProviderFemConstraintRigidBody() { sPixmap = "FEM_ConstraintRigidBody"; + loadSymbol((resourceSymbolDir + "ConstraintRigidBody.iv").c_str()); + ShapeAppearance.setDiffuseColor(0.0f, 0.5f, 0.0f); } -ViewProviderFemConstraintRigidBody::~ViewProviderFemConstraintRigidBody() -{} +ViewProviderFemConstraintRigidBody::~ViewProviderFemConstraintRigidBody() = default; bool ViewProviderFemConstraintRigidBody::setEdit(int ModNum) { @@ -110,71 +108,31 @@ bool ViewProviderFemConstraintRigidBody::setEdit(int ModNum) } } -#define WIDTH (2) -#define HEIGHT (1) -// #define USE_MULTIPLE_COPY //OvG: MULTICOPY fails to update scaled display on initial drawing - -// so disable - void ViewProviderFemConstraintRigidBody::updateData(const App::Property* prop) { - // Gets called whenever a property of the attached object changes - Fem::ConstraintRigidBody* pcConstraint = - static_cast(this->getObject()); - float scaledwidth = - WIDTH * pcConstraint->Scale.getValue(); // OvG: Calculate scaled values once only - float scaledheight = HEIGHT * pcConstraint->Scale.getValue(); + auto obj = static_cast(this->getObject()); -#ifdef USE_MULTIPLE_COPY - // OvG: always need access to cp for scaling - SoMultipleCopy* cp = new SoMultipleCopy(); - if (pShapeSep->getNumChildren() == 0) { - // Set up the nodes - cp->matrix.setNum(0); - cp->addChild((SoNode*)createRigidBody(scaledheight, scaledwidth)); // OvG: Scaling - pShapeSep->addChild(cp); - } -#endif - - if (strcmp(prop->getName(), "Points") == 0) { - const std::vector& points = pcConstraint->Points.getValues(); - const std::vector& normals = pcConstraint->Normals.getValues(); - if (points.size() != normals.size()) { - return; - } - std::vector::const_iterator n = normals.begin(); - -#ifdef USE_MULTIPLE_COPY - cp = static_cast(pShapeSep->getChild(0)); - cp->matrix.setNum(points.size()); - SbMatrix* matrices = cp->matrix.startEditing(); - int idx = 0; -#else - // Note: Points and Normals are always updated together - Gui::coinRemoveAllChildren(pShapeSep); -#endif - - for (std::vector::const_iterator p = points.begin(); p != points.end(); - p++) { - SbVec3f base(p->x, p->y, p->z); - SbVec3f dir(n->x, n->y, n->z); - SbRotation rot(SbVec3f(0, -1, 0), dir); -#ifdef USE_MULTIPLE_COPY - SbMatrix m; - m.setTransform(base, rot, SbVec3f(1, 1, 1)); - matrices[idx] = m; - idx++; -#else - SoSeparator* sep = new SoSeparator(); - createPlacement(sep, base, rot); - createFixed(sep, scaledheight, scaledwidth); // OvG: Scaling - pShapeSep->addChild(sep); -#endif - n++; - } -#ifdef USE_MULTIPLE_COPY - cp->matrix.finishEditing(); -#endif + if (prop == &obj->ReferenceNode) { + updateSymbol(); } ViewProviderFemConstraint::updateData(prop); } + +void ViewProviderFemConstraintRigidBody::transformExtraSymbol() const +{ + SoTransform* symTrans = getExtraSymbolTransform(); + if (symTrans) { + auto obj = static_cast(this->getObject()); + float s = obj->getScaleFactor(); + const Base::Vector3d& refNode = obj->ReferenceNode.getValue(); + SbVec3f tra(refNode.x, refNode.y, refNode.z); + SbVec3f sca(s, s, s); + SbRotation rot(SbVec3f(0, 0, 1), 0); + + SbMatrix mat; + mat.setTransform(tra, rot, sca); + + symTrans->setMatrix(mat); + } +} diff --git a/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.h b/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.h index 19008b3c15..5f35b4e0f8 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.h +++ b/src/Mod/Fem/Gui/ViewProviderFemConstraintRigidBody.h @@ -43,6 +43,8 @@ public: protected: bool setEdit(int ModNum) override; + + void transformExtraSymbol() const override; }; } // namespace FemGui From 35db988ca04cee3b76d8e11ecbc05ea3051215f3 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Wed, 8 May 2024 10:16:02 -0300 Subject: [PATCH 12/13] Fem: Update task dialog of the rigid body constraint --- .../Fem/Gui/TaskFemConstraintRigidBody.cpp | 492 +++++++++--- src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h | 24 +- src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui | 698 +++++++++++++----- 3 files changed, 908 insertions(+), 306 deletions(-) diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp index 73025f46e6..596b0105af 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.cpp @@ -67,45 +67,161 @@ TaskFemConstraintRigidBody::TaskFemConstraintRigidBody( &QListWidget::itemClicked, this, &TaskFemConstraintRigidBody::setSelection); - - // TODO: Relate inputs to property + connect(ui->cb_x_trans_mode, + qOverload(&QComboBox::activated), + this, + &TaskFemConstraintRigidBody::onTransModeXChanged); + connect(ui->cb_y_trans_mode, + qOverload(&QComboBox::activated), + this, + &TaskFemConstraintRigidBody::onTransModeYChanged); + connect(ui->cb_z_trans_mode, + qOverload(&QComboBox::activated), + this, + &TaskFemConstraintRigidBody::onTransModeZChanged); + connect(ui->cb_x_rot_mode, + qOverload(&QComboBox::activated), + this, + &TaskFemConstraintRigidBody::onRotModeXChanged); + connect(ui->cb_y_rot_mode, + qOverload(&QComboBox::activated), + this, + &TaskFemConstraintRigidBody::onRotModeYChanged); + connect(ui->cb_z_rot_mode, + qOverload(&QComboBox::activated), + this, + &TaskFemConstraintRigidBody::onRotModeZChanged); this->groupLayout()->addWidget(proxy); /* Note: */ // Get the feature data - Fem::ConstraintRigidBody* pcConstraint = - static_cast(ConstraintView->getObject()); - double fStates[15]; - fStates[0] = pcConstraint->xRefNode.getValue(); - fStates[1] = pcConstraint->yRefNode.getValue(); - fStates[2] = pcConstraint->zRefNode.getValue(); - fStates[3] = pcConstraint->xDisplacement.getValue(); - fStates[4] = pcConstraint->yDisplacement.getValue(); - fStates[5] = pcConstraint->zDisplacement.getValue(); - fStates[6] = pcConstraint->xRotation.getValue(); - fStates[7] = pcConstraint->yRotation.getValue(); - fStates[8] = pcConstraint->zRotation.getValue(); - fStates[9] = pcConstraint->xForce.getValue(); - fStates[10] = pcConstraint->yForce.getValue(); - fStates[11] = pcConstraint->zForce.getValue(); - fStates[12] = pcConstraint->xMoment.getValue(); - fStates[13] = pcConstraint->yMoment.getValue(); - fStates[14] = pcConstraint->zMoment.getValue(); + auto pcConstraint = static_cast(ConstraintView->getObject()); + + const Base::Vector3d& refNode = pcConstraint->ReferenceNode.getValue(); + const Base::Vector3d& disp = pcConstraint->Displacement.getValue(); + Base::Vector3d rotDir; + double rotAngleRad; + pcConstraint->Rotation.getValue().getValue(rotDir, rotAngleRad); + Base::Quantity rotAngle(rotAngleRad, QString::fromUtf8("rad")); + Base::Quantity forceX = pcConstraint->ForceX.getQuantityValue(); + Base::Quantity forceY = pcConstraint->ForceY.getQuantityValue(); + Base::Quantity forceZ = pcConstraint->ForceZ.getQuantityValue(); + Base::Quantity momentX = pcConstraint->MomentX.getQuantityValue(); + Base::Quantity momentY = pcConstraint->MomentY.getQuantityValue(); + Base::Quantity momentZ = pcConstraint->MomentZ.getQuantityValue(); std::vector Objects = pcConstraint->References.getValues(); std::vector SubElements = pcConstraint->References.getSubValues(); // Fill data into dialog elements - ui->if_ref_node_x->setValue(fStates[0]); - ui->if_ref_node_y->setValue(fStates[1]); - ui->if_ref_node_z->setValue(fStates[2]); - ui->if_ref_force_x->setValue(fStates[9]); - ui->if_ref_force_y->setValue(fStates[10]); - ui->if_ref_force_z->setValue(fStates[11]); - ui->if_rot_force_x->setValue(fStates[12]); - ui->if_rot_force_y->setValue(fStates[13]); - ui->if_rot_force_z->setValue(fStates[14]); + ui->qsb_ref_node_x->setValue(refNode.x); + ui->qsb_ref_node_y->setValue(refNode.y); + ui->qsb_ref_node_z->setValue(refNode.z); + ui->qsb_ref_node_x->bind( + App::ObjectIdentifier::parse(pcConstraint, std::string("ReferenceNode.x"))); + ui->qsb_ref_node_y->bind( + App::ObjectIdentifier::parse(pcConstraint, std::string("ReferenceNode.y"))); + ui->qsb_ref_node_z->bind( + App::ObjectIdentifier::parse(pcConstraint, std::string("ReferenceNode.z"))); + ui->qsb_ref_node_x->setMinimum(-FLOAT_MAX); + ui->qsb_ref_node_x->setMaximum(FLOAT_MAX); + ui->qsb_ref_node_y->setMinimum(-FLOAT_MAX); + ui->qsb_ref_node_y->setMaximum(FLOAT_MAX); + ui->qsb_ref_node_z->setMinimum(-FLOAT_MAX); + ui->qsb_ref_node_z->setMaximum(FLOAT_MAX); + + ui->qsb_disp_x->setValue(disp.x); + ui->qsb_disp_y->setValue(disp.y); + ui->qsb_disp_z->setValue(disp.z); + ui->qsb_disp_x->bind(App::ObjectIdentifier::parse(pcConstraint, std::string("Displacement.x"))); + ui->qsb_disp_y->bind(App::ObjectIdentifier::parse(pcConstraint, std::string("Displacement.y"))); + ui->qsb_disp_z->bind(App::ObjectIdentifier::parse(pcConstraint, std::string("Displacement.z"))); + ui->qsb_disp_x->setMinimum(-FLOAT_MAX); + ui->qsb_disp_x->setMaximum(FLOAT_MAX); + ui->qsb_disp_y->setMinimum(-FLOAT_MAX); + ui->qsb_disp_y->setMaximum(FLOAT_MAX); + ui->qsb_disp_z->setMinimum(-FLOAT_MAX); + ui->qsb_disp_z->setMaximum(FLOAT_MAX); + + ui->spb_rot_axis_x->setValue(rotDir.x); + ui->spb_rot_axis_y->setValue(rotDir.y); + ui->spb_rot_axis_z->setValue(rotDir.z); + ui->qsb_rot_angle->setValue(rotAngle.getValueAs(Base::Quantity::Degree)); + ui->spb_rot_axis_x->bind( + App::ObjectIdentifier::parse(pcConstraint, std::string("Rotation.Axis.x"))); + ui->spb_rot_axis_y->bind( + App::ObjectIdentifier::parse(pcConstraint, std::string("Rotation.Axis.y"))); + ui->spb_rot_axis_z->bind( + App::ObjectIdentifier::parse(pcConstraint, std::string("Rotation.Axis.z"))); + ui->qsb_rot_angle->bind( + App::ObjectIdentifier::parse(pcConstraint, std::string("Rotation.Angle"))); + ui->spb_rot_axis_x->setMinimum(-FLOAT_MAX); + ui->spb_rot_axis_x->setMaximum(FLOAT_MAX); + ui->spb_rot_axis_y->setMinimum(-FLOAT_MAX); + ui->spb_rot_axis_y->setMaximum(FLOAT_MAX); + ui->spb_rot_axis_z->setMinimum(-FLOAT_MAX); + ui->spb_rot_axis_z->setMaximum(FLOAT_MAX); + ui->qsb_rot_angle->setMinimum(-FLOAT_MAX); + ui->qsb_rot_angle->setMaximum(FLOAT_MAX); + + ui->qsb_force_x->setValue(forceX); + ui->qsb_force_y->setValue(forceY); + ui->qsb_force_z->setValue(forceZ); + ui->qsb_force_x->bind(pcConstraint->ForceX); + ui->qsb_force_y->bind(pcConstraint->ForceY); + ui->qsb_force_z->bind(pcConstraint->ForceZ); + ui->qsb_force_x->setMinimum(-FLOAT_MAX); + ui->qsb_force_x->setMaximum(FLOAT_MAX); + ui->qsb_force_y->setMinimum(-FLOAT_MAX); + ui->qsb_force_y->setMaximum(FLOAT_MAX); + ui->qsb_force_z->setMinimum(-FLOAT_MAX); + ui->qsb_force_z->setMaximum(FLOAT_MAX); + + ui->qsb_moment_x->setValue(momentX); + ui->qsb_moment_y->setValue(momentY); + ui->qsb_moment_z->setValue(momentZ); + ui->qsb_moment_x->bind(pcConstraint->MomentX); + ui->qsb_moment_y->bind(pcConstraint->MomentY); + ui->qsb_moment_z->bind(pcConstraint->MomentZ); + ui->qsb_moment_x->setMinimum(-FLOAT_MAX); + ui->qsb_moment_x->setMaximum(FLOAT_MAX); + ui->qsb_moment_y->setMinimum(-FLOAT_MAX); + ui->qsb_moment_y->setMaximum(FLOAT_MAX); + ui->qsb_moment_z->setMinimum(-FLOAT_MAX); + ui->qsb_moment_z->setMaximum(FLOAT_MAX); + + QStringList modeList; + + App::PropertyEnumeration* transMode = &pcConstraint->TranslationalModeX; + for (auto item : transMode->getEnumVector()) { + modeList << QString::fromUtf8(item.c_str()); + } + ui->cb_x_trans_mode->addItems(modeList); + ui->cb_y_trans_mode->addItems(modeList); + ui->cb_z_trans_mode->addItems(modeList); + ui->cb_x_trans_mode->setCurrentIndex(pcConstraint->TranslationalModeX.getValue()); + ui->cb_y_trans_mode->setCurrentIndex(pcConstraint->TranslationalModeY.getValue()); + ui->cb_z_trans_mode->setCurrentIndex(pcConstraint->TranslationalModeZ.getValue()); + + modeList.clear(); + App::PropertyEnumeration* rotMode = &pcConstraint->RotationalModeX; + for (auto item : rotMode->getEnumVector()) { + modeList << QString::fromUtf8(item.c_str()); + } + ui->cb_x_rot_mode->addItems(modeList); + ui->cb_y_rot_mode->addItems(modeList); + ui->cb_z_rot_mode->addItems(modeList); + ui->cb_x_rot_mode->setCurrentIndex(pcConstraint->RotationalModeX.getValue()); + ui->cb_y_rot_mode->setCurrentIndex(pcConstraint->RotationalModeY.getValue()); + ui->cb_z_rot_mode->setCurrentIndex(pcConstraint->RotationalModeZ.getValue()); + + onTransModeXChanged(pcConstraint->TranslationalModeX.getValue()); + onTransModeYChanged(pcConstraint->TranslationalModeY.getValue()); + onTransModeZChanged(pcConstraint->TranslationalModeZ.getValue()); + onRotModeXChanged(pcConstraint->RotationalModeX.getValue()); + onRotModeYChanged(pcConstraint->RotationalModeY.getValue()); + onRotModeZChanged(pcConstraint->RotationalModeZ.getValue()); ui->lw_references->clear(); for (std::size_t i = 0; i < Objects.size(); i++) { @@ -274,6 +390,123 @@ void TaskFemConstraintRigidBody::onReferenceDeleted() TaskFemConstraintRigidBody::removeFromSelection(); } +void TaskFemConstraintRigidBody::onRotModeXChanged(int item) +{ + const char* val = static_cast(ConstraintView->getObject()) + ->RotationalModeX.getEnumVector()[item] + .c_str(); + + if (strcmp(val, "Free") == 0) { + ui->spb_rot_axis_x->setEnabled(false); + ui->qsb_moment_x->setEnabled(false); + } + else if (strcmp(val, "Constraint") == 0) { + ui->spb_rot_axis_x->setEnabled(true); + ui->qsb_moment_x->setEnabled(false); + } + else if (strcmp(val, "Load") == 0) { + ui->spb_rot_axis_x->setEnabled(false); + ui->qsb_moment_x->setEnabled(true); + } +} +void TaskFemConstraintRigidBody::onRotModeYChanged(int item) +{ + const char* val = static_cast(ConstraintView->getObject()) + ->RotationalModeY.getEnumVector()[item] + .c_str(); + + if (strcmp(val, "Free") == 0) { + ui->spb_rot_axis_y->setEnabled(false); + ui->qsb_moment_y->setEnabled(false); + } + else if (strcmp(val, "Constraint") == 0) { + ui->spb_rot_axis_y->setEnabled(true); + ui->qsb_moment_y->setEnabled(false); + } + else if (strcmp(val, "Load") == 0) { + ui->spb_rot_axis_y->setEnabled(false); + ui->qsb_moment_y->setEnabled(true); + } +} +void TaskFemConstraintRigidBody::onRotModeZChanged(int item) +{ + const char* val = static_cast(ConstraintView->getObject()) + ->RotationalModeZ.getEnumVector()[item] + .c_str(); + + if (strcmp(val, "Free") == 0) { + ui->spb_rot_axis_z->setEnabled(false); + ui->qsb_moment_z->setEnabled(false); + } + else if (strcmp(val, "Constraint") == 0) { + ui->spb_rot_axis_z->setEnabled(true); + ui->qsb_moment_z->setEnabled(false); + } + else if (strcmp(val, "Load") == 0) { + ui->spb_rot_axis_z->setEnabled(false); + ui->qsb_moment_z->setEnabled(true); + } +} + +void TaskFemConstraintRigidBody::onTransModeXChanged(int item) +{ + const char* val = static_cast(ConstraintView->getObject()) + ->TranslationalModeX.getEnumVector()[item] + .c_str(); + + if (strcmp(val, "Free") == 0) { + ui->qsb_disp_x->setEnabled(false); + ui->qsb_force_x->setEnabled(false); + } + else if (strcmp(val, "Constraint") == 0) { + ui->qsb_disp_x->setEnabled(true); + ui->qsb_force_x->setEnabled(false); + } + else if (strcmp(val, "Load") == 0) { + ui->qsb_disp_x->setEnabled(false); + ui->qsb_force_x->setEnabled(true); + } +} +void TaskFemConstraintRigidBody::onTransModeYChanged(int item) +{ + const char* val = static_cast(ConstraintView->getObject()) + ->TranslationalModeY.getEnumVector()[item] + .c_str(); + + if (strcmp(val, "Free") == 0) { + ui->qsb_disp_y->setEnabled(false); + ui->qsb_force_y->setEnabled(false); + } + else if (strcmp(val, "Constraint") == 0) { + ui->qsb_disp_y->setEnabled(true); + ui->qsb_force_y->setEnabled(false); + } + else if (strcmp(val, "Load") == 0) { + ui->qsb_disp_y->setEnabled(false); + ui->qsb_force_y->setEnabled(true); + } +} +void TaskFemConstraintRigidBody::onTransModeZChanged(int item) +{ + const char* val = static_cast(ConstraintView->getObject()) + ->TranslationalModeZ.getEnumVector()[item] + .c_str(); + + if (strcmp(val, "Free") == 0) { + ui->qsb_disp_z->setEnabled(false); + ui->qsb_force_z->setEnabled(false); + } + else if (strcmp(val, "Constraint") == 0) { + ui->qsb_disp_z->setEnabled(true); + ui->qsb_force_z->setEnabled(false); + } + else if (strcmp(val, "Load") == 0) { + ui->qsb_disp_z->setEnabled(false); + ui->qsb_force_z->setEnabled(true); + } +} + + const std::string TaskFemConstraintRigidBody::getReferences() const { int rows = ui->lw_references->model()->rowCount(); @@ -284,46 +517,70 @@ const std::string TaskFemConstraintRigidBody::getReferences() const return TaskFemConstraint::getReferences(items); } -double TaskFemConstraintRigidBody::get_xRefNode() const +Base::Vector3d TaskFemConstraintRigidBody::getReferenceNode() const { - return ui->if_ref_node_x->rawValue(); + double x = ui->qsb_ref_node_x->rawValue(); + double y = ui->qsb_ref_node_y->rawValue(); + double z = ui->qsb_ref_node_z->rawValue(); + + return Base::Vector3d(x, y, z); } -double TaskFemConstraintRigidBody::get_yRefNode() const + +Base::Vector3d TaskFemConstraintRigidBody::getDisplacement() const { - return ui->if_ref_node_y->rawValue(); + double x = ui->qsb_disp_x->rawValue(); + double y = ui->qsb_disp_y->rawValue(); + double z = ui->qsb_disp_z->rawValue(); + + return Base::Vector3d(x, y, z); } -double TaskFemConstraintRigidBody::get_zRefNode() const + +Base::Rotation TaskFemConstraintRigidBody::getRotation() const { - return ui->if_ref_node_z->rawValue(); + double x = ui->spb_rot_axis_x->value(); + double y = ui->spb_rot_axis_y->value(); + double z = ui->spb_rot_axis_z->value(); + double angle = ui->qsb_rot_angle->value().getValueAs(Base::Quantity::Radian); + + return Base::Rotation(Base::Vector3d(x, y, z), angle); } -double TaskFemConstraintRigidBody::get_xForce() const + +std::vector TaskFemConstraintRigidBody::getForce() const { - return ui->if_ref_force_x->rawValue(); + std::string x = ui->qsb_force_x->value().getSafeUserString().toStdString(); + std::string y = ui->qsb_force_y->value().getSafeUserString().toStdString(); + std::string z = ui->qsb_force_z->value().getSafeUserString().toStdString(); + + return {x, y, z}; } -double TaskFemConstraintRigidBody::get_yForce() const + +std::vector TaskFemConstraintRigidBody::getMoment() const { - return ui->if_ref_force_y->rawValue(); + std::string x = ui->qsb_moment_x->value().getSafeUserString().toStdString(); + std::string y = ui->qsb_moment_y->value().getSafeUserString().toStdString(); + std::string z = ui->qsb_moment_z->value().getSafeUserString().toStdString(); + + return std::vector({x, y, z}); } -double TaskFemConstraintRigidBody::get_zForce() const + +std::vector TaskFemConstraintRigidBody::getTranslationalMode() const { - return ui->if_ref_force_z->rawValue(); + std::vector transModes(3); + transModes[0] = ui->cb_x_trans_mode->currentText().toStdString(); + transModes[1] = ui->cb_y_trans_mode->currentText().toStdString(); + transModes[2] = ui->cb_z_trans_mode->currentText().toStdString(); + + return transModes; } -double TaskFemConstraintRigidBody::get_xMoment() const + +std::vector TaskFemConstraintRigidBody::getRotationalMode() const { - return ui->if_rot_force_x->rawValue(); -} -double TaskFemConstraintRigidBody::get_yMoment() const -{ - return ui->if_rot_force_y->rawValue(); -} -double TaskFemConstraintRigidBody::get_zMoment() const -{ - return ui->if_rot_force_z->rawValue(); -} -// TODO: This needs to be implemented -bool TaskFemConstraintRigidBody::get_DefineRefNode() const -{ - return true; + std::vector rotModes(3); + rotModes[0] = ui->cb_x_rot_mode->currentText().toStdString(); + rotModes[1] = ui->cb_y_rot_mode->currentText().toStdString(); + rotModes[2] = ui->cb_z_rot_mode->currentText().toStdString(); + + return rotModes; } bool TaskFemConstraintRigidBody::event(QEvent* e) @@ -381,52 +638,95 @@ bool TaskDlgFemConstraintRigidBody::accept() const TaskFemConstraintRigidBody* parameters = static_cast(parameter); try { + Base::Vector3d ref = parameters->getReferenceNode(); Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.xRefNode = %f", + "App.ActiveDocument.%s.ReferenceNode = App.Vector(%f, %f, %f)", name.c_str(), - parameters->get_xRefNode()); - Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.yRefNode = %f", - name.c_str(), - parameters->get_yRefNode()); - Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.zRefNode = %f", - name.c_str(), - parameters->get_zRefNode()); - Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.xForce = %f", - name.c_str(), - parameters->get_xForce()); - Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.yForce = %f", - name.c_str(), - parameters->get_yForce()); - Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.zForce = %f", - name.c_str(), - parameters->get_zForce()); - Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.xMoment = %f", - name.c_str(), - parameters->get_xMoment()); - Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.yMoment = %f", - name.c_str(), - parameters->get_yMoment()); - Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.zMoment = %f", - name.c_str(), - parameters->get_zMoment()); - Gui::Command::doCommand(Gui::Command::Doc, - "App.ActiveDocument.%s.DefineRefNode = %s", - name.c_str(), - parameters->get_DefineRefNode() ? "True" : "False"); + ref.x, + ref.y, + ref.z); + + Base::Vector3d disp = parameters->getDisplacement(); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.Displacement = App.Vector(%f, %f, %f)", + name.c_str(), + disp.x, + disp.y, + disp.z); + + Base::Rotation rot = parameters->getRotation(); + Base::Vector3d axis; + double angle; + rot.getValue(axis, angle); + Gui::Command::doCommand( + Gui::Command::Doc, + "App.ActiveDocument.%s.Rotation = App.Rotation(App.Vector(%f,% f, %f), Radian=%f)", + name.c_str(), + axis.x, + axis.y, + axis.z, + angle); + + auto force = parameters->getForce(); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.ForceX = \"%s\"", + name.c_str(), + force[0].c_str()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.ForceY = \"%s\"", + name.c_str(), + force[1].c_str()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.ForceZ = \"%s\"", + name.c_str(), + force[2].c_str()); + + auto moment = parameters->getMoment(); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.MomentX = \"%s\"", + name.c_str(), + moment[0].c_str()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.MomentY = \"%s\"", + name.c_str(), + moment[1].c_str()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.MomentZ = \"%s\"", + name.c_str(), + moment[2].c_str()); + + auto transModes = parameters->getTranslationalMode(); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.TranslationalModeX = \"%s\"", + name.c_str(), + transModes[0].c_str()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.TranslationalModeY = \"%s\"", + name.c_str(), + transModes[1].c_str()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.TranslationalModeZ = \"%s\"", + name.c_str(), + transModes[2].c_str()); + + auto rotModes = parameters->getRotationalMode(); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.RotationalModeX = \"%s\"", + name.c_str(), + rotModes[0].c_str()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.RotationalModeY = \"%s\"", + name.c_str(), + rotModes[1].c_str()); + Gui::Command::doCommand(Gui::Command::Doc, + "App.ActiveDocument.%s.RotationalModeZ = \"%s\"", + name.c_str(), + rotModes[2].c_str()); - std::string scale = parameters->getScale(); // OvG: determine modified scale Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.Scale = %s", name.c_str(), - scale.c_str()); // OvG: implement modified scale + parameters->getScale().c_str()); } catch (const Base::Exception& e) { QMessageBox::warning(parameter, tr("Input error"), QString::fromLatin1(e.what())); diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h index 24642d2f93..fc03f5b7eb 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.h @@ -41,22 +41,26 @@ public: explicit TaskFemConstraintRigidBody(ViewProviderFemConstraintRigidBody* ConstraintView, QWidget* parent = nullptr); ~TaskFemConstraintRigidBody() override; + const std::string getReferences() const override; - double get_xRefNode() const; - double get_yRefNode() const; - double get_zRefNode() const; - double get_xForce() const; - double get_yForce() const; - double get_zForce() const; - double get_xMoment() const; - double get_yMoment() const; - double get_zMoment() const; - bool get_DefineRefNode() const; + Base::Vector3d getReferenceNode() const; + Base::Vector3d getDisplacement() const; + Base::Rotation getRotation() const; + std::vector getForce() const; + std::vector getMoment() const; + std::vector getTranslationalMode() const; + std::vector getRotationalMode() const; private Q_SLOTS: void onReferenceDeleted(); void addToSelection() override; void removeFromSelection() override; + void onTransModeXChanged(int); + void onTransModeYChanged(int); + void onTransModeZChanged(int); + void onRotModeXChanged(int); + void onRotModeYChanged(int); + void onRotModeZChanged(int); protected: bool event(QEvent* e) override; diff --git a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui index 7aa6cec178..c255931ae2 100644 --- a/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui +++ b/src/Mod/Fem/Gui/TaskFemConstraintRigidBody.ui @@ -63,76 +63,92 @@ - - + + + + 0 + 0 + + + + + + Reference Node + + + + + X: + + + + + + + 1.0 + + + 1000000000.0 + + + mm + + + 0.0 + + + + + + + Y: + + + + + + + 1.0 + + + 1000000000.0 + + + mm + + + 0.0 + + + + + + + Z: + + + + + + + 1.0 + + + 1000000000.0 + + + mm + + + 0.0 + + + + - - - - - - X: - - - - - - - 0 mm - - - mm - - - 0.000000000000000 - - - - - - - Y: - - - - - - - 0 mm - - - mm - - - 0.000000000000000 - - - - - - - Z: - - - - - - - 0 mm - - - mm - - - 0.000000000000000 - - - - - @@ -147,78 +163,211 @@ - - - Force on Reference Node + + + + 0 + 0 + + + + + + Translational Mode + + + + + + X: + + + + + + + Y: + + + + + + + Z: + + + + + + + + + + + + + - - - - - X: - - - - - - - 0 N - - - N - - - 0.000000000000000 - - - - - - - Y: - - - - - - - 0 N - - - N - - - 0.000000000000000 - - - - - - - Z: - - - - - - - 0 N - - - N - - - 0.000000000000000 - - - - + + + + 0 + 0 + + + + + + + Displacement + + + + + + X: + + + + + + + Y: + + + + + + + Z: + + + + + + + false + + + 1.00000000000000 + + + mm + + + + + + + false + + + 1.00000000000000 + + + mm + + + + + + + false + + + 1.00000000000000 + + + mm + + + + + - + + + + 0 + 0 + + + + + + + Force + + + + + + X: + + + + + + + Y: + + + + + + + Z: + + + + + + + false + + + 1.00000000000000 + + + N + + + + + + + false + + + 1.00000000000000 + + + N + + + + + + + false + + + 1.00000000000000 + + + N + + + + + + + + Qt::Vertical @@ -231,75 +380,219 @@ - - - Moment on Rotation Node + + + + 0 + 0 + + + + + + Rotational Mode + + + + + + X: + + + + + + + Y: + + + + + + + Z: + + + + + + + + + + + + + - - - - - X: - - - - - - - 0 N*m - - - N*m - - - 0.000000000000000 - - - - - - - Y: - - - - - - - 0 N*m - - - N*m - - - 0.000000000000000 - - - - - - - Z: - - - - - - - 0 N*m - - - N*m - - - 0.000000000000000 - - - - + + + + 0 + 0 + + + + + + + Rotation + + + + + + X: + + + + + + + Y: + + + + + + + Z: + + + + + + + false + + + 0.10000000000000 + + + + + + + false + + + 0.100000000000000 + + + + + + + false + + + 0.100000000000000 + + + + + + + Angle: + + + + + + + false + + + 1.00000000000000 + + + deg + + + + + + + + + + + 0 + 0 + + + + + + + Moment + + + + + + X: + + + + + + + Y: + + + + + + + Z: + + + + + + + false + + + 1.00000000000000 + + + N*m + + + + + + + false + + + 1.00000000000000 + + + N*m + + + + + + + false + + + 1.00000000000000 + + + N*m + + + + + @@ -307,9 +600,14 @@ - Gui::InputField - QLineEdit -
Gui/InputField.h
+ Gui::QuantitySpinBox + QWidget +
Gui/QuantitySpinBox.h
+
+ + Gui::DoubleSpinBox + QWidget +
Gui/SpinBox.h
From e307595586181d752b67e98e6d8071ee1db4df06 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Sun, 12 May 2024 21:14:11 -0300 Subject: [PATCH 13/13] Fem: Update CalculiX writer of the constraint rigid body --- .../calculix/write_constraint_rigidbody.py | 34 +++------- .../write_constraint_rigidbody_step.py | 62 +++++++++++-------- 2 files changed, 45 insertions(+), 51 deletions(-) diff --git a/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody.py b/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody.py index 0ea4566e80..5d5e28c428 100644 --- a/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody.py +++ b/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody.py @@ -55,6 +55,7 @@ def get_after_write_constraint(): def write_meshdata_constraint(f, femobj, rb_obj, ccxwriter): + f.write("*NSET,NSET=" + rb_obj.Name + "\n") for n in femobj["Nodes"]: f.write("{},\n".format(n)) @@ -62,36 +63,17 @@ def write_meshdata_constraint(f, femobj, rb_obj, ccxwriter): def write_constraint(f, femobj, rb_obj, ccxwriter): - # floats read from ccx should use {:.13G}, see comment in writer module - is_ref_bc_defined = any((rb_obj.xDisplacement, - rb_obj.yDisplacement, - rb_obj.zDisplacement, - rb_obj.xForce, - rb_obj.yForce, - rb_obj.zForce)) - - is_rot_bc_defined = any((rb_obj.xRotation, - rb_obj.yRotation, - rb_obj.zRotation, - rb_obj.xMoment, - rb_obj.yMoment, - rb_obj.zMoment)) - - # FIXME: This needs to be implemented - ref_node_idx = 10000000 - rot_node_idx = 20000000 + rb_obj_idx = ccxwriter.analysis.Group.index(rb_obj) + node_count = ccxwriter.mesh_object.FemMesh.NodeCount + # factor 2 is to prevent conflict with other rigid body constraint + ref_node_idx = node_count + 2*rb_obj_idx + 1 + rot_node_idx = node_count + 2*rb_obj_idx + 2 f.write("*NODE\n") - f.write("{},{},{},{}\n".format(ref_node_idx, rb_obj.xRefNode, rb_obj.yRefNode, rb_obj.zRefNode)) - f.write("{},{},{},{}\n".format(rot_node_idx, rb_obj.xRefNode, rb_obj.yRefNode, rb_obj.zRefNode)) + f.write("{},{},{},{}\n".format(ref_node_idx, *rb_obj.ReferenceNode)) + f.write("{},{},{},{}\n".format(rot_node_idx, *rb_obj.ReferenceNode)) kw_line = "*RIGID BODY, NSET={}, REF NODE={}, ROT NODE={}".format(rb_obj.Name, ref_node_idx, rot_node_idx) - if is_ref_bc_defined: - kw_line = kw_line + ",REF NODE={}".format(ref_node_idx) - - if is_rot_bc_defined: - kw_line = kw_line + ",ROT NODE={}".format(rot_node_idx) - f.write(kw_line + "\n") diff --git a/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody_step.py b/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody_step.py index 4b026675d3..ad7a27d56f 100644 --- a/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody_step.py +++ b/src/Mod/Fem/femsolver/calculix/write_constraint_rigidbody_step.py @@ -26,6 +26,9 @@ __author__ = "Ajinkya Dahale" __url__ = "https://www.freecadweb.org" +import FreeCAD + + def get_analysis_types(): return "all" # write for all analysis types @@ -56,33 +59,42 @@ def get_after_write_constraint(): def write_constraint(f, femobj, rb_obj, ccxwriter): - # floats read from ccx should use {:.13G}, see comment in writer module - is_ref_bc_defined = any((rb_obj.xDisplacement, - rb_obj.yDisplacement, - rb_obj.zDisplacement, - rb_obj.xForce, - rb_obj.yForce, - rb_obj.zForce)) + rb_obj_idx = ccxwriter.analysis.Group.index(rb_obj) + node_count = ccxwriter.mesh_object.FemMesh.NodeCount + # factor 2 is to prevent conflict with other rigid body constraint + ref_node_idx = node_count + 2*rb_obj_idx + 1 + rot_node_idx = node_count + 2*rb_obj_idx + 2 - is_rot_bc_defined = any((rb_obj.xRotation, - rb_obj.yRotation, - rb_obj.zRotation, - rb_obj.xMoment, - rb_obj.yMoment, - rb_obj.zMoment)) + def write_mode(mode, node, dof, constraint, load): + if mode == "Constraint": + f.write("*BOUNDARY\n") + f.write("{},{},{},{:.13G}\n".format(node, dof, dof, constraint)) + elif mode == "Load": + f.write("*CLOAD\n") + f.write("{},{},{:.13G}\n".format(node, dof, load)) - # FIXME: This needs to be implemented - ref_node_idx = 10000000 - rot_node_idx = 20000000 + mode = [rb_obj.TranslationalModeX, rb_obj.TranslationalModeY, rb_obj.TranslationalModeZ] + constraint = rb_obj.Displacement + load = [rb_obj.ForceX, rb_obj.ForceY, rb_obj.ForceZ] + + for i in range(3): + write_mode(mode[i], ref_node_idx, i + 1, constraint[i], load[i].getValueAs("N").Value) - # TODO: Displacement definitions need fixing - f.write("*CLOAD\n") - f.write("{},1,{}\n".format(ref_node_idx, rb_obj.xForce)) - f.write("{},2,{}\n".format(ref_node_idx, rb_obj.yForce)) - f.write("{},3,{}\n".format(ref_node_idx, rb_obj.zForce)) + mode = [rb_obj.RotationalModeX, rb_obj.RotationalModeY, rb_obj.RotationalModeZ] + load = [rb_obj.MomentX,rb_obj.MomentY, rb_obj.MomentZ] - f.write("*CLOAD\n") - f.write("{},1,{}\n".format(rot_node_idx, rb_obj.xMoment)) - f.write("{},2,{}\n".format(rot_node_idx, rb_obj.yMoment)) - f.write("{},3,{}\n".format(rot_node_idx, rb_obj.zMoment)) + # write rotation components according to rotational mode + rot = rb_obj.Rotation + proj_axis = [rot.Axis[i] if mode[i] == "Constraint" else 0 for i in range(3)] + # proj_axis could be null + try: + constraint = FreeCAD.Vector(proj_axis).normalize() * rot.Angle + except: + constraint = FreeCAD.Vector(0, 0, 0) + + for i in range(3): + write_mode(mode[i], rot_node_idx, i + 1, constraint[i], load[i].getValueAs("N*mm").Value) + + + f.write("\n")