From 3d2a2b06f0c8a00338dfe1982aadd2173422ba7d Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 13 Aug 2014 23:33:27 +0200 Subject: [PATCH] + fix and improve discretize() method --- src/Mod/Part/App/GeometryCurvePy.xml | 15 ++- src/Mod/Part/App/GeometryCurvePyImp.cpp | 116 ++++++++++++++++---- src/Mod/Part/App/TopoShapeEdgePy.xml | 15 ++- src/Mod/Part/App/TopoShapeEdgePyImp.cpp | 139 ++++++++++++++++++------ src/Mod/Part/App/TopoShapeWirePy.xml | 15 ++- src/Mod/Part/App/TopoShapeWirePyImp.cpp | 139 ++++++++++++++++++------ 6 files changed, 350 insertions(+), 89 deletions(-) diff --git a/src/Mod/Part/App/GeometryCurvePy.xml b/src/Mod/Part/App/GeometryCurvePy.xml index ba3cc7854..32d481af5 100644 --- a/src/Mod/Part/App/GeometryCurvePy.xml +++ b/src/Mod/Part/App/GeometryCurvePy.xml @@ -21,9 +21,20 @@ Return the shape for the geometry. - + - Discretizes the curve using a given deflection or number of points and returns a list of points + Discretizes the curve and returns a list of points. +The function accepts keywords as argument: +discretize(Number=n) => gives a list of 'n' equidistant points +discretize(Distance=d) => gives a list of equidistant points with distance 'd' +discretize(Deflection=d) => gives a list of points with a maximum deflection 'd' to the curve +discretize(Angular=a,Curvatre=c) => gives a list of points with an angular deflection of 'a' + and a curvature deflection of 'c' + +If no keyword is given then it depends on whether the argument is an int or float. +If it's an int then the behaviour is as if using the keyword 'Number', if it's float +then the behaviour is as if using the keyword 'Distance'. + diff --git a/src/Mod/Part/App/GeometryCurvePyImp.cpp b/src/Mod/Part/App/GeometryCurvePyImp.cpp index 03bf44e8e..e60b9e3de 100644 --- a/src/Mod/Part/App/GeometryCurvePyImp.cpp +++ b/src/Mod/Part/App/GeometryCurvePyImp.cpp @@ -29,6 +29,8 @@ # include # include # include +# include +# include # include # include # include @@ -112,30 +114,62 @@ PyObject* GeometryCurvePy::toShape(PyObject *args) return 0; } -PyObject* GeometryCurvePy::discretize(PyObject *args) +PyObject* GeometryCurvePy::discretize(PyObject *args, PyObject *kwds) { - PyObject* defl_or_num; - if (!PyArg_ParseTuple(args, "O", &defl_or_num)) - return 0; - try { Handle_Geom_Geometry g = getGeometryPtr()->handle(); Handle_Geom_Curve c = Handle_Geom_Curve::DownCast(g); - if (!c.IsNull()) { - GeomAdaptor_Curve adapt(c); - GCPnts_UniformAbscissa discretizer; - if (PyInt_Check(defl_or_num)) { - int num = PyInt_AsLong(defl_or_num); - discretizer.Initialize (adapt, num); + if (c.IsNull()) { + PyErr_SetString(PyExc_Exception, "Geometry is not a curve"); + return 0; + } + + GeomAdaptor_Curve adapt(c); + bool uniformAbscissaPoints = false; + bool uniformAbscissaDistance = false; + int numPoints = -1; + double distance = -1; + + // use no kwds + PyObject* dist_or_num; + if (PyArg_ParseTuple(args, "O", &dist_or_num)) { + if (PyInt_Check(dist_or_num)) { + numPoints = PyInt_AsLong(dist_or_num); + uniformAbscissaPoints = true; } - else if (PyFloat_Check(defl_or_num)) { - double defl = PyFloat_AsDouble(defl_or_num); - discretizer.Initialize (adapt, defl); + else if (PyFloat_Check(dist_or_num)) { + distance = PyFloat_AsDouble(dist_or_num); + uniformAbscissaDistance = true; } else { PyErr_SetString(PyExc_TypeError, "Either int or float expected"); return 0; } + } + else { + // use Number kwds + static char* kwds_numPoints[] = {"Number",NULL}; + PyErr_Clear(); + if (PyArg_ParseTupleAndKeywords(args, kwds, "i", kwds_numPoints, &numPoints)) { + uniformAbscissaPoints = true; + } + else { + // use Abscissa kwds + static char* kwds_Distance[] = {"Distance",NULL}; + PyErr_Clear(); + if (PyArg_ParseTupleAndKeywords(args, kwds, "d", kwds_Distance, &distance)) { + uniformAbscissaDistance = true; + } + } + } + + if (uniformAbscissaPoints || uniformAbscissaDistance) { + GCPnts_UniformAbscissa discretizer; + if (uniformAbscissaPoints) + discretizer.Initialize (adapt, numPoints); + else + discretizer.Initialize (adapt, distance); + if (discretizer.IsDone () && discretizer.NbPoints () > 0) { Py::List points; int nbPoints = discretizer.NbPoints (); @@ -147,18 +181,62 @@ PyObject* GeometryCurvePy::discretize(PyObject *args) return Py::new_reference_to(points); } else { - PyErr_SetString(PyExc_Exception, "Descretization of curve failed"); + PyErr_SetString(PyExc_Exception, "Descretization of wire failed"); + return 0; + } + } + + // use Deflection kwds + static char* kwds_Deflection[] = {"Deflection",NULL}; + PyErr_Clear(); + double deflection; + if (PyArg_ParseTupleAndKeywords(args, kwds, "d", kwds_Deflection, &deflection)) { + GCPnts_UniformDeflection discretizer(adapt, deflection); + if (discretizer.IsDone () && discretizer.NbPoints () > 0) { + Py::List points; + int nbPoints = discretizer.NbPoints (); + for (int i=1; i<=nbPoints; i++) { + gp_Pnt p = discretizer.Value (i); + points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z()))); + } + + return Py::new_reference_to(points); + } + else { + PyErr_SetString(PyExc_Exception, "Descretization of wire failed"); + return 0; + } + } + + // use TangentialDeflection kwds + static char* kwds_TangentialDeflection[] = {"Angular","Curvature",NULL}; + PyErr_Clear(); + double angular; + double curvature; + if (PyArg_ParseTupleAndKeywords(args, kwds, "dd", kwds_TangentialDeflection, &angular, &curvature)) { + GCPnts_TangentialDeflection discretizer(adapt, angular, curvature); + if (discretizer.NbPoints () > 0) { + Py::List points; + int nbPoints = discretizer.NbPoints (); + for (int i=1; i<=nbPoints; i++) { + gp_Pnt p = discretizer.Value (i); + points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z()))); + } + + return Py::new_reference_to(points); + } + else { + PyErr_SetString(PyExc_Exception, "Descretization of wire failed"); return 0; } } } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PyExc_Exception, e->GetMessageString()); + catch (const Base::Exception& e) { + PyErr_SetString(PyExc_Exception, e.what()); return 0; } - PyErr_SetString(PyExc_Exception, "Geometry is not a curve"); + PyErr_SetString(PyExc_Exception,"Wrong arguments"); return 0; } diff --git a/src/Mod/Part/App/TopoShapeEdgePy.xml b/src/Mod/Part/App/TopoShapeEdgePy.xml index 1f300060f..68720421a 100644 --- a/src/Mod/Part/App/TopoShapeEdgePy.xml +++ b/src/Mod/Part/App/TopoShapeEdgePy.xml @@ -69,9 +69,20 @@ Set the tolerance for the edge. - + - Discretizes the edge using a given deflection or number of points and returns a list of points + Discretizes the edge and returns a list of points. +The function accepts keywords as argument: +discretize(Number=n) => gives a list of 'n' equidistant points +discretize(Distance=d) => gives a list of equidistant points with distance 'd' +discretize(Deflection=d) => gives a list of points with a maximum deflection 'd' to the edge +discretize(Angular=a,Curvatre=c) => gives a list of points with an angular deflection of 'a' + and a curvature deflection of 'c' + +If no keyword is given then it depends on whether the argument is an int or float. +If it's an int then the behaviour is as if using the keyword 'Number', if it's float +then the behaviour is as if using the keyword 'Distance'. + diff --git a/src/Mod/Part/App/TopoShapeEdgePyImp.cpp b/src/Mod/Part/App/TopoShapeEdgePyImp.cpp index a0dd79abe..6421db4c8 100644 --- a/src/Mod/Part/App/TopoShapeEdgePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeEdgePyImp.cpp @@ -58,6 +58,8 @@ #include #include #include +#include +#include #include #include @@ -387,49 +389,122 @@ PyObject* TopoShapeEdgePy::derivative3At(PyObject *args) } } -PyObject* TopoShapeEdgePy::discretize(PyObject *args) +PyObject* TopoShapeEdgePy::discretize(PyObject *args, PyObject *kwds) { - PyObject* defl_or_num; - if (!PyArg_ParseTuple(args, "O", &defl_or_num)) - return 0; - try { BRepAdaptor_Curve adapt(TopoDS::Edge(getTopoShapePtr()->_Shape)); - GCPnts_UniformAbscissa discretizer; - if (PyInt_Check(defl_or_num)) { - int num = PyInt_AsLong(defl_or_num); - discretizer.Initialize (adapt, num); - } - else if (PyFloat_Check(defl_or_num)) { - double defl = PyFloat_AsDouble(defl_or_num); - discretizer.Initialize (adapt, defl); - } - else { - PyErr_SetString(PyExc_TypeError, "Either int or float expected"); - return 0; - } - if (discretizer.IsDone () && discretizer.NbPoints () > 0) { - Py::List points; - int nbPoints = discretizer.NbPoints (); - for (int i=1; i<=nbPoints; i++) { - gp_Pnt p = adapt.Value (discretizer.Parameter (i)); - points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z()))); - } + bool uniformAbscissaPoints = false; + bool uniformAbscissaDistance = false; + int numPoints = -1; + double distance = -1; - return Py::new_reference_to(points); + // use no kwds + PyObject* dist_or_num; + if (PyArg_ParseTuple(args, "O", &dist_or_num)) { + if (PyInt_Check(dist_or_num)) { + numPoints = PyInt_AsLong(dist_or_num); + uniformAbscissaPoints = true; + } + else if (PyFloat_Check(dist_or_num)) { + distance = PyFloat_AsDouble(dist_or_num); + uniformAbscissaDistance = true; + } + else { + PyErr_SetString(PyExc_TypeError, "Either int or float expected"); + return 0; + } } else { - PyErr_SetString(PyExc_Exception, "Descretization of curve failed"); - return 0; + // use Number kwds + static char* kwds_numPoints[] = {"Number",NULL}; + PyErr_Clear(); + if (PyArg_ParseTupleAndKeywords(args, kwds, "i", kwds_numPoints, &numPoints)) { + uniformAbscissaPoints = true; + } + else { + // use Abscissa kwds + static char* kwds_Distance[] = {"Distance",NULL}; + PyErr_Clear(); + if (PyArg_ParseTupleAndKeywords(args, kwds, "d", kwds_Distance, &distance)) { + uniformAbscissaDistance = true; + } + } + } + + if (uniformAbscissaPoints || uniformAbscissaDistance) { + GCPnts_UniformAbscissa discretizer; + if (uniformAbscissaPoints) + discretizer.Initialize (adapt, numPoints); + else + discretizer.Initialize (adapt, distance); + + if (discretizer.IsDone () && discretizer.NbPoints () > 0) { + Py::List points; + int nbPoints = discretizer.NbPoints (); + for (int i=1; i<=nbPoints; i++) { + gp_Pnt p = adapt.Value (discretizer.Parameter (i)); + points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z()))); + } + + return Py::new_reference_to(points); + } + else { + PyErr_SetString(PyExc_Exception, "Descretization of curve failed"); + return 0; + } + } + + // use Deflection kwds + static char* kwds_Deflection[] = {"Deflection",NULL}; + PyErr_Clear(); + double deflection; + if (PyArg_ParseTupleAndKeywords(args, kwds, "d", kwds_Deflection, &deflection)) { + GCPnts_UniformDeflection discretizer(adapt, deflection); + if (discretizer.IsDone () && discretizer.NbPoints () > 0) { + Py::List points; + int nbPoints = discretizer.NbPoints (); + for (int i=1; i<=nbPoints; i++) { + gp_Pnt p = discretizer.Value (i); + points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z()))); + } + + return Py::new_reference_to(points); + } + else { + PyErr_SetString(PyExc_Exception, "Descretization of curve failed"); + return 0; + } + } + + // use TangentialDeflection kwds + static char* kwds_TangentialDeflection[] = {"Angular","Curvature",NULL}; + PyErr_Clear(); + double angular; + double curvature; + if (PyArg_ParseTupleAndKeywords(args, kwds, "dd", kwds_TangentialDeflection, &angular, &curvature)) { + GCPnts_TangentialDeflection discretizer(adapt, angular, curvature); + if (discretizer.NbPoints () > 0) { + Py::List points; + int nbPoints = discretizer.NbPoints (); + for (int i=1; i<=nbPoints; i++) { + gp_Pnt p = discretizer.Value (i); + points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z()))); + } + + return Py::new_reference_to(points); + } + else { + PyErr_SetString(PyExc_Exception, "Descretization of curve failed"); + return 0; + } } } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PyExc_Exception, e->GetMessageString()); + catch (const Base::Exception& e) { + PyErr_SetString(PyExc_Exception, e.what()); return 0; } - PyErr_SetString(PyExc_Exception, "Geometry is not a curve"); + PyErr_SetString(PyExc_Exception,"Wrong arguments"); return 0; } diff --git a/src/Mod/Part/App/TopoShapeWirePy.xml b/src/Mod/Part/App/TopoShapeWirePy.xml index faab08586..f797ec4e8 100644 --- a/src/Mod/Part/App/TopoShapeWirePy.xml +++ b/src/Mod/Part/App/TopoShapeWirePy.xml @@ -51,9 +51,20 @@ Make a loft defined by a list of profiles along a wire. Transition can be Approximate B-Spline-curve from this wire - + - Discretizes the wire using a given deflection or number of points and returns a list of points + Discretizes the wire and returns a list of points. +The function accepts keywords as argument: +discretize(Number=n) => gives a list of 'n' equidistant points +discretize(Distance=d) => gives a list of equidistant points with distance 'd' +discretize(Deflection=d) => gives a list of points with a maximum deflection 'd' to the wire +discretize(Angular=a,Curvatre=c) => gives a list of points with an angular deflection of 'a' + and a curvature deflection of 'c' + +If no keyword is given then it depends on whether the argument is an int or float. +If it's an int then the behaviour is as if using the keyword 'Number', if it's float +then the behaviour is as if using the keyword 'Distance'. + diff --git a/src/Mod/Part/App/TopoShapeWirePyImp.cpp b/src/Mod/Part/App/TopoShapeWirePyImp.cpp index 2e5f6ac20..6dad3bc7f 100644 --- a/src/Mod/Part/App/TopoShapeWirePyImp.cpp +++ b/src/Mod/Part/App/TopoShapeWirePyImp.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include #include @@ -328,49 +330,122 @@ PyObject* TopoShapeWirePy::approximate(PyObject *args) } } -PyObject* TopoShapeWirePy::discretize(PyObject *args) +PyObject* TopoShapeWirePy::discretize(PyObject *args, PyObject *kwds) { - PyObject* defl_or_num; - if (!PyArg_ParseTuple(args, "O", &defl_or_num)) - return 0; - try { BRepAdaptor_CompCurve adapt(TopoDS::Wire(getTopoShapePtr()->_Shape)); - GCPnts_UniformAbscissa discretizer; - if (PyInt_Check(defl_or_num)) { - int num = PyInt_AsLong(defl_or_num); - discretizer.Initialize (adapt, num); - } - else if (PyFloat_Check(defl_or_num)) { - double defl = PyFloat_AsDouble(defl_or_num); - discretizer.Initialize (adapt, defl); - } - else { - PyErr_SetString(PyExc_TypeError, "Either int or float expected"); - return 0; - } - if (discretizer.IsDone () && discretizer.NbPoints () > 0) { - Py::List points; - int nbPoints = discretizer.NbPoints (); - for (int i=1; i<=nbPoints; i++) { - gp_Pnt p = adapt.Value (discretizer.Parameter (i)); - points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z()))); - } + bool uniformAbscissaPoints = false; + bool uniformAbscissaDistance = false; + int numPoints = -1; + double distance = -1; - return Py::new_reference_to(points); + // use no kwds + PyObject* dist_or_num; + if (PyArg_ParseTuple(args, "O", &dist_or_num)) { + if (PyInt_Check(dist_or_num)) { + numPoints = PyInt_AsLong(dist_or_num); + uniformAbscissaPoints = true; + } + else if (PyFloat_Check(dist_or_num)) { + distance = PyFloat_AsDouble(dist_or_num); + uniformAbscissaDistance = true; + } + else { + PyErr_SetString(PyExc_TypeError, "Either int or float expected"); + return 0; + } } else { - PyErr_SetString(PyExc_Exception, "Descretization of wire failed"); - return 0; + // use Number kwds + static char* kwds_numPoints[] = {"Number",NULL}; + PyErr_Clear(); + if (PyArg_ParseTupleAndKeywords(args, kwds, "i", kwds_numPoints, &numPoints)) { + uniformAbscissaPoints = true; + } + else { + // use Abscissa kwds + static char* kwds_Distance[] = {"Distance",NULL}; + PyErr_Clear(); + if (PyArg_ParseTupleAndKeywords(args, kwds, "d", kwds_Distance, &distance)) { + uniformAbscissaDistance = true; + } + } + } + + if (uniformAbscissaPoints || uniformAbscissaDistance) { + GCPnts_UniformAbscissa discretizer; + if (uniformAbscissaPoints) + discretizer.Initialize (adapt, numPoints); + else + discretizer.Initialize (adapt, distance); + + if (discretizer.IsDone () && discretizer.NbPoints () > 0) { + Py::List points; + int nbPoints = discretizer.NbPoints (); + for (int i=1; i<=nbPoints; i++) { + gp_Pnt p = adapt.Value (discretizer.Parameter (i)); + points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z()))); + } + + return Py::new_reference_to(points); + } + else { + PyErr_SetString(PyExc_Exception, "Descretization of wire failed"); + return 0; + } + } + + // use Deflection kwds + static char* kwds_Deflection[] = {"Deflection",NULL}; + PyErr_Clear(); + double deflection; + if (PyArg_ParseTupleAndKeywords(args, kwds, "d", kwds_Deflection, &deflection)) { + GCPnts_UniformDeflection discretizer(adapt, deflection); + if (discretizer.IsDone () && discretizer.NbPoints () > 0) { + Py::List points; + int nbPoints = discretizer.NbPoints (); + for (int i=1; i<=nbPoints; i++) { + gp_Pnt p = discretizer.Value (i); + points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z()))); + } + + return Py::new_reference_to(points); + } + else { + PyErr_SetString(PyExc_Exception, "Descretization of wire failed"); + return 0; + } + } + + // use TangentialDeflection kwds + static char* kwds_TangentialDeflection[] = {"Angular","Curvature",NULL}; + PyErr_Clear(); + double angular; + double curvature; + if (PyArg_ParseTupleAndKeywords(args, kwds, "dd", kwds_TangentialDeflection, &angular, &curvature)) { + GCPnts_TangentialDeflection discretizer(adapt, angular, curvature); + if (discretizer.NbPoints () > 0) { + Py::List points; + int nbPoints = discretizer.NbPoints (); + for (int i=1; i<=nbPoints; i++) { + gp_Pnt p = discretizer.Value (i); + points.append(Py::Vector(Base::Vector3d(p.X(),p.Y(),p.Z()))); + } + + return Py::new_reference_to(points); + } + else { + PyErr_SetString(PyExc_Exception, "Descretization of wire failed"); + return 0; + } } } - catch (Standard_Failure) { - Handle_Standard_Failure e = Standard_Failure::Caught(); - PyErr_SetString(PyExc_Exception, e->GetMessageString()); + catch (const Base::Exception& e) { + PyErr_SetString(PyExc_Exception, e.what()); return 0; } - PyErr_SetString(PyExc_Exception, "Geometry is not a curve"); + PyErr_SetString(PyExc_Exception,"Wrong arguments"); return 0; }