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