diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp index 43087c5b7e..2f86b87185 100644 --- a/src/Mod/Part/App/Geometry.cpp +++ b/src/Mod/Part/App/Geometry.cpp @@ -1186,15 +1186,36 @@ void GeomBSplineCurve::setPole(int index, const Base::Vector3d& pole, double wei } } +void GeomBSplineCurve::workAroundOCCTBug(const std::vector& weights) +{ + // If during assignment of weights (during the for loop below) all weights + // become (temporarily) equal even though weights does not have equal values + // OCCT will convert all the weights (the already assigned and those not yet assigned) + // to 1.0 (nonrational b-splines have 1.0 weights). This may lead to the assignment of wrong + // of weight values. + // + // Little hack is to set the last weight to a value different from last but one current and to-be-assigned + + if (weights.size() < 2) // at least two poles/weights + return; + + auto lastindex = myCurve->NbPoles(); // OCCT is base-1 + auto lastbutonevalue = myCurve->Weight(lastindex-1); + double fakelastvalue = lastbutonevalue + weights[weights.size()-2]; + myCurve->SetWeight(weights.size(),fakelastvalue); +} + void GeomBSplineCurve::setPoles(const std::vector& poles, const std::vector& weights) { if (poles.size() != weights.size()) throw Base::ValueError("poles and weights mismatch"); + workAroundOCCTBug(weights); + Standard_Integer index=1; - for (std::size_t it = 0; it < poles.size(); it++, index++) { - setPole(index, poles[it], weights[it]); + for (std::size_t i = 0; i < poles.size(); i++, index++) { + setPole(index, poles[i], weights[i]); } } @@ -1237,6 +1258,8 @@ std::vector GeomBSplineCurve::getWeights() const void GeomBSplineCurve::setWeights(const std::vector& weights) { + workAroundOCCTBug(weights); + try { Standard_Integer index=1; diff --git a/src/Mod/Part/App/Geometry.h b/src/Mod/Part/App/Geometry.h index d52d09fa40..b1f9568298 100644 --- a/src/Mod/Part/App/Geometry.h +++ b/src/Mod/Part/App/Geometry.h @@ -324,6 +324,16 @@ private: bool calculateBiArcPoints(const gp_Pnt& p0, gp_Vec v_start, const gp_Pnt& p4, gp_Vec v_end, gp_Pnt& p1, gp_Pnt& p2, gp_Pnt& p3) const; + + // If during assignment of weights (during the for loop iteratively setting the poles) all weights + // become (temporarily) equal even though weights does not have equal values + // OCCT will convert all the weights (the already assigned and those not yet assigned) + // to 1.0 (nonrational b-splines have 1.0 weights). This may lead to the assignment of wrong + // of weight values. + // + // The work-around is to temporarily set the last weight to be assigned to a value different from + // the current value and the to-be-assigned value for the weight at position last-to-be-assign but one. + void workAroundOCCTBug(const std::vector& weights); private: Handle(Geom_BSplineCurve) myCurve; };