Part: Geometry - BSpline - fix weight assignment

================================================

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.

Fixes:
https://forum.freecadweb.org/viewtopic.php?p=478701#p478702
This commit is contained in:
Abdullah Tahiri
2021-02-18 16:09:07 +01:00
parent 08e226df25
commit 324f6d3e26
2 changed files with 35 additions and 2 deletions

View File

@@ -1186,15 +1186,36 @@ void GeomBSplineCurve::setPole(int index, const Base::Vector3d& pole, double wei
}
}
void GeomBSplineCurve::workAroundOCCTBug(const std::vector<double>& 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<Base::Vector3d>& poles, const std::vector<double>& 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<double> GeomBSplineCurve::getWeights() const
void GeomBSplineCurve::setWeights(const std::vector<double>& weights)
{
workAroundOCCTBug(weights);
try {
Standard_Integer index=1;

View File

@@ -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<double>& weights);
private:
Handle(Geom_BSplineCurve) myCurve;
};