diff --git a/src/Mod/Part/App/BSplineCurvePyImp.cpp b/src/Mod/Part/App/BSplineCurvePyImp.cpp index f07ce26f1d..e4c84ca343 100644 --- a/src/Mod/Part/App/BSplineCurvePyImp.cpp +++ b/src/Mod/Part/App/BSplineCurvePyImp.cpp @@ -801,6 +801,7 @@ PyObject* BSplineCurvePy::approximate(PyObject *args, PyObject *kwds) PyObject* obj; Standard_Integer degMin=3; Standard_Integer degMax=8; + Standard_Integer segMax=8; char* continuity = "C2"; double tol3d = 1e-3; char* parType = "ChordLength"; @@ -809,15 +810,46 @@ PyObject* BSplineCurvePy::approximate(PyObject *args, PyObject *kwds) double weight2 = 0; double weight3 = 0; - static char* kwds_interp[] = {"Points", "DegMax", "Continuity", "Tolerance", "DegMin", "ParamType", "Parameters", - "LengthWeight", "CurvatureWeight", "TorsionWeight", NULL}; + // Approximate this curve with a given continuity and degree + static char* kwds_reapprox[] = {"MaxDegree", "MaxSegments", "Continuity", "Tolerance", nullptr}; + if (PyArg_ParseTupleAndKeywords(args, kwds, "i|isd", kwds_reapprox, + &tol3d, °Max, &segMax, &continuity)) { + GeomAbs_Shape c; + std::string str = continuity; + if (str == "C0") + c = GeomAbs_C0; + else if (str == "G1") + c = GeomAbs_G1; + else if (str == "C1") + c = GeomAbs_C1; + else if (str == "G2") + c = GeomAbs_G2; + else if (str == "C2") + c = GeomAbs_C2; + else if (str == "C3") + c = GeomAbs_C3; + else if (str == "CN") + c = GeomAbs_CN; + else + c = GeomAbs_C2; + + bool ok = this->getGeomBSplineCurvePtr()->approximate(tol3d, segMax, degMax, c); + return Py_BuildValue("O", (ok ? Py_True : Py_False)); + } + + // Approximate a list of points + // + static char* kwds_interp[] = {"Points", "DegMax", "Continuity", "Tolerance", "DegMin", "ParamType", "Parameters", + "LengthWeight", "CurvatureWeight", "TorsionWeight", nullptr}; + + PyErr_Clear(); if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|isdisOddd",kwds_interp, &obj, °Max, &continuity, &tol3d, °Min, &parType, &par, &weight1, &weight2, &weight3)) - return 0; + return nullptr; try { Py::Sequence list(obj); diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp index c03df155d5..db8f838ccf 100644 --- a/src/Mod/Part/App/Geometry.cpp +++ b/src/Mod/Part/App/Geometry.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include @@ -50,6 +51,7 @@ # include # include # include +# include # include # include # include @@ -1338,19 +1340,47 @@ void GeomBSplineCurve::makeC1Continuous(double tol, double ang_tol) GeomConvert::C0BSplineToC1BSplineCurve(this->myCurve, tol, ang_tol); } -void GeomBSplineCurve::increaseDegree(double degree) +void GeomBSplineCurve::increaseDegree(int degree) { try { Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast(this->handle()); curve->IncreaseDegree(degree); - return; } catch (Standard_Failure& e) { - THROWM(Base::CADKernelError,e.GetMessageString()) } } +/*! + * \brief GeomBSplineCurve::approximate + * \param tol3d + * \param maxSegments + * \param maxDegree + * \param continuity + * \return true if the approximation succeeded, false otherwise + */ +bool GeomBSplineCurve::approximate(double tol3d, int maxSegments, int maxDegree, int continuity) +{ + try { + GeomAbs_Shape cont = GeomAbs_C0; + if (continuity >= 0 && continuity <= 6) + cont = static_cast(continuity); + + GeomAdaptor_Curve adapt(myCurve); + Handle(GeomAdaptor_HCurve) hCurve = new GeomAdaptor_HCurve(adapt); + Approx_Curve3d approx(hCurve, tol3d, cont, maxSegments, maxDegree); + if (approx.IsDone() && approx.HasResult()) { + this->setHandle(approx.Curve()); + return true; + } + } + catch (Standard_Failure& e) { + THROWM(Base::CADKernelError,e.GetMessageString()) + } + + return false; +} + void GeomBSplineCurve::increaseMultiplicity(int index, int multiplicity) { try { @@ -1359,7 +1389,6 @@ void GeomBSplineCurve::increaseMultiplicity(int index, int multiplicity) return; } catch (Standard_Failure& e) { - THROWM(Base::CADKernelError,e.GetMessageString()) } } diff --git a/src/Mod/Part/App/Geometry.h b/src/Mod/Part/App/Geometry.h index 48e5c6e76e..44cc311bbb 100644 --- a/src/Mod/Part/App/Geometry.h +++ b/src/Mod/Part/App/Geometry.h @@ -291,7 +291,8 @@ public: void makeC1Continuous(double, double); std::list toBiArcs(double tolerance) const; - void increaseDegree(double degree); + void increaseDegree(int degree); + bool approximate(double tol3d, int maxSegments, int maxDegree, int continuity); void increaseMultiplicity(int index, int multiplicity); bool removeKnot(int index, int multiplicity, double tolerance = Precision::PConfusion());