From 3832db01ff3c47466dd7df49ae6c630a2249aa19 Mon Sep 17 00:00:00 2001 From: Ajinkya Dahale Date: Mon, 23 Dec 2024 13:48:18 +0530 Subject: [PATCH] [Sketcher] Refactor `SketchObject::modifyBSplineKnotMultiplicity` --- src/Mod/Sketcher/App/SketchObject.cpp | 138 +++++++++++--------------- 1 file changed, 60 insertions(+), 78 deletions(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 386166ef9e4c..aaf81eb3fe1f 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -7166,63 +7166,70 @@ bool SketchObject::modifyBSplineKnotMultiplicity(int GeoId, int knotIndex, int m if (GeoId < 0 || GeoId > getHighestCurveIndex()) { THROWMT( Base::ValueError, - QT_TRANSLATE_NOOP("Exceptions", "B-spline Geometry Index (GeoID) is out of bounds.")) + QT_TRANSLATE_NOOP("Exceptions", "B-spline Geometry Index (GeoID) is out of bounds.")); } - if (multiplicityincr == 0)// no change in multiplicity + if (multiplicityincr == 0) { + // no change in multiplicity THROWMT( Base::ValueError, - QT_TRANSLATE_NOOP("Exceptions", "You are requesting no change in knot multiplicity.")) + QT_TRANSLATE_NOOP("Exceptions", "You are requesting no change in knot multiplicity.")); + } const Part::Geometry* geo = getGeometry(GeoId); - if (geo->getTypeId() != Part::GeomBSplineCurve::getClassTypeId()) + if (geo->getTypeId() != Part::GeomBSplineCurve::getClassTypeId()) { THROWMT(Base::TypeError, QT_TRANSLATE_NOOP("Exceptions", - "The Geometry Index (GeoId) provided is not a B-spline.")) + "The Geometry Index (GeoId) provided is not a B-spline.")); + } const Part::GeomBSplineCurve* bsp = static_cast(geo); int degree = bsp->getDegree(); - if (knotIndex > bsp->countKnots() || knotIndex < 1)// knotindex in OCC 1 -> countKnots + if (knotIndex > bsp->countKnots() || knotIndex < 1) { + // knotindex in OCC 1 -> countKnots THROWMT(Base::ValueError, QT_TRANSLATE_NOOP("Exceptions", "The knot index is out of bounds. Note that in accordance with " - "OCC notation, the first knot has index 1 and not zero.")) + "OCC notation, the first knot has index 1 and not zero.")); + } std::unique_ptr bspline; int curmult = bsp->getMultiplicity(knotIndex); // zero is removing the knot, degree is just positional continuity - if ((curmult + multiplicityincr) > degree) + if ((curmult + multiplicityincr) > degree) { THROWMT(Base::ValueError, QT_TRANSLATE_NOOP( "Exceptions", - "The multiplicity cannot be increased beyond the degree of the B-spline.")) + "The multiplicity cannot be increased beyond the degree of the B-spline.")); + } // zero is removing the knot, degree is just positional continuity - if ((curmult + multiplicityincr) < 0) + if ((curmult + multiplicityincr) < 0) { THROWMT( Base::ValueError, - QT_TRANSLATE_NOOP("Exceptions", "The multiplicity cannot be decreased beyond zero.")) + QT_TRANSLATE_NOOP("Exceptions", "The multiplicity cannot be decreased beyond zero.")); + } try { bspline.reset(static_cast(bsp->clone())); - if (multiplicityincr > 0) {// increase multiplicity + if (multiplicityincr > 0) { // increase multiplicity bspline->increaseMultiplicity(knotIndex, curmult + multiplicityincr); } - else {// decrease multiplicity + else { // decrease multiplicity bool result = bspline->removeKnot(knotIndex, curmult + multiplicityincr, 1E6); - if (!result) - THROWMT( - Base::CADKernelError, - QT_TRANSLATE_NOOP( - "Exceptions", - "OCC is unable to decrease the multiplicity within the maximum tolerance.")) + if (!result) { + THROWMT(Base::CADKernelError, + QT_TRANSLATE_NOOP("Exceptions", + "OCC is unable to decrease the multiplicity within the " + "maximum tolerance.")); + } } } catch (const Base::Exception& e) { @@ -7232,87 +7239,62 @@ bool SketchObject::modifyBSplineKnotMultiplicity(int GeoId, int knotIndex, int m // we succeeded with the multiplicity modification, so alignment geometry may be // invalid/inconsistent for the new bspline - std::vector delGeoId; std::vector poles = bsp->getPoles(); std::vector newpoles = bspline->getPoles(); - std::vector prevpole(bsp->countPoles()); + std::vector poleIndexInNew(bsp->countPoles(), -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; - } - } + 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 knots = bsp->getKnots(); std::vector newknots = bspline->getKnots(); - std::vector prevknot(bsp->countKnots()); - - for (int i = 0; i < int(knots.size()); i++) - prevknot[i] = -1; + std::vector knotIndexInNew(bsp->countKnots(), -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; - } - } + const auto it = std::find(newknots.begin(), newknots.end(), knots[j]); + knotIndexInNew[j] = it - newknots.begin(); } const std::vector& cvals = Constraints.getValues(); std::vector newcVals(0); - // modify pole constraints - for (std::vector::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* 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& vals = getInternalGeometry();