[Sketcher] Constrain B-spline knots as linear combination of poles
Also squashes: [Sketcher] Create center of gravity constraint in planegcs [Sketcher] typo [Sketcher] Use accurate "weights" for knots By weights we mean the linear combination factor B_i(x) such that spline(x) = sum(pole_i * B_i(x)) for _non-rational_ splines. [Sketcher] Use more appropriate weights for knots These are relevant for knots _away_ from any ends (and possibly other high multiplicity knots). [Sketcher] Make COG constraint weights user-definable [Sketcher] Make `flattenedknots` for periodic B-Splines [Sketcher] Fix incorrect setup of `flattenedknots` Without ensuring enough space, iterators become invalid. These iterators are needed because for periodic B-splines we need to pad flattenedknots with offset values within flattenedknots. Apparently there is still some iterator issues even after the reserve. Just use fresh vectors instead. [Sketcher] Apply knot constraints by parameter Hopefully this will allow directly applying constraints on knots. [Sketcher] Disable some knot updating [Sketcher] Use center of gravity constraint on knots [Sketcher] Fix knot COG constraint for periodic splines [Sketcher] Add start/end point of periodic spline to solver This removes the trouble of transferring constraints to the underlying knot. [Sketcher] Support knot constraints on rational B-splines [Sketcher] Remove virtual from overridden methods in planegcs Follow 0penbrain's comments [Sketcher][planegcs] Use `unsigned int` in signatures Also `size_t` at places Suggestions by @abdullahtahiriyo
This commit is contained in:
committed by
abdullahtahiriyo
parent
027504ce16
commit
7cd2cbd29c
@@ -1326,13 +1326,63 @@ int System::addConstraintInternalAlignmentParabolaFocus(Parabola &e, Point &p1,
|
||||
return addConstraintEqual(e.focus1.y, p1.y, tagId, driving, Constraint::Alignment::InternalAlignment);
|
||||
}
|
||||
|
||||
int System::addConstraintInternalAlignmentBSplineControlPoint(BSpline &b, Circle &c, int poleindex, int tagId, bool driving)
|
||||
int System::addConstraintInternalAlignmentBSplineControlPoint(BSpline &b, Circle &c, unsigned int poleindex, int tagId, bool driving)
|
||||
{
|
||||
addConstraintEqual(b.poles[poleindex].x, c.center.x, tagId, driving, Constraint::Alignment::InternalAlignment);
|
||||
addConstraintEqual(b.poles[poleindex].y, c.center.y, tagId, driving, Constraint::Alignment::InternalAlignment);
|
||||
return addConstraintEqual(b.weights[poleindex], c.rad, tagId, driving, Constraint::Alignment::InternalAlignment);
|
||||
}
|
||||
|
||||
int System::addConstraintInternalAlignmentKnotPoint(BSpline &b, Point &p, unsigned int knotindex, int tagId, bool driving)
|
||||
{
|
||||
if (b.periodic && knotindex == 0) {
|
||||
// This is done here since knotpoints themselves aren't stored
|
||||
addConstraintP2PCoincident(p, b.start, tagId, driving);
|
||||
addConstraintP2PCoincident(p, b.end, tagId, driving);
|
||||
}
|
||||
|
||||
size_t numpoles = b.degree - b.mult[knotindex] + 1;
|
||||
if (numpoles == 0)
|
||||
numpoles = 1;
|
||||
|
||||
size_t startpole = 0;
|
||||
std::vector<double *> pvec;
|
||||
pvec.push_back(p.x);
|
||||
|
||||
std::vector<double> weights(numpoles, 1.0 / numpoles);
|
||||
|
||||
// TODO: Adjust for periodic knot
|
||||
for (size_t j = 1; j <= knotindex; ++j)
|
||||
startpole += b.mult[j];
|
||||
if (!b.periodic && startpole >= b.poles.size())
|
||||
startpole = b.poles.size() - 1;
|
||||
for (size_t i = 0; i < numpoles; ++i) {
|
||||
pvec.push_back(b.poles[(startpole + i) % b.poles.size()].x);
|
||||
// FIXME: `getLinCombFactor` seg-faults for the last knot so this safeguard exists
|
||||
if (numpoles > 2)
|
||||
weights[i] = b.getLinCombFactor(*(b.knots[knotindex]), startpole + b.degree, startpole + i);
|
||||
}
|
||||
for (size_t i = 0; i < numpoles; ++i)
|
||||
pvec.push_back(b.weights[(startpole + i) % b.poles.size()]);
|
||||
|
||||
Constraint *constr = new ConstraintWeightedLinearCombination(numpoles, pvec, weights);
|
||||
constr->setTag(tagId);
|
||||
constr->setDriving(driving);
|
||||
addConstraint(constr);
|
||||
|
||||
pvec.clear();
|
||||
pvec.push_back(p.y);
|
||||
for (size_t i = 0; i < numpoles; ++i)
|
||||
pvec.push_back(b.poles[(startpole + i) % b.poles.size()].y);
|
||||
for (size_t i = 0; i < numpoles; ++i)
|
||||
pvec.push_back(b.weights[(startpole + i) % b.poles.size()]);
|
||||
|
||||
constr = new ConstraintWeightedLinearCombination(numpoles, pvec, weights);
|
||||
constr->setTag(tagId);
|
||||
constr->setDriving(driving);
|
||||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
//calculates angle between two curves at point of their intersection p. If two
|
||||
//points are supplied, p is used for first curve and p2 for second, yielding a
|
||||
//remote angle computation (this is useful when the endpoints haven't) been
|
||||
|
||||
Reference in New Issue
Block a user