- Guarded `Sol.NbIterations()` calls with `if (Done)` in both `math_FunctionRoot` constructors.
- Prevents `StdFail_NotDone` from being raised during construction when the root is not found.
- Replaced old AppCont_ContMatrices.hxx/.cxx public interface with internal namespace-based .pxx header structure
- Split legacy matrix data into separate internal headers (BB, InvM, IBP, IBT, VB) for better organization
- Fixed out-of-bounds read in IBPMatrix for classe=26 by adding 3 missing data entries
- Added comprehensive GTest suite with 9 tests covering all matrix functions and their mathematical properties
Replace two-step initialization (default constructor + Initialize) with
direct construction for 8 non-copyable/non-movable property and grid
evaluator classes. Objects are now always in a valid state after construction.
Refactored classes:
- GeomProp_Curve, GeomProp_Surface (TKG3d)
- Geom2dProp_Curve (TKG2d)
- BRepProp_Curve, BRepProp_Surface (TKBRep)
- GeomGridEval_Curve, GeomGridEval_Surface (TKG3d)
- Geom2dGridEval_Curve (TKG2d)
Changes per class:
- Remove default constructor and IsInitialized() method.
- Add constructors matching each former Initialize overload.
- Rename Initialize to protected initialization method for internal
and derived class use.
All callers updated across production code (Extrema, BndLib,
IntCurveSurface, IntPatch, HLRBRep, GeomGridEval derived classes)
and test files to use constructor-based initialization.
Add new BRepProp package to TKBRep as a thin wrapper over GeomProp:: free
functions for computing local differential properties of BRep edges and faces
without exceptions. Replaces the legacy BRepLProp macro-based (.gxx) pattern.
New package BRepProp (TKBRep) provides:
- BRepProp_Curve: Local curve property evaluator for BRep edges.
Delegates derivative computation to BRepAdaptor_Curve and passes results
to GeomProp::ComputeTangent, ComputeCurvature, ComputeNormal,
ComputeCentreOfCurvature. Three Initialize overloads: from TopoDS_Edge
(owning), from BRepAdaptor_Curve reference (non-owning), and from
occ::handle<BRepAdaptor_Curve> (shared ownership). Includes static
Continuity() methods for regularity analysis at curve junctions
(replaces BRepLProp::Continuity).
- BRepProp_Surface: Local surface property evaluator for BRep faces.
Delegates derivative computation to BRepAdaptor_Surface and passes results
to GeomProp::ComputeSurfaceNormal, ComputeSurfaceCurvatures,
ComputeMeanGaussian. Same three Initialize overloads as BRepProp_Curve.
Key design decisions:
- No variant dispatch needed: BRepAdaptor_Curve/Surface handle geometry-type
dispatch internally via virtual methods, so BRepProp is a thin wrapper
calling adaptor D1/D2/D3 then GeomProp:: free functions.
- Ownership pattern: occ::handle for owning case + raw const pointer for
non-owning case, consistent with GeomProp_Curve/Surface.
- Returns result structs with IsDefined flags instead of throwing exceptions.
18 GTests: 11 unit tests (line, circle, box, cylinder, sphere) and
7 cross-validation tests against BRepLProp_CLProps/BRepLProp_SLProps.
Add new GeomProp package to TKG3d following the same C++17 std::variant-dispatched
pattern as Geom2dProp (TKG2d) for computing local differential properties
of 3D curves and surfaces without exceptions.
New package GeomProp (TKG3d) provides:
- GeomProp: Result structs (TangentResult, CurvatureResult, NormalResult,
CentreResult, CurveAnalysis for curves; SurfaceNormalResult,
SurfaceCurvatureResult, MeanGaussianResult for surfaces) and
geometry-agnostic free functions for property computation from derivatives.
- GeomProp_Curve: Unified variant dispatcher that auto-detects curve type
from Geom_Curve or Adaptor3d_Curve and delegates to specialized evaluators.
Owns the GeomAdaptor_Curve handle and passes non-owning raw pointers to
per-geometry classes.
- GeomProp_Surface: Unified variant dispatcher that auto-detects surface type
from Geom_Surface or Adaptor3d_Surface and delegates to specialized evaluators.
Owns the GeomAdaptor_Surface handle with non-owning raw pointers.
- Per-geometry curve evaluators (9 types matching GeomAbs_CurveType):
Line (header-only), Circle (header-only), Ellipse, Hyperbola, Parabola,
BezierCurve, BSplineCurve, OffsetCurve, OtherCurve.
- Per-geometry surface evaluators (11 types matching GeomAbs_SurfaceType):
Plane (header-only), Cylinder (header-only), Sphere (header-only),
Cone, Torus, BezierSurface, BSplineSurface, SurfaceOfRevolution,
SurfaceOfExtrusion, OffsetSurface, OtherSurface.
- Surface curvatures computed via first/second fundamental forms with
correct sign convention consistent with surface normal orientation.
Principal directions derived from the shape operator (Weingarten map).
48 GTests covering free functions, curve/surface dispatchers,
cross-validation against GeomLProp_CLProps (8 curve types) and
GeomLProp_SLProps (6 surface types).
Replace archaic LProp/Geom2dLProp macro-based (.gxx) pattern with a modern C++17 std::variant-dispatched package for computing local differential properties of 2D curves: tangent, curvature, normal, centre of curvature, curvature extrema, and inflection points.
New package Geom2dProp (TKG2d) provides:
- Geom2dProp: Result structs (TangentResult, CurvatureResult, NormalResult, CentreResult, CurveAnalysis) and geometry-agnostic free functions for property computation from derivatives.
- Geom2dProp_Curve: Unified variant dispatcher that auto-detects curve type from Geom2d_Curve or Adaptor2d_Curve2d and delegates to specialized evaluators. Owns the Geom2dAdaptor_Curve handle and passes non-owning raw pointers to per-geometry classes.
- Per-geometry evaluators with optimized evaluation:
- Line (header-only): zero curvature, constant tangent
- Circle (header-only): constant curvature 1/R
- Ellipse: analytical extrema at 0, PI/2, PI, 3PI/2
- Hyperbola: analytical extremum at vertex
- Parabola: analytical extremum at vertex
- BezierCurve: numeric curvature extrema/inflection finding
- BSplineCurve: numeric with C3 interval subdivision
- OffsetCurve: numeric approach
- OtherCurve: fallback via adaptor virtual D1/D2/D3
Key design decisions:
- Uses Geom2dAdaptor_Curve for optimized derivative evaluation (D0-DN) with BSpline span caching.
- Non-owning raw pointers in per-geometry classes; lifetime managed by the Geom2dProp_Curve dispatcher which holds the adaptor handle.
- Returns result structs with IsDefined flags instead of throwing exceptions for degenerate cases.
- 106 GTests covering all curve types, free functions, adaptor/geometry initialization, trimmed curves, cross-validation against LProp.
IsClosed() methods across curve and surface classes used gp::Resolution() (~1e-290) for point distance comparison, making the check practically unusable for floating-point evaluated points. Replaced with Precision::Computational() (~DBL_EPSILON) which correctly represents machine-precision arithmetic equality.
TrimmedCurve (2D/3D) and RectangularTrimmedSurface IsClosed() and IsPeriodic() now detect when the trim spans an integer multiple of the basis geometry period using std::remainder(), instead of unconditionally returning false for trimmed parametric ranges.
Added 17 new GTest files (271 tests) for TKG2d covering previously untested packages: Adaptor2d, Geom2dLProp, LProp, and fundamental Geom2d classes (Circle, Ellipse, Line, Hyperbola, Parabola, TrimmedCurve, Transformation, VectorWithMagnitude, Direction, CartesianPoint, AxisPlacement).
IsClosed() tolerance fix applied to:
- Geom2d_TrimmedCurve, Geom_TrimmedCurve
- Geom2d_BSplineCurve, Geom_BSplineCurve
- Geom2d_OffsetCurve, Geom_OffsetCurve
IsPeriodic() / IsUPeriodic() / IsVPeriodic() fix applied to:
- Geom2d_TrimmedCurve, Geom_TrimmedCurve
- Geom_RectangularTrimmedSurface (also IsUClosed/IsVClosed)
- Extract common subexpressions in `EvalD2` (6 intermediate products) and `EvalD3` (10 intermediate products) to avoid redundant multiplications
- Improve inline comments to include explicit formulas for derivative computations
- Fixed `NCollection_KDTree::KNearestPoints` to properly handle empty tree/K=0 cases by initializing output arrays to empty instead of calling Resize with invalid bounds
- Enhanced Linux vcpkg cache download action to include debug library paths for better debug build support
Port of commit 1e1584357 adapted to the new source layout
and modern NCollection_Mat3/NCollection_Mat4 types.
- Graphic3d_ShaderVariable: register NCollection_Mat3<float> and
NCollection_Mat4<float> type IDs; add template instantiations
and Graphic3d_UniformMat3/Graphic3d_UniformMat4 typedefs.
- Graphic3d_ShaderProgram: add PushVariableMat3() and PushVariableMat4()
convenience methods.
- OpenGl_ShaderProgram: add single-value SetUniform() for mat3
(wrapping glUniformMatrix3fv); register mat3/mat4 in
OpenGl_VariableSetterSelector so custom uniforms are dispatched.
- ViewerTest (vshader command): add -vec2, -vec3, -vec4, -mat3, -mat4
argument parsing for setting custom uniform variables from Draw Harness.
- Add Draw Harness test exercising the new uniform types.
- Simplify `findSlotIndex()` in `NCollection_FlatMap` and `NCollection_FlatDataMap` to probe until empty slot or key match.
- Remove lookup early-exit based on probe distance to keep lookup behavior consistent between both flat containers.
- Reorder `NCollection_FlatDataMap::Slot` members to keep hash/probe metadata before key/value storage.
- Refresh class-level Doxygen comments with practical usage guidance and relative notes vs `NCollection_Map` / `NCollection_DataMap`.
- Encode slot state in probe distance (`myProbeDistancePlus1`): 0 = empty, >0 = used
and remove explicit `SlotState`/tombstone handling paths.
- Replace internal `findSlot()` optional-index API with `findSlotIndex()` bool + out index.
- Consolidate insertion logic into `insertRehashedImpl()` variants and reuse cached hash
during rehash to avoid redundant hash recomputation.
- Tune growth policy to max load factor 13/16 (81.25%) and update `reserve()` math.
- Keep behavior and API intact while reducing per-slot metadata overhead and hot-path branching.
Refactor several hot paths in TKBO/TKOffset/TKOpenGl to reduce redundant
lookups/copies and align containers with OCCT collection types.
Changes:
- TKBO:
- Switch BOPTools_Set storage from NCollection_List to NCollection_Vector.
- Replace unsafe C-style edge cast with TopoDS::Edge().
- Apply small lookup/copy optimizations in BOPAlgo_Builder and
BOPAlgo_PaveFiller (Seek() usage, const refs, reduced temporaries).
- TKOffset:
- Reduce repeated vertex/tolerance extraction in BRepOffset_Inter2d.
- Cache MinLoc transformation in ExtentEdge().
- TKMesh:
- Simplify IMeshData_Face surface adaptor initialization.
- Add BRepMesh_FaceChecker_Test and register it in GTests/FILES.cmake.
- TKOpenGl:
- Replace std::map/std::set with NCollection_DataMap/NCollection_Map in
ray-tracing scene update state.
- Simplify texture transform and shader prefix string construction.
- Add OpenGl_View_Raytrace_TextureTransform_Test and register it in
GTests/FILES.cmake.
- Introduced new tests for TopExp class to validate shape mapping and vertex retrieval.
- Added tests for Geom_Circle, Geom_Line, and Geom_Plane classes to ensure correct geometric behavior and transformations.
- Implemented tests for GCPnts_AbscissaPoint to verify length calculations and parameter retrieval for lines and circles.
- Created conversion tests in GeomConvert to check the accuracy of converting geometric entities to B-spline representations.
- Updated CMake files to include new test files for the added tests.
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
Fix two correctness bugs in the solid-level caching optimization for
volumeProperties() introduced in c9bdc4b9f1:
1. SkipShared semantics broken for same-placement duplicates: when
SkipShared=true and a solid TShape appears multiple times with
identical Location and Orientation, the cache-hit branch
unconditionally added transformed properties, double-counting the
solid. Now skip exact duplicate instances to match original
face-level dedup behavior.
2. Free faces/shells dropped when shared solids exist: once
hasSharedSolids=true, the code only iterated TopAbs_SOLID, silently
ignoring any free shells or faces in the compound. Now process
remaining faces via TopExp_Explorer(S, TopAbs_FACE, TopAbs_SOLID)
after the solid loop.
Remove several DRAW Harness tests that consume significant CI/CD time
without providing meaningful regression coverage:
- bugs/heal/bug25712 (~307s CPU): Runs ShapeFix_Solid in a loop of 100
iterations to check non-deterministic behavior. Pure numerical check
with no image verification; determinism is better validated by GTests.
- v3d/anim/videorecorder (~213s CPU): Records a video file using
ray-tracing with MSAA. Requires FFmpeg and produces no reference
image comparison; only verifies that the file is created.
- perf/bop/boxholes (~28s CPU): Cuts 1521 cylinders from a box to
test memory consumption. Pure performance/memory benchmark with no
geometry validation; results vary across hardware configurations.
- perf/bspline/intersect (~20s CPU): Intersects 16 NURBS surfaces
against each other (240 pairs). Pure computation benchmark with
no result validation; only measures elapsed time.
- perf/de/bug23979 (~20s CPU): Exports 10000 prisms to STEP format
to measure write performance. Pure I/O benchmark with no data
validation; results depend on disk and system load.
Introduce EvalRep descriptors for selected Geom and Geom2d curve/surface
classes and add inline EvalRep utilities for evaluation dispatch with
fallback to native paths.
- add per-class Set/Get/Clear EvalRepresentation API and storage
- support full, derivative-bounded and mapped descriptors
- validate mapped parameter transforms in SetEvalRepresentation()
- migrate Geom_OffsetSurface equivalent-surface path to EvalRep
- clone EvalRep descriptors in copy constructors and Copy() paths
- update adaptors to use EvalRep in supported branches
- keep EvalRep invalidation in geometry mutators and fix regressions
Optimized exact vprops path for OCC28402 by reducing TopLoc_Location
composition overhead in edge pcurve lookup.
Changes:
- added fast-path exits in TopLoc_Location::Predivided() for identity and
equal-location cases;
- cached face surface/location in BRepGProp_Face and reused this context in
Load(const TopoDS_Edge&);
- in BRep_Tool::CurveOnSurface(...), compute Predivided() only when edge
has curve representations to iterate.
This keeps algorithmic behavior unchanged and targets the performance
regression reported by tests/bugs/modalg_7/bug28402.
Add a Brent-based coordinate-wise polishing phase to PSO and Differential
Evolution, improving component-level precision from ~1e-4 to 1e-8+ for
separable functions. Introduce BrentAlongCoordinate in MathUtils_LineSearch
as a zero-allocation 1D minimizer for axis-aligned searches.
Changes:
- MathUtils_LineSearch: add BrentAlongCoordinate() for in-place 1D Brent
minimization along a single coordinate axis (no vector allocations)
- MathOpt_PSO: add PolishCoordinateWise() post-processing with configurable
budget (PolishBudgetPerDim, default 50, 0 disables); validate NbParticles > 0;
validate SeededOnly requires seeds; re-evaluate function when seed position
is clamped to bounds (discard stale user-provided value)
- MathOpt_GlobOpt: apply coordinate-wise polishing after DE evolution loop;
propagate PolishBudgetPerDim from GlobalConfig to auto-generated PSOConfig
- MathUtils_Random: add RandomGenerator utility (Lehmer LCG)
- GTests: tighten sphere-type test tolerances to 1e-6; add polishing precision,
SeededOnly validation, and clamped seed re-evaluation tests
Add a general Laguerre polynomial solver to MathPoly and migrate specialized
MathSys Newton solvers (2D/3D/4D) to a unified fixed-size API aligned with
MathUtils statuses and configuration.
MathPoly:
- Add MathPoly_Laguerre.hxx with Laguerre + deflation for higher-degree polynomials.
- Add GeneralPolyResult with real and complex root outputs.
- Add Quintic/Sextic/Octic helpers built on the general solver.
- Add MathPoly_Laguerre gtests and update FILES.cmake/README.
MathSys:
- Add MathSys_NewtonTypes.hxx with NewtonResultN, NewtonBoundsN, NewtonOptions.
- Add/replace specialized APIs:
- Solve2D(), Solve2DSymmetric()
- Solve3D(), SolveCurveSurfaceExtrema3D()
- Solve4D(), SolveSurfaceSurfaceExtrema4D()
- Add dedicated 2D/3D/4D Newton gtests and update FILES.cmake.
- Restore detailed solver comments/docs and update MathSys README.
MathUtils alignment:
- Add Status::NonDescentDirection.
- Make NewtonOptions derive from MathUtils::Config and use FTolerance/
XTolerance/MaxIterations consistently.
- Add shared Newton-related constants in MathUtils_Config.hxx.
- Add Domain1D::IsEqual().
- Update MathUtils README accordingly.
Correctness updates in specialized Newton:
- Convergence is strictly residual-based.
- Armijo directional derivative in symmetric 2D uses J^T*F.
- Singular Jacobian handling keeps robust fallback directions.
- NewtonResultN iteration counter renamed to NbIterations for consistency.
Also updated docs and tests to remove old specialized Newton status/options
references and use MathUtils::Status + FTolerance/XTolerance.
Remove redundant IsCacheValid() checks for Bezier curves and surfaces
in EvalD0/D1/D2/D3 methods. Bezier geometry has a single span, so the
cache is always valid once constructed, unlike multi-span B-splines.
Lower THE_CACHE_THRESHOLD from 4 to 2 in GeomGridEval B-spline
evaluators to use cache-based evaluation more aggressively.
Add new Geom2dGridEval package in TKG2d providing batch evaluation of 2D curves at multiple parameter values, mirroring the existing 3D GeomGridEval package in TKG3d. Specialized evaluators use analytical formulas for conics and cache-based evaluation for BSpline/Bezier curves, with a unified std::variant dispatcher for automatic type-based dispatch.
New classes:
- Geom2dGridEval_Line (header-only), _Circle, _Ellipse, _Hyperbola, _Parabola, _BezierCurve, _BSplineCurve, _OffsetCurve, _OtherCurve
- Geom2dGridEval_Curve: unified dispatcher with Initialize() from Adaptor2d_Curve2d or occ::handle<Geom2d_Curve>
- Geom2dGridEval.hxx: CurveD1/D2/D3 result structures
BSplCLib_Cache changes:
- Add D0Local/D1Local/D2Local/D3Local overloads for gp_Pnt2d/gp_Vec2d
- Refactor existing 2D D0/D1/D2/D3 methods to delegate to D*Local, consistent with the existing 3D delegation pattern
Profiling identified several performance bottlenecks in the BSpline interpolation and blend surface computation pipeline. This commit addresses them through four categories of optimization:
1. Static initialization for GeomFill convertors: the monomial-to-BSpline conversion matrices in GeomFill_QuasiAngularConvertor::Init() and GeomFill_PolynomialConvertor::Init() are mathematical constants that were recomputed on every call via Convert_CompPolynomialToPoles. Now computed once via static lambda-initialized locals.
2. Stack allocation for small matrices/arrays: InterpolationMatrix in BSplCLib::Interpolate, aBSplineBasis in BuildBSpMatrix, and parameters/contact_array in Convert_CompPolynomialToPoles::Perform now use stack buffers when sizes fit, avoiding heap allocation.
3. Raw pointer access in hot loops: replaced multi-layer accessor chains (math_Matrix::Value -> math_DoubleTab::Value -> NCollection_Array2::Value -> NCollection_Array1::at with bounds checks) with direct pointer arithmetic in EvalBsplineBasis, FactorBandedMatrix, BuildBSpMatrix, SolveBandedSystem, and math_VectorBase operations (Multiply, TMultiply, Multiplied, Norm, Norm2).
4. Eliminated redundant recomputation: cached AdvApprox_ApproxAFunction:: NbPoles() results in Approx_SweepApproximation, Approx_CurveOnSurface, and Approx_Curve2d instead of recomputing BSplCLib::NbPoles in inner loops. Cached math_FunctionSetRoot solver in BRepBlend_AppFuncRoot to avoid repeated construction/destruction per SearchPoint call.
Also fixed undefined behavior in BSplCLib::NbPoles where pointer arithmetic created a pointer before the array start (pmu -= f).
Remove empty `GTests/FILES.cmake` stubs from all toolkits in `src/Draw`.
Move `XCAFDoc_Test.cxx` from orphan `src/ApplicationFramework/TKXCAF/GTests`
to `src/DataExchange/TKXCAF/GTests` and register it in
`src/DataExchange/TKXCAF/GTests/FILES.cmake`.
This keeps GTests in real toolkit locations and drops unused Draw-side stubs.
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.
In C++, delete/delete[] on nullptr and free(NULL) are guaranteed no-ops.
This removes redundant null-check guards before these calls across 39
files, reducing code noise without behavioral change. Also simplifies
map value cleanup in BRepClass3d_SolidExplorer by using iterator
reference instead of redundant hash lookups.
Interface_ParamSet:
- Eliminate use-after-free in Append() by deleting old buffer through
a temp variable after reassigning the member pointer (CodeQL #5132/#2684)
delabella.cpp:
- Fix upcast array pointer arithmetic by parenthesizing cast to ensure
pointer arithmetic uses derived class (Vert) size rather than base
class (DelaBella_Vertex) size (CodeQL #5131)
NCollection_SparseArrayBase:
- Rework to replace virtual dispatch (createItem/destroyItem/copyItem)
with function pointers passed as arguments to protected methods
- Store only DestroyItemFunc in base class to enable safe cleanup
in destructor without virtual dispatch
- Pass CreateItemFunc and CopyItemFunc as arguments with zero
per-instance storage overhead
- Move Clear() and UnsetValue() from base public API to protected
clearItems()/unsetValue() with function pointer parameters;
template class provides public wrappers
- Remove vtable entirely (no virtual methods remain)
- This eliminates the pure virtual call during base class destruction
(CodeQL #5012)
AdvApp2Var_MathBase:
- Rewrite comparison to avoid potential signed integer overflow:
*ncfnew + 1 > ncut becomes *ncfnew >= ncut (CodeQL #2692)
Add NCollection_KDTree - a header-only static balanced KD-Tree for
efficient nearest-neighbor, k-nearest, range (sphere), box (AABB),
sphere containment, and weighted nearest queries on point sets.
Key features:
- O(N log N) construction via median-split (std::nth_element)
- O(log N) nearest-neighbor search with bounding box pruning
- Leaf buckets (linear scan for small subtrees) for better performance
- Cache-friendly permutation-based layout (no node allocations)
- Optional per-point radii via compile-time template parameter
(HasRadii=true) with zero overhead when unused
- Works with any point type providing Coord(int) with 1-based indexing
(gp_Pnt, gp_Pnt2d, gp_XYZ, gp_XY out-of-the-box)
Public API:
- Build() from C array or NCollection_Array1 (with or without radii)
- NearestPoint() single nearest with optional squared distance output
- NearestPoints() all equidistant nearest within tolerance
- KNearestPoints() k-nearest sorted by distance
- RangeSearch() sphere query returning NCollection_DynamicArray
- BoxSearch() axis-aligned bounding box query
- ContainingSearch() find all spheres containing a query point (HasRadii)
- NearestWeighted() nearest sphere surface, minimizing dist-radius (HasRadii)
Includes 187 GTests covering construction, copy/move semantics,
2D/3D queries, radii-aware queries, brute-force correctness verification,
identical-point edge cases, and stress tests.
Add two new hash-based containers that preserve insertion order via an intrusive doubly-linked list threaded through the hash nodes:
- NCollection_OrderedMap<K> (key-only, like NCollection_Map)
- NCollection_OrderedDataMap<K,V> (key-value, like NCollection_DataMap)
Both provide O(1) hash lookup, O(1) append/remove, and deterministic iteration in insertion order. Removal unlinks from the doubly-linked list in O(1), unlike NCollection_IndexedMap which requires O(n) swap-and-shrink on its dense array.
Public API mirrors the corresponding unordered containers:
- OrderedMap: Add, Added, Emplace, Emplaced, TryEmplace, TryEmplaced, Contains, Contained, Remove, First, Last
- OrderedDataMap: Bind, Bound, TryBind, TryBound, Emplace, Emplaced, TryEmplace, TryEmplaced, IsBound, Contained, UnBind, Seek, Find, ChangeSeek, ChangeFind, Items, First, Last, FirstValue, LastValue, ChangeFirstValue, ChangeLastValue
Both containers are header-only templates inheriting NCollection_BaseMap. Iterators walk the linked list (not bucket chains) and are compatible with NCollection_StlIterator for STL range-based for loops.
GTests added: 85 tests covering insertion order preservation, add/remove in all positions, copy/move/assign/exchange semantics, resize stability, First/Last access, Contained optional lookup, TryEmplace/TryEmplaced no-overwrite semantics, structured bindings via Items(), and custom stateful hashers.
NCollection_UBTree/EBTree:
- Add move constructor and move assignment operators
- Replace recursive Select() and delNode() with iterative stack-based
traversal to avoid stack overflow on deeply unbalanced trees
- Optimize EBTree::Add() and Remove() to use single-lookup TryEmplaced()
instead of double-lookup UnBind()+Bind() / Contains()+operator()
- Remove unused DEFINE_HUBTREE / DEFINE_HEBTREE / IMPLEMENT_HUBTREE /
IMPLEMENT_HEBTREE macros
- Remove unused includes from EBTree (Standard_Type, Standard_Transient,
NCollection_List, Standard_Integer, NCollection_Sequence)
- Fix doxygen @param tags and comment style
NCollection_LocalArray:
- Add move constructor and move assignment operators with optimized
three-way branching (stack-stack copy, heap-heap swap, stack-heap steal)
- Add Reallocate() method supporting grow-with-copy for use as a
dynamically growable stack
- Add static_assert enforcing trivially copyable element type
NCollection_CellFilter:
- Replace const_cast destructive-copy hack in Cell with proper move
semantics; delete copy constructor and copy assignment
- Add Cell constructor from CellIndex for lightweight lookup keys
- Refactor add()/iterateAdd() to accept CellIndex instead of Cell,
use TryEmplaced() for single-lookup cell insertion
- Refactor remove()/inspect() to use Contained() API with const_cast
instead of C-style cast on Seek()
- Change ListNode default constructor from runtime throw to = delete
- Use size_t for dimension loops and add dimension size guard in IsEqual
- Remove SUN WorkShop 5.3 workaround
- Fix typo "usially" -> "usually" in class documentation
NCollection map API unification (Contained, TryEmplace, TryBind):
- Add Contained() to all map types returning std::optional with
std::reference_wrapper; key-only maps return const key ref,
data maps return std::pair of const key ref + value ref
- Add TryEmplace()/TryEmplaced() to NCollection_FlatMap and
NCollection_IndexedMap for parity with NCollection_Map
- Add TryBind() to NCollection_IndexedDataMap for parity with
NCollection_DataMap and NCollection_FlatDataMap
- Remove Seek()/ChangeSeek() from NCollection_Map (replaced by
Contained())
Dead compiler workaround removal:
- NCollection_DefineAlloc: remove Borland/SUN #if branch, keep only
the version with placement delete
- NCollection_SparseArrayBase: remove SUN WorkShop 5.3 workaround
GTests:
- Add move constructor/assignment tests for LocalArray, UBTree, EBTree
- Add Contained tests for NCollection_Map
- Add CellFilter tests and UBTree deep-unbalanced-tree stress test
Separate direct node indexing and pnindex remapping into distinct code
paths in StepToTopoDS_TranslateFace static helpers. Previously, the
pnindex array was always allocated (even when empty) and an integer
flag was checked everywhere via ternary operators, mixing two behaviors
in one expression. Now the handle null state is the single source of
truth: aPnindices is only allocated when NbPnindex() > 0, and all
consumers check !aPnindices.IsNull() to choose the code path.
Changes:
- GetSimpleFaceElements/GetComplexFaceElements: guard aPnindices
allocation with count > 0, convert thePnIndNb from output parameter
to local variable
- SetNodes: remove theNumPnindex parameter, split into two separate
loops (indirection vs direct)
- SetNormals: rename misleading theNumPnindex to theNbNodes
- CreatePolyTriangulation: compute aNbNodes from aPnindices->Length()
when non-null, remove dead aNumPnindex variable
- Add GTests for StepToTopoDS_TranslateFace
Replace byte-by-byte backward scan with NCollection_UtfIterator-based
forward iteration that correctly handles multibyte UTF-8 sequences.
The old code treated individual UTF-8 bytes (>= 0x80) as non-graphic
via std::isgraph(), causing premature truncation of strings ending
with non-ASCII Unicode characters.
Added GTests for UsefullLength() covering ASCII and UTF-8 cases.
Remove implicit optimization in OpenGl_Aspects that forced UNLIT shading
when material had no reflection properties. This broke PBR materials,
interior color handling, and texture modulation. All legacy code relying
on zero-material for UNLIT now explicitly sets SetShadingModel(Unlit).
Removed unused BUC60720 test command and QABugs_PresentableObject.
Added GTests for Graphic3d_Aspects shading model independence.
Defer EmptyCopied() and BRep_Builder::Add() in dispatchColors() to avoid
redundant shape construction when the copy is not actually needed.
Non-overridden sub-shapes are collected into pre-allocated
NCollection_DynamicArray and the compound is only built when
required (partial override case).
Added GTests covering dispatchColors() dispatch logic.
Eliminate virtual dispatch for elementary geometry evaluation in GeomAdaptor_Curve, GeomAdaptor_Surface, and Geom2dAdaptor_Curve by storing gp_* primitives directly in std::variant and calling ElCLib/ElSLib static methods instead of going through virtual myCurve->D0()/mySurface->D0() calls.
Extend CurveDataVariant/SurfaceDataVariant with elementary types:
- GeomAdaptor_Curve: gp_Lin, gp_Circ, gp_Elips, gp_Hypr, gp_Parab
- GeomAdaptor_Surface: gp_Pln, gp_Cylinder, gp_Cone, gp_Sphere, gp_Torus
- Geom2dAdaptor_Curve: gp_Lin2d, gp_Circ2d, gp_Elips2d, gp_Hypr2d, gp_Parab2d
The load() method now extracts and stores the gp_* primitive at construction time. D0-DN methods dispatch via switch on the curve/surface type enum, calling ElCLib/ElSLib directly for elementary types. Accessor methods (Line(), Circle(), Plane(), etc.) return from the variant when available, avoiding repeated downcasts.
Mark every override method as final on all 29 concrete (leaf) classes in Geom_* and Geom2d_* hierarchies. These classes have no subclasses, so final enables compiler devirtualization and clearly documents the design intent. Affected methods include D0-DN, Reverse, Transform, Copy, DumpJson, and all other overridden virtuals.
Fix ShallowCopy in GeomAdaptor_Curve and GeomAdaptor_Surface where elementary gp_* types stored in the variant were not copied to the new object, which would cause std::bad_variant_access on first evaluation of the copy.
Introduce always-populated weight arrays in BSpline/Bezier curve and surface
classes using non-owning views over a static unit-weights buffer. Migrate
~100 callers across the codebase from deprecated copy-out APIs to direct
const-reference array access. Fix a long-standing typo bug in Hermit.cxx.
Infrastructure (BSplCLib, BSplSLib):
- Add BSplCLib::UnitWeights(n) returning a non-owning NCollection_Array1
view over a compile-time-initialized static array of 2049 ones; falls
back to heap allocation for larger sizes.
- Add BSplCLib::MaxUnitWeightsSize() (constexpr 2049) and
BSplCLib::UnitWeightsData() exposing the raw pointer for BSplSLib.
- Add BSplSLib::UnitWeights(nU, nV) returning a non-owning
NCollection_Array2 view when nU*nV <= 2049, heap-allocated otherwise.
Always-populated myWeights (Geom/Geom2d curve and surface classes):
- myWeights is now always sized to match poles count.
Non-rational: non-owning view via UnitWeights (zero allocation).
Rational: owning array with actual weight values.
- Add WeightsArray() returning const NCollection_Array1<double>& (curves)
or const NCollection_Array2<double>& (surfaces) that is always valid.
- Update all constructors, copy constructors, and restructuring operations
(IncreaseDegree, InsertKnots, RemoveKnot, Segment, SetPeriodic,
SetOrigin, SetNotPeriodic, ExchangeUV, etc.) to maintain the invariant.
- SetWeight: copies non-owning view to owned array before mutation when
transitioning to rational; assigns UnitWeights when becoming non-rational.
- Remove myRational derivation from myWeights.Size() in updateKnots();
rationality is now tracked explicitly via the myRational flag only.
- Fix Geom2d_BSplineCurve::InsertPoleAfter missing myRational update
after inserting a weighted pole.
- Fix Geom_BSplineCurve::DumpJson stale myWeights.Size() > 0 guard
(changed to myRational, matching all other classes).
Caller migration to direct array access (~100 files):
- Replace deprecated copy-out pattern (allocate temp + call Foo(temp))
with const-reference access for Poles(), Knots(), Multiplicities(),
UKnots(), VKnots(), UMultiplicities(), VMultiplicities(),
KnotSequence(), UKnotSequence(), VKnotSequence().
- Replace Weights() null-pointer patterns with WeightsArray() const-ref
or *Weights() dereference where null check is still appropriate.
- Affected modules: GeomConvert, Geom2dConvert, GeomLib, GeomFill,
ProjLib, ShapeUpgrade, ShapeCustom, ShapeConstruct, ShapeAnalysis,
ShapeAlgo, BRepLib, BRepGProp, HLRBRep, ChFi3d, ChFiKPart, BlendFunc,
FairCurve, IntTools, TopOpeBRepTool, TopOpeBRepBuild, LocOpe,
BRepOffset, Adaptor3d, GeomAdaptor, Geom2dAdaptor, BndLib, Extrema,
DrawTrSurf, GeometryTest, GeomliteTest, SWDRAW, QABugs,
GeomToIGES, IGESToBRep, GeomToStep, StdPrs.
Bug fix in Hermit.cxx (PolyTest, both 3D and 2D overloads):
- Fix typo: "Pole0 < 3" changed to "Pole0 < Pole3" — was comparing
a double variable against the integer literal 3 instead of the
variable Pole3 holding the endpoint weight value.
- Fix logic: "if (boucle == 1)" changed to "else if (boucle == 1)"
to make the boucle==1 and boucle==2 branches mutually exclusive.
- Add explanatory comments on BSplCLib::D1 calls that intentionally
pass weight values as scalar "poles" to evaluate the weight function.
NCollection_PackedMapAlgo migration (TDataStd, QABugs):
- Replace deprecated member functions (IsSubset, Subtraction, Subtract,
Unite, Intersect, IsEqual) with NCollection_PackedMapAlgo free functions.
GTests:
- New BSplCLib_Test.cxx: 5 tests for UnitWeights API.
- New BSplSLib_Test.cxx: 5 tests for surface UnitWeights API.
- New Hermit_Test.cxx: 11 tests for Hermit::Solution (3D/2D) and
Hermit::Solutionbis covering uniform, distinct, high-ratio, reversed,
symmetric weights and positive-poles invariant.
- Add WeightsArray tests to Geom_BSplineCurve_Test, Geom_BezierCurve_Test,
Geom_BSplineSurface_Test, Geom_BezierSurface_Test (2 tests each)
verifying const-ref return, non-owning for non-rational, owning for
rational.
- Switched from `__clang_major__ >= 16` gating to `__has_warning(...)` checks
- Added fallback suppression for `-Wcast-function-type` when `-Wcast-function-type-mismatch` is unavailable
Replace handle-based NCollection_HArray1/HArray2 members with direct
NCollection_Array1/Array2 value members in Geom_BSplineCurve,
Geom2d_BSplineCurve, Geom_BSplineSurface, Geom_BezierCurve,
Geom2d_BezierCurve and Geom_BezierSurface. This eliminates heap
indirection and reference counting overhead for exclusively owned data.
Changes:
- Replace handle-wrapped arrays with value members (myPoles, myWeights,
myKnots, myFlatKnots, myMults) using OCCT myFieldName convention
- Bezier classes store only myPoles/myWeights; knots, multiplicities and
flat knots are provided by public instance methods (BezierKnots,
BezierMults, BezierFlatKnots, etc.) returning static arrays by degree
- Add WeightsPtr() inline method on all classes returning nullptr for
non-rational geometry, replacing scattered ternary expressions
- Add InternalFlatKnots(), InternalPoles() inline accessors for grid
evaluation without virtual dispatch
- Deprecate copy-out accessor overloads (Knots(Array1&), Poles(Array1&),
etc.) in favor of const-reference returning versions
- Remove #define macros (POLES, KNOTS, FKNOTS, FMULTS, WEIGHTS) from
BSplineCurve_1.cxx and BSplineSurface_1.cxx, replacing with direct
member access
- Update GeomGridEval and Geom_OsculatingSurface for new accessors
Bug fixes:
- Fix Geom_BSplineCurve::IsEqual skipping knot comparison due to reused
pole loop index; replaced with separate loop-scoped iterators
- Fix Geom_BSplineSurface::SetUNotPeriodic/SetVNotPeriodic using wrong
NCollection_Array2 5-arg constructor; replaced with 4-arg + Init(0.0)
- Fix Geom_BezierSurface::Increase self-referencing Init(myPoles,
&myWeights) call; replaced with direct rationality flag update
NCollection_Array2 enhancements:
- Add ResizeWithTrim() for 2D-preserving resize (copies common sub-matrix
maintaining row/col positions)
- Handle resize from empty arrays and same-size bound changes without
unnecessary reallocation
- Replaced partial bound checks with `std::clamp()` to validate both bounds for `theOutMinIdx` and `theOutMaxIdx`
- Renamed local variable `mult` to `aMultiplier` for better clarity
- Added `std::initializer_list` constructor for convenient list initialization
- Improved const-correctness by providing separate const and non-const `begin()`/`end()` methods
- Optimized move constructor to directly transfer ownership instead of using move assignment
- Added `Exchange()` method for efficient list swapping without reallocation