diff --git a/src/Mod/Part/App/BSplineCurvePy.xml b/src/Mod/Part/App/BSplineCurvePy.xml
index bdd0c039e..2a8510a79 100644
--- a/src/Mod/Part/App/BSplineCurvePy.xml
+++ b/src/Mod/Part/App/BSplineCurvePy.xml
@@ -271,6 +271,14 @@ from the knots table of this B-Spline curve.
+
+
+
+ Builds a B-Spline by a lists of Poles, Mults, Knots.
+ arguments: poles (sequence of Base.Vector), [mults , knots, periodic, degree, weights (sequence of Base.Vector), CheckRational]
+
+
+
diff --git a/src/Mod/Part/App/BSplineCurvePyImp.cpp b/src/Mod/Part/App/BSplineCurvePyImp.cpp
index ee54143e2..845840b55 100644
--- a/src/Mod/Part/App/BSplineCurvePyImp.cpp
+++ b/src/Mod/Part/App/BSplineCurvePyImp.cpp
@@ -869,6 +869,147 @@ PyObject* BSplineCurvePy::buildFromPoles(PyObject *args)
}
}
+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 ne 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),PyObject_IsTrue(CheckRational));
+ 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(PyExc_Exception, msg ? msg : "");
+ return 0;
+ }
+ }
+
+
PyObject* BSplineCurvePy::toBezier(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
diff --git a/src/Mod/Part/App/BSplineSurfacePy.xml b/src/Mod/Part/App/BSplineSurfacePy.xml
index d25b360cc..4b73d4bf8 100644
--- a/src/Mod/Part/App/BSplineSurfacePy.xml
+++ b/src/Mod/Part/App/BSplineSurfacePy.xml
@@ -706,5 +706,13 @@
+
+
+
+ Builds a B-Spline by a lists of Poles, Mults and Knots
+ arguments: poles (sequence of sequence of Base.Vector), umults, vmults, [uknots, vknots, uperiodic, vperiodic, udegree, vdegree, weights (sequence of sequence of float)]
+
+
+
diff --git a/src/Mod/Part/App/BSplineSurfacePyImp.cpp b/src/Mod/Part/App/BSplineSurfacePyImp.cpp
index 3911b65a0..c9b8ebd1b 100644
--- a/src/Mod/Part/App/BSplineSurfacePyImp.cpp
+++ b/src/Mod/Part/App/BSplineSurfacePyImp.cpp
@@ -1397,6 +1397,160 @@ PyObject* BSplineSurfacePy::interpolate(PyObject *args)
}
}
+PyObject* BSplineSurfacePy::buildFromPolesMultsKnots(PyObject *args, PyObject *keywds)
+{
+ static char *kwlist[] = {"poles", "umults", "vmults",
+ "uknots", "vknots", "uperiodic", "vperiodic", "udegree", "vdegree", "weights", NULL};
+ PyObject* uperiodic = Py_False;
+ PyObject* vperiodic = Py_False;
+ PyObject* poles = Py_None;
+ PyObject* umults = Py_None;
+ PyObject* vmults = Py_None;
+ PyObject* uknots = Py_None;
+ PyObject* vknots = Py_None;
+ PyObject* weights = Py_None;
+ int udegree = 3;
+ int vdegree = 3;
+ int number_of_uknots = 0;
+ int number_of_vknots = 0;
+ int sum_of_umults = 0;
+ int sum_of_vmults = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "OOO|OOO!O!iiO", kwlist,
+ &poles, &umults, &vmults, //required
+ &uknots, &vknots, //optional
+ &PyBool_Type, &uperiodic, &PyBool_Type, &vperiodic, //optinoal
+ &udegree, &vdegree, &weights)) //optional
+ return 0;
+ try {
+ Py::Sequence list(poles);
+ Standard_Integer lu = list.size();
+ Py::Sequence col(list.getItem(0));
+ Standard_Integer lv = col.size();
+ TColgp_Array2OfPnt occpoles(1, lu, 1, lv);
+ TColStd_Array2OfReal occweights(1, lu, 1, lv);
+ Standard_Boolean genweights = PyObject_Not(weights) ; //cache
+ Standard_Integer index1 = 0;
+ Standard_Integer index2 = 0;
+ for (Py::Sequence::iterator it1 = list.begin(); it1 != list.end(); ++it1) {
+ index1++;
+ index2=0;
+ Py::Sequence row(*it1);
+ for (Py::Sequence::iterator it2 = row.begin(); it2 != row.end(); ++it2) {
+ index2++;
+ Py::Vector v(*it2);
+ Base::Vector3d pnt = v.toVector();
+ gp_Pnt newPoint(pnt.x,pnt.y,pnt.z);
+ occpoles.SetValue(index1, index2, newPoint);
+ if (genweights) occweights.SetValue(index1, index2, 1.0); //set weights if they are not given
+ }
+ }
+ if (occpoles.RowLength() < 2 || occpoles.ColLength() < 2) {
+ Standard_Failure::Raise("not enough points given");
+ }
+ if (!genweights) {//copy the weights
+ Py::Sequence list(weights);
+ Standard_Integer lwu = list.size();
+ Py::Sequence col(list.getItem(0));
+ Standard_Integer lwv = col.size();
+ if (lwu != lu || lwv != lv) { Standard_Failure::Raise("weights and poles mismatch");}
+ Standard_Integer index1 = 0;
+ Standard_Integer index2 = 0;
+ for (Py::Sequence::iterator it1 = list.begin(); it1 != list.end(); ++it1) {
+ index1++;
+ index2=0;
+ Py::Sequence row(*it1);
+ for (Py::Sequence::iterator it2 = row.begin(); it2 != row.end(); ++it2) {
+ index2++;
+ Py::Float f(*it2);
+ occweights.SetValue(index1, index2, f);
+ }
+ }
+ }
+ number_of_uknots = PyObject_Length(umults);
+ number_of_vknots = PyObject_Length(vmults);
+ if ((PyObject_IsTrue(uknots) && PyObject_Length(uknots) != number_of_uknots) ||
+ (PyObject_IsTrue(vknots) && PyObject_Length(vknots) != number_of_vknots)){
+ Standard_Failure::Raise("number of knots and mults mismatch");
+ return 0;
+ }
+ //copy mults
+ TColStd_Array1OfInteger occumults(1,number_of_uknots);
+ TColStd_Array1OfInteger occvmults(1,number_of_vknots);
+ TColStd_Array1OfReal occuknots(1,number_of_uknots);
+ TColStd_Array1OfReal occvknots(1,number_of_vknots);
+ Py::Sequence umultssq(umults);
+ Standard_Integer index = 1;
+ for (Py::Sequence::iterator it = umultssq.begin(); it != umultssq.end() && index <= occumults.Length(); ++it) {
+ Py::Int mult(*it);
+ if (index < occumults.Length() || PyObject_Not(uperiodic)) {
+ sum_of_umults += mult; //sum up the mults to compare them against the number of poles later
+ }
+ occumults(index++) = mult;
+ }
+ Py::Sequence vmultssq(vmults);
+ index = 1;
+ for (Py::Sequence::iterator it = vmultssq.begin(); it != vmultssq.end() && index <= occvmults.Length(); ++it) {
+ Py::Int mult(*it);
+ if (index < occvmults.Length() || PyObject_Not(vperiodic)) {
+ sum_of_vmults += mult; //sum up the mults to compare them against the number of poles later
+ }
+ occvmults(index++) = mult;
+ }
+ //copy or generate knots
+ if (uknots != Py_None) { //uknots are given
+ Py::Sequence uknotssq(uknots);
+ index = 1;
+ for (Py::Sequence::iterator it = uknotssq.begin(); it != uknotssq.end() && index <= occuknots.Length(); ++it) {
+ Py::Float knot(*it);
+ occuknots(index++) = knot;
+ }
+ }
+ else { // knotes are uniformly spaced 0..1 if not given
+ for (int i=1; i<=occuknots.Length(); i++){
+ occuknots.SetValue(i,(double)(i-1)/(occuknots.Length()-1));
+ }
+ }
+ if (vknots != Py_None) { //vknots are given
+ Py::Sequence vknotssq(vknots);
+ index = 1;
+ for (Py::Sequence::iterator it = vknotssq.begin(); it != vknotssq.end() && index <= occvknots.Length(); ++it) {
+ Py::Float knot(*it);
+ occvknots(index++) = knot;
+ }
+ }
+ else { // knotes are uniformly spaced 0..1 if not given
+ for (int i=1; i<=occvknots.Length(); i++){
+ occvknots.SetValue(i,(double)(i-1)/(occvknots.Length()-1));
+ }
+ }
+ if ((PyObject_IsTrue(uperiodic) && sum_of_umults != lu) ||
+ (PyObject_Not(uperiodic) && sum_of_umults - udegree -1 != lu) ||
+ (PyObject_IsTrue(vperiodic) && sum_of_vmults != lv) ||
+ (PyObject_Not(vperiodic) && sum_of_vmults - vdegree -1 != lv)) {
+ Standard_Failure::Raise("number of poles and sum of mults mismatch");
+ }
+ Handle_Geom_BSplineSurface spline = new Geom_BSplineSurface(occpoles,occweights,
+ occuknots,occvknots,occumults,occvmults,udegree,vdegree,
+ PyObject_IsTrue(uperiodic),PyObject_IsTrue(vperiodic));
+ if (!spline.IsNull()) {
+ this->getGeomBSplineSurfacePtr()->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(PyExc_Exception, msg ? msg : "");
+ return 0;
+ }
+}
+
Py::Int BSplineSurfacePy::getUDegree(void) const
{
Handle_Geom_BSplineSurface surf = Handle_Geom_BSplineSurface::DownCast