diff --git a/src/Gui/PreferencePackTemplates/Shortcuts.cfg b/src/Gui/PreferencePackTemplates/Shortcuts.cfg index 554404ab8b..6ab60513be 100644 --- a/src/Gui/PreferencePackTemplates/Shortcuts.cfg +++ b/src/Gui/PreferencePackTemplates/Shortcuts.cfg @@ -177,6 +177,7 @@ + @@ -959,4 +960,4 @@ - \ No newline at end of file + diff --git a/src/Mod/Fem/App/AppFem.cpp b/src/Mod/Fem/App/AppFem.cpp index b71b06b2e7..a0aa491025 100644 --- a/src/Mod/Fem/App/AppFem.cpp +++ b/src/Mod/Fem/App/AppFem.cpp @@ -1,5 +1,9 @@ /*************************************************************************** - * Copyright (c) 2008 Jürgen Riegel * + * Copyright (c) 2023 Peter McB * + * additional statement(s) for element sets * + * * + * added to: AppFem.cpp * + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * * * * This file is part of the FreeCAD CAx development system. * * * @@ -51,6 +55,7 @@ #include "FemMeshShapeNetgenObject.h" #include "FemMeshShapeObject.h" #include "FemResultObject.h" +#include "FemSetElementNodesObject.h" #include "FemSetElementsObject.h" #include "FemSetFacesObject.h" #include "FemSetGeometryObject.h" @@ -167,6 +172,7 @@ PyMOD_INIT_FUNC(Fem) Fem::FemResultObjectPython ::init(); Fem::FemSetObject ::init(); + Fem::FemSetElementNodesObject ::init(); Fem::FemSetElementsObject ::init(); Fem::FemSetFacesObject ::init(); Fem::FemSetGeometryObject ::init(); diff --git a/src/Mod/Fem/App/CMakeLists.txt b/src/Mod/Fem/App/CMakeLists.txt index cb7c5f5a59..002ef0c635 100644 --- a/src/Mod/Fem/App/CMakeLists.txt +++ b/src/Mod/Fem/App/CMakeLists.txt @@ -130,6 +130,8 @@ SET(FemSet_SRCS FemSetObject.h FemSetNodesObject.cpp FemSetNodesObject.h + FemSetElementNodesObject.cpp + FemSetElementNodesObject.h FemSetElementsObject.cpp FemSetElementsObject.h FemSetFacesObject.cpp diff --git a/src/Mod/Fem/App/FemSetElementNodesObject.cpp b/src/Mod/Fem/App/FemSetElementNodesObject.cpp new file mode 100644 index 0000000000..63cd33847d --- /dev/null +++ b/src/Mod/Fem/App/FemSetElementNodesObject.cpp @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (c) 2023 Peter McB * + * * + * based on: FemSetNodesObject.cpp * + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * 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 + +#include "FemSetElementNodesObject.h" + + +using namespace Fem; +using namespace App; + +PROPERTY_SOURCE(Fem::FemSetElementNodesObject, Fem::FemSetObject) + + +FemSetElementNodesObject::FemSetElementNodesObject() +{ + ADD_PROPERTY_TYPE(Elements, (), "Element indexes", Prop_None, "Elements belonging to the ElementSet"); +} + +FemSetElementNodesObject::~FemSetElementNodesObject() = default; + +short FemSetElementNodesObject::mustExecute() const +{ + return 0; +} + +PyObject* FemSetElementNodesObject::getPyObject() +{ + if (PythonObject.is(Py::_None())) { + // ref counter is set to 1 + PythonObject = Py::Object(new DocumentObjectPy(this), true); + } + return Py::new_reference_to(PythonObject); +} + diff --git a/src/Mod/Fem/App/FemSetElementNodesObject.h b/src/Mod/Fem/App/FemSetElementNodesObject.h new file mode 100644 index 0000000000..7a0de630dd --- /dev/null +++ b/src/Mod/Fem/App/FemSetElementNodesObject.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (c) 2023 Peter McB * + * * + * based on: FemSetNodesObject.h * + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * 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_FemSetElementNodesObject_H +#define Fem_FemSetElementNodesObject_H + +#include "FemSetObject.h" +#include +#include + +namespace Fem +{ + +class FemExport FemSetElementNodesObject : public FemSetObject +{ + PROPERTY_HEADER_WITH_OVERRIDE(Fem::FemSetElementNodesObject); + +public: + /// Constructor + FemSetElementNodesObject(); + ~FemSetElementNodesObject() override; + + App::PropertyIntegerSet Elements; + + // returns the type name of the ViewProvider + const char* getViewProviderName() const override + { + return "FemGui::ViewProviderSetElementNodes"; + } + App::DocumentObjectExecReturn* execute() override + { + return App::DocumentObject::StdReturn; + } + short mustExecute() const override; + PyObject* getPyObject() override; + static std::string elementsName; // = "ElementsSet"; + static std::string uniqueElementsName; // "ElementsSet" latest name + + +}; + +} // namespace Fem + + +#endif // Fem_FemSetElementNodesObject_H diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index c4f36d46a2..0b18a4f285 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -1,4 +1,8 @@ /*************************************************************************** + * Copyright (c) 2023 Peter McB * + * additional statement(s) for element sets * + * * + * added to: AppFemGui.cpp * * Copyright (c) 2008 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * @@ -42,6 +46,7 @@ #include "ViewProviderFemMeshShape.h" #include "ViewProviderFemMeshShapeNetgen.h" #include "ViewProviderSetElements.h" +#include "ViewProviderSetElementNodes.h" #include "ViewProviderSetFaces.h" #include "ViewProviderSetGeometry.h" #include "ViewProviderSetNodes.h" @@ -139,6 +144,7 @@ PyMOD_INIT_FUNC(FemGui) FemGui::PropertyFemMeshItem ::init(); FemGui::ViewProviderSetElements ::init(); + FemGui::ViewProviderSetElementNodes ::init(); FemGui::ViewProviderSetFaces ::init(); FemGui::ViewProviderSetGeometry ::init(); FemGui::ViewProviderSetNodes ::init(); diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index 5635bef1fc..fff0c46727 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -46,6 +46,7 @@ SET(Python_SRCS ) SOURCE_GROUP("Python" FILES ${Python_SRCS}) + set(FemGui_UIC_SRCS DlgSettingsFemCcx.ui DlgSettingsFemElmer.ui @@ -55,6 +56,7 @@ set(FemGui_UIC_SRCS DlgSettingsFemInOutVtk.ui DlgSettingsFemMystran.ui DlgSettingsFemZ88.ui + TaskCreateElementSet.ui TaskCreateNodeSet.ui TaskObjectName.ui TaskFemConstraint.ui @@ -191,6 +193,8 @@ SET(FemGui_SRCS_ViewProvider ViewProviderSolver.h ViewProviderSetNodes.cpp ViewProviderSetNodes.h + ViewProviderSetElementNodes.cpp + ViewProviderSetElementNodes.h ViewProviderSetElements.cpp ViewProviderSetElements.h ViewProviderSetFaces.cpp @@ -242,6 +246,9 @@ SET(FemGui_SRCS_TaskBoxes TaskObjectName.ui TaskObjectName.cpp TaskObjectName.h + TaskCreateElementSet.ui + TaskCreateElementSet.cpp + TaskCreateElementSet.h TaskCreateNodeSet.ui TaskCreateNodeSet.cpp TaskCreateNodeSet.h @@ -279,6 +286,8 @@ endif(BUILD_FEM_VTK) SOURCE_GROUP("Task_Boxes" FILES ${FemGui_SRCS_TaskBoxes}) SET(FemGui_SRCS_TaskDlg + TaskDlgCreateElementSet.h + TaskDlgCreateElementSet.cpp TaskDlgCreateNodeSet.h TaskDlgCreateNodeSet.cpp TaskDlgMeshShapeNetgen.h @@ -308,6 +317,7 @@ SET(FemGui_SRCS_Module ) SOURCE_GROUP("Module" FILES ${FemGui_SRCS_Module}) + if(BUILD_FEM_VTK) SET(FemGui_SRCS_Post ViewProviderFemPostObject.h diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index 8d423da5ba..f2ed1116c0 100644 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -1,4 +1,9 @@ /*************************************************************************** + * Copyright (c) 2022 Peter McB * + * added erase elements function * + * * + * added to: Command.cpp * + * * * Copyright (c) 2008 Jürgen Riegel * * * * This file is part of the FreeCAD CAx development system. * @@ -51,6 +56,7 @@ #include #include #include +#include #include #include "ActiveAnalysisObserver.h" @@ -1180,6 +1186,184 @@ bool CmdFemCreateNodesSet::isActive() return hasActiveDocument(); } +//=========================================================================== +// start of Erase Elements code +//=========================================================================== +std::string Fem::FemSetElementNodesObject::elementsName; +std::string Fem::FemSetElementNodesObject::uniqueElementsName; + + +DEF_STD_CMD_A(CmdFemDefineElementsSet); + +void DefineElementsCallback(void *ud, SoEventCallback *n) +{ + Fem::FemAnalysis* Analysis; + + if (getConstraintPrerequisits(&Analysis)) + return; + + // show the wait cursor because this could take quite some time + Gui::WaitCursor wc; + + // When this callback function is invoked we must in either case leave the edit mode + Gui::View3DInventorViewer* view = static_cast(n->getUserData()); + view->setEditing(false); + view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), DefineElementsCallback, ud); + n->setHandled(); + + Gui::SelectionRole role; + std::vector clPoly = view->getGLPolygon(&role); + if (clPoly.size() < 3) + return; + if (clPoly.front() != clPoly.back()) + clPoly.push_back(clPoly.front()); + + SoCamera* cam = view->getSoRenderManager()->getCamera(); + SbViewVolume vv = cam->getViewVolume(); + Gui::ViewVolumeProjection proj(vv); + Base::Polygon2d polygon; + for (std::vector::const_iterator it = clPoly.begin(); it != clPoly.end(); ++it) + polygon.Add(Base::Vector2d((*it)[0], (*it)[1])); + + std::vector docObj = Gui::Selection().getObjectsOfType(Fem::FemMeshObject::getClassTypeId()); + if (docObj.size() != 1) + return; + + const SMESHDS_Mesh* data = static_cast(docObj[0])->FemMesh.getValue().getSMesh()->GetMeshDS(); + + SMDS_NodeIteratorPtr aNodeIter = data->nodesIterator(); + Base::Vector3f pt2d; + std::set IntSet; + + while (aNodeIter->more()) { + const SMDS_MeshNode* aNode = aNodeIter->next(); + Base::Vector3f vec(aNode->X(), aNode->Y(), aNode->Z()); + pt2d = proj(vec); + if (polygon.Contains(Base::Vector2d(pt2d.x, pt2d.y))) + IntSet.insert(aNode->GetID()); + } + + std::stringstream set; + + set << "["; + for (std::set::const_iterator it = IntSet.begin(); it != IntSet.end(); ++it) + if (it == IntSet.begin()) + set << *it; + else + set << "," << *it; + set << "]"; + + Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Place robot")); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.addObject('Fem::FemSetElementNodesObject','ElementSet')"); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.ActiveObject.Nodes = %s", set.str().c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "App.activeDocument().%s.addObject(App.activeDocument().ElementSet)", Analysis->getNameInDocument()); + + Gui::Command::commitCommand(); + +} + +CmdFemDefineElementsSet::CmdFemDefineElementsSet() + : Command("FEM_DefineElementsSet") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Element set by poly"); + sToolTipText = QT_TR_NOOP("Create Element set by Poly"); + sWhatsThis = "FEM_DefineElementsSet"; + sStatusTip = QT_TR_NOOP("Create Element set by Poly"); + sPixmap = "FEM_CreateElementsSet"; +} + +void CmdFemDefineElementsSet::activated(int) +{ + std::vector docObj = Gui::Selection().getObjectsOfType(Fem::FemMeshObject::getClassTypeId()); + + for (std::vector::iterator it = docObj.begin(); it != docObj.end(); ++it) { + if (it == docObj.begin()) { + Gui::Document* doc = getActiveGuiDocument(); + Gui::MDIView* view = doc->getActiveView(); + if (view->getTypeId().isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + Gui::View3DInventorViewer* viewer = ((Gui::View3DInventor*)view)->getViewer(); + viewer->setEditing(true); + viewer->startSelection(Gui::View3DInventorViewer::Clip); + viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), DefineElementsCallback); + } + else { + return; + } + } + + } +} + +bool CmdFemDefineElementsSet::isActive() +{ + // Check for the selected mesh feature (all Mesh types) + if (getSelection().countObjectsOfType(Fem::FemMeshObject::getClassTypeId()) != 1) + return false; + + Gui::MDIView* view = Gui::getMainWindow()->activeWindow(); + if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + Gui::View3DInventorViewer* viewer = static_cast(view)->getViewer(); + return !viewer->isEditing(); + } + + return false; +} + +//================================================================================================ +DEF_STD_CMD_A(CmdFemCreateElementsSet); + +CmdFemCreateElementsSet::CmdFemCreateElementsSet() + : Command("FEM_CreateElementsSet") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Erase Elements"); + sToolTipText = QT_TR_NOOP("Creates a FEM mesh elements set"); + sWhatsThis = "FEM_CreateElementsSet"; + sStatusTip = sToolTipText; + sPixmap = "FEM_CreateElementsSet"; +} + +void CmdFemCreateElementsSet::activated(int) +{ + Gui::SelectionFilter ObjectFilter("SELECT Fem::FemSetElementNodesObject COUNT 1"); + Gui::SelectionFilter FemMeshFilter("SELECT Fem::FemMeshObject COUNT 1"); + + if (ObjectFilter.match()) { + Fem::FemSetElementNodesObject* NodesObj = static_cast(ObjectFilter.Result[0][0].getObject()); + openCommand(QT_TRANSLATE_NOOP("Command", "Edit Elements set")); + doCommand(Gui, "Gui.activeDocument().setEdit('%s')", NodesObj->getNameInDocument()); + } + // start + else if (FemMeshFilter.match()) { + Fem::FemMeshObject* MeshObj = static_cast(FemMeshFilter.Result[0][0].getObject()); + + Fem::FemSetElementNodesObject::elementsName = "ElementsSet"; + Fem::FemSetElementNodesObject::uniqueElementsName = Command::getUniqueObjectName(Fem::FemSetElementNodesObject::elementsName.c_str()); + + + openCommand(QT_TRANSLATE_NOOP("Command", "Create Elements set")); + doCommand(Doc, "App.activeDocument().addObject('Fem::FemSetElementNodesObject','%s')", Fem::FemSetElementNodesObject::uniqueElementsName.c_str()); + doCommand(Gui, "App.activeDocument().%s.FemMesh = App.activeDocument().%s", Fem::FemSetElementNodesObject::uniqueElementsName.c_str(), MeshObj->getNameInDocument()); + doCommand(Gui, "Gui.activeDocument().setEdit('%s')", Fem::FemSetElementNodesObject::uniqueElementsName.c_str()); + + } + else { + QMessageBox::warning(Gui::getMainWindow(), + qApp->translate("CmdFemCreateElementsSet", "Wrong selection"), + qApp->translate("CmdFemCreateNodesSet", "Select a single FEM Mesh, please.")); + } +} + +bool CmdFemCreateElementsSet::isActive() +{ + return hasActiveDocument(); +} +//=========================================================================== +// end of Erase Elements code +//=========================================================================== //=========================================================================== // FEM_CompEmConstraints (dropdown toolbar button for electromagnetic constraints) @@ -2610,6 +2794,8 @@ void CreateFemCommands() // mesh rcCmdMgr.addCommand(new CmdFemCreateNodesSet()); rcCmdMgr.addCommand(new CmdFemDefineNodesSet()); + rcCmdMgr.addCommand(new CmdFemCreateElementsSet()); + rcCmdMgr.addCommand(new CmdFemDefineElementsSet()); // equations rcCmdMgr.addCommand(new CmdFemCompEmEquations()); diff --git a/src/Mod/Fem/Gui/Resources/Fem.qrc b/src/Mod/Fem/Gui/Resources/Fem.qrc index 9fda988706..e869cf9e37 100755 --- a/src/Mod/Fem/Gui/Resources/Fem.qrc +++ b/src/Mod/Fem/Gui/Resources/Fem.qrc @@ -52,6 +52,7 @@ icons/FEM_EquationMagnetodynamic2D.svg + icons/FEM_CreateElementsSet.svg icons/FEM_CreateNodesSet.svg icons/FEM_FEMMesh2Mesh.svg icons/FEM_MeshBoundaryLayer.svg diff --git a/src/Mod/Fem/Gui/Resources/icons/FEM_CreateElementsSet.svg b/src/Mod/Fem/Gui/Resources/icons/FEM_CreateElementsSet.svg new file mode 100644 index 0000000000..244b814ef4 --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/icons/FEM_CreateElementsSet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/Mod/Fem/Gui/TaskCreateElementSet.cpp b/src/Mod/Fem/Gui/TaskCreateElementSet.cpp new file mode 100644 index 0000000000..21e2dd6215 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskCreateElementSet.cpp @@ -0,0 +1,773 @@ +/*************************************************************************** + * Copyright (c) 2023 Peter McB * + * implementation of the erase elements function * + * * + * loosely based on: TaskCreateNodeSet.cpp * + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * 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 +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "FemSelectionGate.h" +#include "TaskCreateElementSet.h" +#include "ViewProviderFemMesh.h" +#include "ui_TaskCreateElementSet.h" + +#include +#include + + + + +using namespace Gui; +//using namespace Fem; +using namespace FemGui; +using namespace std; + +std::string inp_file = "abaqusOutputFileEraseElements.inp"; + +std::string createdMesh = "cDUMMY"; +std::string startResultMesh = "StartResultMesh"; // StartResultMesh"; +std::string newResultMesh = "NewResultMesh"; +std::string newFemMesh = "NewFemMesh"; + +std::string TaskCreateElementSet::currentProject = ""; + +std::string uniqueMesh = ""; +std::string newProject = ""; +std::string resultMesh = "Result"; +std::string actualResultMesh = "XXXXXX"; +std::string lastName = ""; +std::string highLightMesh; // name of highlighted mesh +std::string meshType; // type of - either 'result' or 'femmesh' +int passResult = 0; +int passFemMesh = 0; +int maxProject = 10; +double **nodeCoords; // these are node coords +int *nodeNumbers; // these are node numbers - probably not required[100]; + + +string myToUpper(std::string str) { + for(int i = 0; i < str.length(); i++) { + str[i] = toupper(str[i]); + } + return str; +} + +void addFaceToMesh(const std::vector nodes, SMESHDS_Mesh *MeshDS, int EID) +{ + int nbNodes = nodes.size(); + switch (nbNodes) + { + case 3: // 3 node triangle + MeshDS->AddFaceWithID( + nodes[0], nodes[1], nodes[2], + EID); + break; + case 4: // 4 node quadrilateral + MeshDS->AddFaceWithID( + nodes[0], nodes[1], nodes[2], nodes[3], + EID); + break; + case 6: // 6 node triangle + MeshDS->AddFaceWithID( + nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5], + EID); + break; + case 8: // 8 node quadrilateral + MeshDS->AddFaceWithID( + nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5], nodes[6], nodes[7], + EID); + break; + } +} // addFaceToMesh + +void addVolumeToMesh(const std::vector nodes, SMESHDS_Mesh *MeshDS, int EID) +{ + + int nbNodes = nodes.size(); + + switch (nbNodes) + { + case 4: // 4 node tetrahedron + MeshDS->AddVolumeWithID( + nodes[0], nodes[1], nodes[2], nodes[3], + EID); + break; + case 5: // 5 node pyramid + MeshDS->AddVolumeWithID( + nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], + EID); + break; + case 6: // 6 node pentahedron + MeshDS->AddVolumeWithID( + nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5], + EID); + break; + case 8: // 8 node hexahedron + MeshDS->AddVolumeWithID( + nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5], nodes[6], nodes[7], + EID); + break; + case 10: // 10 node tetrahedron + MeshDS->AddVolumeWithID( + nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5], nodes[6], nodes[7], + nodes[8], nodes[9], + EID); + break; + case 13: // 13 node pyramid + MeshDS->AddVolumeWithID( + nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5], nodes[6], nodes[7], + nodes[8], nodes[9], nodes[10], nodes[11], + nodes[12], + EID); + break; + case 15: // 15 node pentahedron + MeshDS->AddVolumeWithID( + nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5], nodes[6], nodes[7], + nodes[8], nodes[9], nodes[10], nodes[11], + nodes[12], nodes[13], nodes[14], + EID); + break; + case 20: // 20 node hexahedron + MeshDS->AddVolumeWithID( + nodes[0], nodes[1], nodes[2], nodes[3], + nodes[4], nodes[5], nodes[6], nodes[7], + nodes[8], nodes[9], nodes[10], nodes[11], + nodes[12], nodes[13], nodes[14], nodes[15], + nodes[16], nodes[17], nodes[18], nodes[19], + EID); + break; + } // default: {} + +} // addVolumeToMesh + +void myCopyResultsMesh(std::string oldName, std::string newName) +{ + int error = 0; + + Base::Console().Warning("copy: %s and %s\n", oldName.c_str(), newName.c_str()); + if (oldName.compare(newName) == 0 && error == 0) + { + error = 1; + Base::Console().Warning("Can't copy ResultMesh to ResultMesh: %s and %s\n", oldName.c_str(), newName.c_str()); + QMessageBox::warning(Gui::getMainWindow(), +// QMessageBox::warning(Gui::MainWindow(), + qApp->translate("CmdFemCreateElementsSet", "Wrong selection"), + qApp->translate("CmdFemCreateElementsSet", "Can't copy ResultMesh to ResultMesh")); + } + if ((oldName.find("Result") == std::string::npos || newName.find("Result") == std::string::npos) && error == 0) + { + error = 1; + Base::Console().Warning("Mesh must be results: %s\n", oldName.c_str()); + QMessageBox::warning(Gui::getMainWindow(), +// QMessageBox::warning(Gui::MainWindow(), + qApp->translate("CmdFemCreateElementsSet", "Wrong selection"), + qApp->translate("CmdFemCreateElementsSet", "Mesh must be a Results mesh")); + } + if (error == 0) + { + Gui::Command::doCommand(Gui::Command::Doc, "c = FreeCADGui.ActiveDocument.getObject(\'%s\')", oldName.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "FreeCAD.ActiveDocument.%s.FemMesh = c.Object.FemMesh", newName.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "Gui.ActiveDocument.getObject(\'%s\').BackfaceCulling = False", newName.c_str()); + } +} // copyresultsmesh + +void generateMesh(std::string meshType) +{ + if (passResult + passFemMesh == 0) + { + Gui::Command::doCommand(Gui::Command::Doc, "import Fem,os"); + } + + if (strcmp(meshType.c_str(), "result") == 0) + { + if (passResult == 0) + { + string xstr(startResultMesh.c_str()); + createdMesh = newResultMesh.c_str(); + Gui::Command::doCommand(Gui::Command::Doc, "obj1 = App.ActiveDocument.addObject('Fem::FemMeshObject', \'%s\')", startResultMesh.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "Gui.ActiveDocument.getObject(\'%s\').Visibility = False", startResultMesh.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "ne = Gui.ActiveDocument.getObject(\'%s\')", actualResultMesh.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "obj1.FemMesh = ne.Object.FemMesh"); + } + else if (passResult > 0) + { + createdMesh = newResultMesh.c_str(); + } + passResult += 1; + } + else if (strcmp(meshType.c_str(), "femmesh") == 0) + { + if (passFemMesh == 0) + { + string xstr("no rename required"); + createdMesh = newFemMesh.c_str(); + } + else if (passFemMesh > 0) + { + createdMesh = newFemMesh.c_str(); + } + passFemMesh += 1; + } + App::Document* doc = App::GetApplication().getActiveDocument(); + uniqueMesh = doc->getUniqueObjectName(createdMesh.c_str()); + + Gui::Command::doCommand(Gui::Command::Doc, "Gui.ActiveDocument.getObject(\'%s\').Visibility = False", highLightMesh.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "newermesh = Fem.read(\'%s\')", inp_file.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "obj = App.ActiveDocument.addObject('Fem::FemMeshObject', \'%s\')", uniqueMesh.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "obj.FemMesh = newermesh"); + Gui::Command::doCommand(Gui::Command::Doc, "Gui.ActiveDocument.getObject(\'%s\').BackfaceCulling = False", uniqueMesh.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "Gui.ActiveDocument.getObject(\'%s\').Visibility = True", uniqueMesh.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "os.remove(\'%s\')", inp_file.c_str()); + + if (strcmp(meshType.c_str(), "result") == 0) + { + Gui::Command::doCommand(Gui::Command::Doc, "c = FreeCADGui.ActiveDocument.getObject(\'%s\')", uniqueMesh.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "FreeCAD.ActiveDocument.%s.FemMesh = c.Object.FemMesh", actualResultMesh.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "Gui.ActiveDocument.getObject(\'%s\').BackfaceCulling = False", actualResultMesh.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "Gui.ActiveDocument.getObject(\'%s\').Visibility = True", actualResultMesh.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "Gui.ActiveDocument.getObject(\'%s\').Visibility = False", uniqueMesh.c_str()); + } +} // generate mesh + +void writeToFile(std::string fileName, SMESHDS_Mesh *newMesh, int *nodeNumbers, + double **nodeCoords, int rows, int requiredType) +{ + std::map elType2D; + std::map elType3D; + + elType2D[3] = "S3"; // 3 node triangle + elType2D[6] = "S6"; // 4 node quadrilateral + elType2D[4] = "S4"; // 6 node triangle + elType2D[8] = "S8"; // 8 node quadrilateral + + elType3D[4] = "C3D4"; // 4 node tetrahedron + elType3D[6] = "C3D6"; // 6 node pentahedron + elType3D[8] = "C3D8"; // 8 node hexahedron + elType3D[10] = "C3D10"; // 10 node tetrahedron + elType3D[15] = "C3D15"; // 15 node pentahedron + elType3D[20] = "C3D20"; // 20 node hexahedron +// no pyramid elements + FILE *fptr = fopen(fileName.c_str(), "w"); + if (fptr == NULL) + { + return; + } + fprintf(fptr, "** written by Erase Elements inp file writer for CalculiX,Abaqus meshes\n"); + fprintf(fptr, "** all mesh elements.\n"); + + fprintf(fptr, "\n"); + fprintf(fptr, "\n"); + fprintf(fptr, "** Nodes\n"); + fprintf(fptr, "*Node, NSET=Nall\n"); + + for (int i = 1; i < rows + 1; i++) + { + if (nodeNumbers[i] > 0) + { + fprintf(fptr, "%d, %e, %e, %e\n", + nodeNumbers[i], nodeCoords[i][0], nodeCoords[i][1], nodeCoords[i][2]); + } + } + + SMDS_ElemIteratorPtr srcElemIt; + SMDS_NodeIteratorPtr srcNodeIt; + srcElemIt = newMesh->elementsIterator(); + srcNodeIt = newMesh->nodesIterator(); + const SMDS_MeshNode *nSrc; + int NID, EID; + while (srcNodeIt->more()) + { + const SMDS_MeshNode *node = srcNodeIt->next(); + NID = node->GetID(); + } + int numberNodes = -1; + while (srcElemIt->more()) + { + const SMDS_MeshElement *elem = srcElemIt->next(); + EID = elem->GetID(); + if (elem->GetType() != requiredType) + { + continue; + } + + if (numberNodes != elem->NbNodes()) + { + if (requiredType == 4) + { + fprintf(fptr, "\n"); + fprintf(fptr, "\n"); + fprintf(fptr, "%s", "** Volume elements\n"); + fprintf(fptr, "*Element, TYPE=%s, ELSET=Evolumes\n", elType3D[elem->NbNodes()].c_str()); + } + else if (requiredType == 3) + { + fprintf(fptr, "%s", "** Face elements\n"); + fprintf(fptr, "*Element, TYPE=%s, ELSET=Efaces\n", elType2D[elem->NbNodes()].c_str()); + } + numberNodes = elem->NbNodes(); + } + SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); + fprintf(fptr, "%d", EID); + for (int iN = 0; nIt->more(); ++iN) + { + nSrc = static_cast(nIt->next()); + NID = nSrc->GetID(); + fprintf(fptr, ", %d", NID); + } // for iN + fprintf(fptr, "\n"); + } // while print + if (requiredType == 4) + { + fprintf(fptr, "\n"); + fprintf(fptr, "\n"); + fprintf(fptr, "%s", "** Define element set Eall\n"); + fprintf(fptr, "%s", "*ELSET, ELSET=Eall\n"); + fprintf(fptr, "%s", "Evolumes\n"); + } + else if (requiredType == 3) + { + fprintf(fptr, "%s", "** Define element set Eall\n"); + fprintf(fptr, "%s", "*ELSET, ELSET=Eall\n"); + fprintf(fptr, "%s", "Efaces\n"); + } + + fclose(fptr); + return; +} + +TaskCreateElementSet::TaskCreateElementSet(Fem::FemSetElementNodesObject* pcObject, QWidget* parent) + : TaskBox(Gui::BitmapFactory().pixmap("FEM_CreateElementsSet"), + tr("Elements set"), + true, + parent), + pcObject(pcObject), + selectionMode(none) +{ + proxy = new QWidget(this); + ui = new Ui_TaskCreateElementSet(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + this->groupLayout()->addWidget(proxy); + QObject::connect(ui->toolButton_Poly, SIGNAL(clicked()), this, SLOT(Poly())); + QObject::connect(ui->toolButton_Restore, SIGNAL(clicked()), this, SLOT(Restore())); + QObject::connect(ui->toolButton_Rename, SIGNAL(clicked()), this, SLOT(CopyResultsMesh())); + // check if the Link to the FemMesh is defined + assert(pcObject->FemMesh.getValue()); + MeshViewProvider = dynamic_cast(Gui::Application::Instance->getViewProvider(pcObject->FemMesh.getValue())); + assert(MeshViewProvider); + + elementTempSet = pcObject->Elements.getValues(); + std::set::iterator it; + std::string info; + info = "Delete the generated data in the other project: " + std::string(currentProject); + App::Document* doc = App::GetApplication().getActiveDocument(); + newProject = doc->Label.getValue(); + if (strcmp(currentProject.c_str(), newProject.c_str()) != 0 && + (passResult + passFemMesh != 0)) + { + QMessageBox::warning(Gui::getMainWindow(), +// QMessageBox::warning(Gui::MainWindow(), + qApp->translate("CmdFemCreateElementsSet", "Wrong selection"), + qApp->translate("CmdFemCreateElementsSet", info.c_str())); + return; + } +} + +void TaskCreateElementSet::Poly(void) +{ + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + Gui::MDIView* view = doc->getActiveView(); + if (view->getTypeId().isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + Gui::View3DInventorViewer* viewer = ((Gui::View3DInventor* )view)->getViewer(); + viewer->setEditing(true); + viewer->startSelection(Gui::View3DInventorViewer::Clip); + viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), DefineElementsCallback, this); + } +} + +void TaskCreateElementSet::CopyResultsMesh(void) +{ + std::vector selection = Gui::Selection().getSelection(); // [0]; + highLightMesh = selection[0].FeatName; + myCopyResultsMesh(highLightMesh, actualResultMesh); + Gui::Command::doCommand(Gui::Command::Doc, "Gui.activeDocument().resetEdit()"); +} + +void TaskCreateElementSet::Restore(void) +{ + App::Document* doc = App::GetApplication().getActiveDocument(); + const std::vector &all = doc->getObjects(); + int number = 0, xpos = 0; + int elList = 0; + // put reverse here + + std::vector STR; + for (std::vector::const_iterator it = all.begin(); + it != all.end(); ++it) + { + std::string objectN = all[xpos]->getNameInDocument(); + STR.push_back(objectN); + xpos++; + } + + // iterate through in reverse order + for (std::vector::reverse_iterator it = STR.rbegin(); it != STR.rend(); ++it) + { + std::string objectN = (*it); + if (objectN.find(startResultMesh) != std::string::npos) + { + number++; + myCopyResultsMesh(objectN, actualResultMesh); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.removeObject(\'%s\')", objectN.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + else if (objectN.find(newResultMesh) != std::string::npos) + { + number++; + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.removeObject(\'%s\')", objectN.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + else if (objectN.find(actualResultMesh) != std::string::npos) + { + } + else if (objectN.find(newFemMesh) != std::string::npos) + { + number++; + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.removeObject(\'%s\')", objectN.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + else if (objectN.find(Fem::FemSetElementNodesObject::elementsName) != std::string::npos) + { + if (elList > 0) + { + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.removeObject(\'%s\')", objectN.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + } + else if (elList == 0) + { + elList++; + lastName = objectN; + } + } + } // for + if (strcmp(lastName.c_str(), "") != 0) + { + // blank last name - no action + } + else if (number == 0) + { + QMessageBox::warning(Gui::getMainWindow(), +// QMessageBox::warning(Gui::MainWindow(), + qApp->translate("CmdFemCreateElementsSet", "Wrong selection"), + qApp->translate("CmdFemCreateElementsSet", "No Data To Restore\n")); + return; + } + passResult = 0; + passFemMesh = 0; + currentProject = ""; + Gui::Command::doCommand(Gui::Command::Doc, "Gui.activeDocument().resetEdit()"); + return; +} // restore + +void TaskCreateElementSet::DefineElementsCallback(void* ud, SoEventCallback* n) +{ + Gui::WaitCursor wc; + TaskCreateElementSet* taskBox = static_cast(ud); + // When this callback function is invoked we must in either case leave the edit mode + Gui::View3DInventorViewer* view = reinterpret_cast(n->getUserData()); + view->setEditing(false); + view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), DefineElementsCallback, ud); + n->setHandled(); + + Gui::SelectionRole role; + std::vector clPoly = view->getGLPolygon(&role); + if (clPoly.size() < 3) + return; + if (clPoly.front() != clPoly.back()) + clPoly.push_back(clPoly.front()); + + SoCamera* cam = view->getSoRenderManager()->getCamera(); + SbViewVolume vv = cam->getViewVolume(); + Gui::ViewVolumeProjection proj(vv); + Base::Polygon2d polygon; + for (std::vector::const_iterator it = clPoly.begin(); it != clPoly.end(); ++it) + polygon.Add(Base::Vector2d((*it)[0], (*it)[1])); + + taskBox->DefineNodes(polygon, proj, role == Gui::SelectionRole::Inner ? true : false); +} // DefineElementsCallback + +void TaskCreateElementSet::DefineNodes(const Base::Polygon2d &polygon, + const Gui::ViewVolumeProjection &proj, + bool inner) +{ + const SMESHDS_Mesh* srcMeshDS = const_cast(pcObject->FemMesh.getValue()->FemMesh.getValue().getSMesh())->GetMeshDS(); + + std::vector selection = Gui::Selection().getSelection(); // [0]; + highLightMesh = selection[0].FeatName; + + meshType = "NULL"; + std::size_t found = myToUpper(highLightMesh).find(myToUpper(resultMesh)); +actualResultMesh = highLightMesh; +//highLightMesh.find(myToUpper(resultMesh)); + + if (found != std::string::npos) + { + meshType = "result"; + } + else + { + meshType = "femmesh"; + } +// std::string lightMesh = selection[0].FeatID; + + elementTempSet.clear(); + int nElements = + srcMeshDS->GetMeshInfo().NbElements(); + int nVolumes = + srcMeshDS->GetMeshInfo().NbVolumes(); + int requiredType = nVolumes > 0 ? 4 : 3; // type = 4 - 3D, type = 3 - 2D + + double cOfGX, cOfGY, cOfGZ; + const SMDS_MeshNode* nSrc; + int EID; + currentProject = newProject; + + SMESHDS_Mesh* newMeshDS = new SMESHDS_Mesh(nElements, true); +// FemMesh femMesh = FemMesh(); // *getFemMeshPtr(); + Base::Vector3f pt2d; + + SMDS_ElemIteratorPtr srcElemIt = srcMeshDS->elementsIterator(); + SMDS_NodeIteratorPtr srcNode = srcMeshDS->nodesIterator(); + + const SMDS_MeshNode* nTgt; + std::vector nodes; + int keepElement = 0, maxNode = -1; + while (srcNode->more()) + { + const SMDS_MeshNode *aNode = srcNode->next(); + if (aNode->GetID() > maxNode) + { + maxNode = aNode->GetID(); + } + } + + nodeNumbers = new int[maxNode + 2]; + nodeCoords = new double *[maxNode + 2]; // these are node coords + for (int i = 0; i < maxNode + 2; i++) + { + nodeCoords[i] = new double[3]; // x,y,z + nodeNumbers[i] = 0; + } + + elementTempSet.insert(requiredType* -1); // the type of elements + int pNodes; // the first pnodes are used in the cofg calc + + while (srcElemIt->more()) + { + + pNodes = 4; // the first pnodes are used in the cofg calc + const SMDS_MeshElement* elem = srcElemIt->next(); + nodes.resize(elem->NbNodes()); + EID = elem->GetID(); + if (elem->GetType() != requiredType) + { + continue; + } + SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); + + if (requiredType == 4) // 3D + { + if (elem->NbNodes() == 8 || elem->NbNodes() == 20) + { // 8 or 20 node brick + pNodes = 8; + } + if (elem->NbNodes() == 6 || elem->NbNodes() == 15) + { // 6 or 15 node penta + pNodes = 8; + } + } + else if (requiredType == 3) // 2D + { + if (elem->NbNodes() == 3 || elem->NbNodes() == 6) + { // 3 or 6 node triangles + pNodes = 3; + } + } + cOfGX = 0.0; + cOfGY = 0.0; + cOfGZ = 0.0; + for (int iN = 0; nIt->more(); ++iN) + { + nSrc = static_cast(nIt->next()); + nTgt = srcMeshDS->FindNode(nSrc->GetID()); + nodes[iN] = nTgt; + newMeshDS->AddNodeWithID(nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID()); + if (nodeNumbers[nSrc->GetID()] == 0) + { + nodeCoords[nSrc->GetID()][0] = nSrc->X(); + nodeCoords[nSrc->GetID()][1] = nSrc->Y(); + nodeCoords[nSrc->GetID()][2] = nSrc->Z(); + // write all nodes if result mesh + if (strcmp(meshType.c_str(), "result") == 0) + { + nodeNumbers[nSrc->GetID()] = nSrc->GetID(); + } + } + if (iN < pNodes) + { + cOfGX += nSrc->X() / pNodes; + cOfGY += nSrc->Y() / pNodes; + cOfGZ += nSrc->Z() / pNodes; + } + } // for iN + + SMESH_MeshEditor::ElemFeatures elemFeat(elem->GetType(), elem->IsPoly()); + elemFeat.SetID(EID); + + /* add the bit to determine which elements are outside the poly */ + Base::Vector3f vec(cOfGX, cOfGY, cOfGZ); + pt2d = proj(vec); + if (polygon.Contains(Base::Vector2d(pt2d.x, pt2d.y)) != inner) + { + if (strcmp(meshType.c_str(), "femmesh") == 0) + { + for (long unsigned int i = 0; i < nodes.size(); i++) + { + nodeNumbers[nodes[i]->GetID()] = nodes[i]->GetID(); + } + } + + elementTempSet.insert(EID); + keepElement += 1; + if (requiredType == 4) + { + addVolumeToMesh(nodes, newMeshDS, EID); + } + else if (requiredType == 3) + { + addFaceToMesh(nodes, newMeshDS, EID); + } + } + } // while + int erase; + if (nVolumes != 0) + { + erase = nVolumes - keepElement; + } + else + { + erase = nElements - keepElement; + } + if (keepElement > 0) + { + Base::Console().Warning( + "Number of Elements Kept: %d, Number of Elements Erased: %d\n", keepElement, erase); + writeToFile(inp_file, newMeshDS, nodeNumbers, nodeCoords, maxNode, requiredType); + generateMesh(meshType); + } + else + { + QMessageBox::warning(Gui::getMainWindow(), +// QMessageBox::warning(Gui::MainWindow(), + qApp->translate("CmdFemCreateElementsSet", "Erased Elements"), + qApp->translate("CmdFemCreateElementsSet", "All Elements Erased - no mesh generated.")); + } + newMeshDS->Modified(); + Gui::Command::doCommand(Gui::Command::Doc, "Gui.activeDocument().resetEdit()"); + +} // void TaskCreateElementSet::DefineNodes + +void TaskCreateElementSet::onSelectionChanged(const Gui::SelectionChanges &msg) +{ + if (selectionMode == none) + return; + + if (msg.Type == Gui::SelectionChanges::AddSelection) + { + std::string subName(msg.pSubName); + unsigned int i = 0; + for (; i < subName.size(); i++) + if (msg.pSubName[i] == 'F') + break; + int elem = atoi(subName.substr(4).c_str()); + int face = atoi(subName.substr(i + 1).c_str()); + elementTempSet.clear(); + std::set tmp = pcObject->FemMesh.getValue()->FemMesh.getValue().getSurfaceNodes(elem, face); + elementTempSet.insert(tmp.begin(), tmp.end()); + + selectionMode = none; + Gui::Selection().rmvSelectionGate(); + } +} + +/*********************************************************/ + +TaskCreateElementSet::~TaskCreateElementSet() +{ + // delete last elementsset + if (strcmp(lastName.c_str(), "") != 0) + { + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.removeObject(\'%s\')", lastName.c_str()); + Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); + lastName = ""; + } + delete ui; +} + +#include "moc_TaskCreateElementSet.cpp" diff --git a/src/Mod/Fem/Gui/TaskCreateElementSet.h b/src/Mod/Fem/Gui/TaskCreateElementSet.h new file mode 100644 index 0000000000..985bd6b4de --- /dev/null +++ b/src/Mod/Fem/Gui/TaskCreateElementSet.h @@ -0,0 +1,96 @@ +/*************************************************************************** + * Copyright (c) 2023 Peter McB * + * * + * based on: TaskCreateNodeSet.h * + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * 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_TaskCreateElementSet_H +#define GUI_TASKVIEW_TaskCreateElementSet_H + +#include +#include +#include + + + +class Ui_TaskCreateElementSet; +class SoEventCallback; + +namespace Base +{ +class Polygon2d; +} +namespace App +{ +class Property; +} + +namespace Gui +{ +class ViewProvider; +class ViewVolumeProjection; +} // namespace Gui + +namespace FemGui +{ + +class ViewProviderFemMesh; + + +class TaskCreateElementSet : public Gui::TaskView::TaskBox, public Gui::SelectionObserver +{ + Q_OBJECT + +public: + explicit TaskCreateElementSet(Fem::FemSetElementNodesObject* pcObject,QWidget* parent = nullptr); + ~TaskCreateElementSet() override; + + std::set elementTempSet; + ViewProviderFemMesh* MeshViewProvider; + static std::string currentProject; + +private Q_SLOTS: + void Poly(); + void Restore(); + void CopyResultsMesh(); + +protected: + Fem::FemSetElementNodesObject* pcObject; + static void DefineElementsCallback(void* ud, SoEventCallback* n); + void DefineNodes(const Base::Polygon2d &polygon,const Gui::ViewVolumeProjection &proj, bool); + +protected: + void onSelectionChanged(const Gui::SelectionChanges& msg) override; + enum selectionModes + { + none, + PickElement + } selectionMode; + +private: + QWidget* proxy; + Ui_TaskCreateElementSet* ui; +}; + +} // namespace FemGui + +#endif // GUI_TASKVIEW_TaskCreateElementSet_H diff --git a/src/Mod/Fem/Gui/TaskCreateElementSet.ui b/src/Mod/Fem/Gui/TaskCreateElementSet.ui new file mode 100644 index 0000000000..00006588f4 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskCreateElementSet.ui @@ -0,0 +1,87 @@ + + + TaskCreateElementSet + + + + 0 + 0 + 407 + 270 + + + + + 0 + 0 + + + + Form + + + + + + + + Poly + + + + + + + Erase Elements by Polygon + + + + + + + + + + + true + + + Restore + + + + + + + Delete New Meshes + + + + + + + + + + + true + + + Copy + + + + + + + Copy Result Mesh + + + + + + + + + + diff --git a/src/Mod/Fem/Gui/TaskDlgCreateElementSet.cpp b/src/Mod/Fem/Gui/TaskDlgCreateElementSet.cpp new file mode 100644 index 0000000000..dc7da4b38a --- /dev/null +++ b/src/Mod/Fem/Gui/TaskDlgCreateElementSet.cpp @@ -0,0 +1,106 @@ +/*************************************************************************** + * Copyright (c) 2023 Peter McB * + * * + * based on: TaskDlgCreateNodeSet.cpp * + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * 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 +#include +#include +#include +#include + +#include "TaskDlgCreateElementSet.h" +#include "ViewProviderFemMesh.h" + + +using namespace FemGui; + + +//************************************************************************** +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgCreateElementSet::TaskDlgCreateElementSet(Fem::FemSetElementNodesObject *obj) + : TaskDialog(),FemSetElementNodesObject(obj) +{ + name = new TaskObjectName(obj); + param = new TaskCreateElementSet(obj); + + Content.push_back(name); + Content.push_back(param); +} + +TaskDlgCreateElementSet::~TaskDlgCreateElementSet() +{ + +} + +//==== calls from the TaskView =============================================================== + + +void TaskDlgCreateElementSet::open() +{ + // select->activate(); + // Edge2TaskObject->execute(); + // param->setEdgeAndClusterNbr(Edge2TaskObject->NbrOfEdges,Edge2TaskObject->NbrOfCluster); + +} + +bool TaskDlgCreateElementSet::accept() +{ + try { + FemSetElementNodesObject->Elements.setValues(param->elementTempSet); + FemSetElementNodesObject->recomputeFeature(); + // Gui::Document* doc = Gui::Application::Instance->activeDocument(); + // if(doc) + // doc->resetEdit(); + param->MeshViewProvider->resetHighlightNodes(); + FemSetElementNodesObject->Label.setValue(name->name); + Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeDocument().resetEdit()"); + + return true; + } + catch (const Base::Exception& e) { + Base::Console().Warning("TaskDlgCreateElementSet::accept(): %s\n", e.what()); + } + + return false; +} + +bool TaskDlgCreateElementSet::reject() +{ + FemSetElementNodesObject->execute(); + param->MeshViewProvider->resetHighlightNodes(); + Gui::Command::abortCommand(); + Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeDocument().resetEdit()"); + + return true; +} + +void TaskDlgCreateElementSet::helpRequested() +{} + +#include "moc_TaskDlgCreateElementSet.cpp" diff --git a/src/Mod/Fem/Gui/TaskDlgCreateElementSet.h b/src/Mod/Fem/Gui/TaskDlgCreateElementSet.h new file mode 100644 index 0000000000..9848b2df36 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskDlgCreateElementSet.h @@ -0,0 +1,87 @@ +/*************************************************************************** + * Copyright (c) 2023 Peter McB * + * * + * based on: FemSetNodesObject.h * + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * 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 ROBOTGUI_TaskDlgCreateElementSet_H +#define ROBOTGUI_TaskDlgCreateElementSet_H + +#include +#include + +#include "TaskCreateElementSet.h" +#include "TaskObjectName.h" + + +// forward +namespace Gui +{ +namespace TaskView +{ +class TaskSelectLinkProperty; +} +} // namespace Gui + + +namespace FemGui +{ + + +/// simulation dialog for the TaskView +class TaskDlgCreateElementSet : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskDlgCreateElementSet(Fem::FemSetElementNodesObject *); + ~TaskDlgCreateElementSet() override; + +public: + /// is called the TaskView when the dialog is opened + void open() override; + /// is called by the framework if the dialog is accepted (Ok) + bool accept() override; + /// is called by the framework if the dialog is rejected (Cancel) + bool reject() override; + /// is called by the framework if the user press the help button + void helpRequested() override; + + /// returns for Close and Help button + QDialogButtonBox::StandardButtons getStandardButtons() const override + { + return QDialogButtonBox::Ok | QDialogButtonBox::Cancel; + } + +protected: + TaskCreateElementSet* param; + TaskObjectName* name; + + Fem::FemSetElementNodesObject* FemSetElementNodesObject; +}; + + + +} // namespace FemGui + +#endif // ROBOTGUI_TASKDLGSIMULATE_H diff --git a/src/Mod/Fem/Gui/ViewProviderSetElementNodes.cpp b/src/Mod/Fem/Gui/ViewProviderSetElementNodes.cpp new file mode 100644 index 0000000000..87d26d5297 --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderSetElementNodes.cpp @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (c) 2023 Peter McB * + * * + * based on: ViewProviderSetNodes.cpp * + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * 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 +#include +#include + +#include "ViewProviderSetElementNodes.h" + + +using namespace FemGui; + +PROPERTY_SOURCE(FemGui::ViewProviderSetElementNodes, Gui::ViewProviderGeometryObject) + +bool ViewProviderSetElementNodes::doubleClicked() +{ + Gui::TaskView::TaskDialog* dlg = + new TaskDlgCreateElementSet(static_cast(getObject())); + Gui::Control().showDialog(dlg); + return true; +} + + +bool ViewProviderSetElementNodes::setEdit(int) +{ + Gui::TaskView::TaskDialog* dlg = + new TaskDlgCreateElementSet(static_cast(getObject())); + Gui::Control().showDialog(dlg); + return true; +} + +void ViewProviderSetElementNodes::unsetEdit(int) +{} diff --git a/src/Mod/Fem/Gui/ViewProviderSetElementNodes.h b/src/Mod/Fem/Gui/ViewProviderSetElementNodes.h new file mode 100644 index 0000000000..a8c038dda6 --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderSetElementNodes.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (c) 2023 Peter McB * + * * + * based on: ViewProviderSetNodes.h * + * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * + * * + * 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_ViewProviderSetElementNodes_H +#define FEM_ViewProviderSetElementNodes_H + +#include + +namespace FemGui +{ + +class ViewProviderSetElementNodes : public Gui::ViewProviderGeometryObject +{ + PROPERTY_HEADER_WITH_OVERRIDE(FemGui::ViewProviderSetElementNodes); + +public: + bool doubleClicked() override; + +protected: + bool setEdit(int ModNum) override; + void unsetEdit(int ModNum) override; +}; + +} // namespace FemGui + + +#endif // FEM_ViewProviderSetElementNodes_H diff --git a/src/Mod/Fem/Gui/Workbench.cpp b/src/Mod/Fem/Gui/Workbench.cpp index 344ace35e0..43e14344d4 100644 --- a/src/Mod/Fem/Gui/Workbench.cpp +++ b/src/Mod/Fem/Gui/Workbench.cpp @@ -1,4 +1,9 @@ /*************************************************************************** + * Copyright (c) 2023 Peter McB * + * additional statement(s) for element sets: * + * added entry to Gui::MenuItem* mesh * + * * + * added to: Workbench.cpp * Copyright (c) 2008 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * @@ -318,6 +323,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "FEM_MeshGroup" << "Separator" << "FEM_CreateNodesSet" + << "FEM_CreateElementsSet" << "FEM_FEMMesh2Mesh"; Gui::MenuItem* solve = new Gui::MenuItem; diff --git a/src/Mod/Fem/femmesh/femmesh2mesh.py b/src/Mod/Fem/femmesh/femmesh2mesh.py index 9351045ac3..a2b3e1786d 100644 --- a/src/Mod/Fem/femmesh/femmesh2mesh.py +++ b/src/Mod/Fem/femmesh/femmesh2mesh.py @@ -1,6 +1,11 @@ # *************************************************************************** +# * Copyright (c) 2023 Peter McB * +# * added the function, mesh_2_femmesh, to convert the MESH * +# * into a triangular FEMMESH * # * * # * Copyright (c) 2016 Frantisek Loeffelmann * +# * extension to the work of: * +# Frantisek Loeffelmann, Ulrich Brammer, Bernd Hahnebach * # * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Lesser General Public License (LGPL) * @@ -21,7 +26,7 @@ # *************************************************************************** __title__ = "FemMesh to Mesh converter" -__author__ = "Frantisek Loeffelmann, Ulrich Brammer, Bernd Hahnebach" +__author__ = "Frantisek Loeffelmann, Ulrich Brammer, Bernd Hahnebach, Peter McB" __url__ = "https://www.freecad.org" ## @package FwmMesh2Mesh @@ -30,6 +35,7 @@ __url__ = "https://www.freecad.org" import time import FreeCAD +import Fem # import Mesh @@ -202,4 +208,53 @@ def femmesh_2_mesh(myFemMesh, myResults=None, myDispScale=1): FreeCAD.Console.PrintMessage( "Mesh by surface search method: {}\n".format(end_time - start_time) ) +# call to mesh_2_femmesh to convert mesh to femmesh before return statement + mesh2femmesh = mesh_2_femmesh(myFemMesh, singleFaces, faceCodeDict) return output_mesh + +# additional function to convert mesh to femmesh +def mesh_2_femmesh(myFemMesh, singleFaces, faceCodeDict): + start_time = time.process_time() + femmesh = Fem.FemMesh() + myfemmesh = myFemMesh.Nodes +# nodes contains the nodes that are used + nodes = {} + for myFace in singleFaces: + face_nodes = faceCodeDict[myFace] + for j in (0, 1, 2): + try: + nodes[face_nodes[j]] += 1 + except: + nodes[face_nodes[j]] = 0 + if len(face_nodes) == 4: + j = 3 + try: + nodes[face_nodes[j]] += 1 + except: + nodes[face_nodes[j]] = 0 + sfNode = femmesh.addNode + sfFace = femmesh.addFace + for key in myFemMesh.Nodes: + mynode = myfemmesh[key] + try: + if(nodes[key] >= 0): + sfNode(mynode[0], mynode[1], mynode[2], key) + except: + pass + + output_mesh = [] + + for myFace in singleFaces: + face_nodes = faceCodeDict[myFace] + sfFace(face_nodes[0], face_nodes[1], face_nodes[2]) + if len(face_nodes) == 4: + sfFace(face_nodes[2], face_nodes[3], face_nodes[0]) + obj = FreeCAD.ActiveDocument.addObject( + "Fem::FemMeshObject", "Mesh2Fem") + obj.FemMesh = femmesh + end_time = time.process_time() + FreeCAD.Console.PrintMessage( + "Convert to FemMesh: {}\n".format(end_time - start_time) + ) + return obj +# end of mesh_2_femmesh