Sketcher: Add backwards-compat path for external geo

Before 0aed23c (PR #19582), external geometry projection used a different algorithm and produced slightly different geometry for some kinds of projections (B-splines in particular). This adds a backwards-compatibility path that allows old files to continue to use the old algorithm, while using the new and improved algorithm with new files.
This commit is contained in:
Chris Hennes
2026-03-16 11:20:27 -05:00
committed by Kacper Donat
parent 78674fb121
commit b3894fb5dc
2 changed files with 22 additions and 8 deletions
+21 -8
View File
@@ -170,6 +170,11 @@ SketchObject::SketchObject() : geoLastId(0)
"Internal Geometry",
App::Prop_None,
"Enables selection of closed profiles within a sketch as input for operations");
ADD_PROPERTY_TYPE(_ExternalGeoVersion,
(0),
"Compatibility",
(App::PropertyType)(App::Prop_Hidden | App::Prop_ReadOnly),
"Version of external geometry projection algorithm");
Geometry.setOrderRelevant(true);
@@ -220,6 +225,7 @@ void SketchObject::setupObject()
"User parameter:BaseApp/Preferences/Mod/Sketcher");
ArcFitTolerance.setValue(hGrpp->GetFloat("ArcFitTolerance", Precision::Confusion()*10.0));
MakeInternals.setValue(hGrpp->GetBool("MakeInternals", false));
_ExternalGeoVersion.setValue(1);
inherited::setupObject();
}
@@ -8311,7 +8317,8 @@ void processEdge(const TopoDS_Edge& edge,
const gp_Pln& sketchPlane,
const Base::Rotation& invRot,
gp_Ax3& sketchAx3,
TopoDS_Shape& aProjFace)
TopoDS_Shape& aProjFace,
int externalGeoVersion = 1)
{
using std::numbers::pi;
@@ -8654,8 +8661,11 @@ void processEdge(const TopoDS_Edge& edge,
auto shape = Part::TopoShape(edge);
bool planar = shape.findPlane(plane);
// Check if the edge is planar and plane is perpendicular to the projection plane
if (planar && plane.Axis().IsNormal(sketchPlane.Axis(), Precision::Angular())) {
// Check if the edge is planar and plane is perpendicular to the projection plane.
// The getBoundBoxOptimal approach (version >= 1) produces better results for new
// sketches, but old files (version 0) must use NormalProjection to preserve element maps.
if (externalGeoVersion >= 1
&& planar && plane.Axis().IsNormal(sketchPlane.Axis(), Precision::Angular())) {
// Project an edge to a line. Only works if the edge is planar and its plane is
// perpendicular to the projection plane. OCC has trouble handling
// BSpline projection to a straight line. Although it does correctly projects
@@ -8858,7 +8868,8 @@ void processFace (const Rotation& invRot,
gp_Ax3& sketchAx3,
TopoDS_Shape& aProjFace,
std::vector<std::unique_ptr<Part::Geometry>>& geos,
TopoDS_Shape& refSubShape)
TopoDS_Shape& refSubShape,
int externalGeoVersion = 1)
{
const TopoDS_Face& face = TopoDS::Face(refSubShape);
BRepAdaptor_Surface surface(face);
@@ -8873,7 +8884,7 @@ void processFace (const Rotation& invRot,
for (edgeExp.Init(face, TopAbs_EDGE); edgeExp.More(); edgeExp.Next()) {
TopoDS_Edge edge = TopoDS::Edge(edgeExp.Current());
// Process each edge
processEdge(edge, geos, gPlane, invPlm, mov, sketchPlane, invRot, sketchAx3, aProjFace);
processEdge(edge, geos, gPlane, invPlm, mov, sketchPlane, invRot, sketchAx3, aProjFace, externalGeoVersion);
}
if (fabs(dnormal.Angle(snormal) - std::numbers::pi/2) < Precision::Confusion()) {
@@ -8959,6 +8970,8 @@ void SketchObject::rebuildExternalGeometry(std::optional<ExternalToAdd> extToAdd
{
Base::StateLocker lock(managedoperation, true); // no need to check input data validity as this is an sketchobject managed operation.
int extGeoVersion = _ExternalGeoVersion.getValue();
// Analyze the state of existing external geometries to infer the desired state for new ones.
// If any geometry from a source link is "defining", we'll treat the whole link as "defining".
std::map<std::string, bool> linkIsDefiningMap;
@@ -9190,11 +9203,11 @@ void SketchObject::rebuildExternalGeometry(std::optional<ExternalToAdd> extToAdd
if (projection && !refSubShape.IsNull()) {
switch (refSubShape.ShapeType()) {
case TopAbs_FACE: {
processFace(invRot, invPlm, mov, sketchPlane, gPlane, sketchAx3, aProjFace, geos, refSubShape);
processFace(invRot, invPlm, mov, sketchPlane, gPlane, sketchAx3, aProjFace, geos, refSubShape, extGeoVersion);
} break;
case TopAbs_EDGE: {
const TopoDS_Edge& edge = TopoDS::Edge(refSubShape);
processEdge(edge, geos, gPlane, invPlm, mov, sketchPlane, invRot, sketchAx3, aProjFace);
processEdge(edge, geos, gPlane, invPlm, mov, sketchPlane, invRot, sketchAx3, aProjFace, extGeoVersion);
} break;
case TopAbs_VERTEX: {
importVertex(refSubShape);
@@ -9222,7 +9235,7 @@ void SketchObject::rebuildExternalGeometry(std::optional<ExternalToAdd> extToAdd
auto edges = intersectionShape.getSubTopoShapes(TopAbs_EDGE);
for (const auto& s : edges) {
TopoDS_Edge edge = TopoDS::Edge(s.getShape());
processEdge(edge, geos, gPlane, invPlm, mov, sketchPlane, invRot, sketchAx3, aProjFace);
processEdge(edge, geos, gPlane, invPlm, mov, sketchPlane, invRot, sketchAx3, aProjFace, extGeoVersion);
}
// Section of some face (e.g. sphere) produce more than one arcs
// from the same circle. So we try to fit the arcs with a single
+1
View File
@@ -108,6 +108,7 @@ public:
Part ::PropertyPartShape InternalShape;
App ::PropertyPrecision InternalTolerance;
App ::PropertyBool MakeInternals;
App ::PropertyInteger _ExternalGeoVersion;
/** @name methods override Feature */
//@{
short mustExecute() const override;