diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index cd47b69968..56f5886933 100644 --- a/src/Mod/Part/App/AppPart.cpp +++ b/src/Mod/Part/App/AppPart.cpp @@ -101,6 +101,7 @@ #include #include #include +#include #include #include #include @@ -345,6 +346,7 @@ PyMOD_INIT_FUNC(Part) // ShapeFix sub-module PyObject* shapeFix(module.getAttr("ShapeFix").ptr()); Base::Interpreter().addType(&Part::ShapeFix_RootPy::Type, shapeFix, "Root"); + Base::Interpreter().addType(&Part::ShapeFix_EdgePy::Type, shapeFix, "Edge"); Base::Interpreter().addType(&Part::ShapeFix_FacePy::Type, shapeFix, "Face"); Base::Interpreter().addType(&Part::ShapeFix_ShapePy::Type, shapeFix, "Shape"); Base::Interpreter().addType(&Part::ShapeFix_ShellPy::Type, shapeFix, "Shell"); diff --git a/src/Mod/Part/App/CMakeLists.txt b/src/Mod/Part/App/CMakeLists.txt index 29a3a2fc9c..60bef7cbfc 100644 --- a/src/Mod/Part/App/CMakeLists.txt +++ b/src/Mod/Part/App/CMakeLists.txt @@ -137,6 +137,7 @@ generate_from_xml(HLRBRep/HLRBRep_PolyAlgoPy) generate_from_xml(HLRBRep/PolyHLRToShapePy) generate_from_xml(ShapeFix/ShapeFix_RootPy) +generate_from_xml(ShapeFix/ShapeFix_EdgePy) generate_from_xml(ShapeFix/ShapeFix_FacePy) generate_from_xml(ShapeFix/ShapeFix_ShapePy) generate_from_xml(ShapeFix/ShapeFix_ShellPy) @@ -428,6 +429,8 @@ SOURCE_GROUP("HLRBRep" FILES ${HLRBRepPy_SRCS}) SET(ShapeFixPy_SRCS ShapeFix/ShapeFix_RootPy.xml ShapeFix/ShapeFix_RootPyImp.cpp + ShapeFix/ShapeFix_EdgePy.xml + ShapeFix/ShapeFix_EdgePyImp.cpp ShapeFix/ShapeFix_FacePy.xml ShapeFix/ShapeFix_FacePyImp.cpp ShapeFix/ShapeFix_ShapePy.xml diff --git a/src/Mod/Part/App/ShapeFix/ShapeFix_EdgePy.xml b/src/Mod/Part/App/ShapeFix/ShapeFix_EdgePy.xml new file mode 100644 index 0000000000..0c36a92bab --- /dev/null +++ b/src/Mod/Part/App/ShapeFix/ShapeFix_EdgePy.xml @@ -0,0 +1,65 @@ + + + + + + Fixing invalid edge + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +private: + Handle(ShapeFix_Edge) hEdge; + +public: + void setHandle(Handle(ShapeFix_Edge) handle) { + setTwinPointer(handle.get()); + hEdge = handle; + } + + + diff --git a/src/Mod/Part/App/ShapeFix/ShapeFix_EdgePyImp.cpp b/src/Mod/Part/App/ShapeFix/ShapeFix_EdgePyImp.cpp new file mode 100644 index 0000000000..aa3223b598 --- /dev/null +++ b/src/Mod/Part/App/ShapeFix/ShapeFix_EdgePyImp.cpp @@ -0,0 +1,250 @@ +/*************************************************************************** + * Copyright (c) 2022 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +#endif + +#include "ShapeFix/ShapeFix_EdgePy.h" +#include "ShapeFix/ShapeFix_EdgePy.cpp" +#include +#include +#include +#include +#include "Tools.h" + +using namespace Part; + +// returns a string which represents the object e.g. when printed in python +std::string ShapeFix_EdgePy::representation() const +{ + return ""; +} + +PyObject *ShapeFix_EdgePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +{ + // create a new instance of ShapeFix_EdgePy + return new ShapeFix_EdgePy(nullptr); +} + +// constructor method +int ShapeFix_EdgePy::PyInit(PyObject* args, PyObject* /*kwds*/) +{ + if (!PyArg_ParseTuple(args, "")) + return -1; + + setHandle(new ShapeFix_Edge); + return 0; +} + +PyObject* ShapeFix_EdgePy::fixRemovePCurve(PyObject *args) +{ + PyObject* edge; + PyObject* face; + if (PyArg_ParseTuple(args, "O!O!", &TopoShapeEdgePy::Type, &edge, + &TopoShapeFacePy::Type, &face)) { + TopoDS_Shape e = static_cast(edge)->getTopoShapePtr()->getShape(); + TopoDS_Shape f = static_cast(face)->getTopoShapePtr()->getShape(); + + bool ok = getShapeFix_EdgePtr()->FixRemovePCurve(TopoDS::Edge(e), TopoDS::Face(f)); + return Py::new_reference_to(Py::Boolean(ok)); + } + + PyErr_Clear(); + PyObject* plm; + if (PyArg_ParseTuple(args, "O!O!O!", &TopoShapeEdgePy::Type, &edge, + &GeometrySurfacePy::Type, &face, + &Base::PlacementPy::Type, &plm)) { + TopoDS_Shape e = static_cast(edge)->getTopoShapePtr()->getShape(); + Handle(Geom_Surface) surf = Handle(Geom_Surface)::DownCast(static_cast(face)->getGeometryPtr()->handle()); + Base::Placement* pm = static_cast(plm)->getPlacementPtr(); + TopLoc_Location loc = Tools::fromPlacement(*pm); + + bool ok = getShapeFix_EdgePtr()->FixRemovePCurve(TopoDS::Edge(e), surf, loc); + return Py::new_reference_to(Py::Boolean(ok)); + } + + PyErr_SetString(PyExc_TypeError, "Arguments must be:\n" + "-- fixRemovePCurve(edge, face) or\n" + "-- fixRemovePCurve(edge, surface, placement)"); + return nullptr; +} + +PyObject* ShapeFix_EdgePy::fixRemoveCurve3d(PyObject *args) +{ + PyObject* edge; + if (!PyArg_ParseTuple(args, "O!", &TopoShapeEdgePy::Type, &edge)) + return nullptr; + + TopoDS_Shape e = static_cast(edge)->getTopoShapePtr()->getShape(); + bool ok = getShapeFix_EdgePtr()->FixRemoveCurve3d(TopoDS::Edge(e)); + return Py::new_reference_to(Py::Boolean(ok)); +} + +PyObject* ShapeFix_EdgePy::fixAddPCurve(PyObject *args) +{ + PyObject* edge; + PyObject* face; + PyObject* seam; + double prec = 0.0; + if (PyArg_ParseTuple(args, "O!O!O!|d", &TopoShapeEdgePy::Type, &edge, + &TopoShapeFacePy::Type, &face, + &PyBool_Type, &seam, &prec)) { + TopoDS_Shape e = static_cast(edge)->getTopoShapePtr()->getShape(); + TopoDS_Shape f = static_cast(face)->getTopoShapePtr()->getShape(); + + bool ok = getShapeFix_EdgePtr()->FixAddPCurve(TopoDS::Edge(e), TopoDS::Face(f), + PyObject_IsTrue(seam) ? Standard_True : Standard_False, + prec); + return Py::new_reference_to(Py::Boolean(ok)); + } + + PyErr_Clear(); + PyObject* plm; + if (PyArg_ParseTuple(args, "O!O!O!O!|d", &TopoShapeEdgePy::Type, &edge, + &GeometrySurfacePy::Type, &face, + &Base::PlacementPy::Type, &plm, + &PyBool_Type, &seam, &prec)) { + TopoDS_Shape e = static_cast(edge)->getTopoShapePtr()->getShape(); + Handle(Geom_Surface) surf = Handle(Geom_Surface)::DownCast(static_cast(face)->getGeometryPtr()->handle()); + Base::Placement* pm = static_cast(plm)->getPlacementPtr(); + TopLoc_Location loc = Tools::fromPlacement(*pm); + + bool ok = getShapeFix_EdgePtr()->FixAddPCurve(TopoDS::Edge(e), surf, loc, + PyObject_IsTrue(seam) ? Standard_True : Standard_False, + prec); + return Py::new_reference_to(Py::Boolean(ok)); + } + + PyErr_SetString(PyExc_TypeError, "Arguments must be:\n" + "-- fixAddPCurve(edge, face, isSeam, prec) or\n" + "-- fixAddPCurve(edge, surface, placement, isSeam, prec)"); + return nullptr; +} + +PyObject* ShapeFix_EdgePy::fixAddCurve3d(PyObject *args) +{ + PyObject* edge; + if (!PyArg_ParseTuple(args, "O!", &TopoShapeEdgePy::Type, &edge)) + return nullptr; + + TopoDS_Shape e = static_cast(edge)->getTopoShapePtr()->getShape(); + bool ok = getShapeFix_EdgePtr()->FixAddCurve3d(TopoDS::Edge(e)); + return Py::new_reference_to(Py::Boolean(ok)); +} + +PyObject* ShapeFix_EdgePy::fixVertexTolerance(PyObject *args) +{ + PyObject* edge; + PyObject* face = nullptr; + if (!PyArg_ParseTuple(args, "O!|O!", &TopoShapeEdgePy::Type, &edge, + &TopoShapeFacePy::Type, &face)) + return nullptr; + + TopoDS_Shape e = static_cast(edge)->getTopoShapePtr()->getShape(); + + if (face) { + TopoDS_Shape f = static_cast(face)->getTopoShapePtr()->getShape(); + bool ok = getShapeFix_EdgePtr()->FixVertexTolerance(TopoDS::Edge(e), TopoDS::Face(f)); + return Py::new_reference_to(Py::Boolean(ok)); + } + else { + bool ok = getShapeFix_EdgePtr()->FixVertexTolerance(TopoDS::Edge(e)); + return Py::new_reference_to(Py::Boolean(ok)); + } +} + +PyObject* ShapeFix_EdgePy::fixReversed2d(PyObject *args) +{ + PyObject* edge; + PyObject* face; + if (PyArg_ParseTuple(args, "O!O!", &TopoShapeEdgePy::Type, &edge, + &TopoShapeFacePy::Type, &face)) { + TopoDS_Shape e = static_cast(edge)->getTopoShapePtr()->getShape(); + TopoDS_Shape f = static_cast(face)->getTopoShapePtr()->getShape(); + + bool ok = getShapeFix_EdgePtr()->FixReversed2d(TopoDS::Edge(e), TopoDS::Face(f)); + return Py::new_reference_to(Py::Boolean(ok)); + } + + PyErr_Clear(); + PyObject* plm; + if (PyArg_ParseTuple(args, "O!O!O!", &TopoShapeEdgePy::Type, &edge, + &GeometrySurfacePy::Type, &face, + &Base::PlacementPy::Type, &plm)) { + TopoDS_Shape e = static_cast(edge)->getTopoShapePtr()->getShape(); + Handle(Geom_Surface) surf = Handle(Geom_Surface)::DownCast(static_cast(face)->getGeometryPtr()->handle()); + Base::Placement* pm = static_cast(plm)->getPlacementPtr(); + TopLoc_Location loc = Tools::fromPlacement(*pm); + + bool ok = getShapeFix_EdgePtr()->FixReversed2d(TopoDS::Edge(e), surf, loc); + return Py::new_reference_to(Py::Boolean(ok)); + } + + PyErr_SetString(PyExc_TypeError, "Arguments must be:\n" + "-- FixReversed2d(edge, face) or\n" + "-- FixReversed2d(edge, surface, placement)"); + return nullptr; +} + +PyObject* ShapeFix_EdgePy::fixSameParameter(PyObject *args) +{ + PyObject* edge; + double tolerance = 0.0; + if (PyArg_ParseTuple(args, "O!|d", &TopoShapeEdgePy::Type, &edge, &tolerance)) { + TopoDS_Shape e = static_cast(edge)->getTopoShapePtr()->getShape(); + + bool ok = getShapeFix_EdgePtr()->FixSameParameter(TopoDS::Edge(e), tolerance); + return Py::new_reference_to(Py::Boolean(ok)); + } + + PyErr_Clear(); + PyObject* face; + if (PyArg_ParseTuple(args, "O!O!|d", &TopoShapeEdgePy::Type, &edge, + &TopoShapeFacePy::Type, &face, + &tolerance)) { + TopoDS_Shape e = static_cast(edge)->getTopoShapePtr()->getShape(); + TopoDS_Shape f = static_cast(face)->getTopoShapePtr()->getShape(); + + bool ok = getShapeFix_EdgePtr()->FixSameParameter(TopoDS::Edge(e), TopoDS::Face(f), tolerance); + return Py::new_reference_to(Py::Boolean(ok)); + } + + PyErr_SetString(PyExc_TypeError, "Arguments must be:\n" + "-- fixSameParameter(edge, tolerance) or\n" + "-- fixSameParameter(edge, face, tolerance)"); + return nullptr; +} + +PyObject *ShapeFix_EdgePy::getCustomAttributes(const char* /*attr*/) const +{ + return nullptr; +} + +int ShapeFix_EdgePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} diff --git a/src/Mod/Part/App/ShapeFix/ShapeFix_ShapePyImp.cpp b/src/Mod/Part/App/ShapeFix/ShapeFix_ShapePyImp.cpp index 701384e803..b15e513c5f 100644 --- a/src/Mod/Part/App/ShapeFix/ShapeFix_ShapePyImp.cpp +++ b/src/Mod/Part/App/ShapeFix/ShapeFix_ShapePyImp.cpp @@ -28,7 +28,7 @@ #include "ShapeFix/ShapeFix_ShapePy.h" #include "ShapeFix/ShapeFix_ShapePy.cpp" -//#include "ShapeFix/ShapeFix_EdgePy.h" +#include "ShapeFix/ShapeFix_EdgePy.h" #include "ShapeFix/ShapeFix_WirePy.h" #include "ShapeFix/ShapeFix_FacePy.h" #include "ShapeFix/ShapeFix_ShellPy.h" @@ -139,8 +139,10 @@ PyObject* ShapeFix_ShapePy::fixEdgeTool(PyObject *args) if (!PyArg_ParseTuple(args, "")) return nullptr; - //Handle(ShapeFix_Edge) tool = getShapeFix_ShapePtr()->FixEdgeTool(); - Py_Return; + Handle(ShapeFix_Edge) tool = getShapeFix_ShapePtr()->FixEdgeTool(); + ShapeFix_EdgePy* edge = new ShapeFix_EdgePy(nullptr); + edge->setHandle(tool); + return edge; } Py::Boolean ShapeFix_ShapePy::getFixSolidMode() const diff --git a/src/Mod/Part/App/ShapeFix/ShapeFix_WirePyImp.cpp b/src/Mod/Part/App/ShapeFix/ShapeFix_WirePyImp.cpp index 70676981ce..c7572f4bc4 100644 --- a/src/Mod/Part/App/ShapeFix/ShapeFix_WirePyImp.cpp +++ b/src/Mod/Part/App/ShapeFix/ShapeFix_WirePyImp.cpp @@ -23,18 +23,19 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include # include # include #endif #include "ShapeFix/ShapeFix_WirePy.h" #include "ShapeFix/ShapeFix_WirePy.cpp" +#include "ShapeFix/ShapeFix_EdgePy.h" #include #include #include #include #include "OCCError.h" +#include "Tools.h" using namespace Part; @@ -100,8 +101,10 @@ PyObject* ShapeFix_WirePy::fixEdgeTool(PyObject *args) if (!PyArg_ParseTuple(args, "")) return nullptr; - //Handle(ShapeFix_Edge) tool = getShapeFix_WirePtr()->FixEdgeTool(); - Py_Return; + Handle(ShapeFix_Edge) tool = getShapeFix_WirePtr()->FixEdgeTool(); + ShapeFix_EdgePy* edge = new ShapeFix_EdgePy(nullptr); + edge->setHandle(tool); + return edge; } PyObject* ShapeFix_WirePy::clearModes(PyObject *args) @@ -155,15 +158,7 @@ PyObject* ShapeFix_WirePy::setSurface(PyObject *args) Handle(Geom_Surface) surf = Handle(Geom_Surface)::DownCast(static_cast(surface)->getGeomSurfacePtr()->handle()); if (plm) { Base::Placement* pm = static_cast(plm)->getPlacementPtr(); - Base::Rotation r = pm->getRotation(); - double q1, q2, q3, q4; - r.getValue(q1, q2, q3, q4); - Base::Vector3d t = pm->getPosition(); - - gp_Trsf trf; - trf.SetTranslation(gp_Vec(t.x, t.y, t.z)); - trf.SetRotation(gp_Quaternion(q1, q2, q3, q4)); - TopLoc_Location loc(trf); + TopLoc_Location loc = Tools::fromPlacement(*pm); getShapeFix_WirePtr()->SetSurface(surf, loc); } else { diff --git a/src/Mod/Part/TestPartApp.py b/src/Mod/Part/TestPartApp.py index 96ac8ce212..da7fe3b430 100644 --- a/src/Mod/Part/TestPartApp.py +++ b/src/Mod/Part/TestPartApp.py @@ -454,6 +454,43 @@ class PartTestShapeFix(unittest.TestCase): fix.perform() + def testShapeFix_Edge(self): + surface = Part.Plane() + face = surface.toShape(-1, 1, -1, 1) + + with self.assertRaises(TypeError): + Part.ShapeFix.Edge([]) + + wirefix = Part.ShapeFix.Wire(face.OuterWire, face, 1e-7) + fix = wirefix.fixEdgeTool() + print (fix) + + fix.fixRemovePCurve(face.Edge1, face) + fix.fixRemovePCurve(face.Edge1, face.Surface, face.Placement) + with self.assertRaises(TypeError): + fix.fixRemovePCurve(face) + + fix.fixRemoveCurve3d(face.Edge1) + fix.fixAddCurve3d(face.Edge1) + + fix.fixAddPCurve(face.Edge1, face, False) + fix.fixAddPCurve(face.Edge1, face.Surface, face.Placement, False) + with self.assertRaises(TypeError): + fix.fixAddPCurve(face) + + fix.fixVertexTolerance(face.Edge1) + fix.fixVertexTolerance(face.Edge1, face) + + fix.fixReversed2d(face.Edge1, face) + fix.fixReversed2d(face.Edge1, face.Surface, face.Placement) + with self.assertRaises(TypeError): + fix.fixReversed2d(face) + + fix.fixSameParameter(face.Edge1) + fix.fixSameParameter(face.Edge1, face) + with self.assertRaises(TypeError): + fix.fixSameParameter(face) + def testShapeFix_Face(self): surface = Part.Plane() face = surface.toShape(-1, 1, -1, 1)