[Sketcher] Refactor SketchObject::insertBSplineKnot()
This commit is contained in:
@@ -7349,38 +7349,43 @@ bool SketchObject::insertBSplineKnot(int GeoId, double param, int multiplicity)
|
||||
Base::StateLocker lock(managedoperation, true);
|
||||
|
||||
// handling unacceptable cases
|
||||
if (GeoId < 0 || GeoId > getHighestCurveIndex())
|
||||
if (GeoId < 0 || GeoId > getHighestCurveIndex()) {
|
||||
THROWMT(
|
||||
Base::ValueError,
|
||||
QT_TRANSLATE_NOOP("Exceptions", "B-spline Geometry Index (GeoID) is out of bounds."));
|
||||
}
|
||||
|
||||
if (multiplicity == 0)
|
||||
if (multiplicity == 0) {
|
||||
THROWMT(Base::ValueError,
|
||||
QT_TRANSLATE_NOOP("Exceptions", "Knot cannot have zero multiplicity."));
|
||||
}
|
||||
|
||||
const Part::Geometry* geo = getGeometry(GeoId);
|
||||
|
||||
if (geo->getTypeId() != Part::GeomBSplineCurve::getClassTypeId())
|
||||
if (!geo->is<Part::GeomBSplineCurve>()) {
|
||||
THROWMT(Base::TypeError,
|
||||
QT_TRANSLATE_NOOP("Exceptions",
|
||||
"The Geometry Index (GeoId) provided is not a B-spline."));
|
||||
}
|
||||
|
||||
const Part::GeomBSplineCurve* bsp = static_cast<const Part::GeomBSplineCurve*>(geo);
|
||||
const auto* bsp = static_cast<const Part::GeomBSplineCurve*>(geo);
|
||||
|
||||
int degree = bsp->getDegree();
|
||||
double firstParam = bsp->getFirstParameter();
|
||||
double lastParam = bsp->getLastParameter();
|
||||
|
||||
if (multiplicity > degree)
|
||||
if (multiplicity > degree) {
|
||||
THROWMT(Base::ValueError,
|
||||
QT_TRANSLATE_NOOP(
|
||||
"Exceptions",
|
||||
"Knot multiplicity cannot be higher than the degree of the B-spline."));
|
||||
}
|
||||
|
||||
if (param > lastParam || param < firstParam)
|
||||
if (param > lastParam || param < firstParam) {
|
||||
THROWMT(Base::ValueError,
|
||||
QT_TRANSLATE_NOOP("Exceptions",
|
||||
"Knot cannot be inserted outside the B-spline parameter range."));
|
||||
}
|
||||
|
||||
std::unique_ptr<Part::GeomBSplineCurve> bspline;
|
||||
|
||||
@@ -7400,89 +7405,64 @@ bool SketchObject::insertBSplineKnot(int GeoId, double param, int multiplicity)
|
||||
|
||||
std::vector<Base::Vector3d> poles = bsp->getPoles();
|
||||
std::vector<Base::Vector3d> newpoles = bspline->getPoles();
|
||||
std::vector<int> prevpole(bsp->countPoles());
|
||||
std::vector<int> poleIndexInNew(poles.size(), -1);
|
||||
|
||||
for (int i = 0; i < int(poles.size()); i++)
|
||||
prevpole[i] = -1;
|
||||
|
||||
int taken = 0;
|
||||
for (int j = 0; j < int(poles.size()); j++) {
|
||||
for (int i = taken; i < int(newpoles.size()); i++) {
|
||||
if (newpoles[i] == poles[j]) {
|
||||
prevpole[j] = i;
|
||||
taken++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (size_t j = 0; j < poles.size(); j++) {
|
||||
const auto it = std::find(newpoles.begin(), newpoles.end(), poles[j]);
|
||||
poleIndexInNew[j] = it - newpoles.begin();
|
||||
}
|
||||
|
||||
// on fully removing a knot the knot geometry changes
|
||||
std::vector<double> knots = bsp->getKnots();
|
||||
std::vector<double> newknots = bspline->getKnots();
|
||||
std::vector<int> prevknot(bsp->countKnots());
|
||||
std::vector<int> knotIndexInNew(knots.size(), -1);
|
||||
|
||||
for (int i = 0; i < int(knots.size()); i++)
|
||||
prevknot[i] = -1;
|
||||
|
||||
taken = 0;
|
||||
for (int j = 0; j < int(knots.size()); j++) {
|
||||
for (int i = taken; i < int(newknots.size()); i++) {
|
||||
if (newknots[i] == knots[j]) {
|
||||
prevknot[j] = i;
|
||||
taken++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (size_t j = 0; j < knots.size(); j++) {
|
||||
const auto it = std::find(newknots.begin(), newknots.end(), knots[j]);
|
||||
knotIndexInNew[j] = it - newknots.begin();
|
||||
}
|
||||
|
||||
const std::vector<Sketcher::Constraint*>& cvals = Constraints.getValues();
|
||||
|
||||
std::vector<Constraint*> newcVals(0);
|
||||
|
||||
// modify pole constraints
|
||||
for (std::vector<Sketcher::Constraint*>::const_iterator it = cvals.begin(); it != cvals.end();
|
||||
++it) {
|
||||
if ((*it)->Type == Sketcher::InternalAlignment && (*it)->Second == GeoId) {
|
||||
if ((*it)->AlignmentType == Sketcher::BSplineControlPoint) {
|
||||
if (prevpole[(*it)->InternalAlignmentIndex] != -1) {
|
||||
assert(prevpole[(*it)->InternalAlignmentIndex] < bspline->countPoles());
|
||||
Constraint* newConstr = (*it)->clone();
|
||||
newConstr->InternalAlignmentIndex = prevpole[(*it)->InternalAlignmentIndex];
|
||||
newcVals.push_back(newConstr);
|
||||
}
|
||||
else {
|
||||
// it is an internal alignment geometry that is no longer valid => delete it and
|
||||
// the pole circle
|
||||
delGeoId.push_back((*it)->First);
|
||||
}
|
||||
}
|
||||
else if ((*it)->AlignmentType == Sketcher::BSplineKnotPoint) {
|
||||
if (prevknot[(*it)->InternalAlignmentIndex] != -1) {
|
||||
assert(prevknot[(*it)->InternalAlignmentIndex] < bspline->countKnots());
|
||||
Constraint* newConstr = (*it)->clone();
|
||||
newConstr->InternalAlignmentIndex = prevknot[(*it)->InternalAlignmentIndex];
|
||||
newcVals.push_back(newConstr);
|
||||
}
|
||||
else {
|
||||
// it is an internal alignment geometry that is no longer valid => delete it and
|
||||
// the knot point
|
||||
delGeoId.push_back((*it)->First);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// it is a bspline geometry, but not a controlpoint or knot
|
||||
newcVals.push_back(*it);
|
||||
}
|
||||
// modify pole and knot constraints
|
||||
for (const auto& constr : cvals) {
|
||||
if (!(constr->Type == Sketcher::InternalAlignment && constr->Second == GeoId)) {
|
||||
newcVals.push_back(constr);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<int>* indexInNew = nullptr;
|
||||
|
||||
if (constr->AlignmentType == Sketcher::BSplineControlPoint) {
|
||||
indexInNew = &poleIndexInNew;
|
||||
}
|
||||
else if (constr->AlignmentType == Sketcher::BSplineKnotPoint) {
|
||||
indexInNew = &knotIndexInNew;
|
||||
}
|
||||
else {
|
||||
newcVals.push_back(*it);
|
||||
// it is a bspline geometry, but not a controlpoint or knot
|
||||
newcVals.push_back(constr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (indexInNew && indexInNew->at(constr->InternalAlignmentIndex) == -1) {
|
||||
// it is an internal alignment geometry that is no longer valid
|
||||
// => delete it and the pole circle
|
||||
delGeoId.push_back(constr->First);
|
||||
continue;
|
||||
}
|
||||
|
||||
Constraint* newConstr = constr->clone();
|
||||
newConstr->InternalAlignmentIndex = indexInNew->at(constr->InternalAlignmentIndex);
|
||||
newcVals.push_back(newConstr);
|
||||
}
|
||||
|
||||
const std::vector<Part::Geometry*>& vals = getInternalGeometry();
|
||||
|
||||
std::vector<Part::Geometry*> newVals(vals);
|
||||
|
||||
GeometryFacade::copyId(geo, bspline.get());
|
||||
newVals[GeoId] = bspline.release();
|
||||
|
||||
// Block acceptGeometry in OnChanged to avoid unnecessary checks and updates
|
||||
@@ -7506,12 +7486,11 @@ bool SketchObject::insertBSplineKnot(int GeoId, double param, int multiplicity)
|
||||
// See 247a9f0876a00e08c25b07d1f8802479d8623e87 for suggestions.
|
||||
// Geometry.touch();
|
||||
delGeometriesExclusiveList(delGeoId);
|
||||
}
|
||||
else {
|
||||
Geometry.touch();
|
||||
return true;
|
||||
}
|
||||
|
||||
// handle this last return
|
||||
Geometry.touch();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user