PyObject* GeometryCurvePy::toBSpline(PyObject * args) { Handle_Geom_Geometry g = getGeometryPtr()->handle(); Handle_Geom_Curve c = Handle_Geom_Curve::DownCast(g); try { if (!c.IsNull()) { double u,v; u=c->FirstParameter(); v=c->LastParameter(); if (!PyArg_ParseTuple(args, "|dd", &u,&v)) return 0; ShapeConstruct_Curve scc; Handle_Geom_BSplineCurve spline = scc.ConvertToBSpline(c, u, v, Precision::Confusion()); if (spline.IsNull()) Standard_NullValue::Raise("Conversion to B-Spline failed"); return new BSplineCurvePy(new GeomBSplineCurve(spline)); } } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); return 0; } PyErr_SetString(PartExceptionOCCError, "Geometry is not a curve"); return 0; }
PyObject* BSplineCurvePy::approximate(PyObject *args) { PyObject* obj; if (!PyArg_ParseTuple(args, "O", &obj)) return 0; try { Py::Sequence list(obj); TColgp_Array1OfPnt pnts(1,list.size()); Standard_Integer index = 1; for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { Base::Vector3d vec = Py::Vector(*it).toVector(); pnts(index++) = gp_Pnt(vec.x,vec.y,vec.z); } GeomAPI_PointsToBSpline fit(pnts); Handle_Geom_BSplineCurve spline = fit.Curve(); if (!spline.IsNull()) { this->getGeomBSplineCurvePtr()->setHandle(spline); Py_Return; } else { Standard_Failure::Raise("failed to approximate points"); return 0; // goes to the catch block } } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); return 0; } }
PyObject* BSplineCurvePy::buildFromPoles(PyObject *args) { PyObject* obj; int degree = 3; PyObject* periodic = Py_False; PyObject* interpolate = Py_False; if (!PyArg_ParseTuple(args, "O|O!iO!",&obj, &PyBool_Type, &periodic, °ree, &PyBool_Type, interpolate)) return 0; try { Py::Sequence list(obj); TColgp_Array1OfPnt poles(1, list.size()); Standard_Integer index = 1; for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { Py::Vector v(*it); Base::Vector3d pnt = v.toVector(); poles(index++) = gp_Pnt(pnt.x,pnt.y,pnt.z); } if (poles.Length() <= degree) degree = poles.Length()-1; if (PyObject_IsTrue(periodic)) { int mult; int len; if (PyObject_IsTrue(interpolate)) { mult = degree; len = poles.Length() - mult + 2; } else { mult = 1; len = poles.Length() + 1; } TColStd_Array1OfReal knots(1, len); TColStd_Array1OfInteger mults(1, len); for (int i=1; i<=knots.Length(); i++){ knots.SetValue(i,(double)(i-1)/(knots.Length()-1)); mults.SetValue(i,1); } mults.SetValue(1, mult); mults.SetValue(knots.Length(), mult); Handle_Geom_BSplineCurve spline = new Geom_BSplineCurve(poles, knots, mults, degree, Standard_True); if (!spline.IsNull()) { this->getGeomBSplineCurvePtr()->setHandle(spline); Py_Return; } else { Standard_Failure::Raise("failed to create spline"); return 0; // goes to the catch block } } else { TColStd_Array1OfReal knots(1, poles.Length()+degree+1-2*(degree)); TColStd_Array1OfInteger mults(1, poles.Length()+degree+1-2*(degree)); for (int i=1; i<=knots.Length(); i++){ knots.SetValue(i,(double)(i-1)/(knots.Length()-1)); mults.SetValue(i,1); } mults.SetValue(1, degree+1); mults.SetValue(knots.Length(), degree+1); Handle_Geom_BSplineCurve spline = new Geom_BSplineCurve(poles, knots, mults, degree, Standard_False); if (!spline.IsNull()) { this->getGeomBSplineCurvePtr()->setHandle(spline); Py_Return; } else { Standard_Failure::Raise("failed to create spline"); return 0; // goes to the catch block } } } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); return 0; } }
PyObject* BSplineCurvePy::approximate(PyObject *args, PyObject *kwds) { PyObject* obj; Standard_Integer degMin=3; Standard_Integer degMax=8; char* continuity = "C2"; double tol3d = 1e-3; char* parType = "ChordLength"; PyObject* par = 0; double weight1 = 0; double weight2 = 0; double weight3 = 0; static char* kwds_interp[] = {"Points", "DegMax", "Continuity", "Tolerance", "DegMin", "ParamType", "Parameters", "LengthWeight", "CurvatureWeight", "TorsionWeight", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|isdisOddd",kwds_interp, &obj, °Max, &continuity, &tol3d, °Min, &parType, &par, &weight1, &weight2, &weight3)) return 0; try { Py::Sequence list(obj); TColgp_Array1OfPnt pnts(1,list.size()); Standard_Integer index = 1; for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { Base::Vector3d vec = Py::Vector(*it).toVector(); pnts(index++) = gp_Pnt(vec.x,vec.y,vec.z); } if (degMin > degMax) { Standard_Failure::Raise("DegMin must be lower or equal to DegMax"); } 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; if (weight1 || weight2 || weight3) { // It seems that this function only works with Continuity = C0, C1 or C2 if (!(c == GeomAbs_C0 || c == GeomAbs_C1 || c == GeomAbs_C2)) { c = GeomAbs_C2; } GeomAPI_PointsToBSpline fit(pnts, weight1, weight2, weight3, degMax, c, tol3d); Handle_Geom_BSplineCurve spline = fit.Curve(); if (!spline.IsNull()) { this->getGeomBSplineCurvePtr()->setHandle(spline); Py_Return; } else { Standard_Failure::Raise("Smoothing approximation failed"); return 0; // goes to the catch block } } if (par) { Py::Sequence plist(par); TColStd_Array1OfReal parameters(1,plist.size()); Standard_Integer index = 1; for (Py::Sequence::iterator it = plist.begin(); it != plist.end(); ++it) { Py::Float f(*it); parameters(index++) = static_cast<double>(f); } GeomAPI_PointsToBSpline fit(pnts, parameters, degMin, degMax, c, tol3d); Handle_Geom_BSplineCurve spline = fit.Curve(); if (!spline.IsNull()) { this->getGeomBSplineCurvePtr()->setHandle(spline); Py_Return; } else { Standard_Failure::Raise("Approximation with parameters failed"); return 0; // goes to the catch block } } Approx_ParametrizationType pt; std::string pstr = parType; if (pstr == "Uniform") pt = Approx_IsoParametric; else if (pstr == "Centripetal") pt = Approx_Centripetal; else pt = Approx_ChordLength; GeomAPI_PointsToBSpline fit(pnts, pt, degMin, degMax, c, tol3d); Handle_Geom_BSplineCurve spline = fit.Curve(); if (!spline.IsNull()) { this->getGeomBSplineCurvePtr()->setHandle(spline); Py_Return; } else { Standard_Failure::Raise("failed to approximate points"); return 0; // goes to the catch block } } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); PyErr_SetString(PartExceptionOCCError, e->GetMessageString()); return 0; } }
PyObject* BSplineCurvePy::buildFromPolesMultsKnots(PyObject *args, PyObject *keywds) { static char *kwlist[] = {"poles", "mults", "knots", "periodic", "degree", "weights", "CheckRational", NULL}; PyObject* periodic = Py_False; PyObject* CheckRational = Py_True; PyObject* poles = Py_None; PyObject* mults = Py_None; PyObject* knots = Py_None; PyObject* weights = Py_None; int degree = 3; int number_of_poles = 0; int number_of_knots = 0; int sum_of_mults = 0; if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|OOO!iOO!", kwlist, &poles, &mults, &knots, &PyBool_Type, &periodic, °ree, &weights, &PyBool_Type, &CheckRational)) return 0; try { // poles have to be present Py::Sequence list(poles); number_of_poles = list.size(); if ((number_of_poles) < 2) { Standard_Failure::Raise("need two or more poles"); return 0; } TColgp_Array1OfPnt occpoles(1, number_of_poles); Standard_Integer index = 1; for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { Py::Vector v(*it); Base::Vector3d pnt = v.toVector(); occpoles(index++) = gp_Pnt(pnt.x,pnt.y,pnt.z); } //Calculate the number of knots if (mults != Py_None && knots != Py_None) { number_of_knots = PyObject_Length(mults); if (PyObject_Length(knots) != number_of_knots) { Standard_Failure::Raise("number of knots and mults mismatch"); return 0; } } else { if (mults != Py_None) { number_of_knots = PyObject_Length(mults); } else { if (knots != Py_None) { number_of_knots = PyObject_Length(knots); } else { //guess number of knots if (PyObject_IsTrue(periodic)) { if (number_of_poles < degree) {degree = number_of_poles+1;} number_of_knots = number_of_poles+1; } else { if (number_of_poles <= degree) {degree = number_of_poles-1;} number_of_knots = number_of_poles-degree+1; } } } } TColStd_Array1OfInteger occmults(1,number_of_knots); TColStd_Array1OfReal occknots(1,number_of_knots); TColStd_Array1OfReal occweights(1,number_of_poles); if (mults != Py_None) { //mults are given Py::Sequence multssq(mults); Standard_Integer index = 1; for (Py::Sequence::iterator it = multssq.begin(); it != multssq.end() && index <= occmults.Length(); ++it) { Py::Int mult(*it); if (index < occmults.Length() || PyObject_Not(periodic)) { sum_of_mults += mult; //sum up the mults to compare them against the number of poles later } occmults(index++) = mult; } } else { //mults are 1 or degree+1 at the ends for (int i=1; i<=occmults.Length(); i++){ occmults.SetValue(i,1); } if (PyObject_Not(periodic) && occmults.Length() > 0) { occmults.SetValue(1, degree+1); occmults.SetValue(occmults.Length(), degree+1); sum_of_mults = occmults.Length()+2*degree; } else { sum_of_mults = occmults.Length()-1;} } if (knots != Py_None) { //knots are given Py::Sequence knotssq(knots); index = 1; for (Py::Sequence::iterator it = knotssq.begin(); it != knotssq.end() && index <= occknots.Length(); ++it) { Py::Float knot(*it); occknots(index++) = knot; } } else { // knotes are uniformly spaced 0..1 if not given for (int i=1; i<=occknots.Length(); i++){ occknots.SetValue(i,(double)(i-1)/(occknots.Length()-1)); } } if (weights != Py_None) { //weights are given if (PyObject_Length(weights) != number_of_poles) { Standard_Failure::Raise("number of poles and weights mismatch"); return 0; } //complain about mismatch Py::Sequence weightssq(weights); Standard_Integer index = 1; for (Py::Sequence::iterator it = weightssq.begin(); it != weightssq.end(); ++it) { Py::Float weight(*it); occweights(index++) = weight; } } else { // weights are 1.0 for (int i=1; i<=occweights.Length(); i++){ occweights.SetValue(i,1.0); } } // check if the numer of poles matches the sum of mults if ((PyObject_IsTrue(periodic) && sum_of_mults != number_of_poles) || (PyObject_Not(periodic) && sum_of_mults - degree -1 != number_of_poles)) { Standard_Failure::Raise("number of poles and sum of mults mismatch"); return(0); } Handle_Geom_BSplineCurve spline = new Geom_BSplineCurve(occpoles,occweights,occknots,occmults,degree, PyObject_IsTrue(periodic) ? Standard_True : Standard_False, PyObject_IsTrue(CheckRational) ? Standard_True : Standard_False); if (!spline.IsNull()) { this->getGeomBSplineCurvePtr()->setHandle(spline); Py_Return; } else { Standard_Failure::Raise("failed to create spline"); return 0; // goes to the catch block } } catch (const Standard_Failure & ) { Handle_Standard_Failure e = Standard_Failure::Caught(); Standard_CString msg = e->GetMessageString(); PyErr_SetString(PartExceptionOCCError, msg ? msg : ""); return 0; } }