/*************************************************************************** * Copyright (c) 2009 Jürgen Riegel * * * * 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 #include #include #include #include #include #include #include #include #include #include #include #include "Mod/Fem/App/FemMesh.h" #include #include #include #include #include #include #include #include #include #include // clang-format off // inclusion of the generated files (generated out of FemMeshPy.xml) #include "FemMeshPy.h" #include "FemMeshPy.cpp" #include "HypothesisPy.h" // clang-format on using namespace Fem; // returns a string which represents the object e.g. when printed in python std::string FemMeshPy::representation() const { std::stringstream str; getFemMeshPtr()->getSMesh()->Dump(str); return str.str(); } PyObject* FemMeshPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper { // create a new instance of FemMeshPy and the Twin object return new FemMeshPy(new FemMesh); } // constructor method int FemMeshPy::PyInit(PyObject* args, PyObject* /*kwd*/) { PyObject* pcObj = nullptr; if (!PyArg_ParseTuple(args, "|O", &pcObj)) { return -1; } try { // if no mesh is given if (!pcObj) { return 0; } if (PyObject_TypeCheck(pcObj, &(FemMeshPy::Type))) { getFemMeshPtr()->operator=(*static_cast(pcObj)->getFemMeshPtr()); } else { PyErr_Format( PyExc_TypeError, "Cannot create a FemMesh out of a '%s'", pcObj->ob_type->tp_name ); return -1; } } catch (const Base::Exception& e) { e.setPyException(); return -1; } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return -1; } catch (const Py::Exception&) { return -1; } return 0; } // ===== Methods ============================================================ PyObject* FemMeshPy::setShape(PyObject* args) { PyObject* pcObj; if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapePy::Type), &pcObj)) { return nullptr; } try { TopoDS_Shape shape = static_cast(pcObj)->getTopoShapePtr()->getShape(); getFemMeshPtr()->getSMesh()->ShapeToMesh(shape); } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } Py_Return; } PyObject* FemMeshPy::addHypothesis(PyObject* args) { PyObject* hyp; PyObject* shp = nullptr; // Since we have not a common base class for the Python binding of the // hypotheses classes we cannot pass a certain Python type if (!PyArg_ParseTuple(args, "O|O!", &hyp, &(Part::TopoShapePy::Type), &shp)) { return nullptr; } TopoDS_Shape shape; if (!shp) { shape = getFemMeshPtr()->getSMesh()->GetShapeToMesh(); } else { shape = static_cast(shp)->getTopoShapePtr()->getShape(); } try { Py::Object obj(hyp); Fem::Hypothesis attr(obj.getAttr("this")); SMESH_HypothesisPtr thesis = attr.extensionObject()->getHypothesis(); getFemMeshPtr()->addHypothesis(shape, thesis); } catch (const Py::Exception&) { return nullptr; } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } Py_Return; } PyObject* FemMeshPy::setStandardHypotheses(PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; } try { getFemMeshPtr()->setStandardHypotheses(); } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } Py_Return; } PyObject* FemMeshPy::compute(PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; } try { getFemMeshPtr()->compute(); } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } Py_Return; } PyObject* FemMeshPy::addNode(PyObject* args) { double x, y, z; int i = -1; if (PyArg_ParseTuple(args, "ddd", &x, &y, &z)) { try { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); SMDS_MeshNode* node = meshDS->AddNode(x, y, z); if (!node) { throw std::runtime_error("Failed to add node"); } return Py::new_reference_to(Py::Long(node->GetID())); } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } } PyErr_Clear(); if (PyArg_ParseTuple(args, "dddi", &x, &y, &z, &i)) { try { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); SMDS_MeshNode* node = meshDS->AddNodeWithID(x, y, z, i); if (!node) { throw std::runtime_error("Failed to add node"); } return Py::new_reference_to(Py::Long(node->GetID())); } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } } PyErr_SetString( PyExc_TypeError, "addNode() accepts:\n" "-- addNode(x,y,z)\n" "-- addNode(x,y,z,ElemId)\n" ); return nullptr; } PyObject* FemMeshPy::addEdge(PyObject* args) { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); int n1, n2; if (PyArg_ParseTuple(args, "ii", &n1, &n2)) { try { const SMDS_MeshNode* node1 = meshDS->FindNode(n1); const SMDS_MeshNode* node2 = meshDS->FindNode(n2); if (!node1 || !node2) { throw std::runtime_error("Failed to get node of the given indices"); } SMDS_MeshEdge* edge = meshDS->AddEdge(node1, node2); if (!edge) { throw std::runtime_error("Failed to add edge"); } return Py::new_reference_to(Py::Long(edge->GetID())); } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } } PyErr_Clear(); PyObject* obj; int ElementId = -1; if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId)) { Py::List list(obj); std::vector Nodes; for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { Py::Long NoNr(*it); const SMDS_MeshNode* node = meshDS->FindNode(NoNr); if (!node) { throw std::runtime_error("Failed to get node of the given indices"); } Nodes.push_back(node); } SMDS_MeshEdge* edge = nullptr; if (ElementId != -1) { switch (Nodes.size()) { case 2: edge = meshDS->AddEdgeWithID(Nodes[0], Nodes[1], ElementId); if (!edge) { throw std::runtime_error("Failed to add edge with given ElementId"); } break; case 3: edge = meshDS->AddEdgeWithID(Nodes[0], Nodes[1], Nodes[2], ElementId); if (!edge) { throw std::runtime_error("Failed to add edge with given ElementId"); } break; default: throw std::runtime_error("Unknown node count, [2|3] are allowed"); // unknown // edge type } } else { switch (Nodes.size()) { case 2: edge = meshDS->AddEdge(Nodes[0], Nodes[1]); if (!edge) { throw std::runtime_error("Failed to add edge"); } break; case 3: edge = meshDS->AddEdge(Nodes[0], Nodes[1], Nodes[2]); if (!edge) { throw std::runtime_error("Failed to add edge"); } break; default: throw std::runtime_error("Unknown node count, [2|3] are allowed"); // unknown // edge type } } return Py::new_reference_to(Py::Long(edge->GetID())); } PyErr_SetString( PyExc_TypeError, "addEdge accepts:\n" "-- int,int\n" "-- [2|3],[int]\n" ); return nullptr; } PyObject* FemMeshPy::addFace(PyObject* args) { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); int n1, n2, n3; if (PyArg_ParseTuple(args, "iii", &n1, &n2, &n3)) { // old form, deprecated try { const SMDS_MeshNode* node1 = meshDS->FindNode(n1); const SMDS_MeshNode* node2 = meshDS->FindNode(n2); const SMDS_MeshNode* node3 = meshDS->FindNode(n3); if (!node1 || !node2 || !node3) { throw std::runtime_error("Failed to get node of the given indices"); } SMDS_MeshFace* face = meshDS->AddFace(node1, node2, node3); if (!face) { throw std::runtime_error("Failed to add face"); } return Py::new_reference_to(Py::Long(face->GetID())); } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } } PyErr_Clear(); PyObject* obj; int ElementId = -1; if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId)) { Py::List list(obj); std::vector Nodes; for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { Py::Long NoNr(*it); const SMDS_MeshNode* node = meshDS->FindNode(NoNr); if (!node) { throw std::runtime_error("Failed to get node of the given indices"); } Nodes.push_back(node); } SMDS_MeshFace* face = nullptr; if (ElementId != -1) { switch (Nodes.size()) { case 3: face = meshDS->AddFaceWithID(Nodes[0], Nodes[1], Nodes[2], ElementId); if (!face) { throw std::runtime_error("Failed to add triangular face with given ElementId"); } break; case 4: face = meshDS->AddFaceWithID(Nodes[0], Nodes[1], Nodes[2], Nodes[3], ElementId); if (!face) { throw std::runtime_error("Failed to add face with given ElementId"); } break; case 6: face = meshDS->AddFaceWithID( Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4], Nodes[5], ElementId ); if (!face) { throw std::runtime_error("Failed to add face with given ElementId"); } break; case 8: face = meshDS->AddFaceWithID( Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4], Nodes[5], Nodes[6], Nodes[7], ElementId ); if (!face) { throw std::runtime_error("Failed to add face with given ElementId"); } break; default: throw std::runtime_error( "Unknown node count, [3|4|6|8] are allowed" ); // unknown face type } } else { switch (Nodes.size()) { case 3: face = meshDS->AddFace(Nodes[0], Nodes[1], Nodes[2]); if (!face) { throw std::runtime_error("Failed to add triangular face"); } break; case 4: face = meshDS->AddFace(Nodes[0], Nodes[1], Nodes[2], Nodes[3]); if (!face) { throw std::runtime_error("Failed to add face"); } break; case 6: face = meshDS->AddFace(Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4], Nodes[5]); if (!face) { throw std::runtime_error("Failed to add face"); } break; case 8: face = meshDS->AddFace( Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4], Nodes[5], Nodes[6], Nodes[7] ); if (!face) { throw std::runtime_error("Failed to add face"); } break; default: throw std::runtime_error( "Unknown node count, [4|5|6|8] are allowed" ); // unknown face type } } return Py::new_reference_to(Py::Long(face->GetID())); } PyErr_SetString( PyExc_TypeError, "addFace accepts:\n" "-- int,int,int\n" "-- [3|4|6|8 int],[int]\n" ); return nullptr; } PyObject* FemMeshPy::addQuad(PyObject* args) { int n1, n2, n3, n4; if (!PyArg_ParseTuple(args, "iiii", &n1, &n2, &n3, &n4)) { return nullptr; } try { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); const SMDS_MeshNode* node1 = meshDS->FindNode(n1); const SMDS_MeshNode* node2 = meshDS->FindNode(n2); const SMDS_MeshNode* node3 = meshDS->FindNode(n3); const SMDS_MeshNode* node4 = meshDS->FindNode(n4); if (!node1 || !node2 || !node3 || !node4) { throw std::runtime_error("Failed to get node of the given indices"); } SMDS_MeshFace* face = meshDS->AddFace(node1, node2, node3, node4); if (!face) { throw std::runtime_error("Failed to add quad"); } return Py::new_reference_to(Py::Long(face->GetID())); } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } } PyObject* FemMeshPy::addVolume(PyObject* args) { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); int n1, n2, n3, n4; if (PyArg_ParseTuple(args, "iiii", &n1, &n2, &n3, &n4)) { try { const SMDS_MeshNode* node1 = meshDS->FindNode(n1); const SMDS_MeshNode* node2 = meshDS->FindNode(n2); const SMDS_MeshNode* node3 = meshDS->FindNode(n3); const SMDS_MeshNode* node4 = meshDS->FindNode(n4); if (!node1 || !node2 || !node3 || !node4) { throw std::runtime_error("Failed to get node of the given indices"); } SMDS_MeshVolume* vol = meshDS->AddVolume(node1, node2, node3, node4); if (!vol) { throw std::runtime_error("Failed to add volume"); } return Py::new_reference_to(Py::Long(vol->GetID())); } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } } PyErr_Clear(); PyObject* obj; int ElementId = -1; if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId)) { Py::List list(obj); std::vector Nodes; for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { Py::Long NoNr(*it); const SMDS_MeshNode* node = meshDS->FindNode(NoNr); if (!node) { throw std::runtime_error("Failed to get node of the given indices"); } Nodes.push_back(node); } SMDS_MeshVolume* vol = nullptr; if (ElementId != -1) { switch (Nodes.size()) { case 4: vol = meshDS->AddVolumeWithID(Nodes[0], Nodes[1], Nodes[2], Nodes[3], ElementId); if (!vol) { throw std::runtime_error("Failed to add Tet4 volume with given ElementId"); } break; case 5: vol = meshDS->AddVolumeWithID(Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4], ElementId); if (!vol) { throw std::runtime_error("Failed to add Pyra5 volume with given ElementId"); } break; case 6: vol = meshDS->AddVolumeWithID( Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4], Nodes[5], ElementId ); if (!vol) { throw std::runtime_error("Failed to add Penta6 volume with given ElementId"); } break; case 8: vol = meshDS->AddVolumeWithID( Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4], Nodes[5], Nodes[6], Nodes[7], ElementId ); if (!vol) { throw std::runtime_error("Failed to add Hexa8 volume with given ElementId"); } break; case 10: vol = meshDS->AddVolumeWithID( Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4], Nodes[5], Nodes[6], Nodes[7], Nodes[8], Nodes[9], ElementId ); if (!vol) { throw std::runtime_error("Failed to add Tet10 volume with given ElementId"); } break; case 13: vol = 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], ElementId ); if (!vol) { throw std::runtime_error("Failed to add Pyra13 volume with given ElementId"); } break; case 15: vol = 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], ElementId ); if (!vol) { throw std::runtime_error("Failed to add Penta15 volume with given ElementId"); } break; case 20: vol = 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], ElementId ); if (!vol) { throw std::runtime_error("Failed to add Hexa20 volume with given ElementId"); } break; default: throw std::runtime_error( "Unknown node count, [4|5|6|8|10|13|15|20] are allowed" ); // unknown volume // type } } else { switch (Nodes.size()) { case 4: vol = meshDS->AddVolume(Nodes[0], Nodes[1], Nodes[2], Nodes[3]); if (!vol) { throw std::runtime_error("Failed to add Tet4 volume"); } break; case 5: vol = meshDS->AddVolume(Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4]); if (!vol) { throw std::runtime_error("Failed to add Pyra5 volume"); } break; case 6: vol = meshDS->AddVolume(Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4], Nodes[5]); if (!vol) { throw std::runtime_error("Failed to add Penta6 volume"); } break; case 8: vol = meshDS->AddVolume( Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4], Nodes[5], Nodes[6], Nodes[7] ); if (!vol) { throw std::runtime_error("Failed to add Hexa8 volume"); } break; case 10: vol = meshDS->AddVolume( Nodes[0], Nodes[1], Nodes[2], Nodes[3], Nodes[4], Nodes[5], Nodes[6], Nodes[7], Nodes[8], Nodes[9] ); if (!vol) { throw std::runtime_error("Failed to add Tet10 volume"); } break; case 13: vol = meshDS->AddVolume( 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] ); if (!vol) { throw std::runtime_error("Failed to add Pyra13 volume"); } break; case 15: vol = meshDS->AddVolume( 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] ); if (!vol) { throw std::runtime_error("Failed to add Penta15 volume"); } break; case 20: vol = meshDS->AddVolume( 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] ); if (!vol) { throw std::runtime_error("Failed to add Hexa20 volume"); } break; default: throw std::runtime_error( "Unknown node count, [4|5|6|8|10|13|15|20] are allowed" ); // unknown volume // type } } return Py::new_reference_to(Py::Long(vol->GetID())); } PyErr_SetString( PyExc_TypeError, "addVolume accepts:\n" "-- int,int,int,int\n" "-- [4|5|6|8|10|13|15|20 int],[int]\n" ); return nullptr; } PyObject* FemMeshPy::addEdgeList(PyObject* args) { PyObject* nodesObj = nullptr; PyObject* npObj = nullptr; ; if (!PyArg_ParseTuple(args, "O!O!", &PyList_Type, &nodesObj, &PyList_Type, &npObj)) { return nullptr; } Py::List nodesList(nodesObj); Py::List npList(npObj); SMESHDS_Mesh* meshDS = getFemMeshPtr()->getSMesh()->GetMeshDS(); std::vector nodes; for (Py::List::iterator it = nodesList.begin(); it != nodesList.end(); ++it) { Py::Long n(*it); const SMDS_MeshNode* node = meshDS->FindNode(static_cast(n)); if (!node) { throw std::runtime_error("Failed to get node of the given indices"); } nodes.push_back(node); } std::vector::iterator nodeIt = nodes.begin(); SMDS_MeshEdge* edge = nullptr; Py::List result; int np = 0; for (Py::List::iterator it = npList.begin(); it != npList.end(); ++it, nodeIt += np) { np = Py::Long(*it); std::vector nodesElem(nodeIt, nodeIt + np); switch (np) { case 2: edge = meshDS->AddEdge(nodesElem[0], nodesElem[1]); break; case 3: edge = meshDS->AddEdge(nodesElem[0], nodesElem[1], nodesElem[2]); break; default: PyErr_SetString(PyExc_TypeError, "Unknown node count, [2|3] are allowed"); return nullptr; } if (edge) { result.append(Py::Long(edge->GetID())); } else { PyErr_SetString(PyExc_TypeError, "Failed to add edge"); return nullptr; } } return Py::new_reference_to(result); } PyObject* FemMeshPy::addFaceList(PyObject* args) { PyObject* nodesObj = nullptr; PyObject* npObj = nullptr; ; if (!PyArg_ParseTuple(args, "O!O!", &PyList_Type, &nodesObj, &PyList_Type, &npObj)) { return nullptr; } Py::List nodesList(nodesObj); Py::List npList(npObj); SMESHDS_Mesh* meshDS = getFemMeshPtr()->getSMesh()->GetMeshDS(); std::vector nodes; for (Py::List::iterator it = nodesList.begin(); it != nodesList.end(); ++it) { Py::Long n(*it); const SMDS_MeshNode* node = meshDS->FindNode(static_cast(n)); if (!node) { throw std::runtime_error("Failed to get node of the given indices"); } nodes.push_back(node); } std::vector::iterator nodeIt = nodes.begin(); SMDS_MeshFace* face = nullptr; Py::List result; int np = 0; for (Py::List::iterator it = npList.begin(); it != npList.end(); ++it, nodeIt += np) { np = Py::Long(*it); std::vector nodesElem(nodeIt, nodeIt + np); switch (np) { case 3: face = meshDS->AddFace(nodesElem[0], nodesElem[1], nodesElem[2]); break; case 4: face = meshDS->AddFace(nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3]); break; case 6: face = meshDS->AddFace( nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3], nodesElem[4], nodesElem[5] ); break; case 8: face = meshDS->AddFace( nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3], nodesElem[4], nodesElem[5], nodesElem[6], nodesElem[7] ); break; default: PyErr_SetString(PyExc_TypeError, "Unknown node count, [3|4|6|8] are allowed"); return nullptr; } if (face) { result.append(Py::Long(face->GetID())); } else { PyErr_SetString(PyExc_TypeError, "Failed to add face"); return nullptr; } } return Py::new_reference_to(result); } PyObject* FemMeshPy::addVolumeList(PyObject* args) { PyObject* nodesObj = nullptr; PyObject* npObj = nullptr; ; if (!PyArg_ParseTuple(args, "O!O!", &PyList_Type, &nodesObj, &PyList_Type, &npObj)) { return nullptr; } Py::List nodesList(nodesObj); Py::List npList(npObj); SMESHDS_Mesh* meshDS = getFemMeshPtr()->getSMesh()->GetMeshDS(); std::vector nodes; for (Py::List::iterator it = nodesList.begin(); it != nodesList.end(); ++it) { Py::Long n(*it); const SMDS_MeshNode* node = meshDS->FindNode(static_cast(n)); if (!node) { throw std::runtime_error("Failed to get node of the given indices"); } nodes.push_back(node); } std::vector::iterator nodeIt = nodes.begin(); SMDS_MeshVolume* vol = nullptr; Py::List result; int np = 0; for (Py::List::iterator it = npList.begin(); it != npList.end(); ++it, nodeIt += np) { np = Py::Long(*it); std::vector nodesElem(nodeIt, nodeIt + np); switch (np) { case 4: vol = meshDS->AddVolume(nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3]); break; case 5: vol = meshDS->AddVolume( nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3], nodesElem[4] ); break; case 6: vol = meshDS->AddVolume( nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3], nodesElem[4], nodesElem[5] ); break; case 8: vol = meshDS->AddVolume( nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3], nodesElem[4], nodesElem[5], nodesElem[6], nodesElem[7] ); break; case 10: vol = meshDS->AddVolume( nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3], nodesElem[4], nodesElem[5], nodesElem[6], nodesElem[7], nodesElem[8], nodesElem[9] ); break; case 13: vol = meshDS->AddVolume( nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3], nodesElem[4], nodesElem[5], nodesElem[6], nodesElem[7], nodesElem[8], nodesElem[9], nodesElem[10], nodesElem[11], nodesElem[12] ); break; case 15: vol = meshDS->AddVolume( nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3], nodesElem[4], nodesElem[5], nodesElem[6], nodesElem[7], nodesElem[8], nodesElem[9], nodesElem[10], nodesElem[11], nodesElem[12], nodesElem[13], nodesElem[14] ); break; case 20: vol = meshDS->AddVolume( nodesElem[0], nodesElem[1], nodesElem[2], nodesElem[3], nodesElem[4], nodesElem[5], nodesElem[6], nodesElem[7], nodesElem[8], nodesElem[9], nodesElem[10], nodesElem[11], nodesElem[12], nodesElem[13], nodesElem[14], nodesElem[15], nodesElem[16], nodesElem[17], nodesElem[18], nodesElem[19] ); break; default: PyErr_SetString(PyExc_TypeError, "Unknown node count, [4|5|6|8|10|13|15|20] are allowed"); return nullptr; } if (vol) { result.append(Py::Long(vol->GetID())); } else { PyErr_SetString(PyExc_TypeError, "Failed to add face"); return nullptr; } } return Py::new_reference_to(result); } PyObject* FemMeshPy::copy(PyObject* args) const { if (!PyArg_ParseTuple(args, "")) { return nullptr; } const FemMesh& mesh = *getFemMeshPtr(); return new FemMeshPy(new FemMesh(mesh)); } PyObject* FemMeshPy::read(PyObject* args) { char* Name; if (!PyArg_ParseTuple(args, "et", "utf-8", &Name)) { return nullptr; } std::string EncodedName = std::string(Name); PyMem_Free(Name); try { getFemMeshPtr()->read(EncodedName.c_str()); } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } Py_Return; } PyObject* FemMeshPy::write(PyObject* args) const { char* Name; if (!PyArg_ParseTuple(args, "et", "utf-8", &Name)) { return nullptr; } std::string EncodedName = std::string(Name); PyMem_Free(Name); try { getFemMeshPtr()->write(EncodedName.c_str()); } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } Py_Return; } namespace { std::map volVariantPyMap = { {"standard", ABAQUS_VolumeVariant::Standard}, {"reduced", ABAQUS_VolumeVariant::Reduced}, {"incompatible", ABAQUS_VolumeVariant::Incompatible}, {"modified", ABAQUS_VolumeVariant::Modified}, {"fluid", ABAQUS_VolumeVariant::Fluid} }; std::map faceVariantPyMap = { {"shell", ABAQUS_FaceVariant::Shell}, {"shell reduced", ABAQUS_FaceVariant::Shell_Reduced}, {"membrane", ABAQUS_FaceVariant::Membrane}, {"membrane reduced", ABAQUS_FaceVariant::Membrane_Reduced}, {"stress", ABAQUS_FaceVariant::Stress}, {"stress reduced", ABAQUS_FaceVariant::Stress_Reduced}, {"strain", ABAQUS_FaceVariant::Strain}, {"strain reduced", ABAQUS_FaceVariant::Strain_Reduced}, {"axisymmetric", ABAQUS_FaceVariant::Axisymmetric}, {"axisymmetric reduced", ABAQUS_FaceVariant::Axisymmetric_Reduced} }; std::map edgeVariantPyMap = { {"beam", ABAQUS_EdgeVariant::Beam}, {"beam reduced", ABAQUS_EdgeVariant::Beam_Reduced}, {"truss", ABAQUS_EdgeVariant::Truss}, {"network", ABAQUS_EdgeVariant::Network} }; } // namespace PyObject* FemMeshPy::writeABAQUS(PyObject* args, PyObject* kwd) const { char* Name; int elemParam; PyObject* groupParam; const char* volVariant = "standard"; const char* faceVariant = "shell"; const char* edgeVariant = "beam"; const std::array kwlist { "fileName", "elemParam", "groupParam", "volVariant", "faceVariant", "edgeVariant", nullptr }; if (!Base::Wrapped_ParseTupleAndKeywords( args, kwd, "etiO!|sss", kwlist, "utf-8", &Name, &elemParam, &PyBool_Type, &groupParam, &volVariant, &faceVariant, &edgeVariant )) { return nullptr; } std::string EncodedName = std::string(Name); PyMem_Free(Name); bool grpParam = Base::asBoolean(groupParam); auto itVol = volVariantPyMap.find(volVariant); auto itFace = faceVariantPyMap.find(faceVariant); auto itEdge = edgeVariantPyMap.find(edgeVariant); if (itVol == volVariantPyMap.end() || itFace == faceVariantPyMap.end() || itEdge == edgeVariantPyMap.end()) { PyErr_SetString(PyExc_ValueError, "Invalid variant value"); return nullptr; } try { getFemMeshPtr()->writeABAQUS( EncodedName.c_str(), elemParam, grpParam, itVol->second, itFace->second, itEdge->second ); } catch (const std::exception& e) { PyErr_SetString(Base::PyExc_FC_GeneralError, e.what()); return nullptr; } Py_Return; } PyObject* FemMeshPy::setTransform(PyObject* args) { PyObject* ptr; if (!PyArg_ParseTuple(args, "O!", &(Base::PlacementPy::Type), &ptr)) { return nullptr; } Base::Placement* placement = static_cast(ptr)->getPlacementPtr(); Base::Matrix4D mat = placement->toMatrix(); getFemMeshPtr()->transformGeometry(mat); Py_Return; } PyObject* FemMeshPy::getFacesByFace(PyObject* args) const { PyObject* pW; if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeFacePy::Type), &pW)) { return nullptr; } try { const TopoDS_Shape& sh = static_cast(pW)->getTopoShapePtr()->getShape(); if (sh.IsNull()) { PyErr_SetString(PyExc_ValueError, "Face is empty"); return nullptr; } const TopoDS_Face& fc = TopoDS::Face(sh); Py::List ret; std::list resultSet = getFemMeshPtr()->getFacesByFace(fc); for (std::list::const_iterator it = resultSet.begin(); it != resultSet.end(); ++it) { ret.append(Py::Long(*it)); } return Py::new_reference_to(ret); } catch (Standard_Failure& e) { PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); return nullptr; } } PyObject* FemMeshPy::getEdgesByEdge(PyObject* args) const { PyObject* pW; if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeEdgePy::Type), &pW)) { return nullptr; } try { const TopoDS_Shape& sh = static_cast(pW)->getTopoShapePtr()->getShape(); if (sh.IsNull()) { PyErr_SetString(PyExc_ValueError, "Edge is empty"); return nullptr; } const TopoDS_Edge& fc = TopoDS::Edge(sh); Py::List ret; std::list resultSet = getFemMeshPtr()->getEdgesByEdge(fc); for (std::list::const_iterator it = resultSet.begin(); it != resultSet.end(); ++it) { ret.append(Py::Long(*it)); } return Py::new_reference_to(ret); } catch (Standard_Failure& e) { PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); return nullptr; } } PyObject* FemMeshPy::getVolumesByFace(PyObject* args) const { PyObject* pW; if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeFacePy::Type), &pW)) { return nullptr; } try { const TopoDS_Shape& sh = static_cast(pW)->getTopoShapePtr()->getShape(); if (sh.IsNull()) { PyErr_SetString(PyExc_ValueError, "Face is empty"); return nullptr; } const TopoDS_Face& fc = TopoDS::Face(sh); Py::List ret; std::list> resultSet = getFemMeshPtr()->getVolumesByFace(fc); for (std::list>::const_iterator it = resultSet.begin(); it != resultSet.end(); ++it) { Py::Tuple vol_face(2); vol_face.setItem(0, Py::Long(it->first)); vol_face.setItem(1, Py::Long(it->second)); ret.append(vol_face); } return Py::new_reference_to(ret); } catch (Standard_Failure& e) { PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); return nullptr; } } PyObject* FemMeshPy::getccxVolumesByFace(PyObject* args) const { PyObject* pW; if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeFacePy::Type), &pW)) { return nullptr; } try { const TopoDS_Shape& sh = static_cast(pW)->getTopoShapePtr()->getShape(); if (sh.IsNull()) { PyErr_SetString(PyExc_ValueError, "Face is empty"); return nullptr; } const TopoDS_Face& fc = TopoDS::Face(sh); Py::List ret; std::map resultSet = getFemMeshPtr()->getccxVolumesByFace(fc); for (std::map::const_iterator it = resultSet.begin(); it != resultSet.end(); ++it) { Py::Tuple vol_face(2); vol_face.setItem(0, Py::Long(it->first)); vol_face.setItem(1, Py::Long(it->second)); ret.append(vol_face); } return Py::new_reference_to(ret); } catch (Standard_Failure& e) { PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); return nullptr; } } PyObject* FemMeshPy::getNodeById(PyObject* args) const { int id; if (!PyArg_ParseTuple(args, "i", &id)) { return nullptr; } Base::Matrix4D Mtrx = getFemMeshPtr()->getTransform(); const SMDS_MeshNode* aNode = getFemMeshPtr()->getSMesh()->GetMeshDS()->FindNode(id); if (aNode) { Base::Vector3d vec(aNode->X(), aNode->Y(), aNode->Z()); vec = Mtrx * vec; return new Base::VectorPy(vec); } else { PyErr_SetString(PyExc_ValueError, "No valid node ID"); return nullptr; } } PyObject* FemMeshPy::getNodesBySolid(PyObject* args) const { PyObject* pW; if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeSolidPy::Type), &pW)) { return nullptr; } try { const TopoDS_Shape& sh = static_cast(pW)->getTopoShapePtr()->getShape(); const TopoDS_Solid& fc = TopoDS::Solid(sh); if (sh.IsNull()) { PyErr_SetString(PyExc_ValueError, "Solid is empty"); return nullptr; } Py::List ret; std::set resultSet = getFemMeshPtr()->getNodesBySolid(fc); for (int it : resultSet) { ret.append(Py::Long(it)); } return Py::new_reference_to(ret); } catch (Standard_Failure& e) { PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); return nullptr; } } PyObject* FemMeshPy::getNodesByFace(PyObject* args) const { PyObject* pW; if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeFacePy::Type), &pW)) { return nullptr; } try { const TopoDS_Shape& sh = static_cast(pW)->getTopoShapePtr()->getShape(); const TopoDS_Face& fc = TopoDS::Face(sh); if (sh.IsNull()) { PyErr_SetString(PyExc_ValueError, "Face is empty"); return nullptr; } Py::List ret; std::set resultSet = getFemMeshPtr()->getNodesByFace(fc); for (int it : resultSet) { ret.append(Py::Long(it)); } return Py::new_reference_to(ret); } catch (Standard_Failure& e) { PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); return nullptr; } } PyObject* FemMeshPy::getNodesByEdge(PyObject* args) const { PyObject* pW; if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeEdgePy::Type), &pW)) { return nullptr; } try { const TopoDS_Shape& sh = static_cast(pW)->getTopoShapePtr()->getShape(); const TopoDS_Edge& fc = TopoDS::Edge(sh); if (sh.IsNull()) { PyErr_SetString(PyExc_ValueError, "Edge is empty"); return nullptr; } Py::List ret; std::set resultSet = getFemMeshPtr()->getNodesByEdge(fc); for (int it : resultSet) { ret.append(Py::Long(it)); } return Py::new_reference_to(ret); } catch (Standard_Failure& e) { PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); return nullptr; } } PyObject* FemMeshPy::getNodesByVertex(PyObject* args) const { PyObject* pW; if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapeVertexPy::Type), &pW)) { return nullptr; } try { const TopoDS_Shape& sh = static_cast(pW)->getTopoShapePtr()->getShape(); const TopoDS_Vertex& fc = TopoDS::Vertex(sh); if (sh.IsNull()) { PyErr_SetString(PyExc_ValueError, "Vertex is empty"); return nullptr; } Py::List ret; std::set resultSet = getFemMeshPtr()->getNodesByVertex(fc); for (int it : resultSet) { ret.append(Py::Long(it)); } return Py::new_reference_to(ret); } catch (Standard_Failure& e) { PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); return nullptr; } } PyObject* FemMeshPy::getElementNodes(PyObject* args) const { int id; if (!PyArg_ParseTuple(args, "i", &id)) { return nullptr; } try { std::list resultSet = getFemMeshPtr()->getElementNodes(id); Py::Tuple ret(resultSet.size()); int index = 0; for (std::list::const_iterator it = resultSet.begin(); it != resultSet.end(); ++it) { ret.setItem(index++, Py::Long(*it)); } return Py::new_reference_to(ret); } catch (Standard_Failure& e) { PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); return nullptr; } } using pairStrElemType = std::pair; const std::vector vecTypeName = { {"All", SMDSAbs_All}, {"Node", SMDSAbs_Node}, {"Edge", SMDSAbs_Edge}, {"Face", SMDSAbs_Face}, {"Volume", SMDSAbs_Volume}, {"0DElement", SMDSAbs_0DElement}, {"Ball", SMDSAbs_Ball}, }; PyObject* FemMeshPy::getNodeElements(PyObject* args) const { int id; const char* typeStr = "All"; if (!PyArg_ParseTuple(args, "i|s", &id, &typeStr)) { return nullptr; } auto it = std::find_if(vecTypeName.begin(), vecTypeName.end(), [=](const pairStrElemType& x) { return x.first == typeStr; }); if (it == vecTypeName.end()) { PyErr_SetString(PyExc_ValueError, "Invalid element type"); return nullptr; } SMDSAbs_ElementType elemType = it->second; std::list elemList = getFemMeshPtr()->getNodeElements(id, elemType); Py::Tuple result(elemList.size()); int index = 0; for (int it : elemList) { result.setItem(index++, Py::Long(it)); } return Py::new_reference_to(result); } PyObject* FemMeshPy::getGroupName(PyObject* args) const { int id; if (!PyArg_ParseTuple(args, "i", &id)) { return nullptr; } SMESH_Group* group = getFemMeshPtr()->getSMesh()->GetGroup(id); if (!group) { PyErr_SetString(PyExc_ValueError, "No group for given id"); return nullptr; } return PyUnicode_FromString(group->GetName()); } PyObject* FemMeshPy::getGroupElementType(PyObject* args) const { int id; if (!PyArg_ParseTuple(args, "i", &id)) { return nullptr; } SMESH_Group* group = getFemMeshPtr()->getSMesh()->GetGroup(id); if (!group) { PyErr_SetString(PyExc_ValueError, "No group for given id"); return nullptr; } SMDSAbs_ElementType elemType = group->GetGroupDS()->GetType(); auto it = std::find_if(vecTypeName.begin(), vecTypeName.end(), [=](const pairStrElemType& x) { return x.second == elemType; }); const char* typeStr = it != vecTypeName.end() ? it->first.c_str() : "Unknown"; return PyUnicode_FromString(typeStr); } PyObject* FemMeshPy::getGroupElements(PyObject* args) const { int id; if (!PyArg_ParseTuple(args, "i", &id)) { return nullptr; } SMESH_Group* group = getFemMeshPtr()->getSMesh()->GetGroup(id); if (!group) { PyErr_SetString(PyExc_ValueError, "No group for given id"); return nullptr; } std::set ids; SMDS_ElemIteratorPtr aElemIter = group->GetGroupDS()->GetElements(); while (aElemIter->more()) { const SMDS_MeshElement* aElement = aElemIter->next(); ids.insert(aElement->GetID()); } Py::Tuple tuple(ids.size()); int index = 0; for (int it : ids) { tuple.setItem(index++, Py::Long(it)); } return Py::new_reference_to(tuple); } /* Add Groups and elements to these. */ PyObject* FemMeshPy::addGroup(PyObject* args) const { // get name and typestring from arguments char* Name; char* typeString; int theId = -1; if (!PyArg_ParseTuple(args, "etet|i", "utf-8", &Name, "utf-8", &typeString, &theId)) { return nullptr; } std::string EncodedName = std::string(Name); PyMem_Free(Name); std::string EncodedTypeString = std::string(typeString); PyMem_Free(typeString); int retId = -1; try { retId = getFemMeshPtr()->addGroup(EncodedTypeString, EncodedName, theId); } catch (Standard_Failure& e) { PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); return nullptr; } std::cout << "Added Group: Name: \'" << EncodedName << "\' Type: \'" << EncodedTypeString << "\' id: " << retId << std::endl; return PyLong_FromLong(retId); } PyObject* FemMeshPy::addGroupElements(PyObject* args) const { int id; // the second object should be a list // see // https://stackoverflow.com/questions/22458298/extending-python-with-c-pass-a-list-to-pyarg-parsetuple PyObject* pList; PyObject* pItem; Py_ssize_t n; if (!PyArg_ParseTuple(args, "iO!", &id, &PyList_Type, &pList)) { PyErr_SetString(PyExc_TypeError, "AddGroupElements: 2nd Parameter must be a list."); return nullptr; } std::set ids; n = PyList_Size(pList); std::cout << "AddGroupElements: num elements: " << n << " sizeof: " << sizeof(n) << std::endl; for (Py_ssize_t i = 0; i < n; i++) { pItem = PyList_GetItem(pList, i); if (!PyLong_Check(pItem)) { PyErr_SetString(PyExc_TypeError, "AddGroupElements: List items must be integers."); return nullptr; } ids.insert(PyLong_AsSsize_t(pItem)); // Py_ssize_t transparently handles maximum array lengths on 32bit and 64bit machines // See: https://www.python.org/dev/peps/pep-0353/ } // Downcast Py_ssize_t to int to be compatible with SMESH functions std::set int_ids; for (Py_ssize_t it : ids) { int_ids.insert(Py_SAFE_DOWNCAST(it, Py_ssize_t, int)); } try { getFemMeshPtr()->addGroupElements(id, int_ids); } catch (Standard_Failure& e) { PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); return nullptr; } Py_Return; } PyObject* FemMeshPy::removeGroup(PyObject* args) const { int theId; if (!PyArg_ParseTuple(args, "i", &theId)) { return nullptr; } return PyBool_FromLong((long)(getFemMeshPtr()->removeGroup(theId))); } PyObject* FemMeshPy::renameGroup(PyObject* args) const { int id; const char* name; if (!PyArg_ParseTuple(args, "is", &id, &name)) { return nullptr; } getFemMeshPtr()->renameGroup(id, name); Py_Return; } PyObject* FemMeshPy::getElementType(PyObject* args) const { int id; if (!PyArg_ParseTuple(args, "i", &id)) { return nullptr; } // An element ... SMDSAbs_ElementType elemType = getFemMeshPtr()->getSMesh()->GetElementType(id, true); // ... or a node if (elemType == SMDSAbs_All) { elemType = getFemMeshPtr()->getSMesh()->GetElementType(id, false); } auto it = std::find_if(vecTypeName.begin() + 1, vecTypeName.end(), [=](const pairStrElemType& x) { return x.second == elemType; }); const char* typeStr = it != vecTypeName.end() ? it->first.c_str() : nullptr; if (!typeStr) { PyErr_SetString(PyExc_ValueError, "No node or element for given id"); return nullptr; } return PyUnicode_FromString(typeStr); } PyObject* FemMeshPy::getIdByElementType(PyObject* args) const { const char* typeStr; if (!PyArg_ParseTuple(args, "s", &typeStr)) { return nullptr; } auto it = std::find_if(vecTypeName.begin(), vecTypeName.end(), [=](const pairStrElemType& x) { return x.first == typeStr; }); if (it == vecTypeName.end()) { PyErr_SetString(PyExc_ValueError, "Invalid element type"); return nullptr; } SMDSAbs_ElementType elemType = it->second; std::set ids; SMDS_ElemIteratorPtr aElemIter = getFemMeshPtr()->getSMesh()->GetMeshDS()->elementsIterator( elemType ); while (aElemIter->more()) { const SMDS_MeshElement* aElem = aElemIter->next(); ids.insert(aElem->GetID()); } Py::Tuple tuple(ids.size()); int index = 0; for (int it : ids) { tuple.setItem(index++, Py::Long(it)); } return Py::new_reference_to(tuple); } // ===== Attributes ============================================================ Py::Dict FemMeshPy::getNodes() const { // int count = getFemMeshPtr()->getSMesh()->GetMeshDS()->NbNodes(); // Py::Tuple tup(count); Py::Dict dict; // get the actual transform of the FemMesh Base::Matrix4D Mtrx = getFemMeshPtr()->getTransform(); SMDS_NodeIteratorPtr aNodeIter = getFemMeshPtr()->getSMesh()->GetMeshDS()->nodesIterator(); while (aNodeIter->more()) { const SMDS_MeshNode* aNode = aNodeIter->next(); Base::Vector3d vec(aNode->X(), aNode->Y(), aNode->Z()); // Apply the matrix to hold the BoundBox in absolute space. vec = Mtrx * vec; int id = aNode->GetID(); dict[Py::Long(id)] = Py::asObject(new Base::VectorPy(vec)); } return dict; } Py::Long FemMeshPy::getNodeCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbNodes()); } Py::Tuple FemMeshPy::getEdges() const { std::set ids; SMDS_EdgeIteratorPtr aEdgeIter = getFemMeshPtr()->getSMesh()->GetMeshDS()->edgesIterator(); while (aEdgeIter->more()) { const SMDS_MeshEdge* aEdge = aEdgeIter->next(); ids.insert(aEdge->GetID()); } Py::Tuple tuple(ids.size()); int index = 0; for (int it : ids) { tuple.setItem(index++, Py::Long(it)); } return tuple; } Py::Tuple FemMeshPy::getEdgesOnly() const { std::set resultSet = getFemMeshPtr()->getEdgesOnly(); Py::Tuple tuple(resultSet.size()); int index = 0; for (int it : resultSet) { tuple.setItem(index++, Py::Long(it)); } return tuple; } Py::Long FemMeshPy::getEdgeCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbEdges()); } Py::Tuple FemMeshPy::getFaces() const { std::set ids; SMDS_FaceIteratorPtr aFaceIter = getFemMeshPtr()->getSMesh()->GetMeshDS()->facesIterator(); while (aFaceIter->more()) { const SMDS_MeshFace* aFace = aFaceIter->next(); ids.insert(aFace->GetID()); } Py::Tuple tuple(ids.size()); int index = 0; for (int it : ids) { tuple.setItem(index++, Py::Long(it)); } return tuple; } Py::Tuple FemMeshPy::getFacesOnly() const { std::set resultSet = getFemMeshPtr()->getFacesOnly(); Py::Tuple tuple(resultSet.size()); int index = 0; for (int it : resultSet) { tuple.setItem(index++, Py::Long(it)); } return tuple; } Py::Long FemMeshPy::getFaceCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbFaces()); } Py::Long FemMeshPy::getTriangleCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbTriangles()); } Py::Long FemMeshPy::getQuadrangleCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbQuadrangles()); } Py::Long FemMeshPy::getPolygonCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbPolygons()); } Py::Tuple FemMeshPy::getVolumes() const { std::set ids; SMDS_VolumeIteratorPtr aVolIter = getFemMeshPtr()->getSMesh()->GetMeshDS()->volumesIterator(); while (aVolIter->more()) { const SMDS_MeshVolume* aVol = aVolIter->next(); ids.insert(aVol->GetID()); } Py::Tuple tuple(ids.size()); int index = 0; for (int it : ids) { tuple.setItem(index++, Py::Long(it)); } return tuple; } Py::Long FemMeshPy::getVolumeCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbVolumes()); } Py::Long FemMeshPy::getTetraCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbTetras()); } Py::Long FemMeshPy::getHexaCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbHexas()); } Py::Long FemMeshPy::getPyramidCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbPyramids()); } Py::Long FemMeshPy::getPrismCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbPrisms()); } Py::Long FemMeshPy::getPolyhedronCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbPolyhedrons()); } Py::Long FemMeshPy::getSubMeshCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbSubMesh()); } Py::Long FemMeshPy::getGroupCount() const { return Py::Long(getFemMeshPtr()->getSMesh()->NbGroup()); } Py::Tuple FemMeshPy::getGroups() const { std::list groupIDs = getFemMeshPtr()->getSMesh()->GetGroupIds(); Py::Tuple tuple(groupIDs.size()); int index = 0; for (int it : groupIDs) { tuple.setItem(index++, Py::Long(it)); } return tuple; } Py::Object FemMeshPy::getVolume() const { return Py::asObject(new Base::QuantityPy(new Base::Quantity(getFemMeshPtr()->getVolume()))); } // ===== custom attributes ============================================================ PyObject* FemMeshPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } int FemMeshPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; }