Sketcher: Support Bezier and Offset curves as external geometry (#25144)

* Sketcher: Support Bezier and Offset curves as external geometry

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Sketcher: Fix adding projection of external arc of circle

In processEdge() it's checked if first and last point of the projected arc of circle are almost equal. If yes then a full circle
is assumed but this conclusion is not necessarily correct because it's still possible that the external arc of circle is very
short. The better criterion is to check the parameter range of the arc of circle.

See also: https://github.com/FreeCAD/FreeCAD/pull/25144#issuecomment-3502916685

---------

Co-authored-by: wwmayer <wmayer@freecad.org>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Leandro Heck
2026-01-07 05:23:28 -03:00
committed by GitHub
parent f76ba96c2f
commit 38c2c10bc5
2 changed files with 25 additions and 1 deletions

View File

@@ -75,6 +75,7 @@
# include <GC_MakeCircle.hxx>
# include <GeomAPI_ProjectPointOnCurve.hxx>
# include <GeomAPI_ProjectPointOnSurf.hxx>
# include <GeomConvert.hxx>
# include <GeomConvert_BSplineCurveKnotSplitting.hxx>
# include <GeomLProp_CLProps.hxx>
# include <Geom_BSplineCurve.hxx>

View File

@@ -43,6 +43,7 @@
#include <GC_MakeCircle.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <GeomConvert.hxx>
#include <GeomConvert_BSplineCurveKnotSplitting.hxx>
#include <GeomLProp_CLProps.hxx>
#include <Geom_BSplineCurve.hxx>
@@ -8420,6 +8421,18 @@ void processEdge2(TopoDS_Edge& projEdge, std::vector<std::unique_ptr<Part::Geome
geos.emplace_back(aoe);
}
}
else if (projCurve.GetType() == GeomAbs_BezierCurve) {
Handle(Geom_BSplineCurve) hBSpline = GeomConvert::CurveToBSplineCurve(projCurve.Bezier());
auto* bspline = new Part::GeomBSplineCurve(hBSpline);
GeometryFacade::setConstruction(bspline, true);
geos.emplace_back(bspline);
}
else if (projCurve.GetType() == GeomAbs_OffsetCurve) {
Handle(Geom_BSplineCurve) hBSpline = GeomConvert::CurveToBSplineCurve(projCurve.OffsetCurve());
auto* bspline = new Part::GeomBSplineCurve(hBSpline);
GeometryFacade::setConstruction(bspline, true);
geos.emplace_back(bspline);
}
else {
throw Base::NotImplementedError("Not yet supported geometry for external geometry");
}
@@ -8442,6 +8455,16 @@ void processEdge(const TopoDS_Edge& edge,
geos.emplace_back(projectLine(curve, gPlane, invPlm));
}
else if (curve.GetType() == GeomAbs_Circle) {
auto isFullCircle = [](const BRepAdaptor_Curve& curve) {
double f = curve.FirstParameter();
double l = curve.LastParameter();
gp_Circ c;
c.SetRadius(1.0);
// for a full circle this is ~ 0.0
double diff = std::abs(l - f - c.Length());
return diff < gp::Resolution();
};
gp_Dir vec1 = sketchPlane.Axis().Direction();
gp_Dir vec2 = curve.Circle().Axis().Direction();
@@ -8627,7 +8650,7 @@ void processEdge(const TopoDS_Edge& edge,
Handle(Geom_Ellipse) projCurve = new Geom_Ellipse(elipsDest);
if (beg.SquareDistance(end) < Precision::Confusion()) {
if (isFullCircle(curve)) {
// projection is an ellipse
auto* ellipse = new Part::GeomEllipse();
ellipse->setHandle(projCurve);