diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 239edd142b..5eac3ed695 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -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>& 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 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 linkIsDefiningMap; @@ -9190,11 +9203,11 @@ void SketchObject::rebuildExternalGeometry(std::optional 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 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 diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index b4a0a724ca..1696c1878e 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -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;