Skip to content

Commit

Permalink
[part] More robust tessellation angular deflection default
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
gwicke authored and wwmayer committed Jun 23, 2020
1 parent 648b3bb commit 487215d
Showing 1 changed file with 24 additions and 3 deletions.
27 changes: 24 additions & 3 deletions src/Mod/Part/App/TopoShape.cpp
Expand Up @@ -24,6 +24,7 @@
#include "PreCompiled.h"

#ifndef _PreComp_
# include <algorithm>
# include <array>
# include <cmath>
# include <cstdlib>
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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());
Expand All @@ -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
Expand Down Expand Up @@ -3319,7 +3339,8 @@ void TopoShape::getFaces(std::vector<Base::Vector3d> &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<Domain> domains;
getDomains(domains);
Expand Down

0 comments on commit 487215d

Please sign in to comment.