diff --git a/src/Mod/Part/App/BSplineSurfacePy.xml b/src/Mod/Part/App/BSplineSurfacePy.xml
index b264bd460458..b6df615ee780 100644
--- a/src/Mod/Part/App/BSplineSurfacePy.xml
+++ b/src/Mod/Part/App/BSplineSurfacePy.xml
@@ -683,14 +683,25 @@
Returns a reparametrized copy of this surface
-
+
- approximate(points, degMin, degMax, continuity, tol)
- approximate(zPoints, degMin, degMax, continuity, tol, X0, dX, Y0, dY)
-
Replaces this B-Spline surface by approximating a set of points.
- continuity is an integer between 0 and 3
+ This method uses keywords :
+ - Points = 2Darray of points (or floats, in combination with X0, dX, Y0, dY)
+ - DegMin (int), DegMax (int)
+ - Continuity = 0,1 or 2 (for C0, C1, C2)
+ - Tolerance (float)
+ - X0, dX, Y0, dY (floats) with Points = 2Darray of floats
+ - ParamType = 'Uniform','Centripetal' or 'ChordLength'
+ - LengthWeight, CurvatureWeight, TorsionWeight (floats)
+
+ Possible combinations :
+ - approximate(Points, DegMin, DegMax, Continuity, Tolerance)
+ - approximate(Points, DegMin, DegMax, Continuity, Tolerance, X0, dX, Y0, dY)
+ With explicit keywords :
+ - approximate(Points, DegMin, DegMax, Continuity, Tolerance, ParamType)
+ - approximate(Points, DegMax, Continuity, Tolerance, LengthWeight, CurvatureWeight, TorsionWeight)
diff --git a/src/Mod/Part/App/BSplineSurfacePyImp.cpp b/src/Mod/Part/App/BSplineSurfacePyImp.cpp
index 30dd146b9eab..1bccc18f7679 100644
--- a/src/Mod/Part/App/BSplineSurfacePyImp.cpp
+++ b/src/Mod/Part/App/BSplineSurfacePyImp.cpp
@@ -1235,21 +1235,25 @@ PyObject* BSplineSurfacePy::reparametrize(PyObject * args)
}
}
-PyObject* BSplineSurfacePy::approximate(PyObject *args)
+PyObject* BSplineSurfacePy::approximate(PyObject *args, PyObject *kwds)
{
PyObject* obj;
- Standard_Integer degMin=0;
- Standard_Integer degMax=0;
- Standard_Integer continuity=0;
+ Standard_Integer degMin=3;
+ Standard_Integer degMax=8;
+ Standard_Integer continuity=2;
Standard_Real tol3d = Precision::Approximation();
+ char* parType = "None";
+ Standard_Real weight1 = 1.0;
+ Standard_Real weight2 = 1.0;
+ Standard_Real weight3 = 1.0;
Standard_Real X0=0;
Standard_Real dX=0;
Standard_Real Y0=0;
Standard_Real dY=0;
- int len = PyTuple_GET_SIZE(args);
-
- if (!PyArg_ParseTuple(args, "Oiiid|dddd", &obj, °Min, °Max, &continuity, &tol3d, &X0, &dX, &Y0, &dY))
+ static char* kwds_interp[] = {"Points", "DegMin", "DegMax", "Continuity", "Tolerance", "X0", "dX", "Y0", "dY", "ParamType", "LengthWeight", "CurvatureWeight", "TorsionWeight", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|iiidddddsddd", kwds_interp, &obj, °Min, °Max, &continuity, &tol3d, &X0, &dX, &Y0, &dY, &parType, &weight1, &weight2, &weight3))
return 0;
try {
Py::Sequence list(obj);
@@ -1268,7 +1272,7 @@ PyObject* BSplineSurfacePy::approximate(PyObject *args)
Py::Sequence row(*it1);
for (Py::Sequence::iterator it2 = row.begin(); it2 != row.end(); ++it2) {
index2++;
- if(len == 5){
+ if ((dX == 0) || (dY == 0)){
Py::Vector v(*it2);
Base::Vector3d pnt = v.toVector();
gp_Pnt newPoint(pnt.x,pnt.y,pnt.z);
@@ -1281,15 +1285,15 @@ PyObject* BSplineSurfacePy::approximate(PyObject *args)
}
}
- if (continuity<0 || continuity>3) {
- Standard_Failure::Raise("continuity must be between 0 and 3");
+ if (continuity<0 || continuity>2) {
+ Standard_Failure::Raise("continuity must be between 0 and 2");
}
if (interpolationPoints.RowLength() < 2 || interpolationPoints.ColLength() < 2) {
Standard_Failure::Raise("not enough points given");
}
- GeomAbs_Shape c = GeomAbs_CN;
+ GeomAbs_Shape c = GeomAbs_C2;
switch(continuity){
case 0:
c = GeomAbs_C0;
@@ -1300,17 +1304,43 @@ PyObject* BSplineSurfacePy::approximate(PyObject *args)
case 2:
c = GeomAbs_C2;
break;
- case 3:
- c = GeomAbs_C3;
- break;
}
+
+ Approx_ParametrizationType pt;
+ std::string pstr = parType;
+ Standard_Boolean useParam = Standard_True;
+ if (pstr == "Uniform" )
+ pt = Approx_IsoParametric;
+ else if (pstr == "Centripetal" )
+ pt = Approx_Centripetal;
+ else if (pstr == "ChordLength" )
+ pt = Approx_ChordLength;
+ else
+ useParam = Standard_False;
GeomAPI_PointsToBSplineSurface surInterpolation;
- if (len == 5) {
- surInterpolation.Init(interpolationPoints, degMin, degMax, c, tol3d);
+ if (!(dX == 0) && !(dY == 0)) {
+ // dX and dY are not null : we use the zPoints method
+ surInterpolation.Init(zPoints, X0, dX, Y0, dY, degMin, degMax, c, tol3d);
+ }
+ else if (useParam) {
+ // a parametrization type has been supplied
+ surInterpolation.Init(interpolationPoints, pt, degMin, degMax, c, tol3d);
+ }
+ else if (!(weight1 == 0) || !(weight2 == 0) || !(weight3 == 0)) {
+ // one of the weights is not null, we use the smoothing algorithm
+ // adjust continuity for low values of degMax, instead of failing
+ if (degMax < 3) {
+ c = GeomAbs_C0;
+ }
+ else if ((degMax < 5) && (c == GeomAbs_C2)) {
+ c = GeomAbs_C1;
+ }
+ surInterpolation.Init(interpolationPoints, weight1, weight2, weight3, degMax, c, tol3d);
}
else {
- surInterpolation.Init(zPoints, X0, dX, Y0, dY, degMin, degMax, c, tol3d);
+ // fallback to strandard method
+ surInterpolation.Init(interpolationPoints, degMin, degMax, c, tol3d);
}
Handle_Geom_BSplineSurface sur(surInterpolation.Surface());
this->getGeomBSplineSurfacePtr()->setHandle(sur);
@@ -1325,6 +1355,9 @@ PyObject* BSplineSurfacePy::approximate(PyObject *args)
}
}
+
+
+
PyObject* BSplineSurfacePy::interpolate(PyObject *args)
{
PyObject* obj;