diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index 9f3cf265d4..d2b897c8cc 100644 --- a/src/Mod/Part/App/AppPart.cpp +++ b/src/Mod/Part/App/AppPart.cpp @@ -51,6 +51,7 @@ #include "Mod/Part/App/BRepOffsetAPI_MakePipeShellPy.h" #include "Mod/Part/App/BSplineCurvePy.h" #include "Mod/Part/App/BSplineSurfacePy.h" +#include #include "Mod/Part/App/CirclePy.h" #include "Mod/Part/App/ConePy.h" #include "Mod/Part/App/ConicPy.h" @@ -290,6 +291,7 @@ PyMOD_INIT_FUNC(Part) Base::Interpreter().addType(&Part::GeometryBoolExtensionPy ::Type,partModule,"GeometryBoolExtension"); Base::Interpreter().addType(&Part::GeometryDoubleExtensionPy ::Type,partModule,"GeometryDoubleExtension"); Base::Interpreter().addType(&Part::PrecisionPy ::Type,partModule,"Precision"); + Base::Interpreter().addType(&Part::ChFi2d_FilletAlgoPy::Type,partModule,"ChFi2d_FilletAlgo"); // BRepFeat package PyObject* brepfeatModule(module.getAttr("BRepFeat").ptr()); diff --git a/src/Mod/Part/App/CMakeLists.txt b/src/Mod/Part/App/CMakeLists.txt index 755f01c160..7e5782e6a0 100644 --- a/src/Mod/Part/App/CMakeLists.txt +++ b/src/Mod/Part/App/CMakeLists.txt @@ -91,6 +91,7 @@ generate_from_xml(TopoShapeVertexPy) generate_from_xml(TopoShapeWirePy) generate_from_xml(BRepOffsetAPI_MakePipeShellPy) generate_from_xml(BRepOffsetAPI_MakeFillingPy) +generate_from_xml(ChFi2d_FilletAlgoPy) generate_from_xml(PrecisionPy) # make sure to create the directory at configure time @@ -318,6 +319,8 @@ SET(Python_SRCS BRepOffsetAPI_MakePipeShellPyImp.cpp BRepOffsetAPI_MakeFillingPy.xml BRepOffsetAPI_MakeFillingPyImp.cpp + ChFi2d_FilletAlgoPy.xml + ChFi2d_FilletAlgoPyImp.cpp PrecisionPy.xml PrecisionPyImp.cpp PartPyCXX.cpp diff --git a/src/Mod/Part/App/ChFi2d_FilletAlgoPy.xml b/src/Mod/Part/App/ChFi2d_FilletAlgoPy.xml new file mode 100644 index 0000000000..864a54b41b --- /dev/null +++ b/src/Mod/Part/App/ChFi2d_FilletAlgoPy.xml @@ -0,0 +1,44 @@ + + + + + + Algorithm that creates fillet edge + + + + Initializes a fillet algorithm: accepts a wire consisting of two edges in a plane + + + + + perform(radius) -> bool + +Constructs a fillet edge + + + + + Returns number of possible solutions + + + + + result(point, solution=-1) + +Returns result (fillet edge, modified edge1, modified edge2) + + + + diff --git a/src/Mod/Part/App/ChFi2d_FilletAlgoPyImp.cpp b/src/Mod/Part/App/ChFi2d_FilletAlgoPyImp.cpp new file mode 100644 index 0000000000..0009ebab5d --- /dev/null +++ b/src/Mod/Part/App/ChFi2d_FilletAlgoPyImp.cpp @@ -0,0 +1,188 @@ +/*************************************************************************** + * 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 +# include +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include "Tools.h" + +using namespace Part; + + +PyObject *ChFi2d_FilletAlgoPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper +{ + // create a new instance of ChFi2d_FilletAlgoPy and the Twin object + return new ChFi2d_FilletAlgoPy(new ChFi2d_FilletAlgo); +} + +// constructor method +int ChFi2d_FilletAlgoPy::PyInit(PyObject* args, PyObject* /*kwd*/) +{ + if (PyArg_ParseTuple(args, "")) + return 0; + + PyErr_Clear(); + PyObject* wire; + PyObject* plane; + if (PyArg_ParseTuple(args, "O!O!", &TopoShapeWirePy::Type, &wire, &PlanePy::Type, &plane)) { + TopoDS_Shape shape = static_cast(wire)->getTopoShapePtr()->getShape(); + Handle(Geom_Plane) hPlane = Handle(Geom_Plane)::DownCast(static_cast(plane)->getGeomPlanePtr()->handle()); + getChFi2d_FilletAlgoPtr()->Init(TopoDS::Wire(shape), hPlane->Pln()); + return 0; + } + + PyErr_Clear(); + PyObject* edge1; + PyObject* edge2; + if (PyArg_ParseTuple(args, "O!O!O!", &TopoShapeEdgePy::Type, &edge1, + &TopoShapeEdgePy::Type, &edge2, + &PlanePy::Type, &plane)) { + TopoDS_Shape shape1 = static_cast(edge1)->getTopoShapePtr()->getShape(); + TopoDS_Shape shape2 = static_cast(edge2)->getTopoShapePtr()->getShape(); + Handle(Geom_Plane) hPlane = Handle(Geom_Plane)::DownCast(static_cast(plane)->getGeomPlanePtr()->handle()); + getChFi2d_FilletAlgoPtr()->Init(TopoDS::Edge(shape1), TopoDS::Edge(shape2), hPlane->Pln()); + return 0; + } + + PyErr_SetString(PyExc_TypeError, "Wrong arguments:\n" + "-- ChFi2d_FilletAlgo()\n" + "-- ChFi2d_FilletAlgo(wire, plane)" + "-- ChFi2d_FilletAlgo(edge, edge, plane)\n"); + return -1; +} + +// returns a string which represents the object e.g. when printed in python +std::string ChFi2d_FilletAlgoPy::representation() const +{ + return std::string(""); +} + +PyObject* ChFi2d_FilletAlgoPy::init(PyObject *args) +{ + PyObject* wire; + PyObject* plane; + if (PyArg_ParseTuple(args, "O!O!", &TopoShapeWirePy::Type, &wire, &PlanePy::Type, &plane)) { + TopoDS_Shape shape = static_cast(wire)->getTopoShapePtr()->getShape(); + Handle(Geom_Plane) hPlane = Handle(Geom_Plane)::DownCast(static_cast(plane)->getGeomPlanePtr()->handle()); + getChFi2d_FilletAlgoPtr()->Init(TopoDS::Wire(shape), hPlane->Pln()); + Py_Return; + } + + PyErr_Clear(); + PyObject* edge1; + PyObject* edge2; + if (PyArg_ParseTuple(args, "O!O!O!", &TopoShapeEdgePy::Type, &edge1, + &TopoShapeEdgePy::Type, &edge2, + &PlanePy::Type, &plane)) { + TopoDS_Shape shape1 = static_cast(edge1)->getTopoShapePtr()->getShape(); + TopoDS_Shape shape2 = static_cast(edge2)->getTopoShapePtr()->getShape(); + Handle(Geom_Plane) hPlane = Handle(Geom_Plane)::DownCast(static_cast(plane)->getGeomPlanePtr()->handle()); + getChFi2d_FilletAlgoPtr()->Init(TopoDS::Edge(shape1), TopoDS::Edge(shape2), hPlane->Pln()); + Py_Return; + } + + PyErr_SetString(PyExc_TypeError, "Wrong arguments:\n" + "-- init(wire, plane)" + "-- init(edge, edge, plane)\n"); + return nullptr; +} + +PyObject* ChFi2d_FilletAlgoPy::perform(PyObject *args) +{ + double radius; + if (!PyArg_ParseTuple(args, "d", &radius)) + return nullptr; + + try { + bool ok = getChFi2d_FilletAlgoPtr()->Perform(radius); + return Py::new_reference_to(Py::Boolean(ok)); + } + catch (Standard_Failure& e) { + PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* ChFi2d_FilletAlgoPy::numberOfResults(PyObject *args) +{ + PyObject* pnt; + if (!PyArg_ParseTuple(args, "O!", &Base::VectorPy::Type, &pnt)) + return nullptr; + + try { + Base::Vector3d* vec = static_cast(pnt)->getVectorPtr(); + Standard_Integer num = getChFi2d_FilletAlgoPtr()->NbResults(gp_Pnt(vec->x, vec->y, vec->z)); + return Py::new_reference_to(Py::Long(num)); + } + catch (Standard_Failure& e) { + PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); + return nullptr; + } +} + +PyObject* ChFi2d_FilletAlgoPy::result(PyObject *args) +{ + PyObject* pnt; + int solution = -1; + if (!PyArg_ParseTuple(args, "O!|i", &Base::VectorPy::Type, &pnt, &solution)) + return nullptr; + + Base::Vector3d* vec = static_cast(pnt)->getVectorPtr(); + + try { + TopoDS_Edge theEdge1, theEdge2; + TopoDS_Shape res_edge = getChFi2d_FilletAlgoPtr()->Result(Base::convertTo(*vec), theEdge1, theEdge2, solution); + + Py::TupleN tuple(Py::asObject(TopoShape(res_edge).getPyObject()), + Py::asObject(TopoShape(theEdge1).getPyObject()), + Py::asObject(TopoShape(theEdge2).getPyObject())); + return Py::new_reference_to(tuple); + } + catch (Standard_Failure& e) { + PyErr_SetString(Base::PyExc_FC_CADKernelError, e.GetMessageString()); + return nullptr; + } +} + +PyObject *ChFi2d_FilletAlgoPy::getCustomAttributes(const char* /*attr*/) const +{ + return nullptr; +} + +int ChFi2d_FilletAlgoPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +} diff --git a/src/Mod/Part/TestPartApp.py b/src/Mod/Part/TestPartApp.py index 2777fffeea..22dbbaf365 100644 --- a/src/Mod/Part/TestPartApp.py +++ b/src/Mod/Part/TestPartApp.py @@ -230,3 +230,46 @@ class PartTestCone(unittest.TestCase): self.assertAlmostEqual(v1.getAngle(w1), 0) self.assertAlmostEqual(v2.getAngle(w2), 0) self.assertAlmostEqual(v3.getAngle(w3), 0) + +class PartTestFilletAlgo(unittest.TestCase): + def testChFi2d_FilletAlgo(self): + v = FreeCAD.Vector + edge1 = Part.makeLine(v(0,0,0), v(0,10,0)) + edge2 = Part.makeLine(v(0,10,0), v(10,10,0)) + wire = Part.Wire([edge1, edge2]) + pln = Part.Plane() + + with self.assertRaises(TypeError): + alg = Part.ChFi2d_FilletAlgo(pln) + + alg = Part.ChFi2d_FilletAlgo() + with self.assertRaises(TypeError): + alg.init() + + print (alg) + # Test without shape + with self.assertRaises(Base.CADKernelError): + alg.perform(1) + + with self.assertRaises(TypeError): + alg.perform() + + alg = Part.ChFi2d_FilletAlgo(wire, pln) + alg.init(edge1, edge2, pln) + alg.init(wire, pln) + + alg = Part.ChFi2d_FilletAlgo(edge1, edge2, pln) + alg.perform(1.0) + + with self.assertRaises(TypeError): + alg.numberOfResults() + + with self.assertRaises(TypeError): + alg.result(1) + + self.assertEqual(alg.numberOfResults(Base.Vector(0,10,0)), 1) + result = alg.result(Base.Vector(0,10,0)) + curve = result[0].Curve + self.assertEqual(type(curve), Part.Circle) + self.assertEqual(curve.Axis, pln.Axis) + self.assertEqual(curve.Radius, 1.0)