Download src/Mod/Fem/App/FemMeshPyImp.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 64.2 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Fem/App/FemMeshPyImp.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Fem/App/FemMeshPyImp.cpp
-
curl -L -o FemMeshPyImp.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Fem/App/FemMeshPyImp.cpp
64.2 kB
| /*************************************************************************** | |
| * Copyright (c) 2009 Jürgen Riegel <juergen.riegel@web.de> * | |
| * * | |
| * 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 * | |
| * * | |
| ***************************************************************************/ | |
| // clang-format off | |
| // inclusion of the generated files (generated out of FemMeshPy.xml) | |
| // 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<FemMeshPy*>(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<Part::TopoShapePy*>(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<Part::TopoShapePy*>(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<const SMDS_MeshNode*> 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<const SMDS_MeshNode*> 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<const SMDS_MeshNode*> 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<const SMDS_MeshNode*> nodes; | |
| for (Py::List::iterator it = nodesList.begin(); it != nodesList.end(); ++it) { | |
| Py::Long n(*it); | |
| const SMDS_MeshNode* node = meshDS->FindNode(static_cast<int>(n)); | |
| if (!node) { | |
| throw std::runtime_error("Failed to get node of the given indices"); | |
| } | |
| nodes.push_back(node); | |
| } | |
| std::vector<const SMDS_MeshNode*>::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<const SMDS_MeshNode*> 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<const SMDS_MeshNode*> nodes; | |
| for (Py::List::iterator it = nodesList.begin(); it != nodesList.end(); ++it) { | |
| Py::Long n(*it); | |
| const SMDS_MeshNode* node = meshDS->FindNode(static_cast<int>(n)); | |
| if (!node) { | |
| throw std::runtime_error("Failed to get node of the given indices"); | |
| } | |
| nodes.push_back(node); | |
| } | |
| std::vector<const SMDS_MeshNode*>::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<const SMDS_MeshNode*> 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<const SMDS_MeshNode*> nodes; | |
| for (Py::List::iterator it = nodesList.begin(); it != nodesList.end(); ++it) { | |
| Py::Long n(*it); | |
| const SMDS_MeshNode* node = meshDS->FindNode(static_cast<int>(n)); | |
| if (!node) { | |
| throw std::runtime_error("Failed to get node of the given indices"); | |
| } | |
| nodes.push_back(node); | |
| } | |
| std::vector<const SMDS_MeshNode*>::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<const SMDS_MeshNode*> 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<std::string, ABAQUS_VolumeVariant> volVariantPyMap = { | |
| {"standard", ABAQUS_VolumeVariant::Standard}, | |
| {"reduced", ABAQUS_VolumeVariant::Reduced}, | |
| {"incompatible", ABAQUS_VolumeVariant::Incompatible}, | |
| {"modified", ABAQUS_VolumeVariant::Modified}, | |
| {"fluid", ABAQUS_VolumeVariant::Fluid} | |
| }; | |
| std::map<std::string, ABAQUS_FaceVariant> 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<std::string, ABAQUS_EdgeVariant> 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<const char*, 7> 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<Base::PlacementPy*>(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<Part::TopoShapeFacePy*>(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<int> resultSet = getFemMeshPtr()->getFacesByFace(fc); | |
| for (std::list<int>::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<Part::TopoShapeEdgePy*>(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<int> resultSet = getFemMeshPtr()->getEdgesByEdge(fc); | |
| for (std::list<int>::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<Part::TopoShapeFacePy*>(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<std::pair<int, int>> resultSet = getFemMeshPtr()->getVolumesByFace(fc); | |
| for (std::list<std::pair<int, int>>::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<Part::TopoShapeFacePy*>(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<int, int> resultSet = getFemMeshPtr()->getccxVolumesByFace(fc); | |
| for (std::map<int, int>::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<Part::TopoShapeSolidPy*>(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<int> 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<Part::TopoShapeFacePy*>(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<int> 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<Part::TopoShapeEdgePy*>(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<int> 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<Part::TopoShapeVertexPy*>(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<int> 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<int> resultSet = getFemMeshPtr()->getElementNodes(id); | |
| Py::Tuple ret(resultSet.size()); | |
| int index = 0; | |
| for (std::list<int>::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<std::string, SMDSAbs_ElementType>; | |
| const std::vector<pairStrElemType> 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<int> 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<int> 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<Py_ssize_t> 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> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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<int> 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; | |
| } | |