Replace std::optional return types with direct returns and exception-based
error handling in Geom/Geom2d/Surface EvalD0/D1/D2/D3/DN methods to avoid
performance overhead of std::optional wrapping on the hot evaluation path.
Changes:
- EvalD* methods now return result structs directly instead of
std::optional<T>, throwing Geom_UndefinedValue/Geom_UndefinedDerivative
on failure
- D0/D1/D2/D3/DN inline wrappers simplified to unpack direct returns
instead of checking optional validity
- TryEval* helper functions in EvalRepUtils converted from
std::optional<T> returns to bool + output parameter pattern
- Adaptor classes (Adaptor3d_Curve/Surface, Adaptor2d_Curve2d,
GeomAdaptor_Curve/Surface, Geom2dAdaptor_Curve) simplified by
removing try-catch wrappers around evaluation calls
- Removed dead #include <optional> from 5 header files
- Updated GTests to match new direct-return API
Introduce exception-safe evaluation methods (EvalD0/EvalD1/EvalD2/EvalD3/EvalDN) returning std::optional across the entire Geom_Curve, Geom2d_Curve, and Geom_Surface class hierarchies. These replace the old throwing D0/D1/D2/D3/DN as the primary virtual dispatch points. The old output-parameter methods are retained as non-virtual inline backward-compatible wrappers that throw on failure.
Key design decisions:
- std::optional<T> chosen over embedded-bool structs: identical performance (same 8-byte alignment overhead for POD types), but provides standard C++17 vocabulary, sanitizer-detectable invalid access, and natural return of gp_Pnt for D0 / gp_Vec for DN without wrapper types.
- NRVO optimization: always-succeeding classes (25 of 29) use std::optional<T>{std::in_place} as the local variable, enabling Named Return Value Optimization for zero-copy returns. Failure-path classes (Offset*, GeomPlate, Bisectors) retain early-return std::nullopt pattern.
New headers:
- Geom.hxx: POD result structs Geom_CurveD1/D2/D3, Geom_SurfD1/D2/D3 bundling point + derivative vectors for 3D curves and surfaces.
- Geom2d.hxx: POD result structs Geom2d_CurveD1/D2/D3 for 2D curves.
Base class changes (Geom_Curve, Geom_Surface, Geom2d_Curve):
- New pure virtual EvalD0/EvalD1/EvalD2/EvalD3/EvalDN returning std::optional; std::nullopt signals evaluation failure without exceptions.
- Old void D0(U,P) / void D1(U,P,V1) / gp_Vec DN(U,N) etc. become non-virtual inline wrappers that throw Geom_UndefinedValue/Geom_UndefinedDerivative on nullopt, preserving all existing call sites unchanged.
Leaf class implementations (32 classes, 87 files):
- 7 Geom_Curve leaves: Line, Circle, Ellipse, Hyperbola, Parabola, BSplineCurve, BezierCurve - always succeed, NRVO-optimized.
- 2 Geom_Curve delegators: TrimmedCurve, OffsetCurve - forward to basis curve.
- 11 Geom_Surface leaves: Plane, CylindricalSurface, ConicalSurface, SphericalSurface, ToroidalSurface, BSplineSurface, BezierSurface, SurfaceOfLinearExtrusion, SurfaceOfRevolution - always succeed, NRVO-optimized.
- 2 Geom_Surface delegators: RectangularTrimmedSurface, OffsetSurface.
- 7 Geom2d_Curve leaves: Line, Circle, Ellipse, Hyperbola, Parabola, BSplineCurve, BezierCurve - always succeed, NRVO-optimized.
- 2 Geom2d_Curve delegators: TrimmedCurve, OffsetCurve.
- 3 external subclasses: Bisector_BisecAna, Bisector_BisecCC, Bisector_BisecPC, ShapeExtend_ComplexCurve, ShapeExtend_CompositeSurface, GeomPlate_Surface.
Additional changes:
- GeomGridEval.hxx: replaced duplicated struct definitions with type aliases (using CurveD1 = Geom_CurveD1, etc.).
- GeomAdaptor_Surface.cxx: updated to use new EvalD* API.
GTests added (3 files, 15 test cases):
- Geom_CurveEval_Test.cxx: Circle D0/D1/D2/D3, Line D2, BSpline consistency with old API, EvalDN vs EvalD1 consistency, OffsetCurve nullopt/throw paths.
- Geom_SurfaceEval_Test.cxx: Plane D0/D1, Sphere D1, BSplineSurface D2 consistency with old API, OffsetSurface on regular surface.
- Geom2d_CurveEval_Test.cxx: Circle D0/D1, OffsetCurve nullopt path, BSpline consistency with old API.
This commit completes the refactoring of geometry evaluator classes, replacing polymorphic Handle-based evaluators with inline template utilities and std::variant-based data storage in adaptor classes.
Key changes:
1. Removed GeomEvaluator and Geom2dEvaluator packages:
- Deleted GeomEvaluator_Curve, GeomEvaluator_Surface base classes
- Deleted GeomEvaluator_OffsetCurve, GeomEvaluator_OffsetSurface
- Deleted GeomEvaluator_SurfaceOfExtrusion, GeomEvaluator_SurfaceOfRevolution
- Deleted Geom2dEvaluator_Curve, Geom2dEvaluator_OffsetCurve
2. Added private utility headers (.pxx files) with inline template functions:
- Geom_OffsetCurveUtils.pxx - offset curve evaluation
- Geom_OffsetSurfaceUtils.pxx - offset surface evaluation
- Geom_ExtrusionUtils.pxx - surface of extrusion evaluation
- Geom_RevolutionUtils.pxx - surface of revolution evaluation
- Geom2d_OffsetCurveUtils.pxx - 2D offset curve evaluation
3. Refactored GeomAdaptor_Curve:
- Moved BezierData and BSplineData structs inside the class
- Added std::variant<monostate, OffsetData, BezierData, BSplineData> for type-specific evaluation data
- Removed separate myBSplineCurve and myCurveCache members
- Updated all evaluation methods to use variant-based access
4. Refactored GeomAdaptor_Surface:
- Changed ExtrusionData and RevolutionData to use Handle(Adaptor3d_Curve) instead of Handle(GeomAdaptor_Curve) for flexibility
- Changed RevolutionData to store gp_Ax1 instead of separate AxisLoc/AxisDir
- Updated OffsetData to store Handle(Geom_OffsetSurface) for osculating surface queries instead of creating new Geom_OsculatingSurface
5. Updated Geom_OsculatingSurface:
- Renamed UOscSurf/VOscSurf methods to UOsculatingSurface/VOsculatingSurface for consistency with Geom_OffsetSurface public API
6. Fixed specialized adaptor classes:
- GeomAdaptor_SurfaceOfLinearExtrusion - removed evaluator, uses variant
- GeomAdaptor_SurfaceOfRevolution - removed evaluator, uses variant
- Geom2dAdaptor_Curve - updated to use variant-based data
- Adaptor2d_OffsetCurve - updated to use Geom2d_OffsetCurveUtils
7. Fixed Geom_SurfaceOfRevolution:
- Updated utility calls to use gp_Ax1 parameter instead of separate XYZ
8. Added missing includes in dependent files:
- Adaptor3d_HSurfaceTool.cxx - added GeomAdaptor_Curve.hxx
- GeomAdaptor.cxx - added Adaptor3d_Surface.hxx, GeomAbs_SurfaceType.hxx
- Extrema_GenExtPS.cxx - added Adaptor3d_Curve/Surface.hxx, GeomAbs_IsoType.hxx
- TopOpeBRepTool_GEOMETRY.cxx - added Geom2dAdaptor_Curve.hxx
- BRepAdaptor_Curve2d.cxx - updated ShallowCopy for variant
Benefits:
- Reduced virtual function call overhead in hot evaluation paths
- Better code locality with inline template functions
- Simplified class hierarchy without abstract evaluator base classes
- More efficient memory layout with variant instead of polymorphic handles
- Consistent method naming across related classes
Extract derivative calculation logic from GeomEvaluator and
Geom2dEvaluator classes into dedicated utility headers:
- Geom_OffsetSurfaceUtils.pxx for 3D offset surface derivatives
- Geom_OffsetCurveUtils.pxx for 3D offset curve derivatives
- Geom2d_OffsetCurveUtils.pxx for 2D offset curve derivatives
- Geom_ExtrusionUtils.pxx for extrusion surface calculations
- Geom_RevolutionUtils.pxx for revolution surface calculations
Utility functions provide unified handling of singular and non-singular
cases with osculating surface support for higher-order derivatives.
Buffer management uses NCollection_LocalArray for stack-safe allocation
with heap fallback when sizes exceed expected limits.
Test case expectations updated to reflect improved calculation accuracy.
- Deletion of 20 legacy DRAW test files (.tcl format) from tests/bugs/ directories
- Addition of 15 new GTest C++ test files across multiple modules
- Removal of corresponding QA command implementations from TKQADraw
- Removed 37 DRAW test scripts from `tests/bugs/` directories
- Added 31 new GTest C++ test files in appropriate `GTests/` directories
- Removed corresponding QAcommands implementations from QABugs source files
- Updated CMake FILES.cmake files to include new test files
Added protection against null pointer dereferencing.
Modified BRepOffset_MakeOffset::MakeThickSolid method.
Fixed the problem with negative volume values.
Fixed several unit tests and added a new one.
Integrated DE plugin functionality.
Reworked DE components:
- TKDESTEP: Handling STEP file format.
- TKDEOBJ: Handling OBJ file format.
- TKDEIGES: Handling IGES file format.
- TKDEGLTF: Handling GLTF file format.
- TKDEVRML: Handling VRML file format.
- TKDEPLY: Handling PLY file format.
- TKDESTL: Handling STL file format.
Reworked DE DRAW components:
TKXSDRAWSTEP: Container for DE command to work with STEP.
TKXSDRAWOBJ: Container for DE command to work with OBJ.
TKXSDRAWIGES: Container for DE command to work with IGES.
TKXSDRAWGLTF: Container for DE command to work with GLTF.
TKXSDRAWVRML: Container for DE command to work with VRML.
TKXSDRAWPLY: Container for DE command to work with PLY.
TKXSDRAWSTL: Container for DE command to work with STL.
TKXSDRAW rework to be base DRAW plugin to keep DE session and utils.
Updated documentation
Updated samples
test bugs modalg_7 bug22821 failed on fillet shape with 5-th edge.
Experimentally has been found that reducing of parameter
ChFi3d_Builder::tolesp for this task solves the issue.
So, as soluton it is proposed to link parameter toleps with parameter range of
spine curve. So, production coefficient has been set to pass all tests and
2 teset was extended: tests/blend/complex/A6, tests/bugs/modalg_7/bug22821
first has been extended to test different scaling factors,
second has been extended to make fillet on all edges from 12.
Additionally:
- fixed misusage of tolesp in contexts where tolerance of point in 3d is excepted;
In some context usage of tol_esp is irrelevant, because its essentiality - tolerance of the parameter on the 3d curve.
So, in such context it has been replaced with new parameter tol3d (with fix value 1.0e-4).
Get rid of tolapp3d duplication constant - tol_3d
- tolesp = 5.0e-5 * (umax - umin)
- tolesp replaced by tolpoint2d/tolpoint3d in several classes.
Blend_Walking
BRepBlend_SurfRstLineBuilder
BRepBlend_RstRstLineBuilder
Blend_CSWalking
Instead `tolesp` - `tolgui` is employed in contexts where tolerance of guide curve parameter is excepted.
Instead `tolesp` - `tolpoint2d` or `tolpoint3d` is employed in contexts where tolerance of point in 2d or 3d space is excepted.
- Replace tolesp with tolpoint2d/tolpoint3d in BBPP function argument.
- Use tolapp3d instead tolesp in BonVoisin function,
distmini of two edges returns two solution points instead one.
Second unneeded solution point is the same as first.
The problem was in fact that second edge has continuity C0.
In this case additional extremas analysis performed in special procedure
PERFORM_C0
And second point found in this procedure.
Folowing code of
BRepExtrema_DistanceSS::Perform (variant for Edge/Edge)
we should this additional solution extremas set
to be object of test TRI_SOLUTION before pushing
into main list of solution.
This solves the problem.
Corresponding test and compound with edges has been created.
Additionally, in the function
PERFORM_C0
an obvious error has fixed.
BRepOffset_MakeOffset.cxx - tolerance control for building planar faces is implemented,
updating tolerance for initial entities is avoided
BRepAlgo_Loop.cxx - "total" setting tolerance 0.001 is removing
BRepLib.cxx - checking of "locked" for vertex is removing in static function UpdShTol
QABugs_20.cxx - add new command OCC26441 for checking tolerance differenses between two "identical" shapes
tests/bugs/modalg_7/bug30054 - case now is "BAD", because really result shape is invalid: many faces has not closed wires with huge gaps between ends of edges. Result was "OK" only because tolerances of vertices were increased by algorithm to cover all gaps.
tests/bugs/modalg_8/bug26441 - new test case added
Other test: B3, C8, A7, C8: they were "BAD" and now are "BAD", only some problems are changed.
Problem: From the point of view of the STEP format (and others), it is allowed
to describe a face on a surface with natural boundaries (torus, sphere) without
specifying these boundaries. Thus, a face on a closed surface and containing
an inner wire (or several) is correctly defined and describes a face with a
cutout defined by this wire. At the same time, there is a function
(ShapeFix_Face::FixOrientation) in the ShapeHealing procedure that corrects the
orientation of the wires, and it starts before the function of adding natural
boundaries (ShapeFix_Face::FixAddNaturalBound). There are many shapes that have
incorrectly oriented wires and this procedure successfully heals them, but on a
correctly specified face with single inner wire on closed surface, we do not get
the entire surface with a cutout, but a part of the surface defined by the wire.
This fix is intended to resolve this ambiguity.
Change:
1. Added function isNeedAddNaturalBound that returns TRUE if face needs to add
natural bounds.
2. Corrected condition in FixOrientation to ignoring faces that needs to add
natural bounds.
3. For tests in which one wire was incorrectly oriented on a closed surface,
flag AddNaturalBound was disabled.
5. Test with cutout from torus was created: bugs step bug28414.
Result: By default, it is correct to add natural boundaries, because this case
is correct from the point of view of the STEP format and others.
Adapt test case, the problem is not reproduced any more.
Problem is fixed by the commit: 46478ffe32 (0030008: BRepMesh does not respect angular deflection in internal area of bspline surface)
Added new option '-C' with possibility to set value of Angular and linear tolerances to 'mksweep' command to correct input spine by merging smooth connected neighboring edges
Add choosing the intersect point taking into account the tangentCross when prev UEdge and next UEdge has more than one intersect points;
Add exact correction of edge tolerance (it fix problems with edge tolerance on Linux);
Add exact check of edge tolerance in testcase
1. Modify method IntPatch_ALineToWLine::MakeWLine: add correction of end points of each line on 2 surfaces if an end point is a pole on a surface.
2. Modify method IntPatch_WLine::ComputeVertexParameters: adjust a point on curve to corresponding vertex the following way: set 3D point as the point of the vertex and 2D points as the points of the point on curve.
* Add status flag to GeomFill_Pipe
* Add myIsPerform flag to GeomFill_Pipe
* Add checking vectors in GeomFill_CorrectedFrenet
* Add boolean return to SetCurve virtual methods
* Add test case
* Fix error on computing V first derivative on a cone (take into account the slope of the conical generatrix).
* Add DRAW command 'sderivative' to compute certain derivative on a surface.
Do not limit the normalization factor of the highly anisotropic parametric space when filtering start points in the algorithm of walking line construction.
Additionally check the knots are in the increasing orders when merging two B-spline curves
GeomInt/GeomInt_IntSS.cxx, IntTools/IntTools_FaceFace.cxx - setting deflection 0.01
for case of two bspline surfaces
IntPolyh/IntPolyh_Intersection.cxx, IntPolyh/IntPolyh_Intersection.hxx - status IsParallel is added
BndLib/BndLib_Add3dCurve.cxx, IntTools/IntTools_TopolTool.cxx - fix small bugs
Correction of test scripts according to current behavior of algorithms
lowalgos/intss/bug32849 - test case added
Use distance criteria additionally to parameter criteria when verifying the extrema solution to belong to the edge boundary.
Refactor the BRepExtrema_DistanceSS class to remove the excessive methods with mirrored parameters.
move algorithm of obtaining results from function gproject to method ProjLib_CompProjectedCurve::Perform;
fix tolerances in ProjLib_PrjResolve::ProjLib_PrjResolve;
new treatment of myMaxDist;
use extend bounds in approximation;
add test;
test case "bugs modalg_5 bug25980", "bugs modalg_7 bug24185" have been changed according to new behavior.
Corrected Geom2dConvert_CompCurveToBSplineCurve::Add in Geom2dConvert_CompCurveToBSplineCurve.cxx;
Added the test for this problem;
Corrected "gluing" curves in ProjLib_ProjectedCurve.cxx.
Fixed exception when trying to calculate line and edge normal in methods HLRBRep_Data::OrientOutLine and HLRBRep_Data::OrientOthEdge, added a check for the existence of the normal before subsequent calculations. A correct check for zero derivative, correction of floating point error and division by zero determinant directly in HLRBRep_EdgeFaceTool::CurvatureValue was set.
IntPatch/IntPatch_WLineTool.cxx - adding control of maximal ratio of distances between 3 sequential points.
tests/bugs/modalg_7/bug32569 - new test case added
tests/lowalgos/intss/bug29972_1 test case is modified according new behavior of intersection algorithm
Update information about ON/IN sub-shapes for all touched faces when intersection with shapes of lower types (edges and vertices) complete.
Previously only the faces participating in the Face/Face intersection were updated.
0030620: Tests - perf/bop/buildfaces does not match description (broken)
Allow using meaningful parameters for the commands bbop and bapibop:
* common - for Common operation
* fuse - for Fuse operation
* cut - for Cut operation
* tuc/cut21 - for Cut21 operation
* section - for Section operation
Add description for the commands dealing with Boolean/GF/Split operations.
Validate arguments of these commands.
Correct test case perf/bop/buildfaces to perform GF execution in parallel and serial modes - compare the results.
The following classes have been removed as obsolete:
- BRepAlgo_BooleanOperation
- BRepAlgo_Fuse
- BRepAlgo_Cut
- BRepAlgo_Common
- BRepAlgo_Section
The corresponding classes from BRepAlgoAPI package have to be used instead.
Draw commands:
- fuse
- cut
- common
- section/psection
have also been removed as obsolete.
The corresponding commands for modern Boolean operations algorithm (bfuse/bcut/bcommon/bsection) have to be used instead.
Adjustment of the test cases to use the commands for modern algorithm.