From a5a6ed55e2cc4ec1daaa2160fc72328b064bc7a1 Mon Sep 17 00:00:00 2001 From: Rayno Jiang <46101316+RaynoJiang@users.noreply.github.com> Date: Fri, 9 May 2025 06:02:33 +0800 Subject: [PATCH] Sketcher: Scaling of a sketch containing BSplines doesn't work (#20943) * [FreeCAD-20111] Sketcher: Scaling of a sketch containing BSplines doesn't work When we executing Scale cmd we don't will lose knots information from shape geometry and it cause the scaled spline build with issue knots and it lead solver gets compute issue. 1. Add string format function PythonConverter::makeArryString(const std::stringstream& ss) for processing the control pnts string, mults string and knots string. 2. Add mults and knots information for python obj to make BSplineCurvePy::buildFromPolesMultsKnots(Args...) initialized Geom_BSplineCurve correctly. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * 1. fix typo 2. Add wights info to keep spline shape after convert from python object * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * 1. remove static function makeArrayString() from PythonConverter 1. Add template function makeSplineInfoArrayString() to generate string for cleaner code. 2. change python string format as review suggestion * use fmt format * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Fixes #20111 --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- src/Mod/Sketcher/App/PythonConverter.cpp | 47 ++++++++++++++++-------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/src/Mod/Sketcher/App/PythonConverter.cpp b/src/Mod/Sketcher/App/PythonConverter.cpp index 7c7dbdae19..f5795615fe 100644 --- a/src/Mod/Sketcher/App/PythonConverter.cpp +++ b/src/Mod/Sketcher/App/PythonConverter.cpp @@ -195,6 +195,29 @@ std::string PythonConverter::convert(const std::string& doc, return constraintlist; } +template +std::string makeSplineInfoArrayString(const std::vector& rInfoVec) +{ + std::stringstream stream; + if constexpr (std::is_same_v) { + for (const auto& rInfo : rInfoVec) { + stream << "App.Vector(" << rInfo.x << ", " << rInfo.y << "), "; + } + } + else { + for (const auto& rInfo : rInfoVec) { + stream << rInfo << ", "; + } + } + + std::string res = stream.str(); + // remove last comma and add brackets + int index = res.rfind(','); + res.resize(index); + return fmt::format("[{}]", res); + ; +} + PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry* geo) { static std::map> @@ -307,23 +330,17 @@ PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry* g [](const Part::Geometry* geo) { auto bSpline = static_cast(geo); - std::stringstream stream; - std::vector poles = bSpline->getPoles(); - for (auto& pole : poles) { - stream << "App.Vector(" << pole.x << "," << pole.y << "),"; - } - std::string controlpoints = stream.str(); - // remove last comma and add brackets - int index = controlpoints.rfind(','); - controlpoints.resize(index); - controlpoints.insert(0, 1, '['); - controlpoints.append(1, ']'); + std::string controlpoints = makeSplineInfoArrayString(bSpline->getPoles()); + std::string mults = makeSplineInfoArrayString(bSpline->getMultiplicities()); + std::string knots = makeSplineInfoArrayString(bSpline->getKnots()); + std::string weights = makeSplineInfoArrayString(bSpline->getWeights()); SingleGeometry sg; - sg.creation = boost::str( - boost::format("Part.BSplineCurve (%s, None, None, %s, %d, None, False)") - % controlpoints.c_str() % (bSpline->isPeriodic() ? "True" : "False") - % bSpline->getDegree()); + sg.creation = + boost::str(boost::format("Part.BSplineCurve(%s, %s, %s, %s, %d, %s, False)") + % controlpoints.c_str() % mults.c_str() % knots.c_str() + % (bSpline->isPeriodic() ? "True" : "False") % bSpline->getDegree() + % weights.c_str()); sg.construction = Sketcher::GeometryFacade::getConstruction(geo); return sg; }},