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:
committed by
Kacper Donat
parent
78674fb121
commit
b3894fb5dc
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user