From 5018af974cb92f7e683c98de09429e90b29b19ce Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 30 Nov 2021 18:17:29 +0100 Subject: [PATCH 1/4] Part: implement Part.Wire.makeEvolved and Part.Face.makeEvolved --- src/Mod/Part/App/TopoShapeFacePy.xml | 5 +++ src/Mod/Part/App/TopoShapeFacePyImp.cpp | 58 +++++++++++++++++++++++++ src/Mod/Part/App/TopoShapeWirePy.xml | 5 +++ src/Mod/Part/App/TopoShapeWirePyImp.cpp | 54 +++++++++++++++++++++++ 4 files changed, 122 insertions(+) diff --git a/src/Mod/Part/App/TopoShapeFacePy.xml b/src/Mod/Part/App/TopoShapeFacePy.xml index c3809f047f..cc6c1655f6 100644 --- a/src/Mod/Part/App/TopoShapeFacePy.xml +++ b/src/Mod/Part/App/TopoShapeFacePy.xml @@ -30,6 +30,11 @@ Returns Compound of Wires. Deprecated - use makeOffset2D instead. + + + Profile along the spine + + Get the list of (u,v) nodes of the tessellation diff --git a/src/Mod/Part/App/TopoShapeFacePyImp.cpp b/src/Mod/Part/App/TopoShapeFacePyImp.cpp index 63e8bead74..fba5f73879 100644 --- a/src/Mod/Part/App/TopoShapeFacePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeFacePyImp.cpp @@ -70,6 +70,7 @@ # include # include #endif // _PreComp +#include #include #include @@ -99,6 +100,10 @@ using namespace Part; +namespace Part { + extern Py::Object shape2pyshape(const TopoDS_Shape &shape); +} + // returns a string which represent the object e.g. when printed in python std::string TopoShapeFacePy::representation(void) const { @@ -438,6 +443,59 @@ PyObject* TopoShapeFacePy::makeOffset(PyObject *args) return new TopoShapePy(new TopoShape(mkOffset.Shape())); } +/* +v = App.Vector +profile = Part.makePolygon([v(0.,0.,0.), v(-60.,-60.,-100.), v(-60.,-60.,-140.)]) +spine = Part.Face(Part.makePolygon([v(0.,0.,0.), v(100.,0.,0.), v(100.,100.,0.), v(0.,100.,0.), v(0.,0.,0.)])) +evolve = spine.makeEvolved(profile) +*/ +PyObject* TopoShapeFacePy::makeEvolved(PyObject *args, PyObject *kwds) +{ + PyObject* Profile; + PyObject* AxeProf = Py_True; + PyObject* Solid = Py_False; + PyObject* ProfOnSpine = Py_False; + int JoinType = int(GeomAbs_Arc); + double Tolerance = 0.0000001; + + static char* kwds_evolve[] = {"Profile", "Join", "AxeProf", "Solid", "ProfOnSpine", "Tolerance", nullptr}; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|iO!O!O!d", kwds_evolve, + &TopoShapeWirePy::Type, &Profile, &JoinType, + &PyBool_Type, &AxeProf, &PyBool_Type, &Solid, + &PyBool_Type, &ProfOnSpine, &Tolerance)) + return nullptr; + + const TopoDS_Face& spine = TopoDS::Face(getTopoShapePtr()->getShape()); + BRepBuilderAPI_FindPlane findPlane(spine); + if (!findPlane.Found()) { + PyErr_SetString(PartExceptionOCCError, "No planar face"); + return nullptr; + } + + const TopoDS_Wire& profile = TopoDS::Wire(static_cast(Profile)->getTopoShapePtr()->getShape()); + + GeomAbs_JoinType joinType; + switch (JoinType) { + case GeomAbs_Tangent: + joinType = GeomAbs_Tangent; + break; + case GeomAbs_Intersection: + joinType = GeomAbs_Intersection; + break; + default: + joinType = GeomAbs_Arc; + break; + } + + BRepOffsetAPI_MakeEvolved evolved(spine, profile, joinType, + PyObject_IsTrue(AxeProf) ? Standard_True : Standard_False, + PyObject_IsTrue(Solid) ? Standard_True : Standard_False, + PyObject_IsTrue(ProfOnSpine) ? Standard_True : Standard_False, + Tolerance); + TopoDS_Shape shape = evolved.Shape(); + return Py::new_reference_to(shape2pyshape(shape)); +} + PyObject* TopoShapeFacePy::valueAt(PyObject *args) { double u,v; diff --git a/src/Mod/Part/App/TopoShapeWirePy.xml b/src/Mod/Part/App/TopoShapeWirePy.xml index ab033e2064..04959c1d03 100644 --- a/src/Mod/Part/App/TopoShapeWirePy.xml +++ b/src/Mod/Part/App/TopoShapeWirePy.xml @@ -58,6 +58,11 @@ Transition can be 0 (default), 1 (right corners) or 2 (rounded corners). + + + Profile along the spine + + Approximate B-Spline-curve from this wire diff --git a/src/Mod/Part/App/TopoShapeWirePyImp.cpp b/src/Mod/Part/App/TopoShapeWirePyImp.cpp index a1f32d6d03..f00f3e2e7c 100644 --- a/src/Mod/Part/App/TopoShapeWirePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeWirePyImp.cpp @@ -45,6 +45,7 @@ # include # include #endif +#include #include #include @@ -307,6 +308,59 @@ PyObject* TopoShapeWirePy::makePipeShell(PyObject *args) return 0; } +/* +v = App.Vector +profile = Part.makePolygon([v(0.,0.,0.), v(-60.,-60.,-100.), v(-60.,-60.,-140.)]) +spine = Part.makePolygon([v(0.,0.,0.), v(100.,0.,0.), v(100.,100.,0.), v(0.,100.,0.), v(0.,0.,0.)]) +evolve = spine.makeEvolved(profile) +*/ +PyObject* TopoShapeWirePy::makeEvolved(PyObject *args, PyObject *kwds) +{ + PyObject* Profile; + PyObject* AxeProf = Py_True; + PyObject* Solid = Py_False; + PyObject* ProfOnSpine = Py_False; + int JoinType = int(GeomAbs_Arc); + double Tolerance = 0.0000001; + + static char* kwds_evolve[] = {"Profile", "Join", "AxeProf", "Solid", "ProfOnSpine", "Tolerance", nullptr}; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|iO!O!O!d", kwds_evolve, + &TopoShapeWirePy::Type, &Profile, &JoinType, + &PyBool_Type, &AxeProf, &PyBool_Type, &Solid, + &PyBool_Type, &ProfOnSpine, &Tolerance)) + return nullptr; + + const TopoDS_Wire& spine = TopoDS::Wire(getTopoShapePtr()->getShape()); + BRepBuilderAPI_FindPlane findPlane(spine); + if (!findPlane.Found()) { + PyErr_SetString(PartExceptionOCCError, "No planar wire"); + return nullptr; + } + + const TopoDS_Wire& profile = TopoDS::Wire(static_cast(Profile)->getTopoShapePtr()->getShape()); + + GeomAbs_JoinType joinType; + switch (JoinType) { + case GeomAbs_Tangent: + joinType = GeomAbs_Tangent; + break; + case GeomAbs_Intersection: + joinType = GeomAbs_Intersection; + break; + default: + joinType = GeomAbs_Arc; + break; + } + + BRepOffsetAPI_MakeEvolved evolved(spine, profile, joinType, + PyObject_IsTrue(AxeProf) ? Standard_True : Standard_False, + PyObject_IsTrue(Solid) ? Standard_True : Standard_False, + PyObject_IsTrue(ProfOnSpine) ? Standard_True : Standard_False, + Tolerance); + TopoDS_Shape shape = evolved.Shape(); + return Py::new_reference_to(shape2pyshape(shape)); +} + PyObject* TopoShapeWirePy::makeHomogenousWires(PyObject *args) { PyObject* wire; From edf5d13de6da0c38fc369495d871f471ca069711 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 30 Nov 2021 20:03:26 +0100 Subject: [PATCH 2/4] Part: add module with enums --- src/Mod/Part/CMakeLists.txt | 1 + src/Mod/Part/PartEnums.py | 65 +++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/Mod/Part/PartEnums.py diff --git a/src/Mod/Part/CMakeLists.txt b/src/Mod/Part/CMakeLists.txt index e231288c21..8497099ca8 100644 --- a/src/Mod/Part/CMakeLists.txt +++ b/src/Mod/Part/CMakeLists.txt @@ -8,6 +8,7 @@ set(Part_Scripts Init.py JoinFeatures.py MakeBottle.py + PartEnums.py TestPartApp.py ) diff --git a/src/Mod/Part/PartEnums.py b/src/Mod/Part/PartEnums.py new file mode 100644 index 0000000000..dbd983c908 --- /dev/null +++ b/src/Mod/Part/PartEnums.py @@ -0,0 +1,65 @@ +# *************************************************************************** +# * * +# * Copyright (c) 2021 Werner Mayer * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program 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 program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "PartEnums module" +__author__ = "Werner Mayer" +__url__ = "http://www.freecadweb.org" +__doc__ = "Enum types" + +from enum import IntEnum + +class JoinType(IntEnum): + Arc = 0 + Tangent = 1 + Intersection = 2 + +class Shape(IntEnum): + C0 = 0 + G1 = 1 + C1 = 2 + G2 = 3 + C2 = 4 + C3 = 5 + CN = 6 + +class FillingStyle(IntEnum): + StretchStyle = 0 + CoonsStyle = 1 + CurvedStyle = 2 + +class Orientation(IntEnum): + FORWARD = 0 + REVERSED = 1 + INTERNAL = 2 + EXTERNAL = 3 + +class ShapeEnum(IntEnum): + COMPOUND = 0 + COMPSOLID = 1 + SOLID = 2 + SHELL= 3 + FACE = 4 + WIRE = 5 + EDGE = 6 + VERTEX = 7 + SHAPE = 8 + From a05cd50fa5a2a9363ef4f4d4b83b71e2ae061888 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 30 Nov 2021 20:04:31 +0100 Subject: [PATCH 3/4] Part: add exception handling to Face.makeEvolved/Wire.makeEvolved --- src/Mod/Part/App/TopoShapeFacePyImp.cpp | 23 +++++++++++++++-------- src/Mod/Part/App/TopoShapeWirePyImp.cpp | 23 +++++++++++++++-------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/Mod/Part/App/TopoShapeFacePyImp.cpp b/src/Mod/Part/App/TopoShapeFacePyImp.cpp index fba5f73879..089857d117 100644 --- a/src/Mod/Part/App/TopoShapeFacePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeFacePyImp.cpp @@ -444,10 +444,11 @@ PyObject* TopoShapeFacePy::makeOffset(PyObject *args) } /* +import PartEnums v = App.Vector profile = Part.makePolygon([v(0.,0.,0.), v(-60.,-60.,-100.), v(-60.,-60.,-140.)]) spine = Part.Face(Part.makePolygon([v(0.,0.,0.), v(100.,0.,0.), v(100.,100.,0.), v(0.,100.,0.), v(0.,0.,0.)])) -evolve = spine.makeEvolved(profile) +evolve = spine.makeEvolved(Profile=profile, Join=PartEnums.JoinType.Arc) */ PyObject* TopoShapeFacePy::makeEvolved(PyObject *args, PyObject *kwds) { @@ -487,13 +488,19 @@ PyObject* TopoShapeFacePy::makeEvolved(PyObject *args, PyObject *kwds) break; } - BRepOffsetAPI_MakeEvolved evolved(spine, profile, joinType, - PyObject_IsTrue(AxeProf) ? Standard_True : Standard_False, - PyObject_IsTrue(Solid) ? Standard_True : Standard_False, - PyObject_IsTrue(ProfOnSpine) ? Standard_True : Standard_False, - Tolerance); - TopoDS_Shape shape = evolved.Shape(); - return Py::new_reference_to(shape2pyshape(shape)); + try { + BRepOffsetAPI_MakeEvolved evolved(spine, profile, joinType, + PyObject_IsTrue(AxeProf) ? Standard_True : Standard_False, + PyObject_IsTrue(Solid) ? Standard_True : Standard_False, + PyObject_IsTrue(ProfOnSpine) ? Standard_True : Standard_False, + Tolerance); + TopoDS_Shape shape = evolved.Shape(); + return Py::new_reference_to(shape2pyshape(shape)); + } + catch (Standard_Failure& e) { + PyErr_SetString(PartExceptionOCCError, e.GetMessageString()); + return nullptr; + } } PyObject* TopoShapeFacePy::valueAt(PyObject *args) diff --git a/src/Mod/Part/App/TopoShapeWirePyImp.cpp b/src/Mod/Part/App/TopoShapeWirePyImp.cpp index f00f3e2e7c..c48b6046b0 100644 --- a/src/Mod/Part/App/TopoShapeWirePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeWirePyImp.cpp @@ -309,10 +309,11 @@ PyObject* TopoShapeWirePy::makePipeShell(PyObject *args) } /* +import PartEnums v = App.Vector profile = Part.makePolygon([v(0.,0.,0.), v(-60.,-60.,-100.), v(-60.,-60.,-140.)]) spine = Part.makePolygon([v(0.,0.,0.), v(100.,0.,0.), v(100.,100.,0.), v(0.,100.,0.), v(0.,0.,0.)]) -evolve = spine.makeEvolved(profile) +evolve = spine.makeEvolved(Profile=profile, Join=PartEnums.JoinType.Arc) */ PyObject* TopoShapeWirePy::makeEvolved(PyObject *args, PyObject *kwds) { @@ -352,13 +353,19 @@ PyObject* TopoShapeWirePy::makeEvolved(PyObject *args, PyObject *kwds) break; } - BRepOffsetAPI_MakeEvolved evolved(spine, profile, joinType, - PyObject_IsTrue(AxeProf) ? Standard_True : Standard_False, - PyObject_IsTrue(Solid) ? Standard_True : Standard_False, - PyObject_IsTrue(ProfOnSpine) ? Standard_True : Standard_False, - Tolerance); - TopoDS_Shape shape = evolved.Shape(); - return Py::new_reference_to(shape2pyshape(shape)); + try { + BRepOffsetAPI_MakeEvolved evolved(spine, profile, joinType, + PyObject_IsTrue(AxeProf) ? Standard_True : Standard_False, + PyObject_IsTrue(Solid) ? Standard_True : Standard_False, + PyObject_IsTrue(ProfOnSpine) ? Standard_True : Standard_False, + Tolerance); + TopoDS_Shape shape = evolved.Shape(); + return Py::new_reference_to(shape2pyshape(shape)); + } + catch (Standard_Failure& e) { + PyErr_SetString(PartExceptionOCCError, e.GetMessageString()); + return nullptr; + } } PyObject* TopoShapeWirePy::makeHomogenousWires(PyObject *args) From 770c7f6330403fb6d2882ea41e22940d6ffdfc6b Mon Sep 17 00:00:00 2001 From: Mark O'Donovan Date: Wed, 1 Dec 2021 03:31:34 +0000 Subject: [PATCH 4/4] Replace deprecated qt functions toList() & toSet() (#5213) * Replace deprecated qt functions toList() & toSet() QSet::toList() and QStringList::toSet() are both deprecated. * Add back support for qt < 5.14 --- src/Gui/DocumentRecovery.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Gui/DocumentRecovery.cpp b/src/Gui/DocumentRecovery.cpp index aea8bee3c4..9b3186733a 100644 --- a/src/Gui/DocumentRecovery.cpp +++ b/src/Gui/DocumentRecovery.cpp @@ -706,10 +706,17 @@ void DocumentRecoveryCleaner::clearDirectory(const QFileInfo& dir) void DocumentRecoveryCleaner::subtractFiles(QStringList& files) { if (!ignoreFiles.isEmpty() && !files.isEmpty()) { +#if QT_VERSION >= QT_VERSION_CHECK(5,14,0) + auto set1 = QSet(files.begin(), files.end()); + auto set2 = QSet(ignoreFiles.begin(), ignoreFiles.end()); + set1.subtract(set2); + files = QList(set1.begin(), set1.end()); +#else QSet set1 = files.toSet(); QSet set2 = ignoreFiles.toSet(); set1.subtract(set2); files = set1.toList(); +#endif } }