Skip to content

Commit

Permalink
BSplineSurface approximate, add parametrization type and smoothing algo
Browse files Browse the repository at this point in the history
  • Loading branch information
tomate44 authored and wwmayer committed Mar 18, 2017
1 parent 281e593 commit fedbf42
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 22 deletions.
21 changes: 16 additions & 5 deletions src/Mod/Part/App/BSplineSurfacePy.xml
Expand Up @@ -683,14 +683,25 @@
<UserDocu>Returns a reparametrized copy of this surface</UserDocu>
</Documentation>
</Methode>
<Methode Name="approximate">
<Methode Name="approximate" Keyword="true">
<Documentation>
<UserDocu>
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)
</UserDocu>
</Documentation>
</Methode>
Expand Down
67 changes: 50 additions & 17 deletions src/Mod/Part/App/BSplineSurfacePyImp.cpp
Expand Up @@ -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, &degMin, &degMax, &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, &degMin, &degMax, &continuity, &tol3d, &X0, &dX, &Y0, &dY, &parType, &weight1, &weight2, &weight3))
return 0;
try {
Py::Sequence list(obj);
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -1325,6 +1355,9 @@ PyObject* BSplineSurfacePy::approximate(PyObject *args)
}
}




PyObject* BSplineSurfacePy::interpolate(PyObject *args)
{
PyObject* obj;
Expand Down

0 comments on commit fedbf42

Please sign in to comment.