From 487215d2f5cc1593fcdad69ff58460fa2cc76e6b Mon Sep 17 00:00:00 2001 From: Gabriel Wicke Date: Mon, 22 Jun 2020 18:54:25 -0700 Subject: [PATCH] [part] More robust tessellation angular deflection default OCC currently does not reliably enforce linear deflection on curved surfaces, especially curved lofts over nurbs splines. To avoid surprises when tight tolerances are needed, replace the static default angular deflection of 0.5 radians (~28 degrees), with a more sensible angular deflection derived from the provided linear deflection tolerance. By adding the default heuristic to TopoShape, we can keep typical tessellate() and STL export functionality users simple, and also avoid the need to implement similar heuristics in many places. If more explicit control over angular deflection is needed for some use cases, then we could still choose to expose the option to override the derived default explicitly. The hope is that OCC's linear deflection enforcement will be more reliable at some point, at which point this heuristic will no longer be needed. --- src/Mod/Part/App/TopoShape.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index 41fea8875a..f85999d4d1 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -24,6 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include @@ -232,6 +233,23 @@ const char* BRepBuilderAPI_FaceErrorText(BRepBuilderAPI_FaceError et) } } +/** + * Derive a roughly proportional default angular deflection from a linear + * tolerance. This is a work-around for unreliable linear tolerance enforcement + * in OCC, especially on nurbs surfaces. The intention is to provide sane + * baseline (default) behavior with linear tolerances only, until OCC is fixed. + * If needed for specific use cases, explicit angular deflection parameters can + * still be exposed separately. + */ +inline double defaultAngularDeflection(double linearTolerance) { + // Default OCC angular deflection is 0.5 radians, or about 28.6 degrees. + // That is a bit coarser than necessary for performance, so we default to at + // most 0.1 radians, or 5.7 degrees. We also do not go finer than 0.005, or + // roughly 0.28 degree angular resolution, to avoid performance tanking + // completely at very fine resolutions. + return std::min(0.1, linearTolerance * 5 + 0.005); +} + // ------------------------------------------------ NullShapeException::NullShapeException() @@ -971,7 +989,8 @@ void TopoShape::exportStl(const char *filename, double deflection) const #else BRepMesh_IncrementalMesh aMesh(this->_Shape, deflection, /*isRelative*/ Standard_False, - /*theAngDeflection*/ 0.5, + /*theAngDeflection*/ + defaultAngularDeflection(deflection), /*isInParallel*/ true); #endif writer.Write(this->_Shape,encodeFilename(filename).c_str()); @@ -993,7 +1012,8 @@ void TopoShape::exportFaceSet(double dev, double ca, std::size_t index=0; BRepMesh_IncrementalMesh MESH(this->_Shape, dev, /*isRelative*/ Standard_False, - /*theAngDeflection*/ 0.5, + /*theAngDeflection*/ + defaultAngularDeflection(dev), /*isInParallel*/ true); for (ex.Init(this->_Shape, TopAbs_FACE); ex.More(); ex.Next(), index++) { // get the shape and mesh it @@ -3319,7 +3339,8 @@ void TopoShape::getFaces(std::vector &aPoints, // get the meshes of all faces and then merge them BRepMesh_IncrementalMesh aMesh(this->_Shape, accuracy, /*isRelative*/ Standard_False, - /*theAngDeflection*/ 0.5, + /*theAngDeflection*/ + defaultAngularDeflection(accuracy), /*isInParallel*/ true); std::vector domains; getDomains(domains);