From 6dda56117a7c8a334b00a67a539224426553716e Mon Sep 17 00:00:00 2001 From: Ajinkya Dahale Date: Fri, 5 Jan 2024 20:54:31 +0530 Subject: [PATCH] [Sketcher] Visualize B-spline in edit mode Instead of the control polygon, or "join the dots" for interpolated splines. --- .../Sketcher/Gui/DrawSketchHandlerBSpline.h | 43 +++++++++++++++++-- .../DrawSketchHandlerBSplineByInterpolation.h | 25 +++++++++-- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerBSpline.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerBSpline.h index 080ffac50b..2cae185c6e 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerBSpline.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerBSpline.h @@ -90,7 +90,7 @@ public: } else if (Mode == STATUS_SEEK_ADDITIONAL_CONTROLPOINTS) { - drawControlPolygonToPosition(onSketchPos); + drawBSplineToPosition(onSketchPos); drawCursorToPosition(onSketchPos); @@ -313,7 +313,7 @@ public: // run this in the end to draw lines and position text - drawControlPolygonToPosition(prevCursorPosition); + drawBSplineToPosition(prevCursorPosition); drawCursorToPosition(prevCursorPosition); } catch (const Base::Exception&) { @@ -414,13 +414,50 @@ private: void drawControlPolygonToPosition(Base::Vector2d position) { - std::vector editcurve(BSplinePoles); editcurve.push_back(position); drawEdit(editcurve); } + void drawBSplineToPosition(Base::Vector2d position) + { + std::vector editcurve; + for (auto& pole : BSplinePoles) { + editcurve.emplace_back(pole.x, pole.y, 0.0); + } + editcurve.emplace_back(position.x, position.y, 0.0); + size_t degree = std::min(editcurve.size() - 1, static_cast(SplineDegree)); + bool periodic = (ConstrMethod != 0); + + std::vector weights(editcurve.size(), 1.0); + std::vector knots; + std::vector mults; + if (!periodic) { + for (size_t i = 0; i < editcurve.size() - degree + 1; ++i) { + knots.push_back(i); + } + mults.resize(editcurve.size() - degree + 1, 1); + mults.front() = degree + 1; + mults.back() = degree + 1; + } + else { + for (size_t i = 0; i < editcurve.size() + 1; ++i) { + knots.push_back(i); + } + mults.resize(editcurve.size() + 1, 1); + } + + // TODO: This maybe optimized by storing the spline as an attribute. + Part::GeomBSplineCurve editBSpline(editcurve, weights, knots, mults, degree, periodic); + editBSpline.setPoles(editcurve); + + std::vector editBSplines; + editBSplines.push_back(&editBSpline); + + drawEdit(editBSplines); + } + void drawCursorToPosition(Base::Vector2d position) { if (!BSplinePoles.empty()) { diff --git a/src/Mod/Sketcher/Gui/DrawSketchHandlerBSplineByInterpolation.h b/src/Mod/Sketcher/Gui/DrawSketchHandlerBSplineByInterpolation.h index 593c5f9cf9..3880a0c741 100644 --- a/src/Mod/Sketcher/Gui/DrawSketchHandlerBSplineByInterpolation.h +++ b/src/Mod/Sketcher/Gui/DrawSketchHandlerBSplineByInterpolation.h @@ -90,7 +90,7 @@ public: } else if (Mode == STATUS_SEEK_ADDITIONAL_POINTS) { - drawControlPolygonToPosition(onSketchPos); + drawBSplineToPosition(onSketchPos); drawCursorToPosition(onSketchPos); @@ -311,7 +311,7 @@ public: // run this in the end to draw lines and position text - drawControlPolygonToPosition(prevCursorPosition); + drawBSplineToPosition(prevCursorPosition); drawCursorToPosition(prevCursorPosition); } catch (const Base::Exception&) { @@ -409,13 +409,32 @@ private: // NOTE: In this context, it is not a control polygon, but a 1-degree interpolation void drawControlPolygonToPosition(Base::Vector2d position) { - std::vector editcurve(BSplineKnots); editcurve.push_back(position); drawEdit(editcurve); } + void drawBSplineToPosition(Base::Vector2d position) + { + std::vector editcurve(BSplineKnots); + editcurve.push_back(position); + + std::vector editCurveForOCCT; + for (auto& p : editcurve) { + editCurveForOCCT.emplace_back(p.x, p.y, 0.0); + } + + // TODO: This maybe optimized by storing the spline as an attribute. + Part::GeomBSplineCurve editBSpline; + editBSpline.interpolate(editCurveForOCCT, ConstrMethod != 0); + + std::vector editBSplines; + editBSplines.push_back(&editBSpline); + + drawEdit(editBSplines); + } + void drawCursorToPosition(Base::Vector2d position) { if (!BSplineKnots.empty()) {