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"