[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.
This commit is contained in:
Gabriel Wicke
2020-06-22 18:54:25 -07:00
committed by wwmayer
parent 648b3bbe7e
commit 487215d2f5

View File

@@ -24,6 +24,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <algorithm>
# include <array>
# include <cmath>
# include <cstdlib>
@@ -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<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);