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>
This commit is contained in:
Rayno Jiang
2025-05-09 06:02:33 +08:00
committed by GitHub
parent 30498b7b48
commit a5a6ed55e2

View File

@@ -195,6 +195,29 @@ std::string PythonConverter::convert(const std::string& doc,
return constraintlist;
}
template<typename T>
std::string makeSplineInfoArrayString(const std::vector<T>& rInfoVec)
{
std::stringstream stream;
if constexpr (std::is_same_v<T, Base::Vector3d>) {
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<const Base::Type, std::function<SingleGeometry(const Part::Geometry* geo)>>
@@ -307,23 +330,17 @@ PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry* g
[](const Part::Geometry* geo) {
auto bSpline = static_cast<const Part::GeomBSplineCurve*>(geo);
std::stringstream stream;
std::vector<Base::Vector3d> 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;
}},