From df0c7b7818aa29eab6ddf4653ea7094ab3ee8264 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 5 Oct 2021 12:43:28 +0200 Subject: [PATCH] App: expose methods of ComplexGeoData to Python --- src/App/ComplexGeoDataPy.xml | 101 +++++++++---- src/App/ComplexGeoDataPyImp.cpp | 246 ++++++++++++++++++++++++++++++-- 2 files changed, 313 insertions(+), 34 deletions(-) diff --git a/src/App/ComplexGeoDataPy.xml b/src/App/ComplexGeoDataPy.xml index c341734a18..65e3422e9c 100644 --- a/src/App/ComplexGeoDataPy.xml +++ b/src/App/ComplexGeoDataPy.xml @@ -5,7 +5,7 @@ Name="ComplexGeoDataPy" Twin="ComplexGeoData" Include="App/ComplexGeoData.h" - TwinPointer="ComplexGeoData" + TwinPointer="ComplexGeoData" Namespace="Data" FatherInclude="Base/PersistencePy.h" FatherNamespace="Base" @@ -14,34 +14,85 @@ Father of all complex geometric data types + + + Return a list of element types + + + + + Return the number of elements of a type + + Return vertexes and faces from a sub-element - - - Get the BoundBox of the object - - - - - - Get the current transformation of the object as placement - - - - - - Get the current transformation of the object as matrix - - - - - - Geometry Tag - - - + + + Return vertexes and lines from a sub-element + + + + + Return a tuple of points and normals with a given accuracy + + + + + Return a tuple of points and lines with a given accuracy + + + + + Return a tuple of points and triangles with a given accuracy + + + + + Apply an additional translation to the placement + + + + + Apply an additional rotation to the placement + + + + + Apply a transformation to the underlying geometry + + + + + Get the BoundBox of the object + + + + + + Get the center of gravity + + + + + + Get the current transformation of the object as placement + + + + + + Get the current transformation of the object as matrix + + + + + + Geometry Tag + + + diff --git a/src/App/ComplexGeoDataPyImp.cpp b/src/App/ComplexGeoDataPyImp.cpp index a89e02b29d..013035ef5b 100644 --- a/src/App/ComplexGeoDataPyImp.cpp +++ b/src/App/ComplexGeoDataPyImp.cpp @@ -22,6 +22,9 @@ #include "PreCompiled.h" +#ifndef _PreComp_ +# include +#endif #include "ComplexGeoData.h" @@ -43,24 +46,52 @@ std::string ComplexGeoDataPy::representation(void) const return std::string(""); } -PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args) +PyObject* ComplexGeoDataPy::getElementTypes(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + std::vector types = getComplexGeoDataPtr()->getElementTypes(); + Py::List list; + for (auto it : types) { + list.append(Py::String(it)); + } + return Py::new_reference_to(list); +} + +PyObject* ComplexGeoDataPy::countSubElements(PyObject *args) +{ + char *type; + if (!PyArg_ParseTuple(args, "s", &type)) + return nullptr; + + try { + unsigned long count = getComplexGeoDataPtr()->countSubElements(type); + return Py::new_reference_to(Py::Long(count)); + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to count sub-elements from object"); + return nullptr; + } +} + +PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args) { char *type; int index; if (!PyArg_ParseTuple(args, "si", &type, &index)) - return 0; + return nullptr; std::vector points; std::vector normals; std::vector facets; try { - Data::Segment* segm = getComplexGeoDataPtr()->getSubElement(type, index); - getComplexGeoDataPtr()->getFacesFromSubelement(segm, points, normals, facets); - delete segm; + std::unique_ptr segm(getComplexGeoDataPtr()->getSubElement(type, index)); + getComplexGeoDataPtr()->getFacesFromSubelement(segm.get(), points, normals, facets); } catch (...) { PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object"); - return 0; + return nullptr; } Py::Tuple tuple(2); @@ -82,17 +113,214 @@ PyObject* ComplexGeoDataPy::getFacesFromSubelement(PyObject *args) return Py::new_reference_to(tuple); } -Py::Object ComplexGeoDataPy::getBoundBox(void) const +PyObject* ComplexGeoDataPy::getLinesFromSubelement(PyObject *args) +{ + char *type; + int index; + if (!PyArg_ParseTuple(args, "si", &type, &index)) + return nullptr; + + std::vector points; + std::vector lines; + try { + std::unique_ptr segm(getComplexGeoDataPtr()->getSubElement(type, index)); + getComplexGeoDataPtr()->getLinesFromSubelement(segm.get(), points, lines); + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object"); + return nullptr; + } + + Py::Tuple tuple(2); + Py::List vertex; + for (std::vector::const_iterator it = points.begin(); + it != points.end(); ++it) + vertex.append(Py::asObject(new Base::VectorPy(*it))); + tuple.setItem(0, vertex); + Py::List line; + for (std::vector::const_iterator + it = lines.begin(); it != lines.end(); ++it) { + Py::Tuple l(2); + l.setItem(0,Py::Int((int)it->I1)); + l.setItem(1,Py::Int((int)it->I2)); + line.append(l); + } + tuple.setItem(1, line); + return Py::new_reference_to(tuple); +} + +PyObject* ComplexGeoDataPy::getPoints(PyObject *args) +{ + double accuracy = 0.05; + if (!PyArg_ParseTuple(args, "d", &accuracy)) + return nullptr; + + std::vector points; + std::vector normals; + try { + getComplexGeoDataPtr()->getPoints(points, normals, accuracy); + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object"); + return nullptr; + } + + Py::Tuple tuple(2); + Py::List vertex; + for (std::vector::const_iterator it = points.begin(); + it != points.end(); ++it) { + vertex.append(Py::asObject(new Base::VectorPy(*it))); + } + tuple.setItem(0, vertex); + + Py::List normal; + for (std::vector::const_iterator it = normals.begin(); + it != normals.end(); ++it) { + vertex.append(Py::asObject(new Base::VectorPy(*it))); + } + tuple.setItem(1, normal); + return Py::new_reference_to(tuple); +} + +PyObject* ComplexGeoDataPy::getLines(PyObject *args) +{ + double accuracy = 0.05; + if (!PyArg_ParseTuple(args, "d", &accuracy)) + return nullptr; + + std::vector points; + std::vector lines; + try { + getComplexGeoDataPtr()->getLines(points, lines, accuracy); + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object"); + return nullptr; + } + + Py::Tuple tuple(2); + Py::List vertex; + for (std::vector::const_iterator it = points.begin(); + it != points.end(); ++it) + vertex.append(Py::asObject(new Base::VectorPy(*it))); + tuple.setItem(0, vertex); + Py::List line; + for (std::vector::const_iterator + it = lines.begin(); it != lines.end(); ++it) { + Py::Tuple l(2); + l.setItem(0,Py::Int((int)it->I1)); + l.setItem(1,Py::Int((int)it->I2)); + line.append(l); + } + tuple.setItem(1, line); + return Py::new_reference_to(tuple); +} + +PyObject* ComplexGeoDataPy::getFaces(PyObject *args) +{ + double accuracy = 0.05; + if (!PyArg_ParseTuple(args, "d", &accuracy)) + return nullptr; + + std::vector points; + std::vector facets; + try { + getComplexGeoDataPtr()->getFaces(points, facets, accuracy); + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object"); + return nullptr; + } + + Py::Tuple tuple(2); + Py::List vertex; + for (std::vector::const_iterator it = points.begin(); + it != points.end(); ++it) + vertex.append(Py::asObject(new Base::VectorPy(*it))); + tuple.setItem(0, vertex); + Py::List facet; + for (std::vector::const_iterator + it = facets.begin(); it != facets.end(); ++it) { + Py::Tuple f(3); + f.setItem(0,Py::Int((int)it->I1)); + f.setItem(1,Py::Int((int)it->I2)); + f.setItem(2,Py::Int((int)it->I3)); + facet.append(f); + } + tuple.setItem(1, facet); + return Py::new_reference_to(tuple); +} + +PyObject* ComplexGeoDataPy::applyTranslation(PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type),&obj)) + return nullptr; + + try { + Base::Vector3d move = static_cast(obj)->value(); + getComplexGeoDataPtr()->applyTranslation(move); + Py_Return; + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to apply rotation"); + return nullptr; + } +} + +PyObject* ComplexGeoDataPy::applyRotation(PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O!", &(Base::RotationPy::Type),&obj)) + return nullptr; + + try { + Base::Rotation rot = static_cast(obj)->value(); + getComplexGeoDataPtr()->applyRotation(rot); + Py_Return; + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to apply rotation"); + return nullptr; + } +} + +PyObject* ComplexGeoDataPy::transformGeometry(PyObject *args) +{ + PyObject *obj; + if (!PyArg_ParseTuple(args, "O!", &(Base::MatrixPy::Type),&obj)) + return nullptr; + + try { + Base::Matrix4D mat = static_cast(obj)->value(); + getComplexGeoDataPtr()->transformGeometry(mat); + Py_Return; + } + catch (...) { + PyErr_SetString(PyExc_RuntimeError, "failed to transform geometry"); + return nullptr; + } +} + +Py::Object ComplexGeoDataPy::getBoundBox() const { return Py::BoundingBox(getComplexGeoDataPtr()->getBoundBox()); } +Py::Object ComplexGeoDataPy::getCenterOfGravity() const +{ + Base::Vector3d center; + if (getComplexGeoDataPtr()->getCenterOfGravity(center)) + return Py::Vector(center); + throw Py::RuntimeError("Cannot get center of gravity"); +} + Py::Object ComplexGeoDataPy::getPlacement(void) const { return Py::Placement(getComplexGeoDataPtr()->getPlacement()); } -void ComplexGeoDataPy::setPlacement(Py::Object arg) +void ComplexGeoDataPy::setPlacement(Py::Object arg) { PyObject* p = arg.ptr(); if (PyObject_TypeCheck(p, &(Base::PlacementPy::Type))) { @@ -112,7 +340,7 @@ Py::Object ComplexGeoDataPy::getMatrix(void) const } // FIXME would be better to call it setTransform() as in all other interfaces... -void ComplexGeoDataPy::setMatrix(Py::Object arg) +void ComplexGeoDataPy::setMatrix(Py::Object arg) { PyObject* p = arg.ptr(); if (PyObject_TypeCheck(p, &(Base::MatrixPy::Type))) {