- 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
Add key-value pair iteration support with C++17 structured binding syntax to NCollection map classes. This enables modern iteration patterns like:
for (auto [aKey, aValue] : aMap.Items()) { ... }
Changes include:
- New NCollection_ItemsView.hxx with reusable template utilities organized under namespace NCollection_ItemsView:
- KeyValueRef: key-value pair reference for structured bindings
- KeyValueIndexRef: key-value-index tuple for indexed maps
- KeyIndexRef: key-index pair for key-only indexed maps
- Iterator: generic forward iterator for view classes
- View: generic view class for Items() iteration
- Items() method for NCollection_DataMap, NCollection_FlatDataMap, NCollection_IndexedDataMap returning key-value pair views
- IndexedItems() method for NCollection_IndexedMap and NCollection_IndexedDataMap returning key-index or key-value-index tuple views
- Custom hasher constructors (copy and move) for NCollection_DataMap, NCollection_FlatDataMap, NCollection_FlatMap, NCollection_Map
- GetHasher() accessor methods for all map types with custom hashers
- IsEqual() method for NCollection_FlatDataMap::Iterator and NCollection_FlatMap::Iterator to support proper iterator comparison
- Fixed copy constructors and assignment operators in FlatMap/FlatDataMap to preserve exact capacity and copy hasher state
The iterator equality comparison in NCollection_ItemsView::Iterator correctly checks both More() state and IsEqual() position, matching NCollection_StlIterator.
Added comprehensive GTest coverage for all new functionality including Items() iteration, structured bindings, hasher preservation, and iterator equality semantics.
Add in-place construction support to sequential and array containers, following the pattern already established in map containers.
New methods added:
- NCollection_List: EmplaceAppend, EmplacePrepend, EmplaceBefore, EmplaceAfter
- NCollection_Sequence: EmplaceAppend, EmplacePrepend, EmplaceAfter, EmplaceBefore
- NCollection_DynamicArray: EmplaceAppend, EmplaceValue
- NCollection_Array1: EmplaceValue
- NCollection_Array2: EmplaceValue
NCollection_Sequence::Node class extended with in-place constructor to support the new Emplace methods.
All methods use perfect forwarding to construct elements in-place, avoiding unnecessary copies or moves. This is particularly useful for:
- Types with expensive copy/move operations
- Types with multiple constructor arguments
- Move-only types (non-copyable)
Added corresponding unit tests for all new methods.
Replace the legacy DISCRETPLUGIN/DISCRETALGO symbol-based plugin system
with a clean registry-based factory pattern following the design of
Graphic3d_GraphicDriverFactory.
Problem: TKMesh and TKXMesh both exported the same DISCRETALGO symbol,
causing symbol collisions when both libraries were loaded. The old plugin
system required dlopen/dlsym which was error-prone and limited.
Solution: Each meshing algorithm now registers itself as a factory with
a unique name. Multiple algorithms can coexist and be selected at runtime.
New classes:
- BRepMesh_DiscretAlgoFactory: Abstract factory base with static registry
- BRepMesh_IncrementalMeshFactory: Factory for "FastDiscret" algorithm
- XBRepMesh_Factory: Factory for "XBRepMesh" algorithm
Removed (breaking changes):
- BRepMesh_PluginMacro.hxx: DISCRETPLUGIN macro
- BRepMesh_PluginEntryType.hxx: Legacy function pointer type
- BRepMesh_FactoryError.hxx: Legacy error enum
- XBRepMesh class: Replaced by XBRepMesh_Factory
- BRepMesh_DiscretFactory::Names(), SetFunctionName(), FunctionName(), ErrorStatus()
- Draw commands: mpsetfunctionname, mpgetfunctionname, mperror
Simplified BRepMesh_DiscretFactory API to delegate to the new registry.
Updated MeshTest_PluginCommands to use BRepMesh_DiscretAlgoFactory.
- Replaced macOS Clang (No PCH) job with Ubuntu GCC (No PCH) job in the workflow dependency list
- Updated the build job to use `ubuntu-24.04` runner with GCC compiler instead of `macos-15` with Clang
- Updated the test job to run on Ubuntu with GCC instead of macOS with Clang
- Made ShapeType() non-virtual by embedding the shape type in a compact uint16_t state field alongside flags
- Replaced int myFlags with uint16_t myState using a BitLayout enum for compact storage
- Moved Compose/Reverse/Complement operations from TopAbs.cxx to inline implementations in TopAbs.hxx
- Updated all TShape derived class constructors to pass their type to the base class
- Refactored TopoDS_Iterator to use index-based iteration with updateCurrentShape() helper
- Added precompiled header file for TKBool toolkit with commonly used headers
- Extended TKDESTEP precompiled headers with Interface_EntityIterator.hxx
- Configured Google Test to use precompiled headers when BUILD_USE_PCH is enabled
- Added 900+ deprecated alias headers in `src/Deprecated/NCollectionAliases/` providing typedef wrappers with deprecation warnings
- Updated build system to install deprecated headers alongside regular headers
- Added Try* methods for conditional binding (only insert if key doesn't exist)
- Added Emplace* methods for in-place construction of values
- Fixed memory safety issues in NCollection_FlatMap/FlatDataMap with proper storage management
- Fixed exception safety issue in NCollection_IndexedMap/IndexedDataMap by moving Increment() call