diff --git a/conda/meta.yaml b/conda/meta.yaml index 6514215c4..4976f4ba7 100644 --- a/conda/meta.yaml +++ b/conda/meta.yaml @@ -1,5 +1,5 @@ -{% set OCCT_VER = "8.0.0" %} -{% set OCP_TWEAK = "1" %} +{% set OCCT_VER = "8.0.1" %} +{% set OCP_TWEAK = "0" %} package: name: ocp diff --git a/environment.devenv.yml b/environment.devenv.yml index 8cd69e243..5c8995b36 100644 --- a/environment.devenv.yml +++ b/environment.devenv.yml @@ -2,7 +2,7 @@ name: bindgen channels: - conda-forge dependencies: - - occt=8.0.0=all* + - occt=8.0.1=all* - pybind11=2.13.* - python={{ get_env("PYTHON_VERSION", default="3.13") }} - cmake >3.24 diff --git a/ocp.toml b/ocp.toml index dba47ad2b..b841e0d7e 100644 --- a/ocp.toml +++ b/ocp.toml @@ -1449,7 +1449,7 @@ class Adaptor3d_Surface; [Attributes] - __version__ = "8.0.0.1" + __version__ = "8.0.1.0" [Modules] diff --git a/opencascade/Approx_BSplineApproxInterp.hxx b/opencascade/Approx_BSplineApproxInterp.hxx deleted file mode 100644 index 15fc66ad4..000000000 --- a/opencascade/Approx_BSplineApproxInterp.hxx +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) 2025 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _Approx_BSplineApproxInterp_HeaderFile -#define _Approx_BSplineApproxInterp_HeaderFile - -#include -#include -#include - -#include -#include -#include -#include -#include - -class GeomAdaptor_Curve; - -//! Constrained least-squares B-spline curve approximation with exact interpolation constraints. -//! -//! This class fits a B-spline curve through a set of 3D points, where each point -//! can be either approximated (in the least-squares sense) or exactly interpolated. -//! Selected interpolation points can additionally be marked as "kinks" - the solver -//! then inserts high-multiplicity knots at the corresponding parameters to preserve -//! C0 discontinuities. -//! -//! The algorithm solves a KKT (Karush-Kuhn-Tucker) saddle-point system: -//! @code -//! | A^T*A C^T L^T | | x | | A^T*b | -//! | C 0 0 | * | l | = | d | -//! | L 0 0 | | m | | 0 | -//! @endcode -//! where: -//! - A is the basis matrix for approximated points -//! - C is the basis matrix for interpolated points -//! - L encodes continuity constraints (C1/C2 for closed curves) -//! - x are the control point coordinates -//! - l, m are Lagrange multipliers -//! -//! Usage: -//! @code -//! NCollection_Array1 aPts(1, 100); -//! // ... fill points ... -//! Approx_BSplineApproxInterp anApprox(aPts, 20); -//! anApprox.InterpolatePoint(0); // first point exact -//! anApprox.InterpolatePoint(99); // last point exact -//! anApprox.InterpolatePoint(50, true); // kink at midpoint -//! anApprox.Perform(aParams); -//! if (anApprox.IsDone()) -//! { -//! const occ::handle& aCurve = anApprox.Curve(); -//! double aMaxErr = anApprox.MaxError(); -//! } -//! @endcode -class Approx_BSplineApproxInterp -{ -public: - DEFINE_STANDARD_ALLOC - - //! Creates a constrained approximation solver. - //! @param[in] thePoints array of 3D points to fit (1-based indexing) - //! @param[in] theNbControlPts desired number of control points for the B-spline - //! @param[in] theDegree degree of the B-spline (default 3) - //! @param[in] theContinuousIfClosed if true, enforces C2 continuity for closed curves - Standard_EXPORT Approx_BSplineApproxInterp(const NCollection_Array1& thePoints, - int theNbControlPts, - int theDegree = 3, - bool theContinuousIfClosed = false); - - //! Marks a point to be exactly interpolated rather than approximated. - //! @param[in] thePointIndex 0-based index of the point - //! @param[in] theWithKink if true, a kink (C0 break) is inserted at this parameter - Standard_EXPORT void InterpolatePoint(int thePointIndex, bool theWithKink = false); - - //! Performs the fit using automatically computed parameters. - //! Parameters are computed from input points using current parametrization alpha. - Standard_EXPORT void Perform(); - - //! Performs the fit with given parameters. - //! @param[in] theParams parameter values for each point (size must match point count) - Standard_EXPORT void Perform(const NCollection_Array1& theParams); - - //! Performs the fit with iterative parameter optimization using automatically - //! computed initial parameters. - //! @param[in] theMaxIter maximum number of optimization iterations - Standard_EXPORT void PerformOptimal(int theMaxIter); - - //! Performs the fit with iterative parameter optimization. - //! Parameters of approximated points are re-projected onto the curve - //! after each iteration to improve the fit. - //! @param[in] theParams initial parameter values - //! @param[in] theMaxIter maximum number of optimization iterations - Standard_EXPORT void PerformOptimal(const NCollection_Array1& theParams, int theMaxIter); - - //! Returns true if the fit was successfully computed. - [[nodiscard]] bool IsDone() const { return myIsDone; } - - //! Returns the resulting B-spline curve. - [[nodiscard]] Standard_EXPORT const occ::handle& Curve() const; - - //! Returns the maximum approximation error (distance at approximated points). - [[nodiscard]] double MaxError() const { return myMaxError; } - - //! Sets the parametrization power for automatic parameter computation. - //! 0.0 = uniform, 0.5 = centripetal (default), 1.0 = chord-length. - //! @param[in] theAlpha parametrization exponent in [0, 1] - void SetParametrizationAlpha(double theAlpha) { myAlpha = theAlpha; } - - //! Sets the minimum pivot value for the Gauss solver. - //! Matrices with pivots below this threshold are treated as singular. - //! @param[in] theMinPivot minimum pivot threshold (default 1e-20) - void SetMinPivot(double theMinPivot) { myMinPivot = theMinPivot; } - - //! Sets the relative tolerance for detecting closed curves. - //! Closedness is detected when first/last points are within - //! theRelTol * (bounding box diagonal). - //! @param[in] theRelTol relative tolerance (default 1e-12) - void SetClosedTolerance(double theRelTol) { myClosedRelTol = theRelTol; } - - //! Sets the tolerance for detecting duplicate knot positions during insertion. - //! @param[in] theTol knot matching tolerance (default 1e-4) - void SetKnotInsertionTolerance(double theTol) { myKnotInsertTol = theTol; } - - //! Sets the convergence tolerance for parameter optimization. - //! Optimization stops when relative error reduction falls below this value. - //! @param[in] theTol convergence tolerance (default 1e-3) - void SetConvergenceTolerance(double theTol) { myConvergenceTol = theTol; } - - //! Sets the tolerance for point projection onto curve during optimization. - //! @param[in] theTol projection accuracy (default 1e-6) - void SetProjectionTolerance(double theTol) { myProjectionTol = theTol; } - -private: - //! Computes centripetal/chord-length parameters from point distances. - //! @param[in] theAlpha parametrization power - //! @return array of parameters in [0, 1] - NCollection_Array1 computeParameters(double theAlpha) const; - - //! Computes knot vector from parameters and number of control points. - //! Inserts high-multiplicity knots at kink parameters. - //! @param[in] theNbCP number of control points - //! @param[in] theParams parameter values - //! @param[out] theKnots computed knot values - //! @param[out] theMults computed knot multiplicities - void computeKnots(int theNbCP, - const NCollection_Array1& theParams, - NCollection_Array1& theKnots, - NCollection_Array1& theMults) const; - - //! Solves the constrained least-squares system. - //! @param[in] theParams parameter values - //! @param[in] theKnots knot values - //! @param[in] theMults knot multiplicities - //! @return true if the system was solved successfully - bool solve(const NCollection_Array1& theParams, - const NCollection_Array1& theKnots, - const NCollection_Array1& theMults); - - //! Builds the B-spline basis matrix for given parameters and flat knots. - //! @param[in] theFlatKnots flat knot vector - //! @param[in] theParams parameter values (1-based) - //! @param[in] theDerivOrder derivative order (0 = values, 1 = first deriv, etc.) - //! @return matrix of size (theParams.Length() x nControlPoints) - math_Matrix buildBasisMatrix(const NCollection_Array1& theFlatKnots, - const NCollection_Array1& theParams, - int theDerivOrder = 0) const; - - //! Builds the continuity constraint matrix for closed curve C1/C2 conditions. - //! @param[in] theNbCtrPnts number of control points - //! @param[in] theNbContinuity number of continuity conditions - //! @param[in] theParams parameter values - //! @param[in] theFlatKnots flat knot vector - //! @return continuity matrix (theNbContinuity x theNbCtrPnts) - math_Matrix buildContinuityMatrix(int theNbCtrPnts, - int theNbContinuity, - const NCollection_Array1& theParams, - const NCollection_Array1& theFlatKnots) const; - - //! Re-projects approximated points onto the curve to optimize parameters. - //! @param[in] theCurve current fitted curve - //! @param[in,out] theParams parameters to optimize - void optimizeParameters(const occ::handle& theCurve, - NCollection_Array1& theParams) const; - - //! Projects a point onto a curve using Newton iteration. - //! @param[in] thePnt point to project - //! @param[in] theCurveAdaptor curve adaptor to project onto - //! @param[in] theInitParam initial parameter guess - //! @param[out] theParam optimized parameter - //! @return projection distance - double projectOnCurve(const gp_Pnt& thePnt, - const GeomAdaptor_Curve& theCurveAdaptor, - double theInitParam, - double& theParam) const; - - //! Returns cached adaptor for the given curve, reloading cache when curve changes. - const GeomAdaptor_Curve& curveAdaptor(const occ::handle& theCurve) const; - - //! Returns true if the point set represents a closed curve. - bool isClosed() const; - - //! Returns true if the first and last points are in the interpolated set. - bool isFirstAndLastInterpolated() const; - - //! Computes the diagonal of the bounding box of the points. - double boundingBoxDiagonal() const; - - NCollection_Array1 myPoints; - NCollection_DynamicArray myInterpolated; - NCollection_DynamicArray myApproximated; - NCollection_DynamicArray myKinks; - occ::handle myCurve; - mutable occ::handle myCurveAdaptorCache; - int myDegree = 3; - int myNbControlPts = 0; - double myMaxError = 0.0; - double myAlpha = 0.5; - double myMinPivot = 1.0e-20; - double myClosedRelTol = 1.0e-12; - double myKnotInsertTol = 1.0e-4; - double myConvergenceTol = 1.0e-3; - double myProjectionTol = 1.0e-6; - bool myContinuousIfClosed = false; - bool myIsDone = false; -}; - -#endif // _Approx_BSplineApproxInterp_HeaderFile diff --git a/opencascade/Aspect_GridParams.hxx b/opencascade/Aspect_GridParams.hxx index 48ef46eec..a46def9d2 100644 --- a/opencascade/Aspect_GridParams.hxx +++ b/opencascade/Aspect_GridParams.hxx @@ -22,10 +22,8 @@ #include #include -//! Shader grid appearance (color, scale, bounds, arc, draw mode, background / adaptive flags). -//! Consumed only by the GPU path: V3d_View::GridDisplay -> OpenGl_View::renderGrid. -//! No effect on the CPU path (V3d_Viewer::ActivateGrid). Snap math is independent and -//! lives on Aspect_RectangularGrid / Aspect_CircularGrid. +//! Grid appearance for V3d_View::GridDisplay: color, scale, bounds, arc, draw mode, +//! background and adaptive flags. class Aspect_GridParams { public: @@ -183,8 +181,7 @@ public: //! Return signed plane-normal offset applied at render time. double ZOffset() const { return myZOffset; } - //! Set signed plane-normal offset applied at render time (display only; - //! snap math stays on the unshifted plane). + //! Set signed plane-normal offset applied at render and echo time. void SetZOffset(const double theOffset) { myZOffset = theOffset; } //! Return arc start angle (radians). Meaningful only when IsArc() is true. @@ -229,10 +226,8 @@ public: //! Return TRUE if grid spacing and visible extents adapt to the camera view. bool IsViewAdaptive() const { return myIsViewAdaptive; } - //! Set view-adaptive grid on/off. When enabled, renderer derives temporary - //! cell spacing and bounds from the current camera. The inverse of ScaleY() - //! (or Scale() when ScaleY() is zero) is used as the target number of cells - //! across the view height. + //! Set view-adaptive grid on/off. When enabled, shader renderer keeps the + //! screen-space grid step stable by scaling the cell spacing with camera zoom. void SetIsViewAdaptive(const bool theIsViewAdaptive) { myIsViewAdaptive = theIsViewAdaptive; } private: diff --git a/opencascade/BRepGraph.hxx b/opencascade/BRepGraph.hxx index 1d728dc02..6df93d74f 100644 --- a/opencascade/BRepGraph.hxx +++ b/opencascade/BRepGraph.hxx @@ -17,24 +17,19 @@ #include #include #include -#include +#include #include +#include #include #include #include -#include -#include -#include -#include - #include #include #include #include #include - -#include #include +#include #include @@ -43,19 +38,23 @@ class BRepGraph_MutGuard; struct BRepGraph_Data; class BRepGraphInc_Storage; +class BRepGraph_CacheRegistry; class BRepGraph_Layer; -class BRepGraph_MeshCacheStorage; +class BRepGraph_LayerLock; +class BRepGraph_LayerRegistry; +class BRepGraph_CacheMesh; +class BRepGraph_Validate; +class BRepGraph_Deduplicate; +class BRepGraphODE; +class BRepGraphODE_Storage; class NCollection_BaseAllocator; class TCollection_AsciiString; -class BRepGraph_Builder; -class BRepGraph_History; - //! @brief Topology-geometry graph over TopoDS / BRep. //! //! Stores B-Rep topology as flat entity vectors (incidence-table model) with -//! integer cross-references, enabling cache-friendly traversal, O(1) upward -//! navigation via reverse indices, and parallel face-level geometry extraction. +//! integer cross-references, enabling cache-friendly traversal, relation-table +//! parent navigation, and parallel face-level geometry extraction. //! //! Key design concepts: //! - **NodeId** (Kind + Index): lightweight typed address into per-kind vectors. @@ -64,7 +63,7 @@ class BRepGraph_History; //! Curve3D, Curve2D, Triangulation, Polygon) decoupled from topology nodes. //! - **CoEdge**: half-edge entity owning PCurve data for each edge-face binding; //! seam edges use paired CoEdges with opposite Orientation (Parasolid convention). -//! - **Lifecycle**: BRepGraph_Builder::Add() populates from TopoDS_Shape; +//! - **Lifecycle**: Shapes().Add() populates from TopoDS_Shape; //! Editor() is the single mutation entry point for both structural creation/removal //! (Add*, Remove*, Append*) and field-level RAII-scoped mutation (Mut*()) with //! automatic cache invalidation and upward SubtreeGen propagation. @@ -82,7 +81,7 @@ class BRepGraph_History; //! Deferred invalidation (BRepGraph_DeferredScope) batches SubtreeGen propagation; //! concurrent Editor().Mut*() calls during deferred mode still require external //! serialization. -//! BRepGraph_Builder::Add() is internally parallel when requested. +//! Shapes().Add() is internally parallel when requested. //! //! ## UID persistence //! UIDs use monotonic counters (not vector indices), persisting across Compact() @@ -90,8 +89,9 @@ class BRepGraph_History; //! See BRepGraph_UID.hxx for the serialization contract. //! //! ## Extension model -//! Extend via BRepGraph_Layer (per-node attributes) or BRepGraph_TransientCache -//! (algorithm-computed caches). Direct storage extension is not supported. +//! Extend via BRepGraph_Layer (persistent metadata / observers) or +//! BRepGraph_CacheRegistry (typed algorithm-computed transient cache services). +//! Direct storage extension is not supported. //! //! ## ID systems //! Four ID types with different stability guarantees: @@ -101,38 +101,35 @@ class BRepGraph_History; //! Use for cross-session storage, history tracking, and external references. //! - **RefId** (Kind + per-kind Index): same stability as NodeId, but addresses reference entries //! (Shell->Solid binding, Face->Shell binding, CoEdge->Wire binding) rather than defs. -//! - **RepId** (Kind + per-kind Index): addresses geometry/mesh representation objects (Surface, -//! Curve3D, Curve2D, Triangulation, Polygon) independently of topology nodes. +//! - **RepId** (Kind + per-kind Index): addresses owner-scoped geometry/mesh representation slots +//! (Surface, Curve3D, Curve2D, Triangulation, Polygon). //! //! ## Iterator guide //! Choose the iterator that matches your traversal need: //! - **BRepGraph_Iterator\**: flat sequential scan of ALL definitions of one kind //! (e.g. every FaceDef, skipping removed). Use for bulk per-kind algorithms. //! - **BRepGraph_DefsIterator / BRepGraph_RefsIterator**: single-level typed children of one -//! parent (e.g. active shells of one solid, coedge refs of one wire). Zero allocation. +//! parent (e.g. active shells of one solid, coedges of one wire). Zero allocation. //! Use when you have a specific parent and need its direct children. //! - **BRepGraph_ChildExplorer**: depth-first downward walk from a root with accumulated //! location/orientation per step. Use when visiting descendants across multiple levels or //! when the global transform matters. Supports Recursive and DirectChildren modes. -//! - **BRepGraph_ParentExplorer**: upward walk via reverse indices from a starting node. +//! - **BRepGraph_ParentExplorer**: upward walk via relation tables from a starting node. //! Use when tracing which shells/solids/compounds contain a given face or edge. //! - **BRepGraph_RelatedIterator**: single-level semantic neighbors (adjacent faces, boundary //! edges, incident vertices). No structural descent; no location accumulation. -//! - **BRepGraph_WireExplorer**: ordered edge traversal within a single wire, following -//! connectivity order (graph equivalent of BRepTools_WireExplorer). class BRepGraph { public: DEFINE_STANDARD_ALLOC - BRepGraph(const BRepGraph&) = delete; + //! Copying is intentionally disabled: BRepGraph is the unique owner of graph data. + BRepGraph(const BRepGraph&) = delete; + //! Copying is intentionally disabled: BRepGraph is the unique owner of graph data. BRepGraph& operator=(const BRepGraph&) = delete; //! Default constructor. Creates an empty graph with default allocator. Standard_EXPORT BRepGraph(); - //! Construct with a custom allocator for internal collections. - //! @param[in] theAlloc allocator for internal collections (null uses CommonBaseAllocator) - Standard_EXPORT explicit BRepGraph(const occ::handle& theAlloc); //! Destructor. Standard_EXPORT ~BRepGraph(); //! Move constructor. @@ -143,33 +140,31 @@ public: //! Reset the graph to an empty state. Increments generation and regenerates the graph GUID. Standard_EXPORT void Clear(); - //! Return true if the graph was successfully built. - [[nodiscard]] Standard_EXPORT bool IsDone() const; + //! Return true when the graph contains no topology definitions. + [[nodiscard]] Standard_EXPORT bool IsEmpty() const; - //! Verify reverse-index consistency against forward entity / reference-entry tables. + //! Verify relation consistency against entity / reference-entry tables. //! Intended for debug builds and regression tests of incremental mutation paths. - //! @return true when every forward ref has a matching reverse entry. - [[nodiscard]] Standard_EXPORT bool ValidateReverseIndex() const; + //! @return true when every stored relation matches its endpoints. + [[nodiscard]] Standard_EXPORT bool ValidateRelations() const; //! Return root product identifiers (products not referenced by any active occurrence). //! Maintained incrementally by Editor/EditorView mutations. //! Returns empty vector if the graph has not been built. - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& RootProductIds() const; - //! Replace the internal allocator and re-create all storage. - Standard_EXPORT void SetAllocator(const occ::handle& theAlloc); - //! Return the current allocator. [[nodiscard]] Standard_EXPORT const occ::handle& Allocator() const; -public: - //! Shared cache for edge/vertex shapes during multi-face reconstruction. - using ReconstructCache = NCollection_DataMap; + //! Return true when this wrapper references graph data. + [[nodiscard]] Standard_EXPORT bool IsValid() const noexcept; + + //! Return true when this wrapper does not reference graph data. + [[nodiscard]] bool IsNull() const noexcept { return !IsValid(); } class TopoView; class UIDsView; - class CacheView; class RefsView; class ShapesView; class EditorView; @@ -180,15 +175,11 @@ public: [[nodiscard]] Standard_EXPORT const TopoView& Topo() const; //! Access unique identifiers. [[nodiscard]] Standard_EXPORT const UIDsView& UIDs() const; - //! Access transient cache values through the stable grouped-view API. - //! This is the only public cache interface. - [[nodiscard]] Standard_EXPORT CacheView& Cache(); - //! Access transient cache values (const, read-only Get/Has/CacheKinds). - //! This is the only public cache interface. - [[nodiscard]] Standard_EXPORT const CacheView& Cache() const; //! Access reference entries and their UIDs. [[nodiscard]] Standard_EXPORT const RefsView& Refs() const; //! Access cached and fresh shape reconstruction. + [[nodiscard]] Standard_EXPORT ShapesView& Shapes(); + //! Access shape ingestion, cached shape reconstruction and fresh shape reconstruction. [[nodiscard]] Standard_EXPORT const ShapesView& Shapes() const; //! Access programmatic graph construction and mutation. [[nodiscard]] Standard_EXPORT EditorView& Editor(); @@ -196,19 +187,14 @@ public: //! Exposes IsDeferredMode() and ValidateMutationBoundary() on a const graph. //! All structural mutation methods require the non-const Editor() overload. [[nodiscard]] Standard_EXPORT const EditorView& Editor() const; - //! Access mesh data with cache-first, persistent-fallback priority. - //! For mesh cache writes and rep creation, use BRepGraph_Tool::Mesh. + //! Access mesh data with explicit Cache()/Persistent() sub-views and Editor() for cache + //! mutations. Persistent rep creation lives on Editor().Edges(), Editor().CoEdges(), + //! Editor().Faces() (since reps back the topology defs). + //! @return read-only mesh view [[nodiscard]] Standard_EXPORT const MeshView& Mesh() const; - - //! Access history subsystem directly. - //! History is returned directly rather than through a lightweight view - //! because it is already a self-contained query and recording subsystem - //! with no per-view cached state. - //! @return history subsystem for tracking modifications - [[nodiscard]] Standard_EXPORT BRepGraph_History& History(); - //! Access history subsystem directly (const). - //! @return history subsystem for tracking modifications - [[nodiscard]] Standard_EXPORT const BRepGraph_History& History() const; + //! Non-const access to mesh view (required to call Editor() sub-view for cache mutations). + //! @return mutable mesh view + [[nodiscard]] Standard_EXPORT MeshView& Mesh(); //! Access registered graph layers. //! @return layer registry for managing attribute layers @@ -217,16 +203,35 @@ public: //! @return layer registry for managing attribute layers [[nodiscard]] Standard_EXPORT const BRepGraph_LayerRegistry& LayerRegistry() const; + //! Access registered graph cache services. + //! @return cache registry for managing typed transient cache services + [[nodiscard]] Standard_EXPORT BRepGraph_CacheRegistry& CacheRegistry(); + //! Access registered graph cache services (const). + //! @return cache registry for managing typed transient cache services + [[nodiscard]] Standard_EXPORT const BRepGraph_CacheRegistry& CacheRegistry() const; + private: - friend class BRepGraph_Builder; + friend class BRepGraph_Cache; + friend class BRepGraph_CacheRegistry; friend class BRepGraph_Compact; friend class BRepGraph_Copy; + friend class BRepGraph_Deduplicate; + friend class BRepGraph_Layer; + friend class BRepGraph_LayerLock; + friend class BRepGraph_LayerRegistry; friend class BRepGraph_Tool; friend class BRepGraph_Transform; + friend class BRepGraph_Validate; + friend class BRepGraphInc_Populate; + friend class BRepGraphInc_Reconstruct; + friend class BRepGraphODE; + friend class BRepGraphODE_Storage; template friend class BRepGraph_MutGuard; - //! @{ + friend struct BRepGraph_NodeId; + friend struct BRepGraph_RefId; + friend struct BRepGraph_RepId; //! Access the underlying storage. [[nodiscard]] Standard_EXPORT BRepGraphInc_Storage& incStorage(); @@ -236,70 +241,63 @@ private: [[nodiscard]] Standard_EXPORT BRepGraph_Data* data(); [[nodiscard]] Standard_EXPORT const BRepGraph_Data* data() const; + //! Bind graph-owned views and registries to this owner. + Standard_EXPORT void initViewsAndRegistries() noexcept; + //! Access the layer registry. [[nodiscard]] Standard_EXPORT BRepGraph_LayerRegistry& layerRegistry(); [[nodiscard]] Standard_EXPORT const BRepGraph_LayerRegistry& layerRegistry() const; - //! Access the raw transient cache for friend algorithms and builders. - [[nodiscard]] Standard_EXPORT BRepGraph_TransientCache& transientCache(); - [[nodiscard]] Standard_EXPORT const BRepGraph_TransientCache& transientCache() const; - - //! Access the raw reference transient cache. - [[nodiscard]] Standard_EXPORT BRepGraph_RefTransientCache& refTransientCache(); - [[nodiscard]] Standard_EXPORT const BRepGraph_RefTransientCache& refTransientCache() const; - - //! Access the mesh cache storage. - [[nodiscard]] Standard_EXPORT BRepGraph_MeshCacheStorage& meshCache(); - [[nodiscard]] Standard_EXPORT const BRepGraph_MeshCacheStorage& meshCache() const; + //! Access the cache registry. + [[nodiscard]] Standard_EXPORT BRepGraph_CacheRegistry& cacheRegistry(); + [[nodiscard]] Standard_EXPORT const BRepGraph_CacheRegistry& cacheRegistry() const; //! Generic reference lookup by RefId (const). //! Returns nullptr if the RefId is invalid or out of range. Standard_EXPORT const BRepGraphInc::BaseRef* refEntity(const BRepGraph_RefId theId) const; - //! @} + //! Invalidate reconstructed shapes and dependent caches below a node. + //! @param[in] theNode root node of the invalidated subgraph + Standard_EXPORT void invalidateSubgraphImpl(const BRepGraph_NodeId theNode); - Standard_EXPORT void invalidateSubgraphImpl(const BRepGraph_NodeId theNode); - Standard_EXPORT BRepGraph_UID allocateUID(const BRepGraph_NodeId theNodeId); + //! Allocate and attach a persistent definition UID for a freshly appended node. + //! @param[in] theNodeId node slot receiving the UID + //! @return allocated definition UID + Standard_EXPORT BRepGraph_UID allocateUID(const BRepGraph_NodeId theNodeId); + + //! Allocate and attach a persistent reference UID for a freshly appended reference. + //! @param[in] theRefId reference slot receiving the UID + //! @return allocated reference UID Standard_EXPORT BRepGraph_RefUID allocateRefUID(const BRepGraph_RefId theRefId); + //! Mark a topology definition as modified and propagate cache invalidation. + //! @param[in] theNodeId modified topology definition Standard_EXPORT void markModified(const BRepGraph_NodeId theNodeId) noexcept; + + //! Mark a reference entry as modified and propagate cache invalidation. + //! @param[in] theRefId modified reference entry Standard_EXPORT void markRefModified(const BRepGraph_RefId theRefId) noexcept; //! Optimized overload: skips changeTopoEntity() dispatch //! when the caller already holds a mutable reference to the target entity. Standard_EXPORT void markModified(const BRepGraph_NodeId theNodeId, BRepGraphInc::BaseDef& theEntity) noexcept; - Standard_EXPORT void markRefModified(const BRepGraph_RefId theRefId, - BRepGraphInc::BaseRef& theRef) noexcept; - //! Increment SubtreeGen on a parent node (NOT OwnGen - parent's own data didn't change). //! Uses wave guard to prevent exponential blowup on diamond topologies. //! Mutex-free: no shape cache clear, no dispatch. Standard_EXPORT void markParentSubtreeGen(const BRepGraph_NodeId theParentId) noexcept; - //! Propagate SubtreeGen upward through reverse indices via markParentSubtreeGen(). + //! Propagate SubtreeGen upward through relation tables via markParentSubtreeGen(). Standard_EXPORT void propagateSubtreeGen(const BRepGraph_NodeId theNodeId) noexcept; - //! Increment OwnGen on a representation and propagate mutation - //! to the owning topology node(s). - Standard_EXPORT void markRepModified(const BRepGraph_RepId theRepId) noexcept; - //! Generic topology definition lookup by NodeId (const). Standard_EXPORT const BRepGraphInc::BaseDef* topoEntity(const BRepGraph_NodeId theId) const; //! Generic mutable topology definition lookup by NodeId. Standard_EXPORT BRepGraphInc::BaseDef* changeTopoEntity(const BRepGraph_NodeId theId); - //! Initialize cached view objects to point to this graph. - Standard_EXPORT void initViews(); - // Fields at the bottom (OCCT style) std::unique_ptr myData; - - //! Registered layers are stored on BRepGraph, not BRepGraph_Data, to survive Compact swap. - BRepGraph_LayerRegistry myLayerRegistry; - BRepGraph_TransientCache myTransientCache; //!< Transient algorithm caches (BndBox, UVBounds) - BRepGraph_RefTransientCache myRefTransientCache; //!< Transient per-reference caches }; // Included after BRepGraph is complete so the template body sees markModified(). diff --git a/opencascade/BRepGraphInc_BitFlags.hxx b/opencascade/BRepGraphInc_BitFlags.hxx new file mode 100644 index 000000000..1415136aa --- /dev/null +++ b/opencascade/BRepGraphInc_BitFlags.hxx @@ -0,0 +1,147 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraphInc_BitFlags_HeaderFile +#define _BRepGraphInc_BitFlags_HeaderFile + +#include + +#include +#include + +//! @brief Contiguous bit-vector for per-entity boolean flags. +//! +//! Stores one bit per entity index in a flat array of 64-bit blocks. +//! Provides O(1) Set/Clear/Test operations and cache-friendly sequential +//! traversal (512 flags per 64-byte cache line via eight 64-bit blocks). +//! +//! Used by BRepGraphInc_Storage to store IsRemoved and IsOwned flags +//! outside the entity structs, improving cache locality during traversal +//! and reducing struct size by eliminating bool-field padding. +//! +//! Public helpers in BRepGraphInc_Storage validate indices before reaching this +//! low-level container. Set, Clear, and Test remain unchecked for hot internal +//! paths that already proved the index is in range. +//! +//! @code +//! BRepGraphInc_BitFlags aFlags; +//! aFlags.Resize(1000); +//! aFlags.Set(42); +//! if (aFlags.Test(42)) { ... } +//! aFlags.Clear(42); +//! @endcode +class BRepGraphInc_BitFlags +{ + static constexpr uint32_t THE_BITS_PER_BLOCK = 64; + using BlockType = uint64_t; + +public: + //! Construct an empty bit-vector. + BRepGraphInc_BitFlags() = default; + + //! Resize the bit-vector to hold at least theCount bits. + //! Newly added bits are initialized to false. + void Resize(const size_t theCount) + { + const size_t aBlockCount = (theCount + THE_BITS_PER_BLOCK - 1) / THE_BITS_PER_BLOCK; + myBlocks.Resize(aBlockCount, 0); + myBitCount = theCount; + maskTailBits(); + } + + //! Set the bit at theIndex to true. + void Set(const uint32_t theIndex) + { + const size_t aBlock = theIndex / THE_BITS_PER_BLOCK; + const uint32_t aBit = theIndex % THE_BITS_PER_BLOCK; + myBlocks[aBlock] |= (BlockType(1) << aBit); + } + + //! Clear the bit at theIndex to false. + void Clear(const uint32_t theIndex) + { + const size_t aBlock = theIndex / THE_BITS_PER_BLOCK; + const uint32_t aBit = theIndex % THE_BITS_PER_BLOCK; + myBlocks[aBlock] &= ~(BlockType(1) << aBit); + } + + //! Return the value of the bit at theIndex. + [[nodiscard]] bool Test(const uint32_t theIndex) const + { + const size_t aBlock = theIndex / THE_BITS_PER_BLOCK; + const uint32_t aBit = theIndex % THE_BITS_PER_BLOCK; + return (myBlocks[aBlock] & (BlockType(1) << aBit)) != 0; + } + + //! Set all bits to true. + void SetAll() + { + for (size_t i = 0; i < myBlocks.Size(); ++i) + { + myBlocks[i] = ~BlockType(0); + } + maskTailBits(); + } + + //! Clear all bits to false. + void ClearAll() + { + for (size_t i = 0; i < myBlocks.Size(); ++i) + { + myBlocks[i] = 0; + } + } + + //! Return true if any bit is set. + [[nodiscard]] bool HasAnyBitSet() const + { + for (size_t i = 0; i < myBlocks.Size(); ++i) + { + if (myBlocks[i] != 0) + { + return true; + } + } + return false; + } + + //! Return the number of blocks allocated. + [[nodiscard]] size_t NbBlocks() const { return myBlocks.Size(); } + + //! Return the number of valid bits represented by this vector. + [[nodiscard]] size_t BitCount() const { return myBitCount; } + + //! Return true if theIndex is inside the valid bit range. + [[nodiscard]] bool IsValidIndex(const uint32_t theIndex) const { return theIndex < myBitCount; } + + //! Return the raw block array for direct iteration. + [[nodiscard]] const BlockType* Blocks() const { return myBlocks.Data(); } + +private: + void maskTailBits() + { + const uint32_t aTailBits = static_cast(myBitCount % THE_BITS_PER_BLOCK); + if (aTailBits == 0u || myBlocks.Size() == 0) + { + return; + } + + const BlockType aTailMask = (BlockType(1) << aTailBits) - BlockType(1); + myBlocks[myBlocks.Size() - 1] &= aTailMask; + } + + NCollection_LinearVector myBlocks; + size_t myBitCount = 0; +}; + +#endif // _BRepGraphInc_BitFlags_HeaderFile diff --git a/opencascade/BRepGraphInc_Definition.hxx b/opencascade/BRepGraphInc_Definition.hxx index cffcc67a4..62f815683 100644 --- a/opencascade/BRepGraphInc_Definition.hxx +++ b/opencascade/BRepGraphInc_Definition.hxx @@ -15,41 +15,32 @@ #define _BRepGraphInc_Definition_HeaderFile #include +#include +#include #include -#include #include - #include -#include #include #include -#include -#include - //! @brief Definition structs for the incidence-table topology model. //! -//! Each definition holds intrinsic geometry properties plus forward-direction -//! children (via RefId indices). The incidence model stores topology as flat -//! vectors of definitions (one per kind) with integer cross-references, -//! enabling cache-friendly traversal and parallel geometry extraction. +//! Each definition holds intrinsic geometry properties. Ordered child +//! incidence lives in BRepGraphInc_Relations and reusable parent/child usage +//! edges live in reference records. namespace BRepGraphInc { -//! Helper: reinitialize a vector member with the given allocator and block size. -template -inline void InitVec(NCollection_DynamicArray& theVec, - const occ::handle& theAlloc, - const int theBlockSize = 4) -{ - theVec = NCollection_DynamicArray(theBlockSize, theAlloc); -} - //! Fields shared by every entity. struct BaseDef { using TypeId = BRepGraph_NodeId; + //! Persistent per-kind UID counter value. + //! 0 = invalid sentinel (not yet allocated). Valid UIDs start at 1. + //! Kind is implicit from the concrete struct type (VertexDef, EdgeDef, etc.). + uint32_t UID = 0; + //! Own-data mutation counter, incremented ONLY when the entity's own //! definition fields change (tolerance, point, flags, etc.). //! NOT incremented by descendant changes. @@ -64,10 +55,8 @@ struct BaseDef //! Wave counter from the last propagation that visited this node. //! Used as a re-visit guard in markParentSubtreeGen() to prevent //! exponential blowup on diamond topologies. Compared against - //! BRepGraph_Data::myPropagationWave. + //! BRepGraphInc_Storage::myPropagationWave. uint32_t LastPropWave = 0; - - bool IsRemoved = false; //!< Soft-removal flag }; //! Vertex definition: 3D point + tolerance. @@ -80,55 +69,24 @@ struct VertexDef : public BaseDef //! Tolerance from BRep_TVertex. double Tolerance = 0.0; - - void InitVectors(const occ::handle&) {} }; -//! Edge entity: parameter range, boundary vertices, flags. -//! Geometry (curve, polygon) accessed via rep indices into Storage vectors. +//! Edge entity: parameter range, boundary vertices. +//! Geometry (curve, polygon) accessed via owned use records. +//! Degeneracy, closure, SameRange, and SameParameter are derived from +//! current topology and geometry via BRepGraph_CacheDerivedState. struct EdgeDef : public BaseDef { using TypeId = BRepGraph_EdgeId; - //! Typed representation id into Storage::myCurves3D (invalid for degenerate edges). - BRepGraph_Curve3DRepId Curve3DRepId; + BRepGraph_EdgeCurve3DRepId Curve3DRepId; //!< Owned 3D curve use id (invalid for degenerate edges) - //! Curve parameter range. - double ParamFirst = 0.0; - double ParamLast = 0.0; - - //! Tolerance from BRep_TEdge. - double Tolerance = 0.0; + double Tolerance = 0.0; //!< Tolerance from BRep_TEdge - //! True if this edge collapses to a point on the surface. - bool IsDegenerate = false; + BRepGraph_VertexRefId StartVertexRefId; //!< Start vertex reference + BRepGraph_VertexRefId EndVertexRefId; //!< End vertex reference - //! True if all PCurves are reparametrized to the same range as the 3D curve. - bool SameParameter = false; - - //! True if the PCurve parameter range equals the 3D curve parameter range. - bool SameRange = false; - - //! True if StartVertex == EndVertex (topological loop, e.g. circle edge). - bool IsClosed = false; - - //! Boundary vertex reference ids (indices into VertexRef table). - //! For closed edges, the start and end ref entries point to the same VertexDefId. - BRepGraph_VertexRefId StartVertexRefId; - BRepGraph_VertexRefId EndVertexRefId; - - //! Additional vertex reference ids with INTERNAL or EXTERNAL orientation. - //! Edges with only FORWARD/REVERSED boundary vertices leave this empty. - NCollection_DynamicArray InternalVertexRefIds; - - //! Typed representation id into Storage::myPolygons3D (invalid if no polygon). - BRepGraph_Polygon3DRepId Polygon3DRepId; - - //! Reinitialize inner vectors with the given allocator. - void InitVectors(const occ::handle& theAlloc) - { - InitVec(InternalVertexRefIds, theAlloc, 2); // typically 0 - } + BRepGraph_EdgePolygon3DRepId Polygon3DRepId; //!< Owned 3D polygon use id }; //! CoEdge entity: use of an edge on a specific face, owns PCurve data. @@ -141,38 +99,21 @@ struct CoEdgeDef : public BaseDef { using TypeId = BRepGraph_CoEdgeId; - BRepGraph_EdgeId EdgeDefId; //!< Parent edge definition id - BRepGraph_FaceId FaceDefId; //!< Face this coedge belongs to (invalid for free wires) - TopAbs_Orientation Orientation = TopAbs_FORWARD; //!< Orientation relative to parent edge - - //! Typed representation id into Storage::myCurves2D (invalid for free-wire coedges). - BRepGraph_Curve2DRepId Curve2DRepId; - double ParamFirst = 0.0; - double ParamLast = 0.0; - gp_Pnt2d UV1; //!< UV at ParamFirst - gp_Pnt2d UV2; //!< UV at ParamLast - - //! Typed representation id into Storage::myPolygons2D (invalid if no polygon-on-surface). - BRepGraph_Polygon2DRepId Polygon2DRepId; + BRepGraph_WireId ParentWireId; //!< Ordered owner wire + BRepGraph_EdgeId ChildEdgeId; //!< Connected reusable edge definition + BRepGraph_FaceId FaceId; //!< Face this coedge belongs to (invalid for free wires) + ParityOrientation Orientation = TopAbs_FORWARD; //!< Orientation relative to parent edge - //! Typed representation id into Storage::myPolygonsOnTri (persistent/imported). - BRepGraph_PolygonOnTriRepId PolygonOnTriRepId; - - void InitVectors(const occ::handle&) {} + BRepGraph_CoEdgeCurve2DRepId Curve2DRepId; //!< Owned 2D curve use id + BRepGraph_CoEdgePolygon2DRepId Polygon2DRepId; //!< Owned 2D polygon use id + BRepGraph_CoEdgePolygonOnTriRepId PolygonOnTriRepId; //!< Owned polygon-on-triangulation use id }; -//! Wire entity: ordered coedge references with closure flag. +//! Wire entity: ordered coedge sequence. +//! Wire closure is derived from the ordered coedge chain via BRepGraph_CacheDerivedState. struct WireDef : public BaseDef { using TypeId = BRepGraph_WireId; - - bool IsClosed = false; - NCollection_DynamicArray CoEdgeRefIds; //!< Ordered coedge ref indices - - void InitVectors(const occ::handle& theAlloc) - { - InitVec(CoEdgeRefIds, theAlloc, 8); // typically 3-8 coedges per wire - } }; //! Face entity: surface, triangulations, wires. @@ -180,119 +121,58 @@ struct FaceDef : public BaseDef { using TypeId = BRepGraph_FaceId; - BRepGraph_SurfaceRepId SurfaceRepId; //!< Typed id into mySurfaces - BRepGraph_TriangulationRepId - TriangulationRepId; //!< Typed id into myTriangulations (persistent/imported) - - double Tolerance = 0.0; - bool NaturalRestriction = false; - - NCollection_DynamicArray WireRefIds; //!< Wire ref indices (outer first) + BRepGraph_FaceSurfaceRepId SurfaceRepId; //!< Owned surface use id + BRepGraph_FaceTriangulationRepId + TriangulationRepId; //!< Owned triangulation use id (persistent/imported) - //! Direct INTERNAL/EXTERNAL vertex children (not inside wires). - //! Boundary vertices are normally reached through WireRefIds -> CoEdgeRefIds - //! -> CoEdgeDef.EdgeDefId -> EdgeDef.{StartVertexRefId, EndVertexRefId}. - //! This vector is for additional direct face-owned vertex usage. - NCollection_DynamicArray VertexRefIds; - - void InitVectors(const occ::handle& theAlloc) - { - InitVec(WireRefIds, theAlloc, 2); // typically 1-2 (outer + holes) - InitVec(VertexRefIds, theAlloc, 2); // typically 0 - } + double Tolerance = 0.0; //!< Face tolerance }; -//! Shell entity: ordered face references with local locations. +//! Shell entity. +//! Shell closure is derived from face-boundary edge incidence via BRepGraph_CacheDerivedState. struct ShellDef : public BaseDef { using TypeId = BRepGraph_ShellId; - - bool IsClosed = false; //!< True if shell forms a watertight (closed) boundary. - NCollection_DynamicArray FaceRefIds; //!< Face ref indices - NCollection_DynamicArray - AuxChildRefIds; //!< Non-face children (wires, edges) - - void InitVectors(const occ::handle& theAlloc) - { - InitVec(FaceRefIds, theAlloc, 8); // typically 4-8 faces per shell - InitVec(AuxChildRefIds, theAlloc, 2); // typically 0 - } }; -//! Solid entity: ordered shell references with local locations. +//! Solid entity. struct SolidDef : public BaseDef { using TypeId = BRepGraph_SolidId; - - NCollection_DynamicArray ShellRefIds; //!< Shell ref indices - NCollection_DynamicArray - AuxChildRefIds; //!< Non-shell children (edges, vertices) - - void InitVectors(const occ::handle& theAlloc) - { - InitVec(ShellRefIds, theAlloc, 2); // typically 1 - InitVec(AuxChildRefIds, theAlloc, 2); // typically 0 - } }; -//! Compound entity: heterogeneous child references. +//! Compound entity. struct CompoundDef : public BaseDef { using TypeId = BRepGraph_CompoundId; - - NCollection_DynamicArray ChildRefIds; //!< Child ref indices - - void InitVectors(const occ::handle& theAlloc) - { - InitVec(ChildRefIds, theAlloc, 4); - } }; -//! Comp-solid entity: ordered solid references. +//! Comp-solid entity. struct CompSolidDef : public BaseDef { using TypeId = BRepGraph_CompSolidId; - - NCollection_DynamicArray SolidRefIds; //!< Solid ref indices - - void InitVectors(const occ::handle& theAlloc) - { - InitVec(SolidRefIds, theAlloc, 2); - } }; //! Product entity: reusable shape definition (part or assembly). -//! Children are managed uniformly via OccurrenceRefIds: -//! - A part product has one occurrence whose ChildDefId is a topology root node. -//! - An assembly product has occurrences whose ChildDefId values are other products. +//! Children are managed uniformly via ProductRelations::OccurrenceRefIds: +//! - A part product has one occurrence whose ChildNodeId is a topology root node. +//! - An assembly product has occurrences whose ChildNodeId values are other products. //! Products carry no location or orientation - those live on references. struct ProductDef : public BaseDef { using TypeId = BRepGraph_ProductId; - - NCollection_DynamicArray - OccurrenceRefIds; //!< All children (shape roots and sub-products) - - void InitVectors(const occ::handle& theAlloc) - { - InitVec(OccurrenceRefIds, theAlloc, 4); - } }; //! Occurrence entity: reference to a child node (topology root or product). -//! The parent product is determined from OccurrenceRef::ParentId (BaseRef). +//! Parent products are determined from ProductRelations owner arrays. //! Placement lives on OccurrenceRef::LocalLocation (definitions never carry location). -//! Path-based traversal (PathView::ForEachPathTo) resolves DAG paths without -//! stored parent-occurrence pointers. +//! Path-based traversal (BRepGraph_UsagePath) resolves DAG paths without stored +//! parent-occurrence pointers. struct OccurrenceDef : public BaseDef { using TypeId = BRepGraph_OccurrenceId; - BRepGraph_NodeId ChildDefId; //!< Referenced child node (topology root or product) - - //! No-op: OccurrenceDef has no inner vectors to reinitialize. - //! Present for uniform DefStore::Append() logic. - void InitVectors(const occ::handle&) {} + BRepGraph_NodeId ChildNodeId; //!< Referenced child node (topology root or product) }; } // namespace BRepGraphInc diff --git a/opencascade/BRepGraphInc_Instance.hxx b/opencascade/BRepGraphInc_Instance.hxx index 05e6dcecd..4a9485866 100644 --- a/opencascade/BRepGraphInc_Instance.hxx +++ b/opencascade/BRepGraphInc_Instance.hxx @@ -48,10 +48,14 @@ struct Instance TypedIdT DefId; TopLoc_Location Location; TopAbs_Orientation Orientation = TopAbs_FORWARD; + + //! Returns true if the instance references an existing definition id. + [[nodiscard]] bool IsValid() const { return DefId.IsValid(); } }; using VertexInstance = Instance; using CoEdgeInstance = Instance; +using WireInstance = Instance; using FaceInstance = Instance; using ShellInstance = Instance; using SolidInstance = Instance; @@ -67,12 +71,6 @@ using ProductInstance = Instance; //! implicit conversion to BRepGraph_NodeId. using NodeInstance = Instance; -//! Wire instance with an additional flag indicating whether this is the outer wire. -struct WireInstance : Instance -{ - bool IsOuter = false; -}; - } // namespace BRepGraphInc //! std::hash specialization for BRepGraphInc::Instance. diff --git a/opencascade/BRepGraphInc_Load.hxx b/opencascade/BRepGraphInc_Load.hxx new file mode 100644 index 000000000..129942dee --- /dev/null +++ b/opencascade/BRepGraphInc_Load.hxx @@ -0,0 +1,56 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraphInc_Load_HeaderFile +#define _BRepGraphInc_Load_HeaderFile + +#include + +//! Internal storage-side types for fixed-size indexed load preparation. +namespace BRepGraphInc_Load +{ + +//! Final section counts needed to prepare `BRepGraphInc_Storage` for indexed load. +struct Counts +{ + uint32_t NbVertices = 0; //!< Number of `VertexDef` slots. + uint32_t NbEdges = 0; //!< Number of `EdgeDef` slots. + uint32_t NbCoEdges = 0; //!< Number of `CoEdgeDef` slots. + uint32_t NbWires = 0; //!< Number of `WireDef` slots. + uint32_t NbFaces = 0; //!< Number of `FaceDef` slots. + uint32_t NbShells = 0; //!< Number of `ShellDef` slots. + uint32_t NbSolids = 0; //!< Number of `SolidDef` slots. + uint32_t NbCompounds = 0; //!< Number of `CompoundDef` slots. + uint32_t NbCompSolids = 0; //!< Number of `CompSolidDef` slots. + uint32_t NbProducts = 0; //!< Number of `ProductDef` slots. + uint32_t NbOccurrences = 0; //!< Number of `OccurrenceDef` slots. + uint32_t NbShellRefs = 0; //!< Number of `ShellRef` slots. + uint32_t NbFaceRefs = 0; //!< Number of `FaceRef` slots. + uint32_t NbWireRefs = 0; //!< Number of `WireRef` slots. + uint32_t NbVertexRefs = 0; //!< Number of `VertexRef` slots. + uint32_t NbSolidRefs = 0; //!< Number of `SolidRef` slots. + uint32_t NbChildRefs = 0; //!< Number of `ChildRef` slots. + uint32_t NbOccurrenceRefs = 0; //!< Number of `OccurrenceRef` slots. + uint32_t NbFaceSurfaceReps = 0; //!< Number of `FaceSurfaceRep` slots. + uint32_t NbEdgeCurve3DReps = 0; //!< Number of `EdgeCurve3DRep` slots. + uint32_t NbCoEdgeCurve2DReps = 0; //!< Number of `CoEdgeCurve2DRep` slots. + uint32_t NbFaceTriangulationReps = 0; //!< Number of `FaceTriangulationRep` slots. + uint32_t NbEdgePolygon3DReps = 0; //!< Number of `EdgePolygon3DRep` slots. + uint32_t NbCoEdgePolygon2DReps = 0; //!< Number of `CoEdgePolygon2DRep` slots. + uint32_t NbCoEdgePolygonOnTriReps = 0; //!< Number of `CoEdgePolygonOnTriRep` slots. + uint32_t NbRootProducts = 0; //!< Number of root product ids outside storage tables. +}; + +} // namespace BRepGraphInc_Load + +#endif // _BRepGraphInc_Load_HeaderFile diff --git a/opencascade/BRepGraphInc_ParityOrientation.hxx b/opencascade/BRepGraphInc_ParityOrientation.hxx new file mode 100644 index 000000000..b8c4daa2a --- /dev/null +++ b/opencascade/BRepGraphInc_ParityOrientation.hxx @@ -0,0 +1,64 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraphInc_ParityOrientation_HeaderFile +#define _BRepGraphInc_ParityOrientation_HeaderFile + +#include +#include + +namespace BRepGraphInc +{ + +//! @brief Persisted core-topology orientation stored as forward/reversed parity only. +//! +//! The wrapper keeps storage compact through one bool while remaining implicitly +//! convertible to `TopAbs_Orientation` for existing orientation-facing codepaths. +struct ParityOrientation +{ + //! Stored parity bit: `false` for `TopAbs_FORWARD`, `true` for `TopAbs_REVERSED`. + bool IsReversed = false; + + //! Constructs the parity wrapper from a core forward/reversed orientation. + ParityOrientation() = default; + + //! Constructs the parity wrapper from a core forward/reversed orientation. + ParityOrientation(const TopAbs_Orientation theOrientation) + : IsReversed(toIsReversed(theOrientation)) + { + } + + //! Assigns a core forward/reversed orientation. + ParityOrientation& operator=(const TopAbs_Orientation theOrientation) + { + IsReversed = toIsReversed(theOrientation); + return *this; + } + + //! Converts stored parity back to `TopAbs_Orientation`. + operator TopAbs_Orientation() const { return IsReversed ? TopAbs_REVERSED : TopAbs_FORWARD; } + +private: + //! Converts a core forward/reversed orientation to the stored parity bit. + static bool toIsReversed(const TopAbs_Orientation theOrientation) + { + Standard_ProgramError_Raise_if(theOrientation != TopAbs_FORWARD + && theOrientation != TopAbs_REVERSED, + "BRepGraphInc::ParityOrientation stores only FORWARD/REVERSED"); + return theOrientation == TopAbs_REVERSED; + } +}; + +} // namespace BRepGraphInc + +#endif // _BRepGraphInc_ParityOrientation_HeaderFile diff --git a/opencascade/BRepGraphInc_Populate.hxx b/opencascade/BRepGraphInc_Populate.hxx index 010eee225..1cb4ff015 100644 --- a/opencascade/BRepGraphInc_Populate.hxx +++ b/opencascade/BRepGraphInc_Populate.hxx @@ -15,112 +15,83 @@ #define _BRepGraphInc_Populate_HeaderFile #include - -#include -#include +#include #include +#include class TopoDS_Shape; -class BRepGraphInc_Storage; -class BRepGraph_LayerParam; -class BRepGraph_LayerRegularity; +class BRepGraph; -//! @brief Backend population pipeline for BRepGraphInc_Storage. +//! @brief Backend topology/geometry population for BRepGraph. //! //! This class is part of the BRepGraphInc backend and is intended for //! backend maintenance, tests, and low-level infrastructure only. -//! External code should enter through BRepGraph_Builder::Add(), which owns the +//! External code should enter through BRepGraph::ShapesView::Add(), which owns the //! public lifecycle, cache invalidation, and layer coordination. //! -//! Adapted from BRepGraph_Builder, but writes to incidence-table storage -//! instead of Def/Usage two-layer storage. Entity structs carry forward -//! child references directly (no separate Usage objects). -//! -//! The population pipeline: -//! 1. Sequential hierarchy traversal (Compound/CompSolid/Solid/Shell) -//! 2. Parallel per-face geometry extraction -//! 3. Sequential registration with TShape deduplication -//! 4. Reverse index construction +//! The builder stores forward child relations only. Reverse relations are rebuilt +//! by BRepGraphInc_Storage after population. class BRepGraphInc_Populate { public: DEFINE_STANDARD_ALLOC - //! Options controlling which post-passes are executed during population. - struct Options + //! Result of a build operation. + enum class BuildStatus { - bool ExtractRegularities; //!< Phase 3b: edge regularities - bool ExtractVertexPointReps; //!< Phase 3c: vertex point representations + Success, //!< All faces built successfully. + SuccessWithWarnings, //!< Build completed with diagnostics, e.g. unbounded natural faces. + Failed //!< Build failed (e.g., null shape, internal error). + }; - Options() - : ExtractRegularities(true), - ExtractVertexPointReps(true) - { - } + //! Options controlling population. + struct Options + { }; //! Build backend incidence storage from a TopoDS_Shape. - //! @param[out] theStorage storage to populate (cleared first) + //! @param[out] theGraph graph whose storage to populate (cleared first) //! @param[in] theShape root shape //! @param[in] theParallel if true, face-level extraction runs in parallel //! @param[in] theOptions optional post-pass controls - //! @param[in] theParamLayer optional point-rep layer to populate - //! @param[in] theRegularityLayer optional edge-regularity layer to populate - //! @param[in] theTmpAlloc optional allocator for temporary scratch data - static Standard_EXPORT void Perform( - BRepGraphInc_Storage& theStorage, - const TopoDS_Shape& theShape, - const bool theParallel, - const Options& theOptions = Options(), - const occ::handle& theParamLayer = occ::handle(), - const occ::handle& theRegularityLayer = - occ::handle(), - const occ::handle& theTmpAlloc = - occ::handle()); + //! @return build status indicating success, warnings, or failure + [[nodiscard]] static Standard_EXPORT BuildStatus Perform(BRepGraph& theGraph, + const TopoDS_Shape& theShape, + bool theParallel, + const Options& theOptions = Options()); //! Extend existing backend storage with additional shapes (no clear). //! Flattens hierarchy containers away; Solid/Shell/Compound/CompSolid inputs //! contribute appended face roots instead of container entities. //! Recomputes the built-in metadata layers from the populated storage. - //! @param[in,out] theStorage storage to extend + //! @param[in,out] theGraph graph whose storage to extend //! @param[in] theShape shape to append //! @param[in] theParallel if true, face-level extraction runs in parallel //! @param[out] theAppendedRoots collected root NodeIds for non-container shapes //! @param[in] theOptions optional post-pass controls - //! @param[in] theTmpAlloc optional allocator for temporary scratch data - static Standard_EXPORT void AppendFlattened( - BRepGraphInc_Storage& theStorage, - const TopoDS_Shape& theShape, - const bool theParallel, - NCollection_DynamicArray& theAppendedRoots, - const Options& theOptions = Options(), - const occ::handle& theParamLayer = occ::handle(), - const occ::handle& theRegularityLayer = - occ::handle(), - const occ::handle& theTmpAlloc = - occ::handle()); + //! @return build status indicating success, warnings, or failure + [[nodiscard]] static Standard_EXPORT BuildStatus + AppendFlattened(BRepGraph& theGraph, + const TopoDS_Shape& theShape, + bool theParallel, + NCollection_LinearVector& theAppendedRoots, + const Options& theOptions = Options()); //! Extend existing backend storage with additional shapes (no clear). //! Preserves the full shape hierarchy: Solid/Shell/Compound/CompSolid nodes //! are created alongside Face/Edge/Vertex nodes. Shapes already present in - //! the storage (same TShape pointer) are deduplicated and not re-added. - //! @param[in,out] theStorage storage to extend - //! @param[in] theShape shape to append - //! @param[in] theParallel if true, face-level extraction runs in parallel - //! @param[in] theOptions optional post-pass controls - //! @param[in] theTmpAlloc optional allocator for temporary scratch data - static Standard_EXPORT void Append( - BRepGraphInc_Storage& theStorage, - const TopoDS_Shape& theShape, - const bool theParallel, - const Options& theOptions = Options(), - const occ::handle& theParamLayer = occ::handle(), - const occ::handle& theRegularityLayer = - occ::handle(), - const occ::handle& theTmpAlloc = - occ::handle()); + //! the storage with the same definition identity (TShape + Location, orientation ignored) + //! are deduplicated and not re-added. + //! @param[in,out] theGraph graph whose storage to extend + //! @param[in] theShape shape to append + //! @param[in] theParallel if true, face-level extraction runs in parallel + //! @param[in] theOptions optional post-pass controls + //! @return build status indicating success, warnings, or failure + [[nodiscard]] static Standard_EXPORT BuildStatus Append(BRepGraph& theGraph, + const TopoDS_Shape& theShape, + bool theParallel, + const Options& theOptions = Options()); -private: BRepGraphInc_Populate() = delete; }; diff --git a/opencascade/BRepGraphInc_Reconstruct.hxx b/opencascade/BRepGraphInc_Reconstruct.hxx index 9fbd374b8..b6b404892 100644 --- a/opencascade/BRepGraphInc_Reconstruct.hxx +++ b/opencascade/BRepGraphInc_Reconstruct.hxx @@ -16,14 +16,11 @@ #include #include +#include #include #include -#include - -class BRepGraphInc_Storage; -class BRepGraph_LayerParam; -class BRepGraph_LayerRegularity; +class BRepGraph; //! @brief Backend reconstruction helpers over incidence-table storage. //! @@ -55,98 +52,52 @@ public: { Cache& myCache; - explicit TempScope(Cache& theCache) - : myCache(theCache) - { - if (myCache.myTempScopeDepth == 0 && !myCache.myTempAllocator.IsNull()) - myCache.myTempAllocator->Reset(false); - ++myCache.myTempScopeDepth; - } - - ~TempScope() - { - --myCache.myTempScopeDepth; - if (myCache.myTempScopeDepth == 0 && !myCache.myTempAllocator.IsNull()) - myCache.myTempAllocator->Reset(false); - } + explicit TempScope(Cache& theCache); + ~TempScope(); }; - Cache() - : myAllocator(new NCollection_IncAllocator()), - myTempAllocator(new NCollection_IncAllocator()) - { - for (int aKindIdx = 0; aKindIdx < THE_KIND_COUNT; ++aKindIdx) - { - myKinds[aKindIdx] = - NCollection_DynamicArray(THE_DEFAULT_INCREMENT, myAllocator); - } - } + Cache(); //! Seek a cached shape. Returns nullptr if not yet cached. - const TopoDS_Shape* Seek(const BRepGraph_NodeId theNode) const - { - const int aKindIdx = static_cast(theNode.NodeKind); - if (aKindIdx < 0 || aKindIdx >= THE_KIND_COUNT) - return nullptr; - const NCollection_DynamicArray& aVec = myKinds[aKindIdx]; - if (theNode.Index >= aVec.Size()) - return nullptr; - const TopoDS_Shape& aShape = aVec.Value(static_cast(theNode.Index)); - return aShape.IsNull() ? nullptr : &aShape; - } + [[nodiscard]] Standard_EXPORT const TopoDS_Shape* Seek(const BRepGraph_NodeId theNode) const; //! Bind a reconstructed shape to a node. Grows the vector as needed. - void Bind(const BRepGraph_NodeId theNode, const TopoDS_Shape& theShape) - { - const int aKindIdx = static_cast(theNode.NodeKind); - if (aKindIdx < 0 || aKindIdx >= THE_KIND_COUNT) - return; - NCollection_DynamicArray& aVec = myKinds[aKindIdx]; - aVec.SetValue(static_cast(theNode.Index), theShape); - } + Standard_EXPORT void Bind(const BRepGraph_NodeId theNode, const TopoDS_Shape& theShape); //! Check if a node is already cached. - bool IsBound(const BRepGraph_NodeId theNode) const { return Seek(theNode) != nullptr; } + [[nodiscard]] bool IsBound(const BRepGraph_NodeId theNode) const + { + return Seek(theNode) != nullptr; + } }; //! Reconstruct a TopoDS_Shape from an entity node. //! Creates a local cache internally; shared vertices/edges are not reused //! across calls. - //! @param[in] theStorage incidence storage - //! @param[in] theNode entity node id + //! @param[in] theGraph graph owning the storage and caches + //! @param[in] theNode entity node id //! @return reconstructed shape - static Standard_EXPORT TopoDS_Shape - Node(const BRepGraphInc_Storage& theStorage, - const BRepGraph_NodeId theNode, - const BRepGraph_LayerParam* theParams = nullptr, - const BRepGraph_LayerRegularity* theRegularities = nullptr); + static Standard_EXPORT TopoDS_Shape Node(BRepGraph& theGraph, const BRepGraph_NodeId theNode); //! Reconstruct a TopoDS_Shape with a shared cache for sub-shape reuse. //! Vertices and edges already in theCache are returned directly. - //! @param[in] theStorage incidence storage - //! @param[in] theNode entity node id - //! @param[in,out] theCache shared cache for vertex/edge/face shapes + //! @param[in] theGraph graph owning the storage and caches + //! @param[in] theNode entity node id + //! @param[in,out] theCache shared cache for vertex/edge/face shapes //! @return reconstructed shape - static Standard_EXPORT TopoDS_Shape - Node(const BRepGraphInc_Storage& theStorage, - const BRepGraph_NodeId theNode, - Cache& theCache, - const BRepGraph_LayerParam* theParams = nullptr, - const BRepGraph_LayerRegularity* theRegularities = nullptr); + static Standard_EXPORT TopoDS_Shape Node(BRepGraph& theGraph, + const BRepGraph_NodeId theNode, + Cache& theCache); //! Reconstruct a face with shared edge/vertex cache for multi-face contexts. - //! @param[in] theStorage incidence storage - //! @param[in] theFaceId face entity id - //! @param[in,out] theCache shared cache for edge and vertex shapes + //! @param[in] theGraph graph owning the storage and caches + //! @param[in] theFaceId face entity id + //! @param[in,out] theCache shared cache for edge and vertex shapes //! @return reconstructed face shape - static Standard_EXPORT TopoDS_Shape - FaceWithCache(const BRepGraphInc_Storage& theStorage, - const BRepGraph_FaceId theFaceId, - Cache& theCache, - const BRepGraph_LayerParam* theParams = nullptr, - const BRepGraph_LayerRegularity* theRegularities = nullptr); - -private: + static Standard_EXPORT TopoDS_Shape FaceWithCache(BRepGraph& theGraph, + const BRepGraph_FaceId theFaceId, + Cache& theCache); + BRepGraphInc_Reconstruct() = delete; }; diff --git a/opencascade/BRepGraphInc_Reference.hxx b/opencascade/BRepGraphInc_Reference.hxx index a4c8f1b71..0068c8cc1 100644 --- a/opencascade/BRepGraphInc_Reference.hxx +++ b/opencascade/BRepGraphInc_Reference.hxx @@ -14,19 +14,19 @@ #ifndef _BRepGraphInc_Reference_HeaderFile #define _BRepGraphInc_Reference_HeaderFile +#include #include #include -#include #include //! @brief Managed reference entry structs for the incidence-table storage. //! -//! Each reference entry extends BaseRef with payload fields describing -//! how a child definition is used by its parent (orientation, location). +//! Each reference entry extends BaseRef with representation fields describing +//! how a child definition is used by its parent. //! Reference entries are stored in flat per-kind vectors in BRepGraphInc_Storage //! and support mutation tracking and soft-removal. //! Not every definition kind has a dedicated Ref kind by design: -//! - Edge usage is represented by CoEdgeRef -> CoEdgeDef (which then targets EdgeDef) +//! - CoEdge usage is stored directly on CoEdgeDef and ordered through WireRelations //! - Compound children use ChildRef (heterogeneous NodeId target) //! - Product children use OccurrenceRef (placement owned by OccurrenceDef) //! - CompSolid children use SolidRef @@ -41,9 +41,10 @@ struct BaseRef { using TypeId = BRepGraph_RefId; - BRepGraph_NodeId ParentId; //!< Parent topology node owning this reference usage - uint32_t OwnGen = 0; //!< Per-reference mutation counter - bool IsRemoved = false; //!< Soft-removal flag + //! Persistent per-kind UID counter value. + //! 0 = invalid sentinel (not yet allocated). Valid UIDs start at 1. + //! Kind is implicit from the concrete struct type (ShellRef, FaceRef, etc.). + uint32_t UID = 0; }; //! Shell reference storage entry. @@ -51,9 +52,9 @@ struct ShellRef : public BaseRef { using TypeId = BRepGraph_ShellRefId; - BRepGraph_ShellId ShellDefId; - TopAbs_Orientation Orientation = TopAbs_FORWARD; - TopLoc_Location LocalLocation; + BRepGraph_SolidId ParentSolidId; //!< Parent solid identifier + BRepGraph_ShellId ChildShellId; //!< Child shell identifier + ParityOrientation Orientation = TopAbs_FORWARD; //!< Orientation within parent }; //! Face reference storage entry. @@ -61,9 +62,9 @@ struct FaceRef : public BaseRef { using TypeId = BRepGraph_FaceRefId; - BRepGraph_FaceId FaceDefId; - TopAbs_Orientation Orientation = TopAbs_FORWARD; - TopLoc_Location LocalLocation; + BRepGraph_ShellId ParentShellId; //!< Parent shell identifier + BRepGraph_FaceId ChildFaceId; //!< Child face identifier + ParityOrientation Orientation = TopAbs_FORWARD; //!< Orientation within parent }; //! Wire reference storage entry. @@ -71,22 +72,9 @@ struct WireRef : public BaseRef { using TypeId = BRepGraph_WireRefId; - BRepGraph_WireId WireDefId; - bool IsOuter = false; - TopAbs_Orientation Orientation = TopAbs_FORWARD; - TopLoc_Location LocalLocation; -}; - -//! CoEdge reference storage entry. -//! No Orientation field: CoEdgeDef::Orientation already owns the edge-on-face sense, -//! coupled with PCurve parametrization, so duplicating orientation here would -//! create a second competing source of truth. -struct CoEdgeRef : public BaseRef -{ - using TypeId = BRepGraph_CoEdgeRefId; - - BRepGraph_CoEdgeId CoEdgeDefId; - TopLoc_Location LocalLocation; + BRepGraph_FaceId ParentFaceId; //!< Parent face identifier + BRepGraph_WireId ChildWireId; //!< Child wire identifier + ParityOrientation Orientation = TopAbs_FORWARD; //!< Orientation within parent }; //! Vertex reference storage entry. @@ -94,10 +82,9 @@ struct VertexRef : public BaseRef { using TypeId = BRepGraph_VertexRefId; - BRepGraph_VertexId VertexDefId; - TopAbs_Orientation Orientation = - TopAbs_INTERNAL; //!< INTERNAL: B-Rep vertex classification convention - TopLoc_Location LocalLocation; + BRepGraph_VertexId ChildVertexId; //!< Child vertex identifier + BRepGraph_EdgeId ParentEdgeId; //!< Edge that owns this vertex reference + ParityOrientation Orientation = TopAbs_FORWARD; //!< Orientation within parent }; //! Solid reference storage entry. @@ -105,9 +92,9 @@ struct SolidRef : public BaseRef { using TypeId = BRepGraph_SolidRefId; - BRepGraph_SolidId SolidDefId; - TopAbs_Orientation Orientation = TopAbs_FORWARD; - TopLoc_Location LocalLocation; + BRepGraph_CompSolidId ParentCompSolidId; //!< Parent compsolid identifier + BRepGraph_SolidId ChildSolidId; //!< Child solid identifier + ParityOrientation Orientation = TopAbs_FORWARD; //!< Orientation within parent }; //! Child reference storage entry. @@ -115,9 +102,10 @@ struct ChildRef : public BaseRef { using TypeId = BRepGraph_ChildRefId; - BRepGraph_NodeId ChildDefId; - TopAbs_Orientation Orientation = TopAbs_FORWARD; - TopLoc_Location LocalLocation; + BRepGraph_CompoundId ParentCompoundId; //!< Parent compound identifier + BRepGraph_NodeId ChildNodeId; //!< Child node identifier (heterogeneous) + ParityOrientation Orientation = TopAbs_FORWARD; //!< Orientation within parent + TopLoc_Location LocalLocation; //!< Location relative to parent }; //! Occurrence reference storage entry. @@ -127,7 +115,8 @@ struct OccurrenceRef : public BaseRef { using TypeId = BRepGraph_OccurrenceRefId; - BRepGraph_OccurrenceId OccurrenceDefId; + BRepGraph_ProductId ParentProductId; + BRepGraph_OccurrenceId ChildOccurrenceId; TopLoc_Location LocalLocation; //!< Placement relative to parent product }; diff --git a/opencascade/BRepGraphInc_Relations.hxx b/opencascade/BRepGraphInc_Relations.hxx new file mode 100644 index 000000000..fbf1fc460 --- /dev/null +++ b/opencascade/BRepGraphInc_Relations.hxx @@ -0,0 +1,100 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraphInc_Relations_HeaderFile +#define _BRepGraphInc_Relations_HeaderFile + +#include +#include +#include + +//! @brief Centralized topology relation representations for BRepGraph incidence storage. +//! +//! Relation structs hold ordered child-use lists and incoming incidence indexes +//! outside definition records. Definitions stay focused on intrinsic geometry +//! and flags; reusable child/parent edges live in reference records or coedge +//! use records. +namespace BRepGraphInc +{ + +//! @brief Topology relations for face definitions. +struct FaceRelations +{ + NCollection_LinearVector WireRefIds; //!< Wire references owned by this face + NCollection_LinearVector + ParentFaceRefIds; //!< Upstream face references (compound hierarchy) +}; + +//! @brief Topology relations for wire definitions. +struct WireRelations +{ + NCollection_LinearVector CoEdgeIds; //!< Coedge identifiers in this wire + NCollection_LinearVector ParentWireRefIds; //!< Upstream wire references +}; + +//! @brief Topology relations for edge definitions. +struct EdgeRelations +{ + NCollection_LinearVector CoEdgeIds; //!< Coedge identifiers using this edge +}; + +//! @brief Topology relations for shell definitions. +struct ShellRelations +{ + NCollection_LinearVector FaceRefIds; //!< Face references in this shell + NCollection_LinearVector ParentShellRefIds; //!< Upstream shell references +}; + +//! @brief Topology relations for solid definitions. +struct SolidRelations +{ + NCollection_LinearVector ShellRefIds; //!< Shell references in this solid + NCollection_LinearVector ParentSolidRefIds; //!< Upstream solid references +}; + +//! @brief Topology relations for compound definitions. +struct CompoundRelations +{ + NCollection_LinearVector ChildRefIds; //!< Child references in this compound +}; + +//! @brief Topology relations for compsolid definitions. +struct CompSolidRelations +{ + NCollection_LinearVector + SolidRefIds; //!< Solid references in this compsolid +}; + +//! @brief Topology relations for vertex definitions. +struct VertexRelations +{ + NCollection_LinearVector EdgeIds; //!< Edge identifiers sharing this vertex +}; + +//! @brief Topology relations for product definitions. +struct ProductRelations +{ + NCollection_LinearVector + OccurrenceRefIds; //!< Occurrence references under this product +}; + +//! @brief Topology relations for occurrence definitions. +struct OccurrenceRelations +{ + NCollection_LinearVector + ParentOccurrenceRefIds; //!< Upstream occurrence references +}; + +} // namespace BRepGraphInc + +#endif // _BRepGraphInc_Relations_HeaderFile diff --git a/opencascade/BRepGraphInc_RepId.hxx b/opencascade/BRepGraphInc_RepId.hxx new file mode 100644 index 000000000..d74e50d8b --- /dev/null +++ b/opencascade/BRepGraphInc_RepId.hxx @@ -0,0 +1,221 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraphInc_RepId_HeaderFile +#define _BRepGraphInc_RepId_HeaderFile + +#include +#include + +#include +#include +#include + +class BRepGraph; + +//! Lightweight typed index into a per-kind use-record vector inside BRepGraph. +//! +//! The pair (Kind, Index) forms a unique use-record identifier within one graph +//! instance. Default-constructed RepId has Index = UINT32_MAX (invalid). +//! +//! Use records are session-local representation slots with no public stable UID, +//! graph-level lock state, independent mutation generation, or layer callbacks. +//! They do have a soft-removed state so an owner can clear and later reuse its slot. +struct BRepGraph_RepId +{ + //! Enumeration of use-record kinds. + enum class Kind : int + { + EdgeCurve3D = 0, //!< Geom_Curve use for edges + EdgePolygon3D = 1, //!< Poly_Polygon3D use for edges + CoEdgeCurve2D = 2, //!< Geom2d_Curve use for coedges + CoEdgePolygon2D = 3, //!< Poly_Polygon2D use for coedges + CoEdgePolygonOnTri = 4, //!< Poly_PolygonOnTriangulation use for coedges + FaceSurface = 5, //!< Geom_Surface use for faces + FaceTriangulation = 6 //!< Poly_Triangulation use for faces + }; + + //! True if the kind value is one of the supported use-record kinds. + static bool IsValidKind(const Kind theKind) + { + switch (theKind) + { + case Kind::EdgeCurve3D: + case Kind::EdgePolygon3D: + case Kind::CoEdgeCurve2D: + case Kind::CoEdgePolygon2D: + case Kind::CoEdgePolygonOnTri: + case Kind::FaceSurface: + case Kind::FaceTriangulation: + return true; + } + return false; + } + + //! Compile-time typed wrapper around BRepGraph_RepId. + template + struct Typed + { + static constexpr uint32_t THE_START_INDEX = 0u; + static constexpr uint32_t THE_INVALID_INDEX = std::numeric_limits::max(); + + uint32_t Index; + + //! Default: invalid. + Typed() + : Index(THE_INVALID_INDEX) + { + } + + //! Construct from index. + explicit Typed(const uint32_t theIdx) + : Index(theIdx) + { + } + + //! First valid id in a dense sequence. + [[nodiscard]] static Typed Start() { return Typed(THE_START_INDEX); } + + //! Invalid sentinel id. + [[nodiscard]] static Typed Invalid() { return Typed(); } + + //! True if this id points to an allocated slot. + [[nodiscard]] bool IsValid() const { return Index != THE_INVALID_INDEX; } + + //! True if this id is within [0, theMaxCount). + [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const + { + return IsValid() && Index < theMaxCount; + } + + //! Implicit conversion to untyped RepId. + operator BRepGraph_RepId() const { return BRepGraph_RepId(TheKind, Index); } + + //! Return true if this use entry has been soft-removed in the given graph. + [[nodiscard]] bool IsRemoved(const BRepGraph& theGraph) const + { + return BRepGraph_RepId(*this).IsRemoved(theGraph); + } + + //! Pre-increment. + Typed& operator++() + { + Standard_ASSERT_VOID(Index != THE_INVALID_INDEX, "pre-increment on invalid use id"); + ++Index; + return *this; + } + + //! Post-increment. + Typed operator++(int) + { + Standard_ASSERT_VOID(Index != THE_INVALID_INDEX, "post-increment on invalid use id"); + Typed aPrev = *this; + ++Index; + return aPrev; + } + + bool operator==(const Typed& theOther) const { return Index == theOther.Index; } + + bool operator!=(const Typed& theOther) const { return Index != theOther.Index; } + + bool operator<(const Typed& theOther) const { return Index < theOther.Index; } + + bool operator<=(const Typed& theOther) const { return Index <= theOther.Index; } + + bool operator>(const Typed& theOther) const { return Index > theOther.Index; } + + bool operator>=(const Typed& theOther) const { return Index >= theOther.Index; } + }; + + static constexpr uint32_t THE_START_INDEX = 0u; + static constexpr uint32_t THE_INVALID_INDEX = std::numeric_limits::max(); + + Kind RepKind; + uint32_t Index; + + //! Default: invalid RepId. + BRepGraph_RepId() + : RepKind(Kind::EdgeCurve3D), + Index(THE_INVALID_INDEX) + { + } + + BRepGraph_RepId(const Kind theKind, const uint32_t theIdx) + : RepKind(theKind), + Index(theIdx) + { + } + + //! True if this id points to an allocated slot. + [[nodiscard]] bool IsValid() const { return IsValidKind(RepKind) && Index != THE_INVALID_INDEX; } + + //! True if this id is within [0, theMaxCount). + [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const + { + return IsValid() && Index < theMaxCount; + } + + bool operator==(const BRepGraph_RepId& theOther) const + { + return RepKind == theOther.RepKind && Index == theOther.Index; + } + + bool operator!=(const BRepGraph_RepId& theOther) const { return !(*this == theOther); } + + bool operator<(const BRepGraph_RepId& theOther) const + { + if (RepKind != theOther.RepKind) + { + return static_cast(RepKind) < static_cast(theOther.RepKind); + } + return Index < theOther.Index; + } + + //! Return true if this use entry has been soft-removed in the given graph. + [[nodiscard]] Standard_EXPORT bool IsRemoved(const BRepGraph& theGraph) const; +}; + +// Convenience type aliases for typed RepIds. +using BRepGraph_EdgeCurve3DRepId = BRepGraph_RepId::Typed; +using BRepGraph_EdgePolygon3DRepId = BRepGraph_RepId::Typed; +using BRepGraph_CoEdgeCurve2DRepId = BRepGraph_RepId::Typed; +using BRepGraph_CoEdgePolygon2DRepId = + BRepGraph_RepId::Typed; +using BRepGraph_CoEdgePolygonOnTriRepId = + BRepGraph_RepId::Typed; +using BRepGraph_FaceSurfaceRepId = BRepGraph_RepId::Typed; +using BRepGraph_FaceTriangulationRepId = + BRepGraph_RepId::Typed; + +template <> +struct std::hash +{ + size_t operator()(const BRepGraph_RepId& theId) const noexcept + { + size_t aCombination[2]; + aCombination[0] = opencascade::hash(static_cast(theId.RepKind)); + aCombination[1] = opencascade::hash(theId.Index); + return opencascade::hashBytes(aCombination, sizeof(aCombination)); + } +}; + +template +struct std::hash> +{ + size_t operator()(const BRepGraph_RepId::Typed& theId) const noexcept + { + return std::hash{}(theId.Index); + } +}; + +#endif // _BRepGraphInc_RepId_HeaderFile diff --git a/opencascade/BRepGraphInc_Representation.hxx b/opencascade/BRepGraphInc_Representation.hxx index 58e7b44fa..ee36b3f43 100644 --- a/opencascade/BRepGraphInc_Representation.hxx +++ b/opencascade/BRepGraphInc_Representation.hxx @@ -14,8 +14,8 @@ #ifndef _BRepGraphInc_Representation_HeaderFile #define _BRepGraphInc_Representation_HeaderFile -#include - +#include +#include #include #include #include @@ -23,81 +23,81 @@ #include #include #include +#include -//! @brief Geometry and mesh representation structs for the incidence-table model. +//! @brief Geometry representation records for the BRepGraph incidence storage. //! -//! Each representation struct wraps a single piece of geometry or discretization -//! data (surface, curve, triangulation, polygon) with a typed RepId address -//! and lifecycle tracking fields. Representations are stored in flat per-kind -//! vectors in BRepGraphInc_Storage and referenced from definitions by typed RepId. +//! Curve parameter ranges live in curve-use records because the use record +//! is not reusable - the interval belongs to the owning edge/coedge curve use, +//! not to a shared geometric curve. namespace BRepGraphInc { -//! Fields shared by every representation entity. -struct BaseRep -{ - using TypeId = BRepGraph_RepId; - - uint32_t OwnGen = 0; //!< Per-rep mutation counter - bool IsRemoved = false; //!< Soft-removal flag -}; - -//! Surface geometry representation for faces. -struct SurfaceRep : public BaseRep +//! 3D curve use for edges. Owned by a single edge. +struct EdgeCurve3DRep { - using TypeId = BRepGraph_SurfaceRepId; + using TypeId = BRepGraph_EdgeCurve3DRepId; - occ::handle Surface; //!< The geometric surface + BRepGraph_EdgeId ParentEdgeId; //!< Owning edge identifier + occ::handle Curve; //!< 3D curve geometry + double ParamFirst = 0.0; //!< First curve parameter + double ParamLast = 0.0; //!< Last curve parameter }; -//! 3D curve geometry representation for edges. -struct Curve3DRep : public BaseRep +//! 3D polygon use for edges. Owned by a single edge. +struct EdgePolygon3DRep { - using TypeId = BRepGraph_Curve3DRepId; + using TypeId = BRepGraph_EdgePolygon3DRepId; - occ::handle Curve; //!< The 3D curve geometry + BRepGraph_EdgeId ParentEdgeId; //!< Owning edge identifier + occ::handle Polygon; //!< 3D polygon geometry }; -//! 2D parametric curve (PCurve) representation for coedges. -struct Curve2DRep : public BaseRep +//! 2D parametric curve (PCurve) use for coedges. Owned by a single coedge. +struct CoEdgeCurve2DRep { - using TypeId = BRepGraph_Curve2DRepId; + using TypeId = BRepGraph_CoEdgeCurve2DRepId; - occ::handle Curve; //!< The 2D parametric curve + BRepGraph_CoEdgeId ParentCoEdgeId; //!< Owning coedge identifier + occ::handle Curve; //!< 2D parametric curve geometry + double ParamFirst = 0.0; //!< First curve parameter + double ParamLast = 0.0; //!< Last curve parameter }; -//! Triangulation mesh representation for faces. -struct TriangulationRep : public BaseRep +//! 2D polygon-on-surface use for coedges. Owned by a single coedge. +struct CoEdgePolygon2DRep { - using TypeId = BRepGraph_TriangulationRepId; + using TypeId = BRepGraph_CoEdgePolygon2DRepId; - occ::handle Triangulation; //!< The mesh + BRepGraph_CoEdgeId ParentCoEdgeId; //!< Owning coedge identifier + occ::handle Polygon; //!< 2D polygon geometry }; -//! 3D polygon discretization for edges. -struct Polygon3DRep : public BaseRep +//! Polygon-on-triangulation use for coedges. Owned by a single coedge. +struct CoEdgePolygonOnTriRep { - using TypeId = BRepGraph_Polygon3DRepId; + using TypeId = BRepGraph_CoEdgePolygonOnTriRepId; - occ::handle Polygon; //!< The 3D polygon + BRepGraph_CoEdgeId ParentCoEdgeId; //!< Owning coedge identifier + occ::handle Polygon; //!< Polygon-on-triangulation geometry }; -//! 2D polygon-on-surface discretization for coedges. -struct Polygon2DRep : public BaseRep +//! Surface geometry use for faces. Owned by a single face. +struct FaceSurfaceRep { - using TypeId = BRepGraph_Polygon2DRepId; + using TypeId = BRepGraph_FaceSurfaceRepId; - occ::handle Polygon; //!< The 2D polygon on surface parametric space + BRepGraph_FaceId ParentFaceId; //!< Owning face identifier + occ::handle Surface; //!< Surface geometry }; -//! Polygon-on-triangulation for coedges. -//! Links a polygon to a specific triangulation rep (global index, not face-local). -struct PolygonOnTriRep : public BaseRep +//! Triangulation mesh use for faces. Owned by a single face. +struct FaceTriangulationRep { - using TypeId = BRepGraph_PolygonOnTriRepId; + using TypeId = BRepGraph_FaceTriangulationRepId; - occ::handle Polygon; //!< Polygon indices into triangulation - BRepGraph_TriangulationRepId TriangulationRepId; //!< Typed id into myTriangulationsRep + BRepGraph_FaceId ParentFaceId; //!< Owning face identifier + occ::handle Triangulation; //!< Triangulation mesh }; } // namespace BRepGraphInc diff --git a/opencascade/BRepGraphInc_ReverseIndex.hxx b/opencascade/BRepGraphInc_ReverseIndex.hxx deleted file mode 100644 index 95379e9ef..000000000 --- a/opencascade/BRepGraphInc_ReverseIndex.hxx +++ /dev/null @@ -1,618 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraphInc_ReverseIndex_HeaderFile -#define _BRepGraphInc_ReverseIndex_HeaderFile - -#include -#include -#include -#include - -class BRepGraphInc_Storage; - -namespace BRepGraphInc -{ -struct VertexDef; -struct EdgeDef; -struct CoEdgeDef; -struct WireDef; -struct FaceDef; -struct ShellDef; -struct SolidDef; -struct CompoundDef; -struct CompSolidDef; -struct ProductDef; -struct OccurrenceDef; -struct ShellRef; -struct FaceRef; -struct WireRef; -struct CoEdgeRef; -struct SolidRef; -struct ChildRef; -struct VertexRef; -} // namespace BRepGraphInc - -//! @brief Backend reverse incidence indices for O(1) upward navigation. -//! -//! Built from entity and reference-entry tables after population. -//! Full ReverseIndex::Build() is used for initial construction, while builder-side -//! mutations maintain the index incrementally through targeted bind/unbind -//! operations and ReverseIndex::BuildDelta() for append workflows. -//! -//! ## Two query tiers -//! Pointer-returning methods (e.g. WiresOfEdge() -> nullptr for empty) serve -//! performance-critical backend code that avoids static-empty-vector overhead. -//! Safe-reference methods (e.g. WiresOfEdgeRef() -> static empty vector) serve -//! the public facade (TopoView delegates to Ref variants). -class BRepGraphInc_ReverseIndex -{ -public: - DEFINE_STANDARD_ALLOC - - //! Set allocator for internal index tables. - void SetAllocator(const occ::handle& theAlloc) - { - myAllocator = theAlloc; - } - - //! Clear all indices. - Standard_EXPORT void Clear(); - - //! Rebuild all reverse indices from storage tables. - //! Thin wrapper over the explicit-table overload retained for compatibility. - Standard_EXPORT void Build(const BRepGraphInc_Storage& theStorage); - - //! Rebuild all reverse indices from the entity and reference-entry tables. - //! Edge-to-face index is derived from CoEdge.FaceDefId links. - //! @pre SetAllocator() must have been called (uses myAllocator for inner vectors). - //! @param[in] theEdges edge entity vector (for vertex-to-edge, edge-to-face) - //! @param[in] theCoEdges coedge entity vector (for edge-to-coedge and edge-to-face) - //! @param[in] theWires wire entity vector (parent validation for coedge refs) - //! @param[in] theFaces face entity vector (parent validation for wire refs) - //! @param[in] theShells shell entity vector (parent validation for face refs) - //! @param[in] theSolids solid entity vector (parent validation for shell refs) - //! @param[in] theCompounds compound entity vector (parent validation for child refs) - //! @param[in] theCompSolids compsolid entity vector (parent validation for solid refs) - //! @param[in] theShellRefs shell ref-entry table (solid -> shell reverse) - //! @param[in] theFaceRefs face ref-entry table (shell -> face reverse) - //! @param[in] theWireRefs wire ref-entry table (face -> wire reverse) - //! @param[in] theCoEdgeRefs coedge ref-entry table (wire -> coedge/edge reverse) - //! @param[in] theSolidRefs solid ref-entry table (compsolid -> solid reverse) - //! @param[in] theChildRefs child ref-entry table (compound child reverse) - //! @param[in] theVertexRefs vertex ref-entry table (edge vertex resolution) - Standard_EXPORT void Build( - const NCollection_DynamicArray& theVertices, - const NCollection_DynamicArray& theEdges, - const NCollection_DynamicArray& theCoEdges, - const NCollection_DynamicArray& theWires, - const NCollection_DynamicArray& theFaces, - const NCollection_DynamicArray& theShells, - const NCollection_DynamicArray& theSolids, - const NCollection_DynamicArray& theCompounds, - const NCollection_DynamicArray& theCompSolids, - const NCollection_DynamicArray& theShellRefs, - const NCollection_DynamicArray& theFaceRefs, - const NCollection_DynamicArray& theWireRefs, - const NCollection_DynamicArray& theCoEdgeRefs, - const NCollection_DynamicArray& theSolidRefs, - const NCollection_DynamicArray& theChildRefs, - const NCollection_DynamicArray& theVertexRefs); - - //! Incrementally update reverse indices for entities/ref-parents appended after a previous - //! ReverseIndex::Build(). Only processes entities from the old counts to the current vector - //! lengths and appended reference entries. - //! @param[in] theOldNbEdges edge count before the append operation - //! @param[in] theOldNbWires wire count before the append operation - //! @param[in] theOldNbFaces face count before the append operation - //! @param[in] theOldNbShells shell count before the append operation - //! @param[in] theOldNbSolids solid count before the append operation - //! @param[in] theOldNbCompounds compound count before the append operation - //! @param[in] theOldNbCompSolids compsolid count before the append operation - //! @param[in] theOldNbChildRefs ChildRef count before the append operation - //! @param[in] theOldNbSolidRefs SolidRef count before the append operation - Standard_EXPORT void BuildDelta( - const NCollection_DynamicArray& theVertices, - const NCollection_DynamicArray& theEdges, - const NCollection_DynamicArray& theCoEdges, - const NCollection_DynamicArray& theWires, - const NCollection_DynamicArray& theFaces, - const NCollection_DynamicArray& theShells, - const NCollection_DynamicArray& theSolids, - const NCollection_DynamicArray& theCompounds, - const NCollection_DynamicArray& theCompSolids, - const NCollection_DynamicArray& theShellRefs, - const NCollection_DynamicArray& theFaceRefs, - const NCollection_DynamicArray& theWireRefs, - const NCollection_DynamicArray& theCoEdgeRefs, - const NCollection_DynamicArray& theSolidRefs, - const NCollection_DynamicArray& theChildRefs, - const NCollection_DynamicArray& theVertexRefs, - const uint32_t theOldNbEdges, - const uint32_t theOldNbWires, - const uint32_t theOldNbFaces, - const uint32_t theOldNbShells, - const uint32_t theOldNbSolids, - const uint32_t theOldNbCompounds, - const uint32_t theOldNbCompSolids, - const uint32_t theOldNbChildRefs, - const uint32_t theOldNbSolidRefs); - - //! Build product-to-occurrences reverse index. - //! @param[in] theOccurrences occurrence entity vector - //! @param[in] theNbProducts total number of products (for pre-sizing) - Standard_EXPORT void BuildProductOccurrences( - const NCollection_DynamicArray& theOccurrences, - const uint32_t theNbProducts); - - //! Return wire indices containing the given edge. - [[nodiscard]] const NCollection_DynamicArray* WiresOfEdge( - const BRepGraph_EdgeId theEdgeId) const - { - return seekVec(myEdgeToWires, theEdgeId.Index); - } - - //! Return face indices containing the given edge (derived from CoEdge.FaceDefId links). - [[nodiscard]] const NCollection_DynamicArray* FacesOfEdge( - const BRepGraph_EdgeId theEdgeId) const - { - return seekVec(myEdgeToFaces, theEdgeId.Index); - } - - //! Return coedge indices referencing the given edge. - [[nodiscard]] const NCollection_DynamicArray* CoEdgesOfEdge( - const BRepGraph_EdgeId theEdgeId) const - { - return seekVec(myEdgeToCoEdges, theEdgeId.Index); - } - - //! Return the number of faces incident to an edge - O(1). - //! Derived directly from the edge-to-faces adjacency vector to keep a single source of truth. - [[nodiscard]] uint32_t NbFacesOfEdge(const BRepGraph_EdgeId theEdgeId) const - { - const NCollection_DynamicArray* aFaces = - seekVec(myEdgeToFaces, theEdgeId.Index); - return aFaces != nullptr ? static_cast(aFaces->Size()) : 0u; - } - - //! Return edge indices incident to the given vertex. - [[nodiscard]] const NCollection_DynamicArray* EdgesOfVertex( - const BRepGraph_VertexId theVertexId) const - { - return seekVec(myVertexToEdges, theVertexId.Index); - } - - //! Return face indices containing the given wire. - [[nodiscard]] const NCollection_DynamicArray* FacesOfWire( - const BRepGraph_WireId theWireId) const - { - return seekVec(myWireToFaces, theWireId.Index); - } - - //! Return shell indices containing the given face. - [[nodiscard]] const NCollection_DynamicArray* ShellsOfFace( - const BRepGraph_FaceId theFaceId) const - { - return seekVec(myFaceToShells, theFaceId.Index); - } - - //! Return solid indices containing the given shell. - [[nodiscard]] const NCollection_DynamicArray* SolidsOfShell( - const BRepGraph_ShellId theShellId) const - { - return seekVec(myShellToSolids, theShellId.Index); - } - - //! Return compound indices containing the given solid as a NodeInstance. - [[nodiscard]] const NCollection_DynamicArray* CompoundsOfSolid( - const BRepGraph_SolidId theSolidId) const - { - return seekVec(myCompoundsOfSolid, theSolidId.Index); - } - - //! Return compsolid indices containing the given solid as a SolidInstance. - [[nodiscard]] const NCollection_DynamicArray* CompSolidsOfSolid( - const BRepGraph_SolidId theSolidId) const - { - return seekVec(myCompSolidsOfSolid, theSolidId.Index); - } - - //! Return compound indices containing the given shell as a NodeInstance. - [[nodiscard]] const NCollection_DynamicArray* CompoundsOfShell( - const BRepGraph_ShellId theShellId) const - { - return seekVec(myCompoundsOfShell, theShellId.Index); - } - - //! Return compound indices containing the given face as a NodeInstance. - [[nodiscard]] const NCollection_DynamicArray* CompoundsOfFace( - const BRepGraph_FaceId theFaceId) const - { - return seekVec(myCompoundsOfFace, theFaceId.Index); - } - - //! Return compound indices containing the given compound as a NodeInstance. - [[nodiscard]] const NCollection_DynamicArray* CompoundsOfCompound( - const BRepGraph_CompoundId theCompoundId) const - { - return seekVec(myCompoundsOfCompound, theCompoundId.Index); - } - - //! Return compound indices containing the given compsolid as a NodeInstance. - [[nodiscard]] const NCollection_DynamicArray* CompoundsOfCompSolid( - const BRepGraph_CompSolidId theCompSolidId) const - { - return seekVec(myCompoundsOfCompSolid, theCompSolidId.Index); - } - - //! Return compound indices containing the given wire as a NodeInstance. - //! OCCT `TopoDS_Compound` can legally hold atomic topology (wire / edge / - //! vertex); these reverse maps round-trip that case. - [[nodiscard]] const NCollection_DynamicArray* CompoundsOfWire( - const BRepGraph_WireId theWireId) const - { - return seekVec(myCompoundsOfWire, theWireId.Index); - } - - //! Return compound indices containing the given edge as a NodeInstance. - [[nodiscard]] const NCollection_DynamicArray* CompoundsOfEdge( - const BRepGraph_EdgeId theEdgeId) const - { - return seekVec(myCompoundsOfEdge, theEdgeId.Index); - } - - //! Return compound indices containing the given vertex as a NodeInstance. - [[nodiscard]] const NCollection_DynamicArray* CompoundsOfVertex( - const BRepGraph_VertexId theVertexId) const - { - return seekVec(myCompoundsOfVertex, theVertexId.Index); - } - - //! Return wire indices containing the given coedge. - [[nodiscard]] const NCollection_DynamicArray* WiresOfCoEdge( - const BRepGraph_CoEdgeId theCoEdgeId) const - { - return seekVec(myCoEdgeToWires, theCoEdgeId.Index); - } - - //! Return occurrence indices that reference the given product. - [[nodiscard]] const NCollection_DynamicArray* OccurrencesOfProduct( - const BRepGraph_ProductId theProductId) const - { - return seekVec(myProductToOccurrences, theProductId.Index); - } - - // --- Safe reference accessors (return empty vector instead of nullptr) --- - - //! Return wire indices containing the given edge (safe reference, never null). - [[nodiscard]] const NCollection_DynamicArray& WiresOfEdgeRef( - const BRepGraph_EdgeId theEdgeId) const - { - return seekRef(myEdgeToWires, theEdgeId.Index); - } - - //! Return face indices containing the given edge (safe reference, never null). - [[nodiscard]] const NCollection_DynamicArray& FacesOfEdgeRef( - const BRepGraph_EdgeId theEdgeId) const - { - return seekRef(myEdgeToFaces, theEdgeId.Index); - } - - //! Return coedge indices referencing the given edge (safe reference, never null). - [[nodiscard]] const NCollection_DynamicArray& CoEdgesOfEdgeRef( - const BRepGraph_EdgeId theEdgeId) const - { - return seekRef(myEdgeToCoEdges, theEdgeId.Index); - } - - //! Return face indices containing the given wire (safe reference, never null). - [[nodiscard]] const NCollection_DynamicArray& FacesOfWireRef( - const BRepGraph_WireId theWireId) const - { - return seekRef(myWireToFaces, theWireId.Index); - } - - //! Return edge indices incident to the given vertex (safe reference, never null). - [[nodiscard]] const NCollection_DynamicArray& EdgesOfVertexRef( - const BRepGraph_VertexId theVertexId) const - { - return seekRef(myVertexToEdges, theVertexId.Index); - } - - //! Return shell indices containing the given face (safe reference, never null). - [[nodiscard]] const NCollection_DynamicArray& ShellsOfFaceRef( - const BRepGraph_FaceId theFaceId) const - { - return seekRef(myFaceToShells, theFaceId.Index); - } - - //! Return solid indices containing the given shell (safe reference, never null). - [[nodiscard]] const NCollection_DynamicArray& SolidsOfShellRef( - const BRepGraph_ShellId theShellId) const - { - return seekRef(myShellToSolids, theShellId.Index); - } - - //! Verify reverse index consistency against forward entity/reference-entry tables. - //! For each forward ref (e.g., wire->edge), checks that the corresponding - //! reverse entry exists (edge->wire). Intended for debug validation. - //! @return true if all forward refs have matching reverse entries - Standard_EXPORT bool Validate( - const NCollection_DynamicArray& theVertices, - const NCollection_DynamicArray& theEdges, - const NCollection_DynamicArray& theCoEdges, - const NCollection_DynamicArray& theWires, - const NCollection_DynamicArray& theFaces, - const NCollection_DynamicArray& theShells, - const NCollection_DynamicArray& theSolids, - const NCollection_DynamicArray& theCompounds, - const NCollection_DynamicArray& theCompSolids, - const NCollection_DynamicArray& theShellRefs, - const NCollection_DynamicArray& theFaceRefs, - const NCollection_DynamicArray& theWireRefs, - const NCollection_DynamicArray& theCoEdgeRefs, - const NCollection_DynamicArray& theSolidRefs, - const NCollection_DynamicArray& theChildRefs, - const NCollection_DynamicArray& theVertexRefs) const; - - // --- Incremental mutation --- - - //! Register an edge as belonging to a wire (O(1) amortized). - Standard_EXPORT void BindEdgeToWire(const BRepGraph_EdgeId theEdgeId, - const BRepGraph_WireId theWireId); - - //! Remove a wire from the edge-to-wire index for a given edge. - Standard_EXPORT void UnbindEdgeFromWire(const BRepGraph_EdgeId theEdgeId, - const BRepGraph_WireId theWireId); - - //! Replace an edge in the edge-to-wire index for a specific wire. - Standard_EXPORT void ReplaceEdgeInWireMap(const BRepGraph_EdgeId theOldEdgeId, - const BRepGraph_EdgeId theNewEdgeId, - const BRepGraph_WireId theWireId); - - //! Register a vertex as incident to an edge (O(1) amortized, deduplicates). - Standard_EXPORT void BindVertexToEdge(const BRepGraph_VertexId theVertexId, - const BRepGraph_EdgeId theEdgeId); - - //! Remove an edge from the vertex-to-edge index for a given vertex. - Standard_EXPORT void UnbindVertexFromEdge(const BRepGraph_VertexId theVertexId, - const BRepGraph_EdgeId theEdgeId); - - //! Register a coedge as referencing an edge (O(1) amortized). - Standard_EXPORT void BindEdgeToCoEdge(const BRepGraph_EdgeId theEdgeId, - const BRepGraph_CoEdgeId theCoEdgeId); - - //! Remove a coedge from the edge-to-coedge index for a given edge. - Standard_EXPORT void UnbindEdgeFromCoEdge(const BRepGraph_EdgeId theEdgeId, - const BRepGraph_CoEdgeId theCoEdgeId); - - //! Register a coedge as belonging to a wire (O(1) amortized). - Standard_EXPORT void BindCoEdgeToWire(const BRepGraph_CoEdgeId theCoEdgeId, - const BRepGraph_WireId theWireId); - - //! Remove a wire from the coedge-to-wire index for a given coedge. - Standard_EXPORT void UnbindCoEdgeFromWire(const BRepGraph_CoEdgeId theCoEdgeId, - const BRepGraph_WireId theWireId); - - //! Register an edge as belonging to a face (O(1) amortized, deduplicates). - Standard_EXPORT void BindEdgeToFace(const BRepGraph_EdgeId theEdgeId, - const BRepGraph_FaceId theFaceId); - - //! Remove a face from the edge-to-face index for a given edge. - Standard_EXPORT void UnbindEdgeFromFace(const BRepGraph_EdgeId theEdgeId, - const BRepGraph_FaceId theFaceId); - - //! Register a wire as belonging to a face (O(1) amortized, deduplicates). - Standard_EXPORT void BindWireToFace(const BRepGraph_WireId theWireId, - const BRepGraph_FaceId theFaceId); - - //! Remove a face from the wire-to-face index for a given wire. - Standard_EXPORT void UnbindWireFromFace(const BRepGraph_WireId theWireId, - const BRepGraph_FaceId theFaceId); - - //! Register a face as belonging to a shell (O(1) amortized, deduplicates). - Standard_EXPORT void BindFaceToShell(const BRepGraph_FaceId theFaceId, - const BRepGraph_ShellId theShellId); - - //! Remove a shell from the face-to-shell index for a given face. - Standard_EXPORT void UnbindFaceFromShell(const BRepGraph_FaceId theFaceId, - const BRepGraph_ShellId theShellId); - - //! Register a shell as belonging to a solid (O(1) amortized, deduplicates). - Standard_EXPORT void BindShellToSolid(const BRepGraph_ShellId theShellId, - const BRepGraph_SolidId theSolidId); - - //! Remove a solid from the shell-to-solid index for a given shell. - Standard_EXPORT void UnbindShellFromSolid(const BRepGraph_ShellId theShellId, - const BRepGraph_SolidId theSolidId); - - //! Register a solid as belonging to a compsolid (O(1) amortized, deduplicates). - Standard_EXPORT void BindSolidToCompSolid(const BRepGraph_SolidId theSolidId, - const BRepGraph_CompSolidId theCompSolidId); - - //! Remove a compsolid from the solid-to-compsolid index for a given solid. - Standard_EXPORT void UnbindSolidFromCompSolid(const BRepGraph_SolidId theSolidId, - const BRepGraph_CompSolidId theCompSolidId); - - //! Register a child node as belonging to a compound (dispatched on NodeKind). - //! Routes to the appropriate per-kind compound reverse map. No-op for unsupported kinds. - Standard_EXPORT void BindCompoundChild(const BRepGraph_NodeId theChildDefId, - const BRepGraph_CompoundId theCompoundId); - - //! Remove a compound from the per-kind compound reverse map for a given child node. - Standard_EXPORT void UnbindCompoundChild(const BRepGraph_NodeId theChildDefId, - const BRepGraph_CompoundId theCompoundId); - - //! Register an occurrence as referencing a product (O(1) amortized, deduplicates). - Standard_EXPORT void BindProductOccurrence(const BRepGraph_OccurrenceId theOccurrenceId, - const BRepGraph_ProductId theProductId); - - //! Remove an occurrence from the product-to-occurrences index for a given product. - Standard_EXPORT void UnbindProductOccurrence(const BRepGraph_OccurrenceId theOccurrenceId, - const BRepGraph_ProductId theProductId); - -private: - //! Dense vector type: outer index = entity key, inner vector = typed adjacency list. - template - using TypedIndexTable = NCollection_DynamicArray>; - - //! Bounds-checked lookup returning nullptr for out-of-range or empty slots. - template - static const NCollection_DynamicArray* seekVec(const TypedIndexTable& theIdx, - const uint32_t theKey) - { - if (theKey >= theIdx.Size()) - return nullptr; - const NCollection_DynamicArray& aVec = theIdx.Value(static_cast(theKey)); - return aVec.IsEmpty() ? nullptr : &aVec; - } - - //! Bounds-checked lookup returning a const reference (empty vector for missing keys). - template - static const NCollection_DynamicArray& seekRef(const TypedIndexTable& theIdx, - const uint32_t theKey) - { - const NCollection_DynamicArray* aPtr = seekVec(theIdx, theKey); - if (aPtr != nullptr) - return *aPtr; - static const NCollection_DynamicArray THE_EMPTY; - return THE_EMPTY; - } - - //! Ensure theIdx has at least theSize slots (pre-sizing with empty vectors). - //! If theAlloc is non-null, inner vectors are constructed with it. - template - static void ensureSize(TypedIndexTable& theIdx, - const uint32_t theSize, - const occ::handle& theAlloc = - occ::handle()) - { - if (theSize <= theIdx.Size()) - return; - - if (!theAlloc.IsNull()) - { - for (size_t i = theIdx.Size(), aNb = static_cast(theSize); i < aNb; ++i) - { - theIdx.Append(NCollection_DynamicArray(16, theAlloc)); - } - } - else - { - for (size_t i = theIdx.Size(), aNb = static_cast(theSize); i < aNb; ++i) - { - theIdx.Appended(); - } - } - } - - //! Ensure theVec has at least theSize elements. - //! New elements are default-constructed (zero for scalar types). - template - static void ensureSize(NCollection_DynamicArray& theVec, const uint32_t theSize) - { - while (theVec.Size() < static_cast(theSize)) - { - theVec.Appended(); - } - } - - //! Resize theIdx exactly to theSize slots (clears previous content first). - template - static void preSize(TypedIndexTable& theIdx, - const uint32_t theSize, - const occ::handle& theAlloc = - occ::handle()) - { - theIdx.Clear(); - ensureSize(theIdx, theSize, theAlloc); - } - - //! Add theVal to the vector at theKey, creating if needed. Skips duplicates. - template - static void appendUnique(TypedIndexTable& theIdx, const uint32_t theKey, const T theVal) - { - if (theKey >= theIdx.Size()) - ensureSize(theIdx, theKey + 1u); - - NCollection_DynamicArray& aVec = theIdx.ChangeValue(static_cast(theKey)); - for (const T& anElem : aVec) - { - if (anElem == theVal) - return; - } - aVec.Append(theVal); - } - - //! Add theVal to the vector at theKey unconditionally (no duplicate check). - //! Used during ReverseIndex::Build() where freshly-cleared indices guarantee no duplicates. - template - static void appendDirect(TypedIndexTable& theIdx, const uint32_t theKey, const T theVal) - { - if (theKey >= theIdx.Size()) - ensureSize(theIdx, theKey + 1u); - - theIdx.ChangeValue(static_cast(theKey)).Append(theVal); - } - - //! Remove first occurrence of theVal from the vector at theKey via swap-with-last + erase-last. - //! No-op if theKey is out of range or theVal is absent. O(N) lookup, O(1) removal. - template - static void eraseSwapLast(TypedIndexTable& theIdx, const uint32_t theKey, const T theVal) - { - if (theKey >= theIdx.Size()) - return; - NCollection_DynamicArray& aVec = theIdx.ChangeValue(static_cast(theKey)); - const size_t aNb = aVec.Size(); - for (size_t i = 0; i < aNb; ++i) - { - if (aVec.Value(i) == theVal) - { - if (i + 1u < aNb) - aVec.ChangeValue(i) = aVec.Value(aNb - 1u); - aVec.EraseLast(); - return; - } - } - } - - occ::handle myAllocator; - - TypedIndexTable myEdgeToWires; - TypedIndexTable myEdgeToFaces; - TypedIndexTable myEdgeToCoEdges; - TypedIndexTable myVertexToEdges; - TypedIndexTable myWireToFaces; - TypedIndexTable myFaceToShells; - TypedIndexTable myShellToSolids; - TypedIndexTable myProductToOccurrences; - - TypedIndexTable myCompoundsOfSolid; //!< Solid -> parent Compound indices. - TypedIndexTable - myCompSolidsOfSolid; //!< Solid -> parent CompSolid indices. - TypedIndexTable myCompoundsOfShell; //!< Shell -> parent Compound indices. - TypedIndexTable myCompoundsOfFace; //!< Face -> parent Compound indices. - TypedIndexTable - myCompoundsOfCompound; //!< Compound -> parent Compound indices. - TypedIndexTable - myCompoundsOfCompSolid; //!< CompSolid -> parent Compound indices. - TypedIndexTable myCompoundsOfWire; //!< Wire -> parent Compound indices. - TypedIndexTable myCompoundsOfEdge; //!< Edge -> parent Compound indices. - TypedIndexTable myCompoundsOfVertex; //!< Vertex -> parent Compound indices. - TypedIndexTable myCoEdgeToWires; //!< CoEdge -> parent Wire indices. - - uint32_t myNbIndexedCoEdges = - 0; //!< Number of coedges indexed by ReverseIndex::Build()/BuildDelta(). -}; - -#endif // _BRepGraphInc_ReverseIndex_HeaderFile diff --git a/opencascade/BRepGraphInc_Storage.hxx b/opencascade/BRepGraphInc_Storage.hxx index 791bf56e0..2f063563e 100644 --- a/opencascade/BRepGraphInc_Storage.hxx +++ b/opencascade/BRepGraphInc_Storage.hxx @@ -14,52 +14,184 @@ #ifndef _BRepGraphInc_Storage_HeaderFile #define _BRepGraphInc_Storage_HeaderFile +#include #include -#include #include #include +#include #include +#include #include +#include #include -#include - -#include +#include +#include #include +#include #include +#include +#include #include #include #include #include +#include + +#include +#include +#include //! @brief Central backend storage container for the incidence-table topology model. //! //! Holds all entity vectors (Vertex through Occurrence), representation -//! vectors (Surface, Curve3D, Curve2D, Triangulation, Polygon), reverse -//! indices for O(1) upward navigation, TShape deduplication maps, original +//! vectors (Surface, Curve3D, Curve2D, Triangulation, Polygon), relation +//! tables for connectivity navigation, TShape deduplication maps, original //! shape bindings, and per-kind UID vectors. Provides typed accessors //! enforcing compile-time safety for backend code. External callers should //! normally use the BRepGraph facade rather than reaching into this storage //! directly. BRepGraphInc_Populate has friend access for efficient bulk writes //! during graph population. -class BRepGraph_Builder; - class BRepGraphInc_Storage { public: DEFINE_STANDARD_ALLOC - //! Construct with allocator for internal collections. - //! If null, uses CommonBaseAllocator. - Standard_EXPORT explicit BRepGraphInc_Storage( - const occ::handle& theAlloc = - occ::handle()); + //! Gen-validated shape cache entry. + struct CachedShape + { + //! Reconstructed shape cached for a node id. + TopoDS_Shape Shape; + + //! Subtree generation captured when the cached shape was built. + uint32_t StoredSubtreeGen = 0; + }; - //! Return the allocator used for internal collections. + //! Construct an empty storage with no entities or representations. + Standard_EXPORT BRepGraphInc_Storage(); + + //! Clear allocator-backed containers before member destructors walk them. + Standard_EXPORT ~BRepGraphInc_Storage(); + + //! Return the allocator used for backend storage. [[nodiscard]] const occ::handle& Allocator() const { return myAllocator; } + //! Return products not referenced by any active occurrence. + [[nodiscard]] const NCollection_LinearVector& RootProductIds() const + { + return myRootProductIds; + } + + //! Return products not referenced by any active occurrence. + NCollection_LinearVector& ChangeRootProductIds() { return myRootProductIds; } + + //! Return nodes accumulated during deferred invalidation. + [[nodiscard]] const NCollection_LinearVector& DeferredModified() const + { + return myDeferredModified; + } + + //! Return nodes accumulated during deferred invalidation. + NCollection_LinearVector& ChangeDeferredModified() + { + return myDeferredModified; + } + + //! Return refs accumulated during deferred invalidation. + [[nodiscard]] const NCollection_LinearVector& DeferredRefModified() const + { + return myDeferredRefModified; + } + + //! Return refs accumulated during deferred invalidation. + NCollection_LinearVector& ChangeDeferredRefModified() + { + return myDeferredRefModified; + } + + //! Return true when the graph contains no topology definitions. + //! Checks whether any node kind (Vertex, Edge, Wire, Face, Shell, Solid, + //! Compound, CompSolid, Product, Occurrence) has been allocated. + [[nodiscard]] Standard_EXPORT bool IsEmpty() const; + + //! Return the next UID counter for a given node kind. + [[nodiscard]] Standard_EXPORT uint32_t NextNodeUIDCounter(BRepGraph_NodeId::Kind theKind) const; + + //! Override the next UID counter for a given node kind. + Standard_EXPORT void SetNextNodeUIDCounter(BRepGraph_NodeId::Kind theKind, uint32_t theCounter); + + //! Return the next UID counter for a given reference kind. + [[nodiscard]] Standard_EXPORT uint32_t NextRefUIDCounter(BRepGraph_RefId::Kind theKind) const; + + //! Override the next UID counter for a given reference kind. + Standard_EXPORT void SetNextRefUIDCounter(BRepGraph_RefId::Kind theKind, uint32_t theCounter); + + //! Allocate a node UID: write counter into the entity, bind reverse map, advance counter. + Standard_EXPORT BRepGraph_UID AllocateNodeUID(BRepGraph_NodeId theNodeId); + + //! Allocate a reference UID: write counter into the ref, bind reverse map, advance counter. + Standard_EXPORT BRepGraph_RefUID AllocateRefUID(BRepGraph_RefId theRefId); + + //! Return the current graph generation used by VersionStamp staleness checks. + [[nodiscard]] uint32_t Generation() const { return myGeneration.load(std::memory_order_relaxed); } + + //! Override the current graph generation. + void SetGeneration(const uint32_t theGeneration) + { + myGeneration.store(theGeneration, std::memory_order_relaxed); + } + + //! Increment the graph generation after a structural mutation batch. + void IncrementGeneration() { myGeneration.fetch_add(1, std::memory_order_relaxed); } + + //! Return the stable graph instance GUID. + [[nodiscard]] const Standard_GUID& GraphGUID() const { return myGraphGUID; } + + //! Override the stable graph instance GUID. + void SetGraphGUID(const Standard_GUID& theGuid) { myGraphGUID = theGuid; } + + //! Return whether invalidation is currently deferred. + [[nodiscard]] bool DeferredMode() const { return myDeferredMode.load(std::memory_order_relaxed); } + + //! Enable or disable deferred invalidation mode. + void SetDeferredMode(const bool theEnabled) + { + myDeferredMode.store(theEnabled, std::memory_order_relaxed); + } + + //! Return the current propagation wave id used to avoid revisiting parents. + [[nodiscard]] uint32_t PropagationWave() const + { + return myPropagationWave.load(std::memory_order_relaxed); + } + + //! Increment the propagation wave and return the new value. + [[nodiscard]] uint32_t AdvancePropagationWave() + { + return myPropagationWave.fetch_add(1, std::memory_order_relaxed) + 1; + } + + //! Increment the propagation wave without reading it back. + void IncrementPropagationWave() { myPropagationWave.fetch_add(1, std::memory_order_relaxed); } + + //! Return the recursion depth of the active RemoveSubgraph cascade. + [[nodiscard]] uint32_t RemoveSubgraphDepth() const { return myRemoveSubgraphDepth; } + + //! Enter one nested RemoveSubgraph scope. + void IncrementRemoveSubgraphDepth() { ++myRemoveSubgraphDepth; } + + //! Leave one nested RemoveSubgraph scope. + void DecrementRemoveSubgraphDepth() + { + Standard_ASSERT_VOID(myRemoveSubgraphDepth > 0, "RemoveSubgraphDepth underflow"); + if (myRemoveSubgraphDepth > 0) + { + --myRemoveSubgraphDepth; + } + } + //! Returns the total number of vertex entities (including removed). [[nodiscard]] uint32_t NbVertices() const { return myVertices.Nb(); } @@ -102,9 +234,6 @@ public: //! Returns the total number of wire reference entries (including removed). [[nodiscard]] uint32_t NbWireRefs() const { return myWireRefs.Nb(); } - //! Returns the total number of coedge reference entries (including removed). - [[nodiscard]] uint32_t NbCoEdgeRefs() const { return myCoEdgeRefs.Nb(); } - //! Returns the total number of vertex reference entries (including removed). [[nodiscard]] uint32_t NbVertexRefs() const { return myVertexRefs.Nb(); } @@ -117,48 +246,6 @@ public: //! Returns the total number of occurrence reference entries (including removed). [[nodiscard]] uint32_t NbOccurrenceRefs() const { return myOccurrenceRefs.Nb(); } - //! Returns the total number of surface representations. - [[nodiscard]] uint32_t NbSurfaces() const { return mySurfaces.Nb(); } - - //! Returns the total number of 3D curve representations. - [[nodiscard]] uint32_t NbCurves3D() const { return myCurves3D.Nb(); } - - //! Returns the total number of 2D curve representations. - [[nodiscard]] uint32_t NbCurves2D() const { return myCurves2D.Nb(); } - - //! Returns the total number of triangulation representations. - [[nodiscard]] uint32_t NbTriangulations() const { return myTriangulationsRep.Nb(); } - - //! Returns the total number of 3D polygon representations. - [[nodiscard]] uint32_t NbPolygons3D() const { return myPolygons3D.Nb(); } - - //! Returns the total number of 2D polygon representations. - [[nodiscard]] uint32_t NbPolygons2D() const { return myPolygons2D.Nb(); } - - //! Returns the total number of polygon-on-triangulation representations. - [[nodiscard]] uint32_t NbPolygonsOnTri() const { return myPolygonsOnTri.Nb(); } - - //! Returns the number of active surface representations (excluding removed). - [[nodiscard]] uint32_t NbActiveSurfaces() const { return mySurfaces.NbActive; } - - //! Returns the number of active 3D curve representations (excluding removed). - [[nodiscard]] uint32_t NbActiveCurves3D() const { return myCurves3D.NbActive; } - - //! Returns the number of active 2D curve representations (excluding removed). - [[nodiscard]] uint32_t NbActiveCurves2D() const { return myCurves2D.NbActive; } - - //! Returns the number of active triangulation representations (excluding removed). - [[nodiscard]] uint32_t NbActiveTriangulations() const { return myTriangulationsRep.NbActive; } - - //! Returns the number of active 3D polygon representations (excluding removed). - [[nodiscard]] uint32_t NbActivePolygons3D() const { return myPolygons3D.NbActive; } - - //! Returns the number of active 2D polygon representations (excluding removed). - [[nodiscard]] uint32_t NbActivePolygons2D() const { return myPolygons2D.NbActive; } - - //! Returns the number of active polygon-on-triangulation representations (excluding removed). - [[nodiscard]] uint32_t NbActivePolygonsOnTri() const { return myPolygonsOnTri.NbActive; } - //! Returns the number of active vertex entities (excluding removed). [[nodiscard]] uint32_t NbActiveVertices() const { return myVertices.NbActive; } @@ -201,9 +288,6 @@ public: //! Returns the number of active wire reference entries (excluding removed). [[nodiscard]] uint32_t NbActiveWireRefs() const { return myWireRefs.NbActive; } - //! Returns the number of active coedge reference entries (excluding removed). - [[nodiscard]] uint32_t NbActiveCoEdgeRefs() const { return myCoEdgeRefs.NbActive; } - //! Returns the number of active vertex reference entries (excluding removed). [[nodiscard]] uint32_t NbActiveVertexRefs() const { return myVertexRefs.NbActive; } @@ -226,137 +310,178 @@ public: //! @return true if the ref transitioned from active to removed Standard_EXPORT bool MarkRemovedRef(const BRepGraph_RefId theRefId); - //! Mark a representation entry as removed and decrement its active counter once. - //! @param[in] theRepId typed representation id - //! @return true if the representation transitioned from active to removed - Standard_EXPORT bool MarkRemovedRep(const BRepGraph_RepId theRepId); + //! Returns the number of edge 3D curve use records. + [[nodiscard]] uint32_t NbEdgeCurves3D() const { return myEdgeCurves3D.Nb(); } + + //! Returns the number of edge 3D polygon use records. + [[nodiscard]] uint32_t NbEdgePolygons3D() const { return myEdgePolygons3D.Nb(); } + + //! Returns the number of coedge 2D curve use records. + [[nodiscard]] uint32_t NbCoEdgeCurves2D() const { return myCoEdgeCurves2D.Nb(); } + + //! Returns the number of coedge 2D polygon use records. + [[nodiscard]] uint32_t NbCoEdgePolygons2D() const { return myCoEdgePolygons2D.Nb(); } + + //! Returns the number of coedge polygon-on-triangulation use records. + [[nodiscard]] uint32_t NbCoEdgePolygonsOnTri() const { return myCoEdgePolygonsOnTri.Nb(); } + + //! Returns the number of face surface use records. + [[nodiscard]] uint32_t NbFaceSurfaces() const { return myFaceSurfaces.Nb(); } + + //! Returns the number of face triangulation use records. + [[nodiscard]] uint32_t NbFaceTriangulations() const { return myFaceTriangulations.Nb(); } + + //! Returns the number of active (parent-valid) edge 3D curve use records. + [[nodiscard]] Standard_EXPORT uint32_t NbActiveEdgeCurves3D() const; + + //! Returns the number of active (parent-valid) coedge 2D curve use records. + [[nodiscard]] Standard_EXPORT uint32_t NbActiveCoEdgeCurves2D() const; + + //! Returns the number of active (parent-valid) face surface use records. + [[nodiscard]] Standard_EXPORT uint32_t NbActiveFaceSurfaces() const; + + //! Returns the number of active (parent-valid) face triangulation use records. + [[nodiscard]] Standard_EXPORT uint32_t NbActiveFaceTriangulations() const; + + //! Returns the number of active (parent-valid) edge 3D polygon use records. + [[nodiscard]] Standard_EXPORT uint32_t NbActiveEdgePolygons3D() const; + + //! Returns the number of active (parent-valid) coedge 2D polygon use records. + [[nodiscard]] Standard_EXPORT uint32_t NbActiveCoEdgePolygons2D() const; + + //! Returns the number of active (parent-valid) coedge polygon-on-triangulation use records. + [[nodiscard]] Standard_EXPORT uint32_t NbActiveCoEdgePolygonsOnTri() const; - //! Returns the surface representation at the given typed id. - //! @param[in] theRep typed surface representation id - [[nodiscard]] const BRepGraphInc::SurfaceRep& SurfaceRep( - const BRepGraph_SurfaceRepId theRep) const + //! Returns the edge 3D curve use at the given id. + [[nodiscard]] const BRepGraphInc::EdgeCurve3DRep& EdgeCurve3DRep( + const BRepGraph_EdgeCurve3DRepId theId) const { - return mySurfaces.Get(theRep); + return myEdgeCurves3D.Get(theId); } - //! Returns the 3D curve representation at the given typed id. - //! @param[in] theRep typed curve-3D representation id - [[nodiscard]] const BRepGraphInc::Curve3DRep& Curve3DRep( - const BRepGraph_Curve3DRepId theRep) const + //! Returns a mutable reference to the edge 3D curve use at the given id. + BRepGraphInc::EdgeCurve3DRep& ChangeEdgeCurve3DRep(const BRepGraph_EdgeCurve3DRepId theId) { - return myCurves3D.Get(theRep); + return myEdgeCurves3D.Change(theId); } - //! Returns the 2D curve representation at the given typed id. - //! @param[in] theRep typed curve-2D representation id - [[nodiscard]] const BRepGraphInc::Curve2DRep& Curve2DRep( - const BRepGraph_Curve2DRepId theRep) const + //! Returns the edge 3D polygon use at the given id. + [[nodiscard]] const BRepGraphInc::EdgePolygon3DRep& EdgePolygon3DRep( + const BRepGraph_EdgePolygon3DRepId theId) const { - return myCurves2D.Get(theRep); + return myEdgePolygons3D.Get(theId); } - //! Returns the triangulation representation at the given typed id. - //! @param[in] theRep typed triangulation representation id - [[nodiscard]] const BRepGraphInc::TriangulationRep& TriangulationRep( - const BRepGraph_TriangulationRepId theRep) const + //! Returns a mutable reference to the edge 3D polygon use at the given id. + BRepGraphInc::EdgePolygon3DRep& ChangeEdgePolygon3DRep(const BRepGraph_EdgePolygon3DRepId theId) { - return myTriangulationsRep.Get(theRep); + return myEdgePolygons3D.Change(theId); } - //! Returns the 3D polygon representation at the given typed id. - //! @param[in] theRep typed polygon-3D representation id - [[nodiscard]] const BRepGraphInc::Polygon3DRep& Polygon3DRep( - const BRepGraph_Polygon3DRepId theRep) const + //! Returns the coedge 2D curve use at the given id. + [[nodiscard]] const BRepGraphInc::CoEdgeCurve2DRep& CoEdgeCurve2DRep( + const BRepGraph_CoEdgeCurve2DRepId theId) const { - return myPolygons3D.Get(theRep); + return myCoEdgeCurves2D.Get(theId); } - //! Returns the 2D polygon representation at the given typed id. - //! @param[in] theRep typed polygon-2D representation id - [[nodiscard]] const BRepGraphInc::Polygon2DRep& Polygon2DRep( - const BRepGraph_Polygon2DRepId theRep) const + //! Returns a mutable reference to the coedge 2D curve use at the given id. + BRepGraphInc::CoEdgeCurve2DRep& ChangeCoEdgeCurve2DRep(const BRepGraph_CoEdgeCurve2DRepId theId) { - return myPolygons2D.Get(theRep); + return myCoEdgeCurves2D.Change(theId); } - //! Returns the polygon-on-triangulation representation at the given typed id. - //! @param[in] theRep typed polygon-on-triangulation representation id - [[nodiscard]] const BRepGraphInc::PolygonOnTriRep& PolygonOnTriRep( - const BRepGraph_PolygonOnTriRepId theRep) const + //! Returns the coedge 2D polygon use at the given id. + [[nodiscard]] const BRepGraphInc::CoEdgePolygon2DRep& CoEdgePolygon2DRep( + const BRepGraph_CoEdgePolygon2DRepId theId) const { - return myPolygonsOnTri.Get(theRep); + return myCoEdgePolygons2D.Get(theId); } - //! Returns a mutable reference to the surface representation at the given typed id. - //! @param[in] theRep typed surface representation id - BRepGraphInc::SurfaceRep& ChangeSurfaceRep(const BRepGraph_SurfaceRepId theRep) + //! Returns a mutable reference to the coedge 2D polygon use at the given id. + BRepGraphInc::CoEdgePolygon2DRep& ChangeCoEdgePolygon2DRep( + const BRepGraph_CoEdgePolygon2DRepId theId) { - return mySurfaces.Change(theRep); + return myCoEdgePolygons2D.Change(theId); } - //! Returns a mutable reference to the 3D curve representation at the given typed id. - //! @param[in] theRep typed curve-3D representation id - BRepGraphInc::Curve3DRep& ChangeCurve3DRep(const BRepGraph_Curve3DRepId theRep) + //! Returns the coedge polygon-on-triangulation use at the given id. + [[nodiscard]] const BRepGraphInc::CoEdgePolygonOnTriRep& CoEdgePolygonOnTriRep( + const BRepGraph_CoEdgePolygonOnTriRepId theId) const { - return myCurves3D.Change(theRep); + return myCoEdgePolygonsOnTri.Get(theId); } - //! Returns a mutable reference to the 2D curve representation at the given typed id. - //! @param[in] theRep typed curve-2D representation id - BRepGraphInc::Curve2DRep& ChangeCurve2DRep(const BRepGraph_Curve2DRepId theRep) + //! Returns a mutable reference to the coedge polygon-on-triangulation use at the given id. + BRepGraphInc::CoEdgePolygonOnTriRep& ChangeCoEdgePolygonOnTriRep( + const BRepGraph_CoEdgePolygonOnTriRepId theId) { - return myCurves2D.Change(theRep); + return myCoEdgePolygonsOnTri.Change(theId); } - //! Returns a mutable reference to the triangulation representation at the given typed id. - //! @param[in] theRep typed triangulation representation id - BRepGraphInc::TriangulationRep& ChangeTriangulationRep(const BRepGraph_TriangulationRepId theRep) + //! Returns the face surface use at the given id. + [[nodiscard]] const BRepGraphInc::FaceSurfaceRep& FaceSurfaceRep( + const BRepGraph_FaceSurfaceRepId theId) const { - return myTriangulationsRep.Change(theRep); + return myFaceSurfaces.Get(theId); } - //! Returns a mutable reference to the 3D polygon representation at the given typed id. - //! @param[in] theRep typed polygon-3D representation id - BRepGraphInc::Polygon3DRep& ChangePolygon3DRep(const BRepGraph_Polygon3DRepId theRep) + //! Returns a mutable reference to the face surface use at the given id. + BRepGraphInc::FaceSurfaceRep& ChangeFaceSurfaceRep(const BRepGraph_FaceSurfaceRepId theId) { - return myPolygons3D.Change(theRep); + return myFaceSurfaces.Change(theId); } - //! Returns a mutable reference to the 2D polygon representation at the given typed id. - //! @param[in] theRep typed polygon-2D representation id - BRepGraphInc::Polygon2DRep& ChangePolygon2DRep(const BRepGraph_Polygon2DRepId theRep) + //! Returns the face triangulation use at the given id. + [[nodiscard]] const BRepGraphInc::FaceTriangulationRep& FaceTriangulationRep( + const BRepGraph_FaceTriangulationRepId theId) const { - return myPolygons2D.Change(theRep); + return myFaceTriangulations.Get(theId); } - //! Returns a mutable reference to the polygon-on-triangulation representation at the given typed - //! id. - //! @param[in] theRep typed polygon-on-triangulation representation id - BRepGraphInc::PolygonOnTriRep& ChangePolygonOnTriRep(const BRepGraph_PolygonOnTriRepId theRep) + //! Returns a mutable reference to the face triangulation use at the given id. + BRepGraphInc::FaceTriangulationRep& ChangeFaceTriangulationRep( + const BRepGraph_FaceTriangulationRepId theId) { - return myPolygonsOnTri.Change(theRep); + return myFaceTriangulations.Change(theId); } - //! Appends a new surface representation slot and returns its typed id. - BRepGraph_SurfaceRepId AppendSurfaceRep() { return mySurfaces.Append(); } + //! Appends a new edge 3D curve use record and returns its id. + BRepGraph_EdgeCurve3DRepId AppendEdgeCurve3DRep() { return myEdgeCurves3D.Append(); } - //! Appends a new 3D curve representation slot and returns its typed id. - BRepGraph_Curve3DRepId AppendCurve3DRep() { return myCurves3D.Append(); } + //! Appends a new edge 3D polygon use record and returns its id. + BRepGraph_EdgePolygon3DRepId AppendEdgePolygon3DRep() { return myEdgePolygons3D.Append(); } - //! Appends a new 2D curve representation slot and returns its typed id. - BRepGraph_Curve2DRepId AppendCurve2DRep() { return myCurves2D.Append(); } + //! Appends a new coedge 2D curve use record and returns its id. + BRepGraph_CoEdgeCurve2DRepId AppendCoEdgeCurve2DRep() { return myCoEdgeCurves2D.Append(); } - //! Appends a new triangulation representation slot and returns its typed id. - BRepGraph_TriangulationRepId AppendTriangulationRep() { return myTriangulationsRep.Append(); } + //! Appends a new coedge 2D polygon use record and returns its id. + BRepGraph_CoEdgePolygon2DRepId AppendCoEdgePolygon2DRep() { return myCoEdgePolygons2D.Append(); } - //! Appends a new 3D polygon representation slot and returns its typed id. - BRepGraph_Polygon3DRepId AppendPolygon3DRep() { return myPolygons3D.Append(); } + //! Appends a new coedge polygon-on-triangulation use record and returns its id. + BRepGraph_CoEdgePolygonOnTriRepId AppendCoEdgePolygonOnTriRep() + { + return myCoEdgePolygonsOnTri.Append(); + } + + //! Appends a new face surface use record and returns its id. + BRepGraph_FaceSurfaceRepId AppendFaceSurfaceRep() { return myFaceSurfaces.Append(); } + + //! Appends a new face triangulation use record and returns its id. + BRepGraph_FaceTriangulationRepId AppendFaceTriangulationRep() + { + return myFaceTriangulations.Append(); + } - //! Appends a new 2D polygon representation slot and returns its typed id. - BRepGraph_Polygon2DRepId AppendPolygon2DRep() { return myPolygons2D.Append(); } + //! Mark a representation-use record as removed and decrement its active counter once. + //! @param[in] theRepId typed use id + //! @return true if the use transitioned from active to removed + Standard_EXPORT bool MarkRemoved(const BRepGraph_RepId theRepId); - //! Appends a new polygon-on-triangulation representation slot and returns its typed id. - BRepGraph_PolygonOnTriRepId AppendPolygonOnTriRep() { return myPolygonsOnTri.Append(); } + //! Set or clear the soft-removal flag for a representation-use record. + //! @param[in] theRepId typed use id + //! @param[in] theVal true to mark removed, false to mark active + Standard_EXPORT void SetRemoved(const BRepGraph_RepId theRepId, const bool theVal); //! Returns the vertex entity at the given typed id. //! @param[in] theVertex typed vertex id @@ -456,12 +581,6 @@ public: return myWireRefs.Get(theRefId); } - //! Returns the coedge reference entry at the given typed id. - [[nodiscard]] const BRepGraphInc::CoEdgeRef& CoEdgeRef(const BRepGraph_CoEdgeRefId theRefId) const - { - return myCoEdgeRefs.Get(theRefId); - } - //! Returns the vertex reference entry at the given typed id. [[nodiscard]] const BRepGraphInc::VertexRef& VertexRef(const BRepGraph_VertexRefId theRefId) const { @@ -582,12 +701,6 @@ public: return myWireRefs.Change(theRefId); } - //! Returns a mutable reference to the coedge reference entry at the given typed id. - BRepGraphInc::CoEdgeRef& ChangeCoEdgeRef(const BRepGraph_CoEdgeRefId theRefId) - { - return myCoEdgeRefs.Change(theRefId); - } - //! Returns a mutable reference to the vertex reference entry at the given typed id. BRepGraphInc::VertexRef& ChangeVertexRef(const BRepGraph_VertexRefId theRefId) { @@ -612,38 +725,187 @@ public: return myOccurrenceRefs.Change(theRefId); } + //! Return the face relations for a given face identifier. + //! @param[in] theId face identifier + //! @return const reference to the face relation representation + [[nodiscard]] const BRepGraphInc::FaceRelations& FaceRelations(const BRepGraph_FaceId theId) const + { + return myFaceRelations.Value(static_cast(theId.Index)); + } + + //! Return the wire relations for a given wire identifier. + //! @param[in] theId wire identifier + //! @return const reference to the wire relation representation + [[nodiscard]] const BRepGraphInc::WireRelations& WireRelations(const BRepGraph_WireId theId) const + { + return myWireRelations.Value(static_cast(theId.Index)); + } + + //! Return the edge relations for a given edge identifier. + //! @param[in] theId edge identifier + //! @return const reference to the edge relation representation + [[nodiscard]] const BRepGraphInc::EdgeRelations& EdgeRelations(const BRepGraph_EdgeId theId) const + { + return myEdgeRelations.Value(static_cast(theId.Index)); + } + + //! Return the shell relations for a given shell identifier. + //! @param[in] theId shell identifier + //! @return const reference to the shell relation representation + [[nodiscard]] const BRepGraphInc::ShellRelations& ShellRelations( + const BRepGraph_ShellId theId) const + { + return myShellRelations.Value(static_cast(theId.Index)); + } + + //! Return the solid relations for a given solid identifier. + //! @param[in] theId solid identifier + //! @return const reference to the solid relation representation + [[nodiscard]] const BRepGraphInc::SolidRelations& SolidRelations( + const BRepGraph_SolidId theId) const + { + return mySolidRelations.Value(static_cast(theId.Index)); + } + + //! Return the compound relations for a given compound identifier. + //! @param[in] theId compound identifier + //! @return const reference to the compound relation representation + [[nodiscard]] const BRepGraphInc::CompoundRelations& CompoundRelations( + const BRepGraph_CompoundId theId) const + { + return myCompoundRelations.Value(static_cast(theId.Index)); + } + + //! Return the compsolid relations for a given compsolid identifier. + //! @param[in] theId compsolid identifier + //! @return const reference to the compsolid relation representation + [[nodiscard]] const BRepGraphInc::CompSolidRelations& CompSolidRelations( + const BRepGraph_CompSolidId theId) const + { + return myCompSolidRelations.Value(static_cast(theId.Index)); + } + + //! Return the vertex relations for a given vertex identifier. + //! @param[in] theId vertex identifier + //! @return const reference to the vertex relation representation + [[nodiscard]] const BRepGraphInc::VertexRelations& VertexRelations( + const BRepGraph_VertexId theId) const + { + return myVertexRelations.Value(static_cast(theId.Index)); + } + + //! Return the product relations for a given product identifier. + //! @param[in] theId product identifier + //! @return const reference to the product relation representation + [[nodiscard]] const BRepGraphInc::ProductRelations& ProductRelations( + const BRepGraph_ProductId theId) const + { + return myProductRelations.Value(static_cast(theId.Index)); + } + + //! Return the occurrence relations for a given occurrence identifier. + //! @param[in] theId occurrence identifier + //! @return const reference to the occurrence relation representation + [[nodiscard]] const BRepGraphInc::OccurrenceRelations& OccurrenceRelations( + const BRepGraph_OccurrenceId theId) const + { + return myOccurrenceRelations.Value(static_cast(theId.Index)); + } + + //! Return the compound child reference identifiers that point to a given node. + //! @param[in] theNode node identifier + //! @return const reference to the list of child reference identifiers + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& + CompoundRefsOfNode(const BRepGraph_NodeId theNode) const; + + //! Return the occurrence reference identifiers that point to a given node. + //! @param[in] theNode node identifier + //! @return const reference to the list of occurrence reference identifiers + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& + OccurrenceRefsOfNode(const BRepGraph_NodeId theNode) const; + //! Appends a new vertex entity and returns its typed id. - BRepGraph_VertexId AppendVertex() { return myVertices.Append(myAllocator); } + BRepGraph_VertexId AppendVertex() + { + const BRepGraph_VertexId anId = myVertices.Append(); + myVertexRelations.Appended(); + return anId; + } //! Appends a new edge entity and returns its typed id. - BRepGraph_EdgeId AppendEdge() { return myEdges.Append(myAllocator); } + BRepGraph_EdgeId AppendEdge() + { + const BRepGraph_EdgeId anId = myEdges.Append(); + myEdgeRelations.Appended(); + return anId; + } //! Appends a new coedge entity and returns its typed id. - BRepGraph_CoEdgeId AppendCoEdge() { return myCoEdges.Append(myAllocator); } + BRepGraph_CoEdgeId AppendCoEdge() { return myCoEdges.Append(); } //! Appends a new wire entity and returns its typed id. - BRepGraph_WireId AppendWire() { return myWires.Append(myAllocator); } + BRepGraph_WireId AppendWire() + { + const BRepGraph_WireId anId = myWires.Append(); + myWireRelations.Appended(); + return anId; + } //! Appends a new face entity and returns its typed id. - BRepGraph_FaceId AppendFace() { return myFaces.Append(myAllocator); } + BRepGraph_FaceId AppendFace() + { + const BRepGraph_FaceId anId = myFaces.Append(); + myFaceRelations.Appended(); + return anId; + } //! Appends a new shell entity and returns its typed id. - BRepGraph_ShellId AppendShell() { return myShells.Append(myAllocator); } + BRepGraph_ShellId AppendShell() + { + const BRepGraph_ShellId anId = myShells.Append(); + myShellRelations.Appended(); + return anId; + } //! Appends a new solid entity and returns its typed id. - BRepGraph_SolidId AppendSolid() { return mySolids.Append(myAllocator); } + BRepGraph_SolidId AppendSolid() + { + const BRepGraph_SolidId anId = mySolids.Append(); + mySolidRelations.Appended(); + return anId; + } //! Appends a new compound entity and returns its typed id. - BRepGraph_CompoundId AppendCompound() { return myCompounds.Append(myAllocator); } + BRepGraph_CompoundId AppendCompound() + { + const BRepGraph_CompoundId anId = myCompounds.Append(); + myCompoundRelations.Appended(); + return anId; + } //! Appends a new compsolid entity and returns its typed id. - BRepGraph_CompSolidId AppendCompSolid() { return myCompSolids.Append(myAllocator); } + BRepGraph_CompSolidId AppendCompSolid() + { + const BRepGraph_CompSolidId anId = myCompSolids.Append(); + myCompSolidRelations.Appended(); + return anId; + } //! Appends a new product entity and returns its typed id. - BRepGraph_ProductId AppendProduct() { return myProducts.Append(myAllocator); } + BRepGraph_ProductId AppendProduct() + { + const BRepGraph_ProductId anId = myProducts.Append(); + myProductRelations.Appended(); + return anId; + } //! Appends a new occurrence entity and returns its typed id. - BRepGraph_OccurrenceId AppendOccurrence() { return myOccurrences.Append(myAllocator); } + BRepGraph_OccurrenceId AppendOccurrence() + { + const BRepGraph_OccurrenceId anId = myOccurrences.Append(); + myOccurrenceRelations.Appended(); + return anId; + } //! Appends a new shell reference entry and returns its typed id. BRepGraph_ShellRefId AppendShellRef() { return myShellRefs.Append(); } @@ -654,9 +916,6 @@ public: //! Appends a new wire reference entry and returns its typed id. BRepGraph_WireRefId AppendWireRef() { return myWireRefs.Append(); } - //! Appends a new coedge reference entry and returns its typed id. - BRepGraph_CoEdgeRefId AppendCoEdgeRef() { return myCoEdgeRefs.Append(); } - //! Appends a new vertex reference entry and returns its typed id. BRepGraph_VertexRefId AppendVertexRef() { return myVertexRefs.Append(); } @@ -669,16 +928,279 @@ public: //! Appends a new occurrence reference entry and returns its typed id. BRepGraph_OccurrenceRefId AppendOccurrenceRef() { return myOccurrenceRefs.Append(); } - //! Return the per-kind UID vector for a given Kind. - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& UIDs( - const BRepGraph_NodeId::Kind theKind) const; - - //! Return the per-kind UID vector for a given Kind (mutable). - Standard_EXPORT NCollection_DynamicArray& ChangeUIDs( - const BRepGraph_NodeId::Kind theKind); - - //! Clear all UID vectors (reset lengths to 0). - Standard_EXPORT void ResetAllUIDs(); + //! Create a coedge use record binding an edge to a wire within a face context. + //! @param[in] theParentWireId owning wire identifier + //! @param[in] theChildEdgeId referenced edge identifier + //! @param[in] theFaceId face context identifier + //! @param[in] theOrientation orientation of the coedge + //! @return the newly created coedge identifier + Standard_EXPORT BRepGraph_CoEdgeId + CreateCoEdgeUse(const BRepGraph_WireId theParentWireId, + const BRepGraph_EdgeId theChildEdgeId, + const BRepGraph_FaceId theFaceId, + const BRepGraphInc::ParityOrientation theOrientation); + + //! Attach an edge to a vertex by creating a vertex reference. + //! @param[in] theEdgeId edge identifier + //! @param[in] theVertexId vertex identifier + Standard_EXPORT void AttachEdgeToVertex(const BRepGraph_EdgeId theEdgeId, + const BRepGraph_VertexId theVertexId); + + //! Attach a wire to a face by creating a wire reference. + //! @param[in] theParentFaceId parent face identifier + //! @param[in] theChildWireId child wire identifier + //! @param[in] theOrientation orientation within parent + //! @return the newly created wire reference identifier + Standard_EXPORT BRepGraph_WireRefId + AttachWireToFace(const BRepGraph_FaceId theParentFaceId, + const BRepGraph_WireId theChildWireId, + const BRepGraphInc::ParityOrientation theOrientation = TopAbs_FORWARD); + + //! Attach a face to a shell by creating a face reference. + //! @param[in] theParentShellId parent shell identifier + //! @param[in] theChildFaceId child face identifier + //! @param[in] theOrientation orientation within parent + //! @return the newly created face reference identifier + Standard_EXPORT BRepGraph_FaceRefId + AttachFaceToShell(const BRepGraph_ShellId theParentShellId, + const BRepGraph_FaceId theChildFaceId, + const BRepGraphInc::ParityOrientation theOrientation = TopAbs_FORWARD); + + //! Attach a shell to a solid by creating a shell reference. + //! @param[in] theParentSolidId parent solid identifier + //! @param[in] theChildShellId child shell identifier + //! @param[in] theOrientation orientation within parent + //! @return the newly created shell reference identifier + Standard_EXPORT BRepGraph_ShellRefId + AttachShellToSolid(const BRepGraph_SolidId theParentSolidId, + const BRepGraph_ShellId theChildShellId, + const BRepGraphInc::ParityOrientation theOrientation = TopAbs_FORWARD); + + //! Attach a solid to a compsolid by creating a solid reference. + //! @param[in] theParentCompSolidId parent compsolid identifier + //! @param[in] theChildSolidId child solid identifier + //! @param[in] theOrientation orientation within parent + //! @return the newly created solid reference identifier + Standard_EXPORT BRepGraph_SolidRefId + AttachSolidToCompSolid(const BRepGraph_CompSolidId theParentCompSolidId, + const BRepGraph_SolidId theChildSolidId, + const BRepGraphInc::ParityOrientation theOrientation = TopAbs_FORWARD); + + //! Attach a child node to a compound by creating a child reference. + //! @param[in] theParentCompoundId parent compound identifier + //! @param[in] theChildNodeId child node identifier + //! @param[in] theLocation optional location transformation + //! @param[in] theOrientation orientation within parent + //! @return the newly created child reference identifier + Standard_EXPORT BRepGraph_ChildRefId + AttachChildToCompound(const BRepGraph_CompoundId theParentCompoundId, + const BRepGraph_NodeId theChildNodeId, + const TopLoc_Location& theLocation = TopLoc_Location(), + const BRepGraphInc::ParityOrientation theOrientation = TopAbs_FORWARD); + + //! Attach an occurrence to a product by creating an occurrence reference. + //! @param[in] theParentProductId parent product identifier + //! @param[in] theChildOccurrenceId child occurrence identifier + //! @param[in] theLocation optional location transformation + //! @return the newly created occurrence reference identifier + Standard_EXPORT BRepGraph_OccurrenceRefId + AttachOccurrenceToProduct(const BRepGraph_ProductId theParentProductId, + const BRepGraph_OccurrenceId theChildOccurrenceId, + const TopLoc_Location& theLocation = TopLoc_Location()); + + //! Detach a coedge use from its parent wire. + //! @param[in] theParentWireId owning wire identifier + //! @param[in] theCoEdgeId coedge identifier to detach + //! @return true if the coedge was found and removed + Standard_EXPORT bool DetachCoEdgeUse(const BRepGraph_WireId theParentWireId, + const BRepGraph_CoEdgeId theCoEdgeId); + + //! Replace a single coedge with a pair of new coedges in a wire. + //! @param[in] theParentWireId owning wire identifier + //! @param[in] theOldCoEdgeId coedge to replace + //! @param[in] theNewFirstCoEdgeId first replacement coedge + //! @param[in] theNewSecondCoEdgeId second replacement coedge + //! @return true if the replacement succeeded + Standard_EXPORT bool ReplaceCoEdgeUseWithPair(const BRepGraph_WireId theParentWireId, + const BRepGraph_CoEdgeId theOldCoEdgeId, + const BRepGraph_CoEdgeId theNewFirstCoEdgeId, + const BRepGraph_CoEdgeId theNewSecondCoEdgeId); + + //! Detach a wire reference from its parent face. + //! @param[in] theParentFaceId parent face identifier + //! @param[in] theRefId wire reference identifier to detach + //! @return true if the reference was found and removed + Standard_EXPORT bool DetachWireFromFace(const BRepGraph_FaceId theParentFaceId, + const BRepGraph_WireRefId theRefId); + + //! Detach a face reference from its parent shell. + //! @param[in] theParentShellId parent shell identifier + //! @param[in] theRefId face reference identifier to detach + //! @return true if the reference was found and removed + Standard_EXPORT bool DetachFaceFromShell(const BRepGraph_ShellId theParentShellId, + const BRepGraph_FaceRefId theRefId); + + //! Detach a shell reference from its parent solid. + //! @param[in] theParentSolidId parent solid identifier + //! @param[in] theRefId shell reference identifier to detach + //! @return true if the reference was found and removed + Standard_EXPORT bool DetachShellFromSolid(const BRepGraph_SolidId theParentSolidId, + const BRepGraph_ShellRefId theRefId); + + //! Detach a solid reference from its parent compsolid. + //! @param[in] theParentCompSolidId parent compsolid identifier + //! @param[in] theRefId solid reference identifier to detach + //! @return true if the reference was found and removed + Standard_EXPORT bool DetachSolidFromCompSolid(const BRepGraph_CompSolidId theParentCompSolidId, + const BRepGraph_SolidRefId theRefId); + + //! Detach a child reference from its parent compound. + //! @param[in] theParentCompoundId parent compound identifier + //! @param[in] theRefId child reference identifier to detach + //! @return true if the reference was found and removed + Standard_EXPORT bool DetachChildFromCompound(const BRepGraph_CompoundId theParentCompoundId, + const BRepGraph_ChildRefId theRefId); + + //! Detach an occurrence reference from its parent product. + //! @param[in] theParentProductId parent product identifier + //! @param[in] theRefId occurrence reference identifier to detach + //! @return true if the reference was found and removed + Standard_EXPORT bool DetachOccurrenceFromProduct(const BRepGraph_ProductId theParentProductId, + const BRepGraph_OccurrenceRefId theRefId); + + //! Rebind the child node of an occurrence to a new node. + //! @param[in] theOccurrence occurrence identifier + //! @param[in] theOldChild old child node identifier + //! @param[in] theNewChild new child node identifier + Standard_EXPORT void RebindOccurrenceChild(const BRepGraph_OccurrenceId theOccurrence, + const BRepGraph_NodeId theOldChild, + const BRepGraph_NodeId theNewChild); + + //! Rebind vertex edge references from one vertex to another, excluding a specific ref. + //! @param[in] theOldVertex old vertex identifier + //! @param[in] theNewVertex new vertex identifier + //! @param[in] theEdge edge identifier + //! @param[in] theExcludingRef reference identifier to exclude from rebinding + Standard_EXPORT void RebindVertexEdge(const BRepGraph_VertexId theOldVertex, + const BRepGraph_VertexId theNewVertex, + const BRepGraph_EdgeId theEdge, + const BRepGraph_VertexRefId theExcludingRef); + + //! Rebind a vertex reference to point to a new vertex. + //! @param[in] theRefId vertex reference identifier + //! @param[in] theOldVertex old vertex identifier + //! @param[in] theNewVertex new vertex identifier + Standard_EXPORT void RebindVertexRef(const BRepGraph_VertexRefId theRefId, + const BRepGraph_VertexId theOldVertex, + const BRepGraph_VertexId theNewVertex); + + //! Rebind a coedge to reference a different edge. + //! @param[in] theCoEdge coedge identifier + //! @param[in] theOldEdge old edge identifier + //! @param[in] theNewEdge new edge identifier + Standard_EXPORT void RebindCoEdgeEdge(const BRepGraph_CoEdgeId theCoEdge, + const BRepGraph_EdgeId theOldEdge, + const BRepGraph_EdgeId theNewEdge); + + //! Rebind a wire reference to point to a new wire. + //! @param[in] theRefId wire reference identifier + //! @param[in] theOldWire old wire identifier + //! @param[in] theNewWire new wire identifier + Standard_EXPORT void RebindWireRef(const BRepGraph_WireRefId theRefId, + const BRepGraph_WireId theOldWire, + const BRepGraph_WireId theNewWire); + + //! Rebind a face reference to point to a new face. + //! @param[in] theRefId face reference identifier + //! @param[in] theOldFace old face identifier + //! @param[in] theNewFace new face identifier + Standard_EXPORT void RebindFaceRef(const BRepGraph_FaceRefId theRefId, + const BRepGraph_FaceId theOldFace, + const BRepGraph_FaceId theNewFace); + + //! Rebind a shell reference to point to a new shell. + //! @param[in] theRefId shell reference identifier + //! @param[in] theOldShell old shell identifier + //! @param[in] theNewShell new shell identifier + Standard_EXPORT void RebindShellRef(const BRepGraph_ShellRefId theRefId, + const BRepGraph_ShellId theOldShell, + const BRepGraph_ShellId theNewShell); + + //! Rebind a solid reference to point to a new solid. + //! @param[in] theRefId solid reference identifier + //! @param[in] theOldSolid old solid identifier + //! @param[in] theNewSolid new solid identifier + Standard_EXPORT void RebindSolidRef(const BRepGraph_SolidRefId theRefId, + const BRepGraph_SolidId theOldSolid, + const BRepGraph_SolidId theNewSolid); + + //! Rebind a child reference to point to a new child node. + //! @param[in] theRefId child reference identifier + //! @param[in] theOldChild old child node identifier + //! @param[in] theNewChild new child node identifier + Standard_EXPORT void RebindChildRef(const BRepGraph_ChildRefId theRefId, + const BRepGraph_NodeId theOldChild, + const BRepGraph_NodeId theNewChild); + + //! Rebind an occurrence reference to point to a new occurrence. + //! @param[in] theRefId occurrence reference identifier + //! @param[in] theOldOccurrence old occurrence identifier + //! @param[in] theNewOccurrence new occurrence identifier + Standard_EXPORT void RebindOccurrenceRef(const BRepGraph_OccurrenceRefId theRefId, + const BRepGraph_OccurrenceId theOldOccurrence, + const BRepGraph_OccurrenceId theNewOccurrence); + + //! Reverse the order of coedges in a wire. + //! @param[in] theWireId wire identifier + Standard_EXPORT void ReverseWireCoEdges(const BRepGraph_WireId theWireId); + + //! Replace the coedge list of a wire with a new set. + //! @param[in] theWireId wire identifier + //! @param[in] theCoEdgeIds new coedge identifiers + Standard_EXPORT void SetWireCoEdges(const BRepGraph_WireId theWireId, + const NCollection_Array1& theCoEdgeIds); + + //! Replace the wire reference list of a face with a new set. + //! @param[in] theFaceId face identifier + //! @param[in] theWireRefIds new wire reference identifiers + Standard_EXPORT void SetFaceWireRefs( + const BRepGraph_FaceId theFaceId, + const NCollection_Array1& theWireRefIds); + + //! Replace the face reference list of a shell with a new set. + //! @param[in] theShellId shell identifier + //! @param[in] theFaceRefIds new face reference identifiers + Standard_EXPORT void SetShellFaceRefs( + const BRepGraph_ShellId theShellId, + const NCollection_Array1& theFaceRefIds); + + //! Replace the shell reference list of a solid with a new set. + //! @param[in] theSolidId solid identifier + //! @param[in] theShellRefIds new shell reference identifiers + Standard_EXPORT void SetSolidShellRefs( + const BRepGraph_SolidId theSolidId, + const NCollection_Array1& theShellRefIds); + + //! Replace the solid reference list of a compsolid with a new set. + //! @param[in] theCompSolidId compsolid identifier + //! @param[in] theSolidRefIds new solid reference identifiers + Standard_EXPORT void SetCompSolidSolidRefs( + const BRepGraph_CompSolidId theCompSolidId, + const NCollection_Array1& theSolidRefIds); + + //! Replace the child reference list of a compound with a new set. + //! @param[in] theCompoundId compound identifier + //! @param[in] theChildRefIds new child reference identifiers + Standard_EXPORT void SetCompoundChildRefs( + const BRepGraph_CompoundId theCompoundId, + const NCollection_Array1& theChildRefIds); + + //! Replace the occurrence reference list of a product with a new set. + //! @param[in] theProductId product identifier + //! @param[in] theOccurrenceRefIds new occurrence reference identifiers + Standard_EXPORT void SetProductOccurrenceRefs( + const BRepGraph_ProductId theProductId, + const NCollection_Array1& theOccurrenceRefIds); //! Return the BaseRef portion of any ref entry by generic RefId. //! @param[in] theRefId generic reference identifier @@ -688,75 +1210,57 @@ public: //! Return the mutable BaseRef portion of any ref entry by generic RefId. //! @param[in] theRefId generic reference identifier - //! @return mutable reference to the BaseRef base of the ref entry - Standard_EXPORT BRepGraphInc::BaseRef& ChangeBaseRef(const BRepGraph_RefId theRefId); + //! @return mutable pointer to the BaseRef base of the ref entry, or nullptr if not found + [[nodiscard]] Standard_EXPORT BRepGraphInc::BaseRef* ChangeBaseRef( + const BRepGraph_RefId theRefId); - //! Return the per-kind transitional reference UID vector. - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& RefUIDs( - const BRepGraph_RefId::Kind theKind) const; + //! Resolve an active node UID through storage reverse maps. + [[nodiscard]] Standard_EXPORT BRepGraph_NodeId FindNodeIdByUID(const BRepGraph_UID& theUID) const; - //! Return the per-kind transitional reference UID vector (mutable). - Standard_EXPORT NCollection_DynamicArray& ChangeRefUIDs( - const BRepGraph_RefId::Kind theKind); + //! Resolve an active reference UID through storage reverse maps. + [[nodiscard]] Standard_EXPORT BRepGraph_RefId + FindRefIdByUID(const BRepGraph_RefUID& theUID) const; - //! Clear all transitional reference UID vectors. - Standard_EXPORT void ResetAllRefUIDs(); + //! Returns the node id bound to the given shape definition key, or invalid if not bound. + [[nodiscard]] Standard_EXPORT BRepGraph_NodeId + FindDefinitionByShape(const TopoDS_Shape& theShape) const; - //! Returns the reverse index for parent-child relationship queries. - [[nodiscard]] const BRepGraphInc_ReverseIndex& ReverseIndex() const { return myReverseIdx; } + //! Returns true if the given shape definition key is bound to a node. + [[nodiscard]] Standard_EXPORT bool HasShapeBinding(const TopoDS_Shape& theShape) const; - //! Returns a mutable reference to the reverse index. - BRepGraphInc_ReverseIndex& ChangeReverseIndex() { return myReverseIdx; } + //! Set or update the shape-to-node binding. Uses replacement semantics: + //! binds if absent, updates if already bound. + Standard_EXPORT void SetDefinitionShapeBinding(const TopoDS_Shape& theShape, + const BRepGraph_NodeId theNodeId); - //! Returns the node id bound to the given TShape, or nullptr if not bound. - [[nodiscard]] const BRepGraph_NodeId* FindNodeByTShape(const TopoDS_TShape* theTShape) const - { - return myTShapeToNodeId.Seek(theTShape); - } + //! Remove the shape-to-node binding only if it points to the expected node. + //! Returns true if the binding was removed. + Standard_EXPORT bool RemoveDefinitionShapeBinding(const TopoDS_Shape& theShape, + const BRepGraph_NodeId theExpectedNodeId); - //! Returns true if the given TShape is bound to a node. - [[nodiscard]] bool HasTShapeBinding(const TopoDS_TShape* theTShape) const - { - return myTShapeToNodeId.IsBound(theTShape); - } - - //! Binds the given TShape to a node id. - void BindTShapeToNode(const TopoDS_TShape* theTShape, const BRepGraph_NodeId theNodeId) - { - myTShapeToNodeId.Bind(theTShape, theNodeId); - } + //! Back-reference to the construction-time `TopoDS_Shape` key a node was built from. + //! Only populated during graph construction; absent bindings are a valid state. - //! Back-reference to the source `TopoDS_Shape` a node was built from. - //! Only populated during Build; absent bindings are a valid state. - - //! Returns the original shape for the given node id, or nullptr if not bound. - [[nodiscard]] const TopoDS_Shape* FindOriginal(const BRepGraph_NodeId theNodeId) const - { - return myOriginalShapes.Seek(theNodeId); - } + //! Returns the original shape for the given node id, or a null shape if not bound. + [[nodiscard]] Standard_EXPORT TopoDS_Shape FindOriginal(const BRepGraph_NodeId theNodeId) const; //! Returns true if the given node id has an original shape binding. - [[nodiscard]] bool HasOriginal(const BRepGraph_NodeId theNodeId) const - { - return myOriginalShapes.IsBound(theNodeId); - } + [[nodiscard]] Standard_EXPORT bool HasOriginal(const BRepGraph_NodeId theNodeId) const; - //! Binds the given node id to its original shape. - void BindOriginal(const BRepGraph_NodeId theNodeId, const TopoDS_Shape& theShape) - { - myOriginalShapes.Bind(theNodeId, theShape); - } + //! Binds the given node id to its construction-time shape key. + Standard_EXPORT void BindOriginal(const BRepGraph_NodeId theNodeId, const TopoDS_Shape& theShape); //! Removes the original shape binding for the given node id. - void UnBindOriginal(const BRepGraph_NodeId theNodeId) { myOriginalShapes.UnBind(theNodeId); } + Standard_EXPORT void UnBindOriginal(const BRepGraph_NodeId theNodeId); - //! Iterate all TShape-to-NodeId bindings, invoking theFunc(TShape*, NodeId) for each entry. + //! Iterate all shape-to-NodeId bindings, invoking theFunc(shape, NodeId) for each entry. //! Used by Compact to rebuild the map after the rebuild-and-swap. template - void ForEachTShapeBinding(FuncT&& theFunc) const + void ForEachShapeBinding(FuncT&& theFunc) const { - for (NCollection_DataMap::Iterator anIt( - myTShapeToNodeId); + std::shared_lock aLock(myShapeBindingsMutex); + for (NCollection_FlatDataMap::Iterator + anIt(myShapeToNodeId); anIt.More(); anIt.Next()) { @@ -769,7 +1273,8 @@ public: template void ForEachOriginalBinding(FuncT&& theFunc) const { - for (NCollection_DataMap::Iterator anIt(myOriginalShapes); + std::shared_lock aLock(myShapeBindingsMutex); + for (NCollection_FlatDataMap::Iterator anIt(myOriginalShapes); anIt.More(); anIt.Next()) { @@ -777,58 +1282,254 @@ public: } } - [[nodiscard]] bool GetIsDone() const { return myIsDone; } + //! Copy shape-to-NodeId and Original shape bindings from another storage. + //! Used by identity copy to preserve shape reconstruction bindings. + Standard_EXPORT void CopyShapeBindingsFrom(const BRepGraphInc_Storage& theSource); - void SetIsDone(const bool theVal) { myIsDone = theVal; } + //! Return the generation-validated node-to-shape reconstruction cache. + [[nodiscard]] const NCollection_FlatDataMap& CurrentShapes() const + { + return myCurrentShapes; + } + + //! Return the mutable generation-validated node-to-shape reconstruction cache. + NCollection_FlatDataMap& ChangeCurrentShapes() + { + return myCurrentShapes; + } + + //! Return the mutex protecting the reconstruction cache. + [[nodiscard]] std::shared_mutex& CurrentShapesMutex() const { return myCurrentShapesMutex; } + + //! Clear the generation-validated shape reconstruction cache. + Standard_EXPORT void ClearCurrentShapes(); + + //! Remove one entry from the generation-validated shape reconstruction cache. + Standard_EXPORT void UnbindCurrentShape(const BRepGraph_NodeId theNode); + + //! Clear deferred invalidation queues and release their batch allocator. + Standard_EXPORT void ClearDeferredQueues(); //! Clear all storage. Standard_EXPORT void Clear(); - //! Build reverse indices from entity and relationship tables. - //! Call after population is complete. - Standard_EXPORT void BuildReverseIndex(); - - //! Incrementally update reverse indices for entities appended after a previous - //! BuildReverseIndex(). Only processes entities and refs from the old counts to the - //! current vector lengths - the caller must snapshot ChildRef / SolidRef counts before - //! any Append so this remains O(delta), not O(total). - Standard_EXPORT void BuildDeltaReverseIndex(const uint32_t theOldNbEdges, - const uint32_t theOldNbWires, - const uint32_t theOldNbFaces, - const uint32_t theOldNbShells, - const uint32_t theOldNbSolids, - const uint32_t theOldNbCompounds, - const uint32_t theOldNbCompSolids, - const uint32_t theOldNbChildRefs, - const uint32_t theOldNbSolidRefs); - - //! Debug: verify reverse index consistency against entity tables. - //! @return true if all forward refs have matching reverse entries - Standard_EXPORT bool ValidateReverseIndex() const; + //! Prepare fixed-size destination ranges for indexed load. + //! + //! This is an internal backend preparation API intended for persistence read + //! paths that know final section sizes in advance. It clears previous content, + //! pre-sizes defs/refs/reps and UID vectors, and initializes relation tables + //! exactly once. The load path then restores serialized relation lists and + //! calls RebuildDerivedRelations() once to refresh derived incoming maps. + //! @param theCounts final per-section slot counts. + Standard_EXPORT void PrepareForLoad(const BRepGraphInc_Load::Counts& theCounts); + + //! Override active-slot counters after a trusted indexed load path. + //! + //! This is intended for persistence backends that already touched every slot + //! during load and therefore know exact active counts without rescanning + //! storage after relation construction. + //! @param theCounts trusted active per-section counts. + Standard_EXPORT void SetActiveCounts(const BRepGraphInc_Load::Counts& theCounts); + + //! Build a Counts struct from current allocated slot counts. + [[nodiscard]] Standard_EXPORT BRepGraphInc_Load::Counts Counts() const; + + //! Build a Counts struct from current active (non-removed) counts. + [[nodiscard]] Standard_EXPORT BRepGraphInc_Load::Counts ActiveCounts() const; + + //! Recount active-slot counters from current `IsRemoved` flags without rebuilding indexes. + Standard_EXPORT void RecountActiveCounts(); + + //! Rebuild centralized relation tables from entity and reference endpoints. + //! This is intended for raw load, compact, and explicit repair paths only; + //! editor mutations maintain relation containers incrementally. + Standard_EXPORT void RebuildDerivedRelations(); + + //! Rebuild relation maps after a trusted load already restored active counts. + Standard_EXPORT void RebuildDerivedRelationsPreservingActiveCounts(); + + //! Bulk-copy all RemovedFlags bit-planes from theSource. + //! Source must have been loaded with the same entity counts (identity copy path). + Standard_EXPORT void CopyRemovedFlagsFrom(const BRepGraphInc_Storage& theSource); + + //! Debug: verify relation-table consistency against entity/reference endpoints. + //! @return true if all relations are consistent + Standard_EXPORT bool ValidateRelations() const; + + //! Verify coedge ordering consistency for a specific wire. + //! @param[in] theWireId wire identifier + //! @return true if the coedge order is valid + Standard_EXPORT bool ValidateWireCoEdgeOrder(const BRepGraph_WireId theWireId) const; + + //! Verify coedge ordering consistency for all wires. + //! @return true if all wire coedge orders are valid + Standard_EXPORT bool ValidateWireCoEdgeOrders() const; + + //! Result of wire coedge order canonicalization. + enum class WireCoEdgeOrderStatus + { + Connected, //!< Stored order was already connected. + Reordered, //!< Stored coedges were reordered into an exactly connected chain. + ToleranceOrdered, //!< Stored coedges were ordered using tolerance-equivalent endpoints. + Partial, //!< Stored coedges were grouped into best-effort connected runs. + InvalidInput //!< Wire or coedge ownership/input data is invalid. + }; + + //! Canonicalize the coedge ordering of a wire and report the achieved order quality. + //! @param[in] theWireId wire identifier + //! @return canonicalization status + Standard_EXPORT WireCoEdgeOrderStatus + CanonicalizeWireCoEdgeOrderStatus(const BRepGraph_WireId theWireId); + + //! Canonicalize the coedge ordering of a wire to a consistent form. + //! @param[in] theWireId wire identifier + //! @return true if canonicalization succeeded + Standard_EXPORT bool CanonicalizeWireCoEdgeOrder(const BRepGraph_WireId theWireId); + + //! Rebuild UID reverse indexes (UID->NodeId, RefUID->RefId) + //! from the current UID vectors. Clears indexes and resets allocators before rebuilding. + //! Called after Compact, Load, etc. where UID vectors have been modified externally. + Standard_EXPORT void RebuildUIDReverseIndexes(); + + //! Mark UID reverse indexes stale after bulk UID-vector replacement. + Standard_EXPORT void MarkUIDReverseIndexesDirty(); + + //! Lazily rebuild the node UID reverse index if it is stale. + Standard_EXPORT void EnsureUIDReverseIndex() const; + + //! Lazily rebuild the reference UID reverse index if it is stale. + Standard_EXPORT void EnsureRefUIDReverseIndex() const; + + //! Copy all forward/reverse relation vectors directly from theSource. + //! Used by identity copy to avoid the clear+rebuild cycle. + Standard_EXPORT void CopyDerivedRelationsFrom(const BRepGraphInc_Storage& theSource); private: friend class BRepGraphInc_Populate; friend class BRepGraph; - friend class BRepGraphInc_ReverseIndex; - //! @brief Template store for topology entity kinds. - //! Groups the entity vector, per-kind UID vector, and active count - //! into a single struct, eliminating repeated boilerplate. + Standard_EXPORT void ClearStorageForReuse(); + Standard_EXPORT void ClearUIDIndexes(); + Standard_EXPORT void ClearShapeCache(); + Standard_EXPORT void ClearRelations(); + + BRepGraphInc::FaceRelations& ChangeFaceRelationsInternal(const BRepGraph_FaceId theId) + { + return myFaceRelations.ChangeValue(static_cast(theId.Index)); + } + + BRepGraphInc::WireRelations& ChangeWireRelationsInternal(const BRepGraph_WireId theId) + { + return myWireRelations.ChangeValue(static_cast(theId.Index)); + } + + BRepGraphInc::EdgeRelations& ChangeEdgeRelationsInternal(const BRepGraph_EdgeId theId) + { + return myEdgeRelations.ChangeValue(static_cast(theId.Index)); + } + + BRepGraphInc::ShellRelations& ChangeShellRelationsInternal(const BRepGraph_ShellId theId) + { + return myShellRelations.ChangeValue(static_cast(theId.Index)); + } + + BRepGraphInc::SolidRelations& ChangeSolidRelationsInternal(const BRepGraph_SolidId theId) + { + return mySolidRelations.ChangeValue(static_cast(theId.Index)); + } + + BRepGraphInc::CompoundRelations& ChangeCompoundRelationsInternal(const BRepGraph_CompoundId theId) + { + return myCompoundRelations.ChangeValue(static_cast(theId.Index)); + } + + BRepGraphInc::CompSolidRelations& ChangeCompSolidRelationsInternal( + const BRepGraph_CompSolidId theId) + { + return myCompSolidRelations.ChangeValue(static_cast(theId.Index)); + } + + BRepGraphInc::VertexRelations& ChangeVertexRelationsInternal(const BRepGraph_VertexId theId) + { + return myVertexRelations.ChangeValue(static_cast(theId.Index)); + } + + BRepGraphInc::ProductRelations& ChangeProductRelationsInternal(const BRepGraph_ProductId theId) + { + return myProductRelations.ChangeValue(static_cast(theId.Index)); + } + + BRepGraphInc::OccurrenceRelations& ChangeOccurrenceRelationsInternal( + const BRepGraph_OccurrenceId theId) + { + return myOccurrenceRelations.ChangeValue(static_cast(theId.Index)); + } + + Standard_EXPORT NCollection_LinearVector& ChangeCompoundRefsOfNodeInternal( + const BRepGraph_NodeId theNode); + + Standard_EXPORT NCollection_LinearVector& + ChangeOccurrenceRefsOfNodeInternal(const BRepGraph_NodeId theNode); + + Standard_EXPORT void rebuildDerivedRelationsInternal(const bool theRecountActiveCounts); + + //! Return true if the typed entity has at least one parent compound (internal). + template + [[nodiscard]] bool HasCompoundParentTyped(const T theId) const; + + //! Set or clear the "has parent compound" flag for a typed entity (internal). + template + void SetHasCompoundParentTyped(const T theId, const bool theVal); + + //! Return true if the typed entity has at least one parent occurrence (internal). + template + [[nodiscard]] bool HasOccurrenceParentTyped(const T theId) const; + + //! Set or clear the "has parent occurrence" flag for a typed entity (internal). + template + void SetHasOccurrenceParentTyped(const T theId, const bool theVal); + + //! Set or clear the "has parent compound" flag for a generic NodeId (internal dispatch). + Standard_EXPORT void SetHasCompoundParent(const BRepGraph_NodeId theNode, bool theVal); + + //! Set or clear the "has parent occurrence" flag for a generic NodeId (internal dispatch). + Standard_EXPORT void SetHasOccurrenceParent(const BRepGraph_NodeId theNode, bool theVal); + + //! Template store for topology entity kinds. template struct DefStore { using TypeId = typename EntityT::TypeId; using ValueType = EntityT; - NCollection_DynamicArray Entities; - NCollection_DynamicArray UIDs; - uint32_t NbActive = 0; + //! Entity representations stored by typed id index. + NCollection_DynamicArray Entities; + + //! Bit-flag plane for soft-removal status. + BRepGraphInc_BitFlags RemovedFlags; + + //! Bit-flag plane for ownership status. + BRepGraphInc_BitFlags OwnedFlags; + + //! Bit-flag plane for active MutGuard tracking. + BRepGraphInc_BitFlags GuardFlags; + + //! Bit-flag plane: node has at least one parent compound (ChildRef). + BRepGraphInc_BitFlags HasCompoundParentFlags; - DefStore() = default; + //! Bit-flag plane: node has at least one parent occurrence (OccurrenceRef). + BRepGraphInc_BitFlags HasOccurrenceParentFlags; + + //! Number of non-removed entities currently present in the store. + uint32_t NbActive = 0; + + //! Per-kind monotonic UID counter. Valid UIDs start at 1. + std::atomic NextUIDCounter{1}; + + DefStore() = delete; DefStore(const int theBlockSize, const occ::handle& theAlloc) - : Entities(theBlockSize, theAlloc), - UIDs(theBlockSize, theAlloc) + : Entities(theBlockSize, theAlloc) { } @@ -845,11 +1546,16 @@ private: } //! Append a default-constructed entity and return its typed slot id. - TypeId Append(const occ::handle& theAlloc) + TypeId Append() { const TypeId anId(static_cast(Entities.Size())); ++NbActive; - Entities.Appended().InitVectors(theAlloc); + Entities.Appended(); + RemovedFlags.Resize(static_cast(anId.Index) + 1); + OwnedFlags.Resize(static_cast(anId.Index) + 1); + GuardFlags.Resize(static_cast(anId.Index) + 1); + HasCompoundParentFlags.Resize(static_cast(anId.Index) + 1); + HasOccurrenceParentFlags.Resize(static_cast(anId.Index) + 1); return anId; } @@ -857,7 +1563,9 @@ private: { Standard_ASSERT_VOID(NbActive > 0u, "DefStore::DecrementActive: underflow"); if (NbActive > 0u) + { --NbActive; + } } bool MarkRemoved(const TypeId theId) @@ -867,68 +1575,99 @@ private: return false; } - EntityT& anEntity = Change(theId); - if (anEntity.IsRemoved) + if (RemovedFlags.Test(theId.Index)) { return false; } - anEntity.IsRemoved = true; + RemovedFlags.Set(theId.Index); DecrementActive(); return true; } - void Clear() + void Clear(const bool theReleaseMemory = false) { - Entities.Clear(); - UIDs.Clear(); + Entities.Clear(theReleaseMemory); + RemovedFlags.ClearAll(); + OwnedFlags.ClearAll(); + GuardFlags.ClearAll(); + HasCompoundParentFlags.ClearAll(); + HasOccurrenceParentFlags.ClearAll(); NbActive = 0; + // Note: NextUIDCounter is NOT reset. UIDs stay monotonic across Clear() cycles. + // Generation + GraphGUID protect against stale UID aliasing. } }; - //! @brief Template store for representation entity kinds. - //! Groups the representation vector and active count into a single struct. - template - struct RepStore + //! Template store for transitional reference kinds. + template + struct RefStore { - using TypeId = typename RepT::TypeId; - using ValueType = RepT; + using TypeId = typename RefT::TypeId; + using ValueType = RefT; - NCollection_DynamicArray Entities; - uint32_t NbActive = 0; + //! Reference representations stored by typed id index. + NCollection_DynamicArray Refs; - RepStore() = default; + //! Bit-flag plane for soft-removal status. + BRepGraphInc_BitFlags RemovedFlags; - RepStore(const int theBlockSize, const occ::handle& theAlloc) - : Entities(theBlockSize, theAlloc) - { - } + //! Bit-flag plane for ownership status. + BRepGraphInc_BitFlags OwnedFlags; - uint32_t Nb() const { return static_cast(Entities.Size()); } + //! Bit-flag plane for active MutGuard tracking. + BRepGraphInc_BitFlags GuardFlags; + + //! Bit-flag plane: ref has at least one parent compound (unused for refs, kept for macro + //! uniformity). + BRepGraphInc_BitFlags HasCompoundParentFlags; + + //! Bit-flag plane: ref has at least one parent occurrence (unused for refs, kept for macro + //! uniformity). + BRepGraphInc_BitFlags HasOccurrenceParentFlags; - const RepT& Get(const TypeId theId) const + //! Number of non-removed references currently present in the store. + uint32_t NbActive = 0; + + //! Per-kind monotonic UID counter. Valid UIDs start at 1. + std::atomic NextUIDCounter{1}; + + RefStore() = delete; + + RefStore(const int theBlockSize, const occ::handle& theAlloc) + : Refs(theBlockSize, theAlloc) { - return Entities.Value(static_cast(theId.Index)); } - RepT& Change(const TypeId theId) + uint32_t Nb() const { return static_cast(Refs.Size()); } + + const RefT& Get(const TypeId theId) const { - return Entities.ChangeValue(static_cast(theId.Index)); + return Refs.Value(static_cast(theId.Index)); } - //! Append a default-constructed rep and return its typed slot id. + RefT& Change(const TypeId theId) { return Refs.ChangeValue(static_cast(theId.Index)); } + + //! Append a default-constructed ref entry and return its typed slot id. TypeId Append() { - const TypeId anId(static_cast(Entities.Size())); + const TypeId anId(static_cast(Refs.Size())); ++NbActive; - Entities.Appended(); + Refs.Appended(); + RemovedFlags.Resize(static_cast(anId.Index) + 1); + OwnedFlags.Resize(static_cast(anId.Index) + 1); + GuardFlags.Resize(static_cast(anId.Index) + 1); + HasCompoundParentFlags.Resize(static_cast(anId.Index) + 1); + HasOccurrenceParentFlags.Resize(static_cast(anId.Index) + 1); return anId; } void DecrementActive() { - Standard_ASSERT_VOID(NbActive > 0u, "RepStore::DecrementActive: underflow"); + Standard_ASSERT_VOID(NbActive > 0u, "RefStore::DecrementActive: underflow"); if (NbActive > 0u) + { --NbActive; + } } bool MarkRemoved(const TypeId theId) @@ -938,76 +1677,152 @@ private: return false; } - RepT& aRep = Change(theId); - if (aRep.IsRemoved) + if (RemovedFlags.Test(theId.Index)) { return false; } - aRep.IsRemoved = true; + RemovedFlags.Set(theId.Index); DecrementActive(); return true; } - void EraseLast() - { - Standard_ASSERT_VOID(NbActive > 0u, "RepStore::EraseLast: underflow"); - if (NbActive > 0u) - { - Entities.EraseLast(); - --NbActive; - } - } - - void Clear() + void Clear(const bool theReleaseMemory = false) { - Entities.Clear(); + Refs.Clear(theReleaseMemory); + RemovedFlags.ClearAll(); + OwnedFlags.ClearAll(); + GuardFlags.ClearAll(); + HasCompoundParentFlags.ClearAll(); + HasOccurrenceParentFlags.ClearAll(); NbActive = 0; + // Note: NextUIDCounter is NOT reset. UIDs stay monotonic across Clear() cycles. } }; - //! @brief Template store for transitional reference entry kinds. - //! Groups reference vectors and per-kind UID vectors into a single struct. - template - struct RefStore + //! Primary allocator for backend arrays, stores, and transient backend maps. + occ::handle myAllocator = new NCollection_IncAllocator; + + //! Backend-owned root products and deferred invalidation queues. + NCollection_LinearVector myRootProductIds; + NCollection_LinearVector myDeferredModified; + NCollection_LinearVector myDeferredRefModified; + + //! Vertex definition store. + DefStore myVertices; + + //! Edge definition store. + DefStore myEdges; + + //! Coedge definition store. + DefStore myCoEdges; + + //! Wire definition store. + DefStore myWires; + + //! Face definition store. + DefStore myFaces; + + //! Shell definition store. + DefStore myShells; + + //! Solid definition store. + DefStore mySolids; + + //! Compound definition store. + DefStore myCompounds; + + //! CompSolid definition store. + DefStore myCompSolids; + + //! Product definition store. + DefStore myProducts; + + //! Occurrence definition store. + DefStore myOccurrences; + + //! Shell reference store. + RefStore myShellRefs; + + //! Face reference store. + RefStore myFaceRefs; + + //! Wire reference store. + RefStore myWireRefs; + + //! Vertex reference store. + RefStore myVertexRefs; + + //! Solid reference store. + RefStore mySolidRefs; + + //! Child reference store. + RefStore myChildRefs; + + //! Occurrence reference store. + RefStore myOccurrenceRefs; + + //! Centralized relation tables parallel to entity stores. + NCollection_DynamicArray myFaceRelations; + NCollection_DynamicArray myWireRelations; + NCollection_DynamicArray myEdgeRelations; + NCollection_DynamicArray myShellRelations; + NCollection_DynamicArray mySolidRelations; + NCollection_DynamicArray myCompoundRelations; + NCollection_DynamicArray myCompSolidRelations; + NCollection_DynamicArray myVertexRelations; + NCollection_DynamicArray myProductRelations; + NCollection_DynamicArray myOccurrenceRelations; + + //! Sparse incoming compound child refs keyed by referenced node. + NCollection_DataMap> + myNodeToCompounds; + + //! Sparse incoming product occurrence refs keyed by occurrence child node. + NCollection_DataMap> + myNodeToOccurrences; + + //! Representation-use store with removal tracking. + template + struct RepStore { - using TypeId = typename RefT::TypeId; - using ValueType = RefT; + using TypeId = typename UseT::TypeId; - NCollection_DynamicArray Refs; - NCollection_DynamicArray UIDs; - uint32_t NbActive = 0; + NCollection_DynamicArray Uses; + BRepGraphInc_BitFlags RemovedFlags; + uint32_t NbActive = 0; - RefStore() = default; + RepStore() = delete; - RefStore(const int theBlockSize, const occ::handle& theAlloc) - : Refs(theBlockSize, theAlloc), - UIDs(theBlockSize, theAlloc) + RepStore(const int theBlockSize, const occ::handle& theAlloc) + : Uses(theBlockSize, theAlloc) { } - uint32_t Nb() const { return static_cast(Refs.Size()); } + uint32_t Nb() const { return static_cast(Uses.Size()); } - const RefT& Get(const TypeId theId) const + const UseT& Get(const TypeId theId) const { - return Refs.Value(static_cast(theId.Index)); + return Uses.Value(static_cast(theId.Index)); } - RefT& Change(const TypeId theId) { return Refs.ChangeValue(static_cast(theId.Index)); } + UseT& Change(const TypeId theId) { return Uses.ChangeValue(static_cast(theId.Index)); } - //! Append a default-constructed ref entry and return its typed slot id. TypeId Append() { - const TypeId anId(static_cast(Refs.Size())); + const TypeId anId(static_cast(Uses.Size())); ++NbActive; - Refs.Appended(); + Uses.Appended(); + RemovedFlags.Resize(static_cast(anId.Index) + 1); return anId; } void DecrementActive() { - Standard_ASSERT_VOID(NbActive > 0u, "RefStore::DecrementActive: underflow"); + Standard_ASSERT_VOID(NbActive > 0u, "RepStore::DecrementActive: underflow"); if (NbActive > 0u) + { --NbActive; + } } bool MarkRemoved(const TypeId theId) @@ -1016,65 +1831,155 @@ private: { return false; } - - RefT& aRef = Change(theId); - if (aRef.IsRemoved) + if (RemovedFlags.Test(theId.Index)) { return false; } - aRef.IsRemoved = true; + RemovedFlags.Set(theId.Index); DecrementActive(); return true; } - void Clear() + bool IsRemoved(const TypeId theId) const + { + return theId.IsValid(Nb()) && RemovedFlags.Test(theId.Index); + } + + void Clear(const bool theReleaseMemory = false) { - Refs.Clear(); - UIDs.Clear(); + Uses.Clear(theReleaseMemory); + RemovedFlags.ClearAll(); NbActive = 0; } }; - // Topology entity stores - DefStore myVertices; - DefStore myEdges; - DefStore myCoEdges; - DefStore myWires; - DefStore myFaces; - DefStore myShells; - DefStore mySolids; - DefStore myCompounds; - DefStore myCompSolids; - DefStore myProducts; - DefStore myOccurrences; + //! Edge 3D curve use store. + RepStore myEdgeCurves3D; - // Transitional reference entry stores - RefStore myShellRefs; - RefStore myFaceRefs; - RefStore myWireRefs; - RefStore myCoEdgeRefs; - RefStore myVertexRefs; - RefStore mySolidRefs; - RefStore myChildRefs; - RefStore myOccurrenceRefs; + //! Edge 3D polygon use store. + RepStore myEdgePolygons3D; + + //! CoEdge 2D curve use store. + RepStore myCoEdgeCurves2D; + + //! CoEdge 2D polygon use store. + RepStore myCoEdgePolygons2D; + + //! CoEdge polygon-on-triangulation use store. + RepStore myCoEdgePolygonsOnTri; + + //! Face surface use store. + RepStore myFaceSurfaces; - // Representation entity stores - RepStore mySurfaces; - RepStore myCurves3D; - RepStore myCurves2D; - RepStore myTriangulationsRep; - RepStore myPolygons3D; - RepStore myPolygons2D; - RepStore myPolygonsOnTri; + //! Face triangulation use store. + RepStore myFaceTriangulations; - BRepGraphInc_ReverseIndex myReverseIdx; + //! UID reverse indexes: eagerly maintained on allocate/remove, rebuilt on compact/load. + mutable NCollection_FlatDataMap myUIDToNodeId; + mutable std::shared_mutex myUIDToNodeIdMutex; + mutable NCollection_FlatDataMap myRefUIDToRefId; + mutable std::shared_mutex myRefUIDToRefIdMutex; + mutable std::atomic myUIDToNodeIdDirty{false}; + mutable std::atomic myRefUIDToRefIdDirty{false}; - NCollection_DataMap myTShapeToNodeId; - NCollection_DataMap myOriginalShapes; + //! Bindings from reconstructed / source OCCT shapes back to backend ids. + NCollection_FlatDataMap myShapeToNodeId; + NCollection_FlatDataMap myOriginalShapes; + mutable std::shared_mutex myShapeBindingsMutex; - occ::handle myAllocator; + //! Persistent backend identity state. + std::atomic myGeneration{0}; + Standard_GUID myGraphGUID; - bool myIsDone = false; + //! Transient mutation-control state used by EditorView invalidation paths. + std::atomic myDeferredMode{false}; + std::atomic myPropagationWave{0}; + uint32_t myRemoveSubgraphDepth = 0; + + //! Transient generation-validated shape reconstruction cache. + mutable NCollection_FlatDataMap myCurrentShapes; + mutable std::shared_mutex myCurrentShapesMutex; + +private: + //! Trait mapping a typed identifier to its store's bit-flag planes. + //! One specialization per typed ID type provides O(1) compile-time dispatch. + template + struct TypedStorePlanes; + + template + friend struct TypedStorePlanes; + + template + [[nodiscard]] bool isInRange(const T theId) const; + + template + [[nodiscard]] bool dispatchItemId(const BRepGraph_ItemId& theId, FuncT&& theFunc) const; + +public: + //! Return true if the entity identified by the given typed ID is soft-removed. + //! @param[in] theId typed entity identifier + template + [[nodiscard]] bool IsRemoved(const T theId) const; + + //! Set or clear the soft-removal flag for the entity identified by the given typed ID. + //! @param[in] theId typed entity identifier + //! @param[in] theVal true to mark removed, false to mark active + template + void SetRemoved(const T theId, const bool theVal); + + //! Return true if the entity identified by the given typed ID has a registered owner. + //! @param[in] theId typed entity identifier + template + [[nodiscard]] bool IsOwned(const T theId) const; + + //! Set or clear the ownership flag for the entity identified by the given typed ID. + //! @param[in] theId typed entity identifier + //! @param[in] theVal true to mark owned, false to mark unowned + template + void SetOwned(const T theId, const bool theVal); + + //! Return true if the entity identified by the given typed ID has an active MutGuard. + //! @param[in] theId typed entity identifier + template + [[nodiscard]] bool IsGuarded(const T theId) const; + + //! Register an active MutGuard on the entity identified by the given typed ID. + //! @param[in] theId typed entity identifier + template + void SetGuarded(const T theId); + + //! Deregister an active MutGuard from the entity identified by the given typed ID. + //! @param[in] theId typed entity identifier + template + void ClearGuarded(const T theId); + + //! Return true if the node identified by the given generic NodeId has a parent compound. + //! Dispatches by node kind to the appropriate per-kind bitset. + //! @param[in] theNode generic node identifier + [[nodiscard]] Standard_EXPORT bool HasCompoundParent(const BRepGraph_NodeId theNode) const; + + //! Return true if the node identified by the given generic NodeId has a parent occurrence. + //! Dispatches by node kind to the appropriate per-kind bitset. + //! @param[in] theNode generic node identifier + [[nodiscard]] Standard_EXPORT bool HasOccurrenceParent(const BRepGraph_NodeId theNode) const; + + //! Return true if the entity identified by the given generic item id has an active MutGuard. + //! @param[in] theId generic item identifier (node, reference, or representation) + [[nodiscard]] bool IsGuarded(const BRepGraph_ItemId& theId) const; + + //! Register an active MutGuard on the entity identified by the given generic item id. + //! @param[in] theId generic item identifier (node, reference, or representation) + void SetGuarded(const BRepGraph_ItemId& theId); + + //! Deregister an active MutGuard from the entity identified by the given generic item id. + //! @param[in] theId generic item identifier (node, reference, or representation) + void ClearGuarded(const BRepGraph_ItemId& theId); + + //! Return true if any entity in any store has an active MutGuard. + //! Used to assert no guards are active before Clear(). + [[nodiscard]] Standard_EXPORT bool HasAnyGuard() const; }; +#include + #endif // _BRepGraphInc_Storage_HeaderFile diff --git a/opencascade/BRepGraphInc_Storage.lxx b/opencascade/BRepGraphInc_Storage.lxx new file mode 100644 index 000000000..dfe7ef6d3 --- /dev/null +++ b/opencascade/BRepGraphInc_Storage.lxx @@ -0,0 +1,375 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +//! @name TypedStorePlanes specializations for entity and reference stores. +//! +//! Each store (e.g. myVertices, myEdges) is a DefStore or RefStore that owns +//! per-entity bit-flag planes. The specialization exposes those planes through +//! a uniform static interface so that generic template methods (IsRemoved, +//! SetRemoved, IsGuarded, ...) can operate on any typed ID without a virtual +//! dispatch. +//! +//! Parameter T is the typed identifier (e.g. BRepGraph_VertexId). +//! Parameter F is the member store field name (e.g. myVertices). +#define OCCT_BG_STORE_PLANES(T, F) \ + template <> \ + struct BRepGraphInc_Storage::TypedStorePlanes \ + { \ + static uint32_t Nb(const BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.Nb(); \ + } \ + static uint32_t& NbActive(BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.NbActive; \ + } \ + static BRepGraphInc_BitFlags& Removed(BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.RemovedFlags; \ + } \ + static const BRepGraphInc_BitFlags& Removed(const BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.RemovedFlags; \ + } \ + static BRepGraphInc_BitFlags& Owned(BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.OwnedFlags; \ + } \ + static const BRepGraphInc_BitFlags& Owned(const BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.OwnedFlags; \ + } \ + static BRepGraphInc_BitFlags& Guard(BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.GuardFlags; \ + } \ + static const BRepGraphInc_BitFlags& Guard(const BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.GuardFlags; \ + } \ + static BRepGraphInc_BitFlags& HasCompoundParent(BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.HasCompoundParentFlags; \ + } \ + static const BRepGraphInc_BitFlags& HasCompoundParent(const BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.HasCompoundParentFlags; \ + } \ + static BRepGraphInc_BitFlags& HasOccurrenceParent(BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.HasOccurrenceParentFlags; \ + } \ + static const BRepGraphInc_BitFlags& HasOccurrenceParent( \ + const BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.HasOccurrenceParentFlags; \ + } \ + }; + +OCCT_BG_STORE_PLANES(BRepGraph_VertexId, myVertices) +OCCT_BG_STORE_PLANES(BRepGraph_EdgeId, myEdges) +OCCT_BG_STORE_PLANES(BRepGraph_CoEdgeId, myCoEdges) +OCCT_BG_STORE_PLANES(BRepGraph_WireId, myWires) +OCCT_BG_STORE_PLANES(BRepGraph_FaceId, myFaces) +OCCT_BG_STORE_PLANES(BRepGraph_ShellId, myShells) +OCCT_BG_STORE_PLANES(BRepGraph_SolidId, mySolids) +OCCT_BG_STORE_PLANES(BRepGraph_CompoundId, myCompounds) +OCCT_BG_STORE_PLANES(BRepGraph_CompSolidId, myCompSolids) +OCCT_BG_STORE_PLANES(BRepGraph_ProductId, myProducts) +OCCT_BG_STORE_PLANES(BRepGraph_OccurrenceId, myOccurrences) + +OCCT_BG_STORE_PLANES(BRepGraph_VertexRefId, myVertexRefs) +OCCT_BG_STORE_PLANES(BRepGraph_ShellRefId, myShellRefs) +OCCT_BG_STORE_PLANES(BRepGraph_FaceRefId, myFaceRefs) +OCCT_BG_STORE_PLANES(BRepGraph_WireRefId, myWireRefs) +OCCT_BG_STORE_PLANES(BRepGraph_SolidRefId, mySolidRefs) +OCCT_BG_STORE_PLANES(BRepGraph_ChildRefId, myChildRefs) +OCCT_BG_STORE_PLANES(BRepGraph_OccurrenceRefId, myOccurrenceRefs) + +#undef OCCT_BG_STORE_PLANES + +//! @name TypedStorePlanes specializations for representation-use stores. +//! +//! Representation stores (e.g. myFaceSurfaces, myEdgeCurves3D) track geometric +//! or triangulation data attached to topology entities. They have Removed +//! flags and an NbActive counter but no Owned, Guard, HasCompoundParent, or +//! HasOccurrenceParent planes. Those methods are intentionally omitted -- +//! calling IsOwned/IsGuarded/HasCompoundParentTyped/HasOccurrenceParentTyped +//! on a representation ID will produce a compile error, which is the desired +//! behavior since representation entities have no ownership or guard lifecycle. +#define OCCT_BG_REP_PLANES(T, F) \ + template <> \ + struct BRepGraphInc_Storage::TypedStorePlanes \ + { \ + static uint32_t Nb(const BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.Nb(); \ + } \ + static uint32_t& NbActive(BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.NbActive; \ + } \ + static BRepGraphInc_BitFlags& Removed(BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.RemovedFlags; \ + } \ + static const BRepGraphInc_BitFlags& Removed(const BRepGraphInc_Storage& theStorage) \ + { \ + return theStorage.F.RemovedFlags; \ + } \ + }; + +OCCT_BG_REP_PLANES(BRepGraph_FaceSurfaceRepId, myFaceSurfaces) +OCCT_BG_REP_PLANES(BRepGraph_FaceTriangulationRepId, myFaceTriangulations) +OCCT_BG_REP_PLANES(BRepGraph_EdgeCurve3DRepId, myEdgeCurves3D) +OCCT_BG_REP_PLANES(BRepGraph_EdgePolygon3DRepId, myEdgePolygons3D) +OCCT_BG_REP_PLANES(BRepGraph_CoEdgeCurve2DRepId, myCoEdgeCurves2D) +OCCT_BG_REP_PLANES(BRepGraph_CoEdgePolygon2DRepId, myCoEdgePolygons2D) +OCCT_BG_REP_PLANES(BRepGraph_CoEdgePolygonOnTriRepId, myCoEdgePolygonsOnTri) + +#undef OCCT_BG_REP_PLANES + +//================================================================================================= + +template +bool BRepGraphInc_Storage::isInRange(const T theId) const +{ + return theId.IsValid(TypedStorePlanes::Nb(*this)) + && TypedStorePlanes::Removed(*this).IsValidIndex(theId.Index); +} + +//================================================================================================= + +template +bool BRepGraphInc_Storage::dispatchItemId(const BRepGraph_ItemId& theId, FuncT&& theFunc) const +{ + switch (theId.ItemDomain()) + { + case BRepGraph_ItemId::Domain::Node: + switch (static_cast(theId.RawKind())) + { + case BRepGraph_NodeId::Kind::Vertex: + return std::forward(theFunc)(BRepGraph_VertexId(theId.Index())); + case BRepGraph_NodeId::Kind::Edge: + return std::forward(theFunc)(BRepGraph_EdgeId(theId.Index())); + case BRepGraph_NodeId::Kind::CoEdge: + return std::forward(theFunc)(BRepGraph_CoEdgeId(theId.Index())); + case BRepGraph_NodeId::Kind::Wire: + return std::forward(theFunc)(BRepGraph_WireId(theId.Index())); + case BRepGraph_NodeId::Kind::Face: + return std::forward(theFunc)(BRepGraph_FaceId(theId.Index())); + case BRepGraph_NodeId::Kind::Shell: + return std::forward(theFunc)(BRepGraph_ShellId(theId.Index())); + case BRepGraph_NodeId::Kind::Solid: + return std::forward(theFunc)(BRepGraph_SolidId(theId.Index())); + case BRepGraph_NodeId::Kind::Compound: + return std::forward(theFunc)(BRepGraph_CompoundId(theId.Index())); + case BRepGraph_NodeId::Kind::CompSolid: + return std::forward(theFunc)(BRepGraph_CompSolidId(theId.Index())); + case BRepGraph_NodeId::Kind::Product: + return std::forward(theFunc)(BRepGraph_ProductId(theId.Index())); + case BRepGraph_NodeId::Kind::Occurrence: + return std::forward(theFunc)(BRepGraph_OccurrenceId(theId.Index())); + } + break; + case BRepGraph_ItemId::Domain::Reference: + switch (static_cast(theId.RawKind())) + { + case BRepGraph_RefId::Kind::Shell: + return std::forward(theFunc)(BRepGraph_ShellRefId(theId.Index())); + case BRepGraph_RefId::Kind::Face: + return std::forward(theFunc)(BRepGraph_FaceRefId(theId.Index())); + case BRepGraph_RefId::Kind::Wire: + return std::forward(theFunc)(BRepGraph_WireRefId(theId.Index())); + case BRepGraph_RefId::Kind::Vertex: + return std::forward(theFunc)(BRepGraph_VertexRefId(theId.Index())); + case BRepGraph_RefId::Kind::Solid: + return std::forward(theFunc)(BRepGraph_SolidRefId(theId.Index())); + case BRepGraph_RefId::Kind::Child: + return std::forward(theFunc)(BRepGraph_ChildRefId(theId.Index())); + case BRepGraph_RefId::Kind::Occurrence: + return std::forward(theFunc)(BRepGraph_OccurrenceRefId(theId.Index())); + } + break; + default: + break; + } + return false; +} + +//================================================================================================= + +template +bool BRepGraphInc_Storage::IsRemoved(const T theId) const +{ + return isInRange(theId) && TypedStorePlanes::Removed(*this).Test(theId.Index); +} + +//================================================================================================= + +template +void BRepGraphInc_Storage::SetRemoved(const T theId, const bool theVal) +{ + if (!isInRange(theId)) + { + return; + } + auto& aF = TypedStorePlanes::Removed(*this); + const bool aWasRemoved = aF.Test(theId.Index); + if (aWasRemoved == theVal) + { + return; + } + uint32_t& aNbActive = TypedStorePlanes::NbActive(*this); + if (theVal) + { + aF.Set(theId.Index); + Standard_ASSERT_VOID(aNbActive > 0u, + "BRepGraphInc_Storage::SetRemoved: active count underflow"); + if (aNbActive > 0u) + { + --aNbActive; + } + } + else + { + aF.Clear(theId.Index); + ++aNbActive; + } +} + +//================================================================================================= + +template +bool BRepGraphInc_Storage::IsOwned(const T theId) const +{ + return isInRange(theId) && TypedStorePlanes::Owned(*this).Test(theId.Index); +} + +//================================================================================================= + +template +void BRepGraphInc_Storage::SetOwned(const T theId, const bool theVal) +{ + if (!isInRange(theId)) + { + return; + } + auto& aF = TypedStorePlanes::Owned(*this); + theVal ? aF.Set(theId.Index) : aF.Clear(theId.Index); +} + +//================================================================================================= + +template +bool BRepGraphInc_Storage::IsGuarded(const T theId) const +{ + return isInRange(theId) && TypedStorePlanes::Guard(*this).Test(theId.Index); +} + +//================================================================================================= + +template +void BRepGraphInc_Storage::SetGuarded(const T theId) +{ + if (isInRange(theId)) + { + TypedStorePlanes::Guard(*this).Set(theId.Index); + } +} + +//================================================================================================= + +template +void BRepGraphInc_Storage::ClearGuarded(const T theId) +{ + if (isInRange(theId)) + { + TypedStorePlanes::Guard(*this).Clear(theId.Index); + } +} + +//================================================================================================= + +template +bool BRepGraphInc_Storage::HasCompoundParentTyped(const T theId) const +{ + return isInRange(theId) && TypedStorePlanes::HasCompoundParent(*this).Test(theId.Index); +} + +//================================================================================================= + +template +void BRepGraphInc_Storage::SetHasCompoundParentTyped(const T theId, const bool theVal) +{ + if (!isInRange(theId)) + { + return; + } + auto& aF = TypedStorePlanes::HasCompoundParent(*this); + theVal ? aF.Set(theId.Index) : aF.Clear(theId.Index); +} + +//================================================================================================= + +template +bool BRepGraphInc_Storage::HasOccurrenceParentTyped(const T theId) const +{ + return isInRange(theId) && TypedStorePlanes::HasOccurrenceParent(*this).Test(theId.Index); +} + +//================================================================================================= + +template +void BRepGraphInc_Storage::SetHasOccurrenceParentTyped(const T theId, const bool theVal) +{ + if (!isInRange(theId)) + { + return; + } + auto& aF = TypedStorePlanes::HasOccurrenceParent(*this); + theVal ? aF.Set(theId.Index) : aF.Clear(theId.Index); +} + +//================================================================================================= + +inline bool BRepGraphInc_Storage::IsGuarded(const BRepGraph_ItemId& theId) const +{ + return dispatchItemId(theId, [this](const auto theTypedId) { return IsGuarded(theTypedId); }); +} + +//================================================================================================= + +inline void BRepGraphInc_Storage::SetGuarded(const BRepGraph_ItemId& theId) +{ + if (!dispatchItemId(theId, [this](const auto theTypedId) { + SetGuarded(theTypedId); + return true; + })) + { + Standard_ASSERT_VOID(false, "BRepGraphInc_Storage::SetGuarded: invalid item id"); + } +} + +//================================================================================================= + +inline void BRepGraphInc_Storage::ClearGuarded(const BRepGraph_ItemId& theId) +{ + if (!dispatchItemId(theId, [this](const auto theTypedId) { + ClearGuarded(theTypedId); + return true; + })) + { + Standard_ASSERT_VOID(false, "BRepGraphInc_Storage::ClearGuarded: invalid item id"); + } +} diff --git a/opencascade/BRepGraph_Builder.hxx b/opencascade/BRepGraph_Builder.hxx deleted file mode 100644 index 523630332..000000000 --- a/opencascade/BRepGraph_Builder.hxx +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraph_Builder_HeaderFile -#define _BRepGraph_Builder_HeaderFile - -#include -#include -#include -#include -#include -#include -#include - -class BRepGraph; -class TopoDS_Shape; - -//! @brief Static helper that ingests a TopoDS_Shape into a BRepGraph. -class BRepGraph_Builder -{ -public: - DEFINE_STANDARD_ALLOC - - //! Build-time options. - struct Options - { - BRepGraphInc_Populate::Options Populate{}; - bool CreateAutoProduct = true; //!< wrap topology root in a Product (unparented Add only) - bool Flatten = false; //!< drop hierarchy containers, append faces as roots - bool Parallel = false; //!< run face-level construction in parallel - }; - - //! Outcome of a single Add() call. - struct Result - { - BRepGraph_NodeId TopologyRoot; - BRepGraph_ProductId Product; - BRepGraph_OccurrenceId Occurrence; - BRepGraph_RefId InsertedRef; - bool Ok = false; - }; - - //! Ingest a TopoDS_Shape as a new root subgraph, wrapping the topology root in a Product. - //! @param[in,out] theGraph graph to populate - //! @param[in] theShape shape to ingest - //! @return Result with TopologyRoot, Product and Occurrence set on success. - [[nodiscard]] static Standard_EXPORT Result Add(BRepGraph& theGraph, - const TopoDS_Shape& theShape); - - //! Ingest a TopoDS_Shape as a new root subgraph with explicit options. - //! @param[in,out] theGraph graph to populate - //! @param[in] theShape shape to ingest - //! @param[in] theOptions build-time options - //! @return Result with TopologyRoot set on success; Product/Occurrence set - //! when theOptions.CreateAutoProduct is true. - [[nodiscard]] static Standard_EXPORT Result Add(BRepGraph& theGraph, - const TopoDS_Shape& theShape, - const Options& theOptions); - - //! Ingest a TopoDS_Shape under an existing parent. - //! - //! Parent kind dispatch: - //! - Product: creates a child part-product, links via Occurrence with shape.Location(). - //! - Compound: appends topology root as a child reference. - //! - Shell: appends a Face as a FaceRef; other shapes via AddChild. - //! - Solid: appends a Shell as a ShellRef; other shapes via AddChild. - //! - CompSolid: appends a Solid as a SolidRef. - //! Other parent kinds (Wire, Edge, Vertex, Occurrence) are not supported and yield - //! an invalid Result (Result::Ok == false) without modification to the graph. - //! @param[in,out] theGraph graph to populate - //! @param[in] theShape shape to ingest - //! @param[in] theParent parent node receiving the topology - //! @return Result with TopologyRoot set, plus (Product, Occurrence, InsertedRef) for Product - //! parents or InsertedRef for topology container parents. - [[nodiscard]] static Standard_EXPORT Result Add(BRepGraph& theGraph, - const TopoDS_Shape& theShape, - const BRepGraph_NodeId theParent); - - //! Ingest a shape under an existing parent with explicit options. - //! Options::CreateAutoProduct is ignored. - [[nodiscard]] static Standard_EXPORT Result Add(BRepGraph& theGraph, - const TopoDS_Shape& theShape, - const BRepGraph_NodeId theParent, - const Options& theOptions); - -private: - static void appendImpl(BRepGraph& theGraph, - const TopoDS_Shape& theShape, - const Options& theOptions, - NCollection_DynamicArray* theOutFlatRoots = nullptr); - - static BRepGraph_NodeId detectTopologyRoot(const BRepGraph& theGraph, - const TopAbs_ShapeEnum theShapeType, - const uint32_t theOldCountOfShapeKind); - - static uint32_t snapshotCountForKind(const BRepGraph& theGraph, - const TopAbs_ShapeEnum theShapeType); - - static void populateUIDs(BRepGraph& theGraph); - - static void populateUIDsIncremental(BRepGraph& theGraph, - const int theOldVtx, - const int theOldEdge, - const int theOldCoEdge, - const int theOldWire, - const int theOldFace, - const int theOldShell, - const int theOldSolid, - const int theOldComp, - const int theOldCS, - const int theOldProduct, - const int theOldOccurrence, - const int theOldShellRef, - const int theOldFaceRef, - const int theOldWireRef, - const int theOldCoEdgeRef, - const int theOldVertexRef, - const int theOldSolidRef, - const int theOldChildRef); - - BRepGraph_Builder() = delete; -}; - -#endif // _BRepGraph_Builder_HeaderFile diff --git a/opencascade/BRepGraph_Cache.hxx b/opencascade/BRepGraph_Cache.hxx new file mode 100644 index 000000000..04979ea1f --- /dev/null +++ b/opencascade/BRepGraph_Cache.hxx @@ -0,0 +1,230 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_Cache_HeaderFile +#define _BRepGraph_Cache_HeaderFile + +#include +#include +#include +#include +#include +#include +#include + +#include + +class BRepGraph; +class BRepGraph_CacheRegistry; +class BRepGraph_CopyRemap; + +//! @brief Lightweight owner-bound base for transient graph cache services. +//! +//! A cache service stores typed, recomputable, graph-local data such as +//! bounding boxes, UV bounds, or display-resolution results. The registry owns +//! only service identity and lifetime binding; concrete caches own their own +//! typed storage and validate freshness lazily via graph generation counters. +class BRepGraph_Cache : public Standard_Transient +{ +public: + //! Cache service identity, unique within a graph registry. + [[nodiscard]] virtual const Standard_GUID& ID() const = 0; + + //! Cache service display name. + [[nodiscard]] virtual const TCollection_AsciiString& Name() const = 0; + + //! Clear all transient data owned by this cache. + Standard_EXPORT virtual void Clear() noexcept; + + //! Copy fresh, remappable cache data into the target graph described by the remap. + //! Default implementation copies nothing. + Standard_EXPORT virtual void CopyFreshTo(const BRepGraph_CopyRemap& theCopy) const; + + DEFINE_STANDARD_RTTIEXT(BRepGraph_Cache, Standard_Transient) + +protected: + //! @brief Value base for node-derived cache entries. + //! + //! Concrete cache services inherit this from their private entry structs and + //! store entries by value in their own typed storage. The base records the + //! node identity plus the generation counter used to validate freshness. + class NodeEntry + { + public: + //! Reset to an unbound stale state. + Standard_EXPORT void Reset() noexcept; + + //! Bind this entry to the current OwnGen of a node. + //! @return false when the cache is detached or the node is inactive + [[nodiscard]] Standard_EXPORT bool BindOwnGen(const BRepGraph_Cache& theCache, + const BRepGraph_NodeId theNode) noexcept; + + //! Bind this entry to the current SubtreeGen of a node. + //! @return false when the cache is detached or the node is inactive + [[nodiscard]] Standard_EXPORT bool BindSubtreeGen(const BRepGraph_Cache& theCache, + const BRepGraph_NodeId theNode) noexcept; + + //! Validate against the current OwnGen of the same node. + [[nodiscard]] Standard_EXPORT bool IsFreshOwn(const BRepGraph_Cache& theCache, + const BRepGraph_NodeId theNode) const noexcept; + + //! Validate against the current SubtreeGen of the same node. + [[nodiscard]] Standard_EXPORT bool IsFreshSubtree( + const BRepGraph_Cache& theCache, + const BRepGraph_NodeId theNode) const noexcept; + + //! Validate against the generation kind captured at bind time. + [[nodiscard]] Standard_EXPORT bool IsFresh(const BRepGraph_Cache& theCache) const noexcept; + + //! True if the entry was successfully bound to a node generation. + [[nodiscard]] bool IsBound() const noexcept { return myKind != GenKind::None; } + + //! Node identity captured at bind time. + [[nodiscard]] BRepGraph_NodeId Node() const noexcept { return myNode; } + + private: + enum class GenKind : uint8_t + { + None, + Own, + Subtree + }; + + [[nodiscard]] Standard_EXPORT bool bind(const BRepGraph_Cache& theCache, + const BRepGraph_NodeId theNode, + const GenKind theKind) noexcept; + + [[nodiscard]] Standard_EXPORT bool isFresh(const BRepGraph_Cache& theCache, + const BRepGraph_NodeId theNode, + const GenKind theKind) const noexcept; + + BRepGraph_NodeId myNode; + uint32_t myGeneration = 0; + GenKind myKind = GenKind::None; + }; + + //! @brief Value base for reference-derived cache entries. + class RefEntry + { + public: + //! Reset to an unbound stale state. + Standard_EXPORT void Reset() noexcept; + + //! Bind this entry to the current OwnGen of a reference. + //! @return false when the cache is detached or the reference is inactive + [[nodiscard]] Standard_EXPORT bool BindOwnGen(const BRepGraph_Cache& theCache, + const BRepGraph_RefId theRef) noexcept; + + //! Validate against the current OwnGen of the same reference. + [[nodiscard]] Standard_EXPORT bool IsFreshOwn(const BRepGraph_Cache& theCache, + const BRepGraph_RefId theRef) const noexcept; + + //! Validate against the reference captured at bind time. + [[nodiscard]] Standard_EXPORT bool IsFresh(const BRepGraph_Cache& theCache) const noexcept; + + //! True if the entry was successfully bound to a reference generation. + [[nodiscard]] bool IsBound() const noexcept { return myIsBound; } + + //! Reference identity captured at bind time. + [[nodiscard]] BRepGraph_RefId Ref() const noexcept { return myRef; } + + private: + BRepGraph_RefId myRef; + uint32_t myGeneration = 0; + bool myIsBound = false; + }; + + //! @brief Value base for item-derived cache entries. + class ItemEntry + { + public: + //! Reset to an unbound stale state. + Standard_EXPORT void Reset() noexcept; + + //! Bind this entry to the current OwnGen of a graph item. + //! @return false when the cache is detached or the item is inactive + [[nodiscard]] Standard_EXPORT bool BindOwnGen(const BRepGraph_Cache& theCache, + const BRepGraph_ItemId theItem) noexcept; + + //! Validate against the current OwnGen of the same item. + [[nodiscard]] Standard_EXPORT bool IsFreshOwn(const BRepGraph_Cache& theCache, + const BRepGraph_ItemId theItem) const noexcept; + + //! Validate against the item captured at bind time. + [[nodiscard]] Standard_EXPORT bool IsFresh(const BRepGraph_Cache& theCache) const noexcept; + + //! True if the entry was successfully bound to an item generation. + [[nodiscard]] bool IsBound() const noexcept { return myIsBound; } + + //! Item identity captured at bind time. + [[nodiscard]] BRepGraph_ItemId Item() const noexcept { return myItem; } + + private: + BRepGraph_ItemId myItem; + uint32_t myGeneration = 0; + bool myIsBound = false; + }; + + Standard_EXPORT BRepGraph_Cache(); + + //! True while this cache is registered in a live graph registry. + [[nodiscard]] bool IsAttached() const noexcept { return myGraph != nullptr; } + + //! Attached graph for read-only cache services. Raises Standard_ProgramError if detached. + [[nodiscard]] Standard_EXPORT const BRepGraph& Graph() const; + + //! Attached mutable graph for graph-owned cache services. Returns null if detached. + [[nodiscard]] BRepGraph* AttachedGraph() const noexcept { return myGraph; } + + //! Called after the cache is attached to a graph registry. + Standard_EXPORT virtual void OnAttached() noexcept; + + //! Called before the cache is detached from a graph registry. + Standard_EXPORT virtual void OnDetached() noexcept; + + //! Return current SubtreeGen for an active node. + [[nodiscard]] Standard_EXPORT bool NodeSubtreeGen(const BRepGraph_NodeId theNode, + uint32_t& theGen) const noexcept; + + //! Return current OwnGen for an active node. + [[nodiscard]] Standard_EXPORT bool NodeOwnGen(const BRepGraph_NodeId theNode, + uint32_t& theGen) const noexcept; + + //! Return current OwnGen for an active reference. + [[nodiscard]] Standard_EXPORT bool RefOwnGen(const BRepGraph_RefId theRef, + uint32_t& theGen) const noexcept; + + //! Return current OwnGen for an active graph item. + [[nodiscard]] Standard_EXPORT bool ItemOwnGen(const BRepGraph_ItemId theItem, + uint32_t& theGen) const noexcept; + + //! Resolve an active reference to its active child node. + [[nodiscard]] Standard_EXPORT bool ResolveActiveRefChild( + const BRepGraph_RefId theRef, + BRepGraph_NodeId& theNode) const noexcept; + + //! Resolve an active face reference to its active face node. + [[nodiscard]] Standard_EXPORT bool ResolveActiveFaceRef(const BRepGraph_FaceRefId theRef, + BRepGraph_FaceId& theFace) const noexcept; + +private: + friend class ::BRepGraph_CacheRegistry; + + Standard_EXPORT void attachGraph(BRepGraph* theGraph) noexcept; + Standard_EXPORT void rebindGraph(BRepGraph* theGraph) noexcept; + Standard_EXPORT void detachGraph() noexcept; + + BRepGraph* myGraph = nullptr; +}; + +#endif // _BRepGraph_Cache_HeaderFile diff --git a/opencascade/BRepGraph_CacheDerivedState.hxx b/opencascade/BRepGraph_CacheDerivedState.hxx new file mode 100644 index 000000000..10af419d7 --- /dev/null +++ b/opencascade/BRepGraph_CacheDerivedState.hxx @@ -0,0 +1,353 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_CacheDerivedState_HeaderFile +#define _BRepGraph_CacheDerivedState_HeaderFile + +#include +#include +#include +#include +#include + +#include +#include + +class BRepGraphInc_Storage; + +//! @brief Cache for derived edge, wire, and shell properties. +//! +//! Each query is independent and caches only its own result. +//! Callers request specific values (IsDegenerated, SameParameter, etc.) +//! and the cache computes + stores only what is needed. +class BRepGraph_CacheDerivedState : public BRepGraph_Cache +{ +public: + //! Returns the unique cache service GUID. + [[nodiscard]] Standard_EXPORT static const Standard_GUID& GetID(); + + //! Returns the unique cache service GUID. + [[nodiscard]] Standard_EXPORT const Standard_GUID& ID() const override; + + //! Returns the cache service display name. + [[nodiscard]] Standard_EXPORT const TCollection_AsciiString& Name() const override; + + //! Clears all cached entries. + Standard_EXPORT void Clear() noexcept override; + + //! Copy fresh, remappable derived-state entries into the target graph. + Standard_EXPORT void CopyFreshTo(const BRepGraph_CopyRemap& theCopy) const override; + + //! @brief Test if an edge is degenerate (no 3D curve and vertex collapse). + //! Computes and caches only Status - does NOT compute SameParameter/SameRange. + //! @param[in] theEdge edge definition identifier + //! @return true if the edge is degenerate + [[nodiscard]] Standard_EXPORT bool IsDegenerated(BRepGraph_EdgeId theEdge); + + //! @brief Test if a single coedge has SameParameter. + //! @param[in] theCoEdge coedge definition identifier + //! @return true if the coedge has SameParameter + [[nodiscard]] Standard_EXPORT bool SameParameter(BRepGraph_CoEdgeId theCoEdge); + + //! @brief Test if a single coedge has SameRange. + //! @param[in] theCoEdge coedge definition identifier + //! @return true if the coedge has SameRange + [[nodiscard]] Standard_EXPORT bool SameRange(BRepGraph_CoEdgeId theCoEdge); + + //! @brief Test if an edge is closed (start vertex == end vertex). + //! Computes and caches only IsClosed. + //! @param[in] theEdge edge definition identifier + //! @return true if the edge is closed + [[nodiscard]] Standard_EXPORT bool IsClosed(BRepGraph_EdgeId theEdge); + + //! @brief Return wire closure, computing and storing a fresh entry. + //! @param[in] theWire wire definition identifier + //! @param[out] theClosed filled with the fresh derived value + //! @return true if computation succeeded + [[nodiscard]] Standard_EXPORT bool GetWireIsClosed(BRepGraph_WireId theWire, bool& theClosed); + + //! @brief Store a pre-computed wire closure value. + //! @param[in] theWire wire definition identifier + //! @param[in] theClosed pre-computed closure value + Standard_EXPORT void SetWireIsClosed(BRepGraph_WireId theWire, bool theClosed); + + //! @brief Test if a shell is closed. + //! @param[in] theShell shell definition identifier + //! @return true if the shell is closed + [[nodiscard]] Standard_EXPORT bool IsShellClosed(BRepGraph_ShellId theShell); + + //! Compute edge-own derived state (Status, IsClosed). + //! SameRange/SameParameter are per-CoEdge - use the per-CoEdge cache directly. + //! @param[in] theGraph source graph + //! @param[in] theEdge edge definition identifier + //! @param[out] theIsDegenerated true if edge is degenerate + //! @param[out] theIsClosed true if edge is closed + //! @return true if computation succeeded + [[nodiscard]] Standard_EXPORT static bool ComputeEdgeProperties(const BRepGraph& theGraph, + BRepGraph_EdgeId theEdge, + bool& theIsDegenerated, + bool& theIsClosed); + + //! Compute shell closure directly from a BRepGraph without caching. + //! @param[in] theGraph source graph + //! @param[in] theShell shell definition identifier + //! @return true if the shell is closed + [[nodiscard]] Standard_EXPORT static bool ComputeShellIsClosed(const BRepGraph& theGraph, + BRepGraph_ShellId theShell); + + //! Compute wire closure directly from a BRepGraph without caching. + //! @param[in] theGraph source graph + //! @param[in] theWire wire definition identifier + //! @return true if the wire is closed + [[nodiscard]] Standard_EXPORT static bool ComputeWireIsClosed(const BRepGraph& theGraph, + BRepGraph_WireId theWire); + + DEFINE_STANDARD_RTTIEXT(BRepGraph_CacheDerivedState, BRepGraph_Cache) + +private: + //! Edge-own derived state: Status (HasCurve3D/Degenerate/Missing), IsClosed. + //! Depends only on Edge OwnGen (vertices, 3D curve). + //! Packed into a single atomic byte for lock-free reads. + struct EdgeEntry : public NodeEntry + { + enum class GeomStatus : uint8_t + { + HasCurve3D, + DegenerateOnSurface, + MissingCurve3D, + Invalid + }; + + enum Flags : uint8_t + { + FlagNone = 0, + StatusMask = 0x07, + FlagClosed = 1 << 3, + FlagComputed = 1 << 4, + }; + + std::atomic Packed{FlagNone}; + + EdgeEntry() = default; + + EdgeEntry(const EdgeEntry& theOther) + : NodeEntry(theOther), + Packed(theOther.Packed.load(std::memory_order_relaxed)) + { + } + + EdgeEntry& operator=(const EdgeEntry& theOther) + { + NodeEntry::operator=(theOther); + Packed.store(theOther.Packed.load(std::memory_order_relaxed), std::memory_order_relaxed); + return *this; + } + + [[nodiscard]] GeomStatus GetStatus() const + { + return static_cast(Packed.load(std::memory_order_acquire) & StatusMask); + } + + [[nodiscard]] bool IsClosed() const + { + return (Packed.load(std::memory_order_acquire) & FlagClosed) != 0; + } + + [[nodiscard]] bool IsComputed() const + { + return (Packed.load(std::memory_order_acquire) & FlagComputed) != 0; + } + + void Set(GeomStatus theStatus, bool theClosed) + { + uint8_t aFlags = FlagComputed | static_cast(theStatus); + if (theClosed) + { + aFlags |= FlagClosed; + } + Packed.store(aFlags, std::memory_order_release); + } + }; + + //! Per-CoEdge entry for SameRange/SameParameter. + //! Bound to CoEdge OwnGen - invalidates automatically when PCurve changes. + //! Packed into a single atomic byte for lock-free reads. + struct CoEdgeSameRangeEntry : public NodeEntry + { + enum Flags : uint8_t + { + FlagNone = 0, + ComputedSameRange = 1 << 0, + ComputedSameParam = 1 << 1, + FlagSameRange = 1 << 2, + FlagSameParameter = 1 << 3, + }; + + std::atomic Packed{FlagNone}; + + CoEdgeSameRangeEntry() = default; + + CoEdgeSameRangeEntry(const CoEdgeSameRangeEntry& theOther) + : NodeEntry(theOther), + Packed(theOther.Packed.load(std::memory_order_relaxed)) + { + } + + CoEdgeSameRangeEntry& operator=(const CoEdgeSameRangeEntry& theOther) + { + NodeEntry::operator=(theOther); + Packed.store(theOther.Packed.load(std::memory_order_relaxed), std::memory_order_relaxed); + return *this; + } + + [[nodiscard]] bool SameRange() const + { + return (Packed.load(std::memory_order_acquire) & FlagSameRange) != 0; + } + + [[nodiscard]] bool SameParameter() const + { + return (Packed.load(std::memory_order_acquire) & FlagSameParameter) != 0; + } + + [[nodiscard]] uint8_t Computed() const { return Packed.load(std::memory_order_acquire); } + + void SetSameRange(bool theVal) + { + uint8_t aFlags = ComputedSameRange; + if (theVal) + { + aFlags |= FlagSameRange; + } + Packed.fetch_or(aFlags, std::memory_order_release); + } + + void SetSameParameter(bool theVal) + { + uint8_t aFlags = ComputedSameParam; + if (theVal) + { + aFlags |= FlagSameParameter; + } + Packed.fetch_or(aFlags, std::memory_order_release); + } + }; + + struct WireEntry : public NodeEntry + { + enum Flags : uint8_t + { + FlagNone = 0, + FlagClosed = 1 << 0, + FlagComputed = 1 << 1, + }; + + std::atomic Packed{FlagNone}; + + WireEntry() = default; + + WireEntry(const WireEntry& theOther) + : NodeEntry(theOther), + Packed(theOther.Packed.load(std::memory_order_relaxed)) + { + } + + WireEntry& operator=(const WireEntry& theOther) + { + NodeEntry::operator=(theOther); + Packed.store(theOther.Packed.load(std::memory_order_relaxed), std::memory_order_relaxed); + return *this; + } + + [[nodiscard]] bool IsClosed() const + { + return (Packed.load(std::memory_order_acquire) & FlagClosed) != 0; + } + + [[nodiscard]] bool IsComputed() const + { + return (Packed.load(std::memory_order_acquire) & FlagComputed) != 0; + } + + void SetClosed(bool theVal) + { + uint8_t aFlags = FlagComputed; + if (theVal) + { + aFlags |= FlagClosed; + } + Packed.store(aFlags, std::memory_order_release); + } + }; + + struct ShellEntry : public NodeEntry + { + enum class ClosureStatus : uint8_t + { + Empty, + Open, + Closed, + NonManifold, + Invalid + }; + + std::atomic Status{ClosureStatus::Invalid}; + + ShellEntry() = default; + + ShellEntry(const ShellEntry& theOther) + : NodeEntry(theOther), + Status(theOther.Status.load(std::memory_order_relaxed)) + { + } + + ShellEntry& operator=(const ShellEntry& theOther) + { + NodeEntry::operator=(theOther); + Status.store(theOther.Status.load(std::memory_order_relaxed), std::memory_order_relaxed); + return *this; + } + }; + + //! Ensure edge-own entry (Status, IsClosed) is fresh. Uses OwnGen only. + bool ensureEdgeEntry(BRepGraph_EdgeId theEdge, EdgeEntry& theEntry); + + //! Ensure per-CoEdge entry is fresh. Bound to CoEdge OwnGen. + bool ensureCoEdgeSameRangeEntry(BRepGraph_CoEdgeId theCoEdge, + uint8_t theRequiredFlags, + CoEdgeSameRangeEntry& theEntry); + + static void computeStatusOnly(const BRepGraph& theGraph, + BRepGraph_EdgeId theEdge, + EdgeEntry& theEntry); + + static void computeSameRange(const BRepGraph& theGraph, + BRepGraph_CoEdgeId theCoEdge, + CoEdgeSameRangeEntry& theEntry); + + static void computeSameParameter(const BRepGraph& theGraph, + BRepGraph_CoEdgeId theCoEdge, + CoEdgeSameRangeEntry& theEntry); + + static ShellEntry::ClosureStatus computeShellClosure(const BRepGraph& theGraph, + BRepGraph_ShellId theShell); + + mutable std::mutex myMutex; + + NCollection_DynamicArray myEdgeEntries; + NCollection_DynamicArray myCoEdgeSameRangeEntries; + NCollection_DynamicArray myWireEntries; + NCollection_DynamicArray myShellEntries; +}; + +#endif // _BRepGraph_CacheDerivedState_HeaderFile diff --git a/opencascade/BRepGraph_CacheIterator.hxx b/opencascade/BRepGraph_CacheIterator.hxx new file mode 100644 index 000000000..818c14932 --- /dev/null +++ b/opencascade/BRepGraph_CacheIterator.hxx @@ -0,0 +1,63 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_CacheIterator_HeaderFile +#define _BRepGraph_CacheIterator_HeaderFile + +#include +#include + +//! @brief Iterator over registered cache families in a BRepGraph_CacheRegistry. +//! +//! Supports OCCT More()/Next()/Value() pattern and STL range-for via begin()/end(). +class BRepGraph_CacheIterator +{ +public: + //! Construct an iterator over all cache families in the registry. + explicit BRepGraph_CacheIterator(const BRepGraph_CacheRegistry& theRegistry) + : myRegistry(&theRegistry), + myCount(theRegistry.NbCaches()) + { + } + + //! True if the iterator has a current element. + [[nodiscard]] bool More() const { return myCurrent < myCount; } + + //! Advance to the next cache family. + void Next() { ++myCurrent; } + + //! Return the current cache family descriptor. + [[nodiscard]] occ::handle Value() const { return myRegistry->Cache(myCurrent); } + + //! Return the current slot index in the registry. + [[nodiscard]] uint32_t Slot() const { return myCurrent; } + + //! Number of cache families in the registry. + [[nodiscard]] uint32_t NbCaches() const { return myRegistry->NbCaches(); } + + //! STL range-for support. + NCollection_ForwardRangeIterator begin() + { + return NCollection_ForwardRangeIterator(this); + } + + //! Sentinel marking end of iteration. + NCollection_ForwardRangeSentinel end() const { return NCollection_ForwardRangeSentinel{}; } + +private: + const BRepGraph_CacheRegistry* myRegistry; + uint32_t myCount; + uint32_t myCurrent = 0; +}; + +#endif // _BRepGraph_CacheIterator_HeaderFile diff --git a/opencascade/BRepGraph_CacheKindIterator.hxx b/opencascade/BRepGraph_CacheKindIterator.hxx deleted file mode 100644 index 10caa2f31..000000000 --- a/opencascade/BRepGraph_CacheKindIterator.hxx +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraph_CacheKindIterator_HeaderFile -#define _BRepGraph_CacheKindIterator_HeaderFile - -#include -#include - -//! @brief Zero-allocation iterator over populated cache kinds on a node or reference. -//! -//! Template parameter TKeyId is either BRepGraph_NodeId or BRepGraph_RefId. -//! Supports OCCT More()/Next()/Value() pattern and STL range-for via begin()/end(). -//! -//! Constructed by BRepGraph::CacheView::CacheKindIter(). Stores populated -//! kind slot indices in a fixed-size stack buffer (no heap allocation). -//! -//! @code -//! // Range-for: -//! for (const occ::handle& aKind : aGraph.Cache().CacheKindIter(aNode)) -//! doSomething(aKind); -//! -//! // Traditional: -//! for (auto anIt = aGraph.Cache().CacheKindIter(aNode); anIt.More(); anIt.Next()) -//! doSomething(anIt.Value()); -//! @endcode -template -class BRepGraph_CacheKindIterator -{ -public: - //! True if the iterator has a current element. - [[nodiscard]] bool More() const { return myCurrent < myCount; } - - //! Advance to the next populated cache kind. - void Next() { ++myCurrent; } - - //! Return the current cache kind descriptor. - [[nodiscard]] occ::handle Value() const - { - return BRepGraph_CacheKindRegistry::FindKind(mySlots[myCurrent]); - } - - //! Return the current cache-kind slot index (for fast slot-based access). - [[nodiscard]] int KindSlot() const { return mySlots[myCurrent]; } - - //! Number of populated cache kinds found. - [[nodiscard]] int NbKinds() const { return myCount; } - - //! STL range-for support. - NCollection_ForwardRangeIterator begin() - { - return NCollection_ForwardRangeIterator(this); - } - - //! Sentinel marking end of iteration. - NCollection_ForwardRangeSentinel end() const { return NCollection_ForwardRangeSentinel{}; } - -private: - friend class BRepGraph::CacheView; - static constexpr int THE_MAX_SLOTS = BRepGraph_TransientCache::THE_DEFAULT_RESERVED_KIND_COUNT; - int mySlots[THE_MAX_SLOTS]; - int myCount = 0; - int myCurrent = 0; -}; - -#endif // _BRepGraph_CacheKindIterator_HeaderFile diff --git a/opencascade/BRepGraph_CacheMesh.hxx b/opencascade/BRepGraph_CacheMesh.hxx new file mode 100644 index 000000000..eaa4dac17 --- /dev/null +++ b/opencascade/BRepGraph_CacheMesh.hxx @@ -0,0 +1,354 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_CacheMesh_HeaderFile +#define _BRepGraph_CacheMesh_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class BRepGraph; + +//! @brief Registry-owned runtime mesh cache for BRepGraph. +//! +//! CacheMesh stores transient triangulations and polygons produced by meshing drivers. +//! It is not copied, transformed, or serialized. Persistent mesh representations remain +//! in topology definitions and are filled only by import, authored primitive creation, +//! or explicit promotion. +class BRepGraph_CacheMesh : public BRepGraph_Cache +{ +public: + using SlotId = uint32_t; + + static constexpr SlotId DefaultDisplaySlot = 0; + + //! Entry stamp against the slot recipe and cache-local generation. + struct EntryStamp + { + uint64_t RecipeHash = 0; + uint32_t SlotGeneration = 0; + + void Reset() noexcept + { + RecipeHash = 0; + SlotGeneration = 0; + } + }; + + //! Cached mesh entry for a face: single triangulation. + struct FaceMeshEntry : public NodeEntry + { + occ::handle Triangulation; + EntryStamp Stamp; + uint32_t MeshGeneration = 0; + + [[nodiscard]] bool IsPresent() const { return !Triangulation.IsNull(); } + + //! Clear triangulation representation. Does NOT bump MeshGeneration - + //! callers must call BRepGraph_CacheMesh::BumpFaceMeshGeneration() separately. + void ClearRepresentation() noexcept { Triangulation.Nullify(); } + + void Reset() noexcept + { + NodeEntry::Reset(); + Triangulation.Nullify(); + Stamp.Reset(); + MeshGeneration = 0; + } + }; + + //! Cached mesh entry for a coedge: polygon-in-parametric-space and polygon-on-triangulation. + //! + //! CoEdgeMeshEntry composes two NodeEntry fields instead of inheriting from one. + //! This breaks the inheritance pattern used by other entries because the coedge + //! has two independent freshness dimensions: coedge topology and face mesh content. + struct CoEdgeMeshEntry + { + //! Coedge topology freshness (for Polygon2D). + NodeEntry CoEdgeStamp; + + //! Face topology freshness (for PolygonsOnTri). + NodeEntry FaceTopologyStamp; + + //! Face mesh content freshness (for PolygonsOnTri). + uint32_t FaceMeshGeneration = 0; + //! Face whose MeshGeneration we track. + BRepGraph_FaceId BoundFaceId; + + //! Slot recipe freshness. + EntryStamp SlotStamp; + + //! Cached polygon-on-surface. + occ::handle Polygon2D; + //! Cached polygons-on-triangulation. + NCollection_LinearVector> PolygonsOnTri; + + [[nodiscard]] bool IsPresent() const { return !Polygon2D.IsNull() || !PolygonsOnTri.IsEmpty(); } + + void Reset() noexcept + { + CoEdgeStamp.Reset(); + FaceTopologyStamp.Reset(); + FaceMeshGeneration = 0; + BoundFaceId = BRepGraph_FaceId(); + SlotStamp.Reset(); + Polygon2D.Nullify(); + PolygonsOnTri.Clear(); + } + }; + + //! Cached mesh entry for an edge: polygon-3D. + struct EdgeMeshEntry : public NodeEntry + { + occ::handle Polygon3D; + EntryStamp Stamp; + + [[nodiscard]] bool IsPresent() const { return !Polygon3D.IsNull(); } + + void Reset() noexcept + { + NodeEntry::Reset(); + Polygon3D.Nullify(); + Stamp.Reset(); + } + }; + + //! Dirty topology set requested from a cache driver. + struct DirtySet + { + NCollection_LinearVector Faces; + NCollection_LinearVector FreeEdges; + + [[nodiscard]] bool IsEmpty() const { return Faces.IsEmpty() && FreeEdges.IsEmpty(); } + + void Clear() + { + Faces.Clear(); + FreeEdges.Clear(); + } + }; + + //! Runtime state of a cache slot. + struct SlotState + { + SlotId Slot = DefaultDisplaySlot; + uint64_t RecipeHash = 0; + uint32_t Generation = 1; + bool HasDriver = false; + }; + + //! Mesh recomputation driver registered by a meshing toolkit. + class Driver : public Standard_Transient + { + public: + [[nodiscard]] virtual const Standard_GUID& ID() const = 0; + [[nodiscard]] virtual uint64_t RecipeHash() const = 0; + + [[nodiscard]] virtual bool Fill(BRepGraph& theGraph, + SlotId theSlot, + const DirtySet& theDirtySet, + const Message_ProgressRange& theRange) = 0; + + DEFINE_STANDARD_RTTIEXT(Driver, Standard_Transient) + }; + + Standard_EXPORT BRepGraph_CacheMesh(); + + BRepGraph_CacheMesh(const BRepGraph_CacheMesh&) = delete; + BRepGraph_CacheMesh& operator=(const BRepGraph_CacheMesh&) = delete; + + //! Returns the unique cache service GUID. + [[nodiscard]] static Standard_EXPORT const Standard_GUID& GetID(); + + //! Returns the unique cache service GUID. + [[nodiscard]] Standard_EXPORT const Standard_GUID& ID() const override; + + //! Returns the cache service display name. + [[nodiscard]] Standard_EXPORT const TCollection_AsciiString& Name() const override; + + //! Clears all cache slots and registered drivers. + Standard_EXPORT void Clear() noexcept override; + + //! Copy fresh, remappable mesh cache entries into the target graph. + Standard_EXPORT void CopyFreshTo(const BRepGraph_CopyRemap& theCopy) const override; + + //! Get/set the currently active display slot. + //! EffectiveView reads from this slot. + [[nodiscard]] SlotId ActiveDisplaySlot() const { return myActiveSlot; } + + void SetActiveDisplaySlot(SlotId theSlot) { myActiveSlot = theSlot; } + + //! Register or replace a meshing driver for a cache slot. + Standard_EXPORT void RegisterDriver(SlotId theSlot, const occ::handle& theDriver); + + //! Remove a meshing driver from a cache slot and invalidate the slot. + Standard_EXPORT void UnregisterDriver(SlotId theSlot); + + //! Return driver registered for a slot, or null. + [[nodiscard]] Standard_EXPORT const occ::handle& DriverOf(SlotId theSlot) const; + + //! Return current state of a cache slot. + [[nodiscard]] Standard_EXPORT SlotState State(SlotId theSlot = DefaultDisplaySlot) const; + + //! Recompute stale data in a slot using its registered driver. + [[nodiscard]] Standard_EXPORT bool Ensure( + BRepGraph& theGraph, + SlotId theSlot = DefaultDisplaySlot, + const Message_ProgressRange& theRange = Message_ProgressRange()); + + //! Recompute stale data below a topology node using the slot driver. + [[nodiscard]] Standard_EXPORT bool Ensure( + BRepGraph& theGraph, + const BRepGraph_NodeId theRoot, + SlotId theSlot = DefaultDisplaySlot, + const Message_ProgressRange& theRange = Message_ProgressRange()); + + //! Recompute stale data for requested topology nodes using the slot driver. + [[nodiscard]] Standard_EXPORT bool Ensure( + BRepGraph& theGraph, + const NCollection_Array1& theNodes, + SlotId theSlot = DefaultDisplaySlot, + const Message_ProgressRange& theRange = Message_ProgressRange()); + + //! Return true when a cache slot has stale or missing mesh below the topology node. + //! Uses the same actualness rules as Ensure() but does not invoke the driver. + [[nodiscard]] Standard_EXPORT bool Needs(BRepGraph& theGraph, + BRepGraph_NodeId theRoot, + SlotId theSlot = DefaultDisplaySlot) const; + + [[nodiscard]] Standard_EXPORT bool HasFaceMesh(BRepGraph_FaceId theFace) const; + [[nodiscard]] Standard_EXPORT const FaceMeshEntry* FindFaceMesh(BRepGraph_FaceId theFace) const; + [[nodiscard]] Standard_EXPORT FaceMeshEntry& ChangeFaceMesh(BRepGraph_FaceId theFace); + Standard_EXPORT void ClearFaceMesh(BRepGraph_FaceId theFace); + + [[nodiscard]] Standard_EXPORT bool HasCoEdgeMesh(BRepGraph_CoEdgeId theCoEdge) const; + [[nodiscard]] Standard_EXPORT CoEdgeMeshEntry& ChangeCoEdgeMesh(BRepGraph_CoEdgeId theCoEdge); + Standard_EXPORT void ClearCoEdgeMesh(BRepGraph_CoEdgeId theCoEdge); + + [[nodiscard]] Standard_EXPORT bool HasEdgeMesh(BRepGraph_EdgeId theEdge) const; + [[nodiscard]] Standard_EXPORT const EdgeMeshEntry* FindEdgeMesh(BRepGraph_EdgeId theEdge) const; + [[nodiscard]] Standard_EXPORT EdgeMeshEntry& ChangeEdgeMesh(BRepGraph_EdgeId theEdge); + Standard_EXPORT void ClearEdgeMesh(BRepGraph_EdgeId theEdge); + + [[nodiscard]] Standard_EXPORT bool HasFaceMesh(SlotId theSlot, BRepGraph_FaceId theFace) const; + [[nodiscard]] Standard_EXPORT const FaceMeshEntry* FindFaceMesh(SlotId theSlot, + BRepGraph_FaceId theFace) const; + [[nodiscard]] Standard_EXPORT FaceMeshEntry& ChangeFaceMesh(SlotId theSlot, + BRepGraph_FaceId theFace); + Standard_EXPORT void ClearFaceMesh(SlotId theSlot, BRepGraph_FaceId theFace); + + [[nodiscard]] Standard_EXPORT bool HasCoEdgeMesh(SlotId theSlot, + BRepGraph_CoEdgeId theCoEdge) const; + [[nodiscard]] Standard_EXPORT CoEdgeMeshEntry& ChangeCoEdgeMesh(SlotId theSlot, + BRepGraph_CoEdgeId theCoEdge); + Standard_EXPORT void ClearCoEdgeMesh(SlotId theSlot, BRepGraph_CoEdgeId theCoEdge); + + [[nodiscard]] Standard_EXPORT bool HasEdgeMesh(SlotId theSlot, BRepGraph_EdgeId theEdge) const; + [[nodiscard]] Standard_EXPORT const EdgeMeshEntry* FindEdgeMesh(SlotId theSlot, + BRepGraph_EdgeId theEdge) const; + [[nodiscard]] Standard_EXPORT EdgeMeshEntry& ChangeEdgeMesh(SlotId theSlot, + BRepGraph_EdgeId theEdge); + Standard_EXPORT void ClearEdgeMesh(SlotId theSlot, BRepGraph_EdgeId theEdge); + + //! Stamp a freshly written default-slot entry. + Standard_EXPORT void BindFresh(FaceMeshEntry& theEntry, BRepGraph_FaceId theFace) const; + Standard_EXPORT void BindFresh(CoEdgeMeshEntry& theEntry, BRepGraph_CoEdgeId theCoEdge) const; + Standard_EXPORT void BindFresh(EdgeMeshEntry& theEntry, BRepGraph_EdgeId theEdge) const; + + //! Bump face mesh generation after cached content changed. + //! This is the ONLY mutator for MeshGeneration. ClearRepresentation() does not bump. + //! Creates the face entry if it doesn't exist yet (via ensureSize). + Standard_EXPORT void BumpFaceMeshGeneration(BRepGraph_FaceId theFace, + SlotId theSlot = DefaultDisplaySlot); + + //! Raw face entry access (no freshness filtering). For internal use. + [[nodiscard]] Standard_EXPORT const FaceMeshEntry* findFaceEntryRaw( + SlotId theSlot, + BRepGraph_FaceId theFace) const; + + //! Raw coedge entry access (no freshness/generation filtering). + //! Returns nullptr if the slot is absent or the entry has no representation. + //! For internal use. + [[nodiscard]] Standard_EXPORT const CoEdgeMeshEntry* findCoEdgeEntryRaw( + SlotId theSlot, + BRepGraph_CoEdgeId theCoEdge) const; + + //! Return coedge entry if Polygon2D is fresh, nullptr otherwise. + [[nodiscard]] Standard_EXPORT const CoEdgeMeshEntry* FindCoEdgePolygon2D( + SlotId theSlot, + BRepGraph_CoEdgeId theCoEdge) const; + + //! Return coedge entry if PolygonsOnTri is fresh, nullptr otherwise. + [[nodiscard]] Standard_EXPORT const CoEdgeMeshEntry* FindCoEdgePolygonOnTri( + SlotId theSlot, + BRepGraph_CoEdgeId theCoEdge) const; + + //! Return coedge entry if Polygon2D is fresh (default slot), nullptr otherwise. + [[nodiscard]] Standard_EXPORT const CoEdgeMeshEntry* FindCoEdgePolygon2D( + BRepGraph_CoEdgeId theCoEdge) const; + + //! Return coedge entry if PolygonsOnTri is fresh (default slot), nullptr otherwise. + [[nodiscard]] Standard_EXPORT const CoEdgeMeshEntry* FindCoEdgePolygonOnTri( + BRepGraph_CoEdgeId theCoEdge) const; + + DEFINE_STANDARD_RTTIEXT(BRepGraph_CacheMesh, BRepGraph_Cache) + +private: + struct Slot; + + template + static void ensureSize(NCollection_DynamicArray& theVec, size_t theIndex); + + [[nodiscard]] Slot& changeSlot(SlotId theSlot); + [[nodiscard]] const Slot* findSlot(SlotId theSlot) const; + + [[nodiscard]] bool isSlotActual(const Slot& theSlot, const EntryStamp& theStamp) const noexcept; + void bindEntry(FaceMeshEntry& theEntry, BRepGraph_FaceId theFace, const Slot& theSlot) const; + void bindEntry(CoEdgeMeshEntry& theEntry, + BRepGraph_CoEdgeId theCoEdge, + const Slot& theSlot) const; + void bindEntry(EdgeMeshEntry& theEntry, BRepGraph_EdgeId theEdge, const Slot& theSlot) const; + + [[nodiscard]] bool isCoEdgePolygon2DFresh(const CoEdgeMeshEntry& theEntry, + const Slot& theSlot) const noexcept; + [[nodiscard]] bool isCoEdgePolygonOnTriFresh(const CoEdgeMeshEntry& theEntry, + const Slot& theSlot) const noexcept; + [[nodiscard]] bool isFaceMeshFresh(const CoEdgeMeshEntry& theEntry, + const Slot& theSlot) const noexcept; + + [[nodiscard]] const CoEdgeMeshEntry* findCoEdgeMesh(SlotId theSlot, + BRepGraph_CoEdgeId theCoEdge) const; + + [[nodiscard]] DirtySet collectDirty(BRepGraph& theGraph, const Slot& theSlot) const; + [[nodiscard]] DirtySet collectDirty(BRepGraph& theGraph, + const BRepGraph_NodeId theRoot, + const Slot& theSlot) const; + [[nodiscard]] DirtySet collectDirty(BRepGraph& theGraph, + const NCollection_Array1& theNodes, + const Slot& theSlot) const; + + NCollection_LinearVector mySlots; + SlotId myActiveSlot = DefaultDisplaySlot; +}; + +#endif // _BRepGraph_CacheMesh_HeaderFile diff --git a/opencascade/BRepGraph_CacheRegistry.hxx b/opencascade/BRepGraph_CacheRegistry.hxx new file mode 100644 index 000000000..cae43aed8 --- /dev/null +++ b/opencascade/BRepGraph_CacheRegistry.hxx @@ -0,0 +1,174 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_CacheRegistry_HeaderFile +#define _BRepGraph_CacheRegistry_HeaderFile + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +class BRepGraph; +struct BRepGraph_Data; +class BRepGraph_CacheIterator; + +//! @brief GUID-keyed runtime registry of graph cache services. +//! +//! Stores registered cache services in a stable slot array for O(1) slot access +//! and a GUID-to-slot map for lookup by stable public identity. Cache services +//! own their typed transient data; this registry only manages identity and +//! owner binding. +class BRepGraph_CacheRegistry +{ +public: + DEFINE_STANDARD_ALLOC + + Standard_EXPORT BRepGraph_CacheRegistry(); + + BRepGraph_CacheRegistry(const BRepGraph_CacheRegistry&) = delete; + BRepGraph_CacheRegistry& operator=(const BRepGraph_CacheRegistry&) = delete; + + Standard_EXPORT BRepGraph_CacheRegistry(BRepGraph_CacheRegistry&& theOther) noexcept; + Standard_EXPORT BRepGraph_CacheRegistry& operator=(BRepGraph_CacheRegistry&& theOther) noexcept; + + //! Register a cache service. Replaces an existing cache with the same GUID. + //! @param[in] theCache cache service + //! @return graph-local slot index + Standard_EXPORT uint32_t RegisterCache(const occ::handle& theCache); + + //! Register a cache service. Short form used by graph-local cache operations. + //! @param[in] theCache cache service + //! @return graph-local slot index + Standard_EXPORT uint32_t Register(const occ::handle& theCache); + + //! Remove a cache service by GUID. + //! @param[in] theGUID cache identity + Standard_EXPORT void UnregisterCache(const Standard_GUID& theGUID); + + //! Find a cache service by GUID. + //! @param[in] theGUID cache identity + //! @return cache service, or null handle if not found + [[nodiscard]] Standard_EXPORT occ::handle FindCache( + const Standard_GUID& theGUID) const; + + //! Typed convenience lookup by cache GUID. + template + [[nodiscard]] occ::handle FindCache() const + { + return Find(); + } + + //! Typed lookup by cache GUID. + template + [[nodiscard]] occ::handle Find() const + { + return occ::down_cast(FindCache(T::GetID())); + } + + //! Return an existing cache service or create and register a default one. + //! Template convenience wrapper: extracts GUID and calls ensureCache. + template + [[nodiscard]] occ::handle Ensure() + { + return occ::down_cast( + ensureCache(T::GetID(), []() -> occ::handle { return new T(); })); + } + + //! Return current graph-local slot for a GUID. + //! @param[in] theGUID cache family identity + //! @param[out] theSlot graph-local slot index + //! @return true if the cache service is registered + [[nodiscard]] Standard_EXPORT bool FindSlot(const Standard_GUID& theGUID, + uint32_t& theSlot) const; + + //! Return current graph-local slot for a cache service. + //! @param[in] theCache cache service + //! @param[out] theSlot graph-local slot index + //! @return true if the cache service is registered + [[nodiscard]] Standard_EXPORT bool FindSlot(const occ::handle& theCache, + uint32_t& theSlot) const; + + //! Return cache service by graph-local slot, or null handle if the slot is out of range. + //! @param[in] theSlot graph-local cache slot + [[nodiscard]] Standard_EXPORT occ::handle Cache(uint32_t theSlot) const; + + //! Number of registered cache services. + [[nodiscard]] uint32_t NbCaches() const + { + std::shared_lock aLock(myMutex); + return static_cast(myCaches.Size()); + } + + //! Iterate registered cache services. + [[nodiscard]] Standard_EXPORT BRepGraph_CacheIterator CacheIter() const; + + //! Clear data in all registered cache services. + Standard_EXPORT void ClearAll() noexcept; + + //! Ask registered cache services to copy fresh, remappable data into the target graph. + Standard_EXPORT void CopyFreshCachesTo( + BRepGraph& theTargetGraph, + const NCollection_FlatDataMap& theItemRemap, + const BRepGraph_CopyRemap::Mode theMode) const; + + //! Ask registered cache services to copy fresh data using identity mapping. + Standard_EXPORT void CopyFreshCachesTo(BRepGraph& theTargetGraph, + BRepGraph_CopyRemap::MappingKind theMappingKind, + BRepGraph_CopyRemap::Mode theMode) const; + + //! Unregister all cache services. + Standard_EXPORT void Clear() noexcept; + +private: + friend class ::BRepGraph; + friend struct ::BRepGraph_Data; + + //! Attach this registry to graph owner. Propagates context to registered caches. + Standard_EXPORT void Attach(BRepGraph* theGraph) noexcept; + + //! Clear the graph data binding. + Standard_EXPORT void Detach() noexcept; + + [[nodiscard]] Standard_EXPORT occ::handle findCacheLocked( + const Standard_GUID& theGUID) const; + + //! Return an existing cache service or create and register a default one. + //! Uses double-checked locking: shared lock for fast path (cache exists), + //! exclusive lock only for creation (rare, first-call only). + [[nodiscard]] Standard_EXPORT occ::handle ensureCache( + const Standard_GUID& theGUID, + const std::function()>& theFactory); + + [[nodiscard]] Standard_EXPORT occ::handle cacheAt(uint32_t theSlot) const; + + Standard_EXPORT uint32_t registerCacheLocked(const occ::handle& theCache); + + Standard_EXPORT void detachAllLocked() noexcept; + + NCollection_LinearVector> myCaches; + NCollection_DataMap myGuidToSlot; + BRepGraph* myGraph = nullptr; + mutable std::shared_mutex myMutex; +}; + +#include + +#endif // _BRepGraph_CacheRegistry_HeaderFile diff --git a/opencascade/BRepGraph_CacheView.hxx b/opencascade/BRepGraph_CacheView.hxx deleted file mode 100644 index 995128212..000000000 --- a/opencascade/BRepGraph_CacheView.hxx +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraph_CacheView_HeaderFile -#define _BRepGraph_CacheView_HeaderFile - -#include -#include - -//! @brief Non-const view for managing transient cache values on nodes. -//! -//! This view is the stable public cache API for BRepGraph callers. -//! External code should use Cache() for all cache access. -//! Low-level storage operations such as reserve or cross-graph cache transfer -//! stay internal to graph-maintenance code through the graph's private cache access. -//! -//! Cached values are keyed by BRepGraph_CacheKind descriptors (Handle-based) -//! and stored as Handle(BRepGraph_CacheValue). Each CacheKind carries a -//! Standard_GUID for stable identity and is registered in -//! BRepGraph_CacheKindRegistry which maps GUIDs to dense runtime slot -//! indices for O(1) internal storage lookup. -//! -//! Supports set, get, remove, invalidate, and kind enumeration per node. -//! Cached data is stored centrally in BRepGraph_TransientCache with -//! generation-based freshness tracking via SubtreeGen. -//! Hot-path callers may pre-resolve a cache-kind slot once through -//! BRepGraph_CacheKindRegistry::Register() and then use slot-based overloads -//! to avoid repeated registry locking. -//! Obtained via BRepGraph::Cache(). -class BRepGraph::CacheView -{ -public: - //! Attach a cached value to a node. - //! @param[in] theNode node to attach the value to - //! @param[in] theKind cache kind descriptor identifying the slot - //! @param[in] theValue cached value to store - Standard_EXPORT void Set(const BRepGraph_NodeId theNode, - const occ::handle& theKind, - const occ::handle& theValue); - - //! Attach a cached value using a pre-resolved cache-kind slot. - Standard_EXPORT void Set(const BRepGraph_NodeId theNode, - const int theKindSlot, - const occ::handle& theValue); - - //! Retrieve a cached value from a node. - //! @param[in] theNode node to query - //! @param[in] theKind cache kind descriptor identifying the slot - //! @return cached value, or null handle if not present or stale - [[nodiscard]] Standard_EXPORT occ::handle Get( - const BRepGraph_NodeId theNode, - const occ::handle& theKind) const; - - //! Retrieve a cached value using a pre-resolved cache-kind slot. - [[nodiscard]] Standard_EXPORT occ::handle Get( - const BRepGraph_NodeId theNode, - const int theKindSlot) const; - - //! Check if a non-stale cached value exists on a node. - //! @param[in] theNode node to query - //! @param[in] theKind cache kind descriptor identifying the slot - //! @return true if a current value exists for this node and kind - [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_NodeId theNode, - const occ::handle& theKind) const; - - //! Check if a non-stale cached value exists using a pre-resolved slot. - [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_NodeId theNode, - const int theKindSlot) const; - - //! Remove a cached value from a node. - //! @param[in] theNode node to remove the value from - //! @param[in] theKind cache kind descriptor identifying the slot - //! @return true if a value was actually removed - Standard_EXPORT bool Remove(const BRepGraph_NodeId theNode, - const occ::handle& theKind); - - //! Remove a cached value using a pre-resolved cache-kind slot. - Standard_EXPORT bool Remove(const BRepGraph_NodeId theNode, const int theKindSlot); - - //! Invalidate (but do not remove) a cached value on a node. - //! @param[in] theNode node whose cache entry to invalidate - //! @param[in] theKind cache kind descriptor identifying the slot - Standard_EXPORT void Invalidate(const BRepGraph_NodeId theNode, - const occ::handle& theKind); - - //! Invalidate a cached value using a pre-resolved cache-kind slot. - Standard_EXPORT void Invalidate(const BRepGraph_NodeId theNode, const int theKindSlot); - - //! Create a zero-allocation iterator over all cache kinds populated on a node. - //! @param[in] theNode node to query - Standard_EXPORT BRepGraph_CacheKindIterator CacheKindIter( - const BRepGraph_NodeId theNode) const; - - //! Create a zero-allocation iterator over all cache kinds populated on a reference. - //! @param[in] theRef reference to query - Standard_EXPORT BRepGraph_CacheKindIterator CacheKindIter( - const BRepGraph_RefId theRef) const; - - // --- Reference-level cache --- - - //! Attach a cached value to a reference. - //! @param[in] theRef reference to attach the value to - //! @param[in] theKind cache kind descriptor identifying the slot - //! @param[in] theValue cached value to store - Standard_EXPORT void Set(const BRepGraph_RefId theRef, - const occ::handle& theKind, - const occ::handle& theValue); - - //! Attach a cached value to a reference using a pre-resolved cache-kind slot. - Standard_EXPORT void Set(const BRepGraph_RefId theRef, - const int theKindSlot, - const occ::handle& theValue); - - //! Retrieve a cached value from a reference. - //! @return cached value, or null handle if not present or stale (OwnGen changed) - [[nodiscard]] Standard_EXPORT occ::handle Get( - const BRepGraph_RefId theRef, - const occ::handle& theKind) const; - - //! Retrieve a cached value from a reference using a pre-resolved cache-kind slot. - [[nodiscard]] Standard_EXPORT occ::handle Get(const BRepGraph_RefId theRef, - const int theKindSlot) const; - - //! Check if a non-stale cached value exists on a reference. - [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_RefId theRef, - const occ::handle& theKind) const; - - //! Check if a non-stale cached value exists on a reference using a pre-resolved slot. - [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_RefId theRef, const int theKindSlot) const; - - //! Remove a cached value from a reference. - //! @return true if a value was actually removed - Standard_EXPORT bool Remove(const BRepGraph_RefId theRef, - const occ::handle& theKind); - - //! Remove a cached value from a reference using a pre-resolved cache-kind slot. - Standard_EXPORT bool Remove(const BRepGraph_RefId theRef, const int theKindSlot); - - //! Invalidate (but do not remove) a cached value on a reference. - Standard_EXPORT void Invalidate(const BRepGraph_RefId theRef, - const occ::handle& theKind); - - //! Invalidate a cached value on a reference using a pre-resolved cache-kind slot. - Standard_EXPORT void Invalidate(const BRepGraph_RefId theRef, const int theKindSlot); - -private: - friend class BRepGraph; - friend struct BRepGraph_Data; - - explicit CacheView(BRepGraph* theGraph) - : myGraph(theGraph) - { - } - - BRepGraph* myGraph; -}; - -#endif // _BRepGraph_CacheView_HeaderFile diff --git a/opencascade/BRepGraph_ChildExplorer.hxx b/opencascade/BRepGraph_ChildExplorer.hxx index 134c18781..64de1a2de 100644 --- a/opencascade/BRepGraph_ChildExplorer.hxx +++ b/opencascade/BRepGraph_ChildExplorer.hxx @@ -18,10 +18,9 @@ #include #include #include - +#include #include #include - #include #include @@ -41,8 +40,7 @@ //! Compound -> children, CompSolid -> Solids, Solid -> Shells, //! Shell -> Faces, Face -> Wires (+direct Vertices), Wire -> CoEdges, //! CoEdge -> Edge, Edge -> Vertices, -//! Product(assembly) -> Occurrences, Product(part) -> ShapeRoot, -//! Occurrence -> Product. +//! Product -> Occurrences, Occurrence -> Product/topology-root. //! //! Unlike flat definition traversal by typed ids, BRepGraph_ChildExplorer visits //! each occurrence. If Edge[5] is reachable through Face[0] and Face[1], @@ -78,10 +76,8 @@ public: //! Consolidated configuration for the explorer. //! - //! Prefer this struct over the historical 11-overload constructor family. The - //! overloads remain supported for existing callers but the `Config`-based - //! constructor is the stable long-term idiom: new options can be added as - //! fields without another constructor explosion. + //! The `Config`-based constructor is the preferred idiom: new options can be + //! added as fields without additional constructor overloads. //! //! @code //! BRepGraph_ChildExplorer::Config aConfig; @@ -113,28 +109,57 @@ public: const BRepGraph_NodeId theRoot, const Config& theConfig); + //! Explore all descendants of the root node using recursive traversal. + //! @param[in] theGraph graph to walk + //! @param[in] theRoot root node where the walk begins Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, const BRepGraph_NodeId theRoot); + //! Explore descendants of the root node using the given traversal mode. + //! @param[in] theGraph graph to walk + //! @param[in] theRoot root node where the walk begins + //! @param[in] theMode traversal strategy (recursive or direct children) Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, const BRepGraph_NodeId theRoot, TraversalMode theMode); + //! Explore descendants while pruning branches at the avoid kind. + //! @param[in] theGraph graph to walk + //! @param[in] theRoot root node where the walk begins + //! @param[in] theAvoidKind node kind to avoid descending into + //! @param[in] theEmitAvoidKind if true, emit matching avoid-kind nodes once before skipping + //! @param[in] theMode traversal strategy Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, const BRepGraph_NodeId theRoot, const std::optional& theAvoidKind, bool theEmitAvoidKind, TraversalMode theMode = TraversalMode::Recursive); + //! Explore only descendants of the given target kind. + //! @param[in] theGraph graph to walk + //! @param[in] theRoot root node where the walk begins + //! @param[in] theTargetKind kind of nodes to emit Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, const BRepGraph_NodeId theRoot, BRepGraph_NodeId::Kind theTargetKind); + //! Explore only descendants of the given target kind using the given traversal mode. + //! @param[in] theGraph graph to walk + //! @param[in] theRoot root node where the walk begins + //! @param[in] theTargetKind kind of nodes to emit + //! @param[in] theMode traversal strategy Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, const BRepGraph_NodeId theRoot, BRepGraph_NodeId::Kind theTargetKind, TraversalMode theMode); + //! Explore descendants of the given target kind while pruning branches at the avoid kind. + //! @param[in] theGraph graph to walk + //! @param[in] theRoot root node where the walk begins + //! @param[in] theTargetKind kind of nodes to emit + //! @param[in] theAvoidKind node kind to avoid descending into + //! @param[in] theEmitAvoidKind if true, emit matching avoid-kind nodes once before skipping + //! @param[in] theMode traversal strategy Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, const BRepGraph_NodeId theRoot, BRepGraph_NodeId::Kind theTargetKind, @@ -142,12 +167,19 @@ public: bool theEmitAvoidKind, TraversalMode theMode = TraversalMode::Recursive); + //! Explore only descendants of the given target kind starting from a product. + //! @param[in] theGraph graph to walk + //! @param[in] theProduct product whose occurrences and topology are explored + //! @param[in] theTargetKind kind of nodes to emit Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, const BRepGraph_ProductId theProduct, BRepGraph_NodeId::Kind theTargetKind); //! Disambiguates non-product typed ids from the ProductId-specific overload //! family above and keeps them on the generic NodeId traversal path. + //! @param[in] theGraph graph to walk + //! @param[in] theRoot typed root node where the walk begins + //! @param[in] theTargetKind kind of nodes to emit template = 0> BRepGraph_ChildExplorer(const BRepGraph& theGraph, @@ -157,6 +189,12 @@ public: { } + //! Explore only descendants of the given target kind starting from a product, + //! using the given traversal mode. + //! @param[in] theGraph graph to walk + //! @param[in] theProduct product whose occurrences and topology are explored + //! @param[in] theTargetKind kind of nodes to emit + //! @param[in] theMode traversal strategy Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, const BRepGraph_ProductId theProduct, BRepGraph_NodeId::Kind theTargetKind, @@ -164,6 +202,10 @@ public: //! Disambiguates non-product typed ids from the ProductId-specific overload //! family above and keeps them on the generic NodeId traversal path. + //! @param[in] theGraph graph to walk + //! @param[in] theRoot typed root node where the walk begins + //! @param[in] theTargetKind kind of nodes to emit + //! @param[in] theMode traversal strategy template = 0> BRepGraph_ChildExplorer(const BRepGraph& theGraph, @@ -174,6 +216,13 @@ public: { } + //! Explore only descendants of the given target kind with explicit location/orientation control. + //! @param[in] theGraph graph to walk + //! @param[in] theRoot root node where the walk begins + //! @param[in] theTargetKind kind of nodes to emit + //! @param[in] theCumLoc if true, accumulate location down the walk + //! @param[in] theCumOri if true, accumulate orientation down the walk + //! @param[in] theMode traversal strategy Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, const BRepGraph_NodeId theRoot, BRepGraph_NodeId::Kind theTargetKind, @@ -181,6 +230,14 @@ public: bool theCumOri, TraversalMode theMode = TraversalMode::Recursive); + //! Explore only descendants of the given target kind starting from a product, + //! with explicit location/orientation control. + //! @param[in] theGraph graph to walk + //! @param[in] theProduct product whose occurrences and topology are explored + //! @param[in] theTargetKind kind of nodes to emit + //! @param[in] theCumLoc if true, accumulate location down the walk + //! @param[in] theCumOri if true, accumulate orientation down the walk + //! @param[in] theMode traversal strategy Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, const BRepGraph_ProductId theProduct, BRepGraph_NodeId::Kind theTargetKind, @@ -190,6 +247,12 @@ public: //! Disambiguates non-product typed ids from the ProductId-specific overload //! family above and keeps them on the generic NodeId traversal path. + //! @param[in] theGraph graph to walk + //! @param[in] theRoot typed root node where the walk begins + //! @param[in] theTargetKind kind of nodes to emit + //! @param[in] theCumLoc if true, accumulate location down the walk + //! @param[in] theCumOri if true, accumulate orientation down the walk + //! @param[in] theMode traversal strategy template = 0> BRepGraph_ChildExplorer(const BRepGraph& theGraph, @@ -207,6 +270,13 @@ public: { } + //! Explore only descendants of the given target kind with an explicit initial transform. + //! @param[in] theGraph graph to walk + //! @param[in] theRoot root node where the walk begins + //! @param[in] theTargetKind kind of nodes to emit + //! @param[in] theStartLoc initial accumulated location + //! @param[in] theStartOri initial accumulated orientation + //! @param[in] theMode traversal strategy Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, const BRepGraph_NodeId theRoot, BRepGraph_NodeId::Kind theTargetKind, @@ -218,10 +288,13 @@ public: //! Read-only - configuration is fixed for the lifetime of the explorer. [[nodiscard]] const Config& GetConfig() const { return myConfig; } + //! True if another matching descendant is available. [[nodiscard]] bool More() const { return myHasMore; } + //! Advance to the next matching descendant. Standard_EXPORT void Next(); + //! Current matching descendant node with accumulated location and orientation. [[nodiscard]] BRepGraphInc::NodeInstance Current() const { return {myCurrent, myLocation, myOrientation}; @@ -237,18 +310,38 @@ public: //! Returns the exact parent-owned RefId for Current(), when the current step //! is represented by a reference entry. Returns invalid RefId for structural //! links without a dedicated ref entry such as CoEdge->Edge, - //! Product(part)->ShapeRoot and Occurrence->Product. + //! Occurrence->Product/topology-root. [[nodiscard]] Standard_EXPORT BRepGraph_RefId CurrentRef() const; + //! Returns the explicit concrete traversal path from the explorer root to Current(). + [[nodiscard]] Standard_EXPORT BRepGraph_UsagePath CurrentUsagePath() const; + + //! Returns the accumulated location at the most recent ancestor of the given kind. + //! @param[in] theKind node kind to search for in the ancestor chain + //! @return accumulated location at the matching ancestor [[nodiscard]] Standard_EXPORT TopLoc_Location LocationOf(const BRepGraph_NodeId::Kind theKind) const; + //! Returns the node id of the most recent ancestor of the given kind. + //! @param[in] theKind node kind to search for in the ancestor chain + //! @return node id of the matching ancestor [[nodiscard]] Standard_EXPORT BRepGraph_NodeId NodeOf(const BRepGraph_NodeId::Kind theKind) const; + //! Returns the accumulated location at the given stack level. + //! @param[in] theLevel zero-based stack depth (0 = root) + //! @return accumulated location at the specified level [[nodiscard]] Standard_EXPORT TopLoc_Location LocationAt(const int theLevel) const; + //! Returns the node id at the given stack level. + //! @param[in] theLevel zero-based stack depth (0 = root) + //! @return node id at the specified level [[nodiscard]] Standard_EXPORT BRepGraph_NodeId NodeAt(const int theLevel) const; + //! Number of valid ancestor frames currently on the stack (excluding the + //! sentinel below the root). O(1); avoids the O(depth^2) NodeAt(i) walk used + //! to compute container priority in selection-mode building. + [[nodiscard]] int Depth() const noexcept { return myStackTop < 0 ? 0 : myStackTop + 1; } + //! Returns an STL-compatible iterator for range-based for loops. NCollection_ForwardRangeIterator begin() { @@ -264,11 +357,12 @@ private: BRepGraph_NodeId Node; uint32_t NextChildIdx = 0; int StepFromParent = -1; + BRepGraph_RefId Ref; //!< RefId resolved at push time (O(1) in CurrentRef) TopLoc_Location AccLocation; TopAbs_Orientation AccOrientation = TopAbs_FORWARD; }; - void advance(); + Standard_EXPORT void advance(); void startTraversal(const TopLoc_Location& theStartLoc, TopAbs_Orientation theStartOri); diff --git a/opencascade/BRepGraph_Compact.hxx b/opencascade/BRepGraph_Compact.hxx index f87a1007e..ba8ff4d05 100644 --- a/opencascade/BRepGraph_Compact.hxx +++ b/opencascade/BRepGraph_Compact.hxx @@ -15,7 +15,6 @@ #define _BRepGraph_Compact_HeaderFile #include - #include //! @brief Graph compaction algorithm that reclaims removed node slots. @@ -35,24 +34,33 @@ public: //! Configuration for compaction. struct Options { - bool HistoryMode = true; //!< Record index remapping in history. + enum class CachePolicy + { + Drop, //!< Keep registered cache services but clear transient entries. + CopyFresh //!< Copy fresh, remappable transient entries into the compacted graph. + }; + + bool HistoryMode = true; //!< Record index remapping in history. + CachePolicy CacheMode = CachePolicy::Drop; //!< Runtime cache migration policy. }; //! Result counters for diagnostics. struct Result { - int NbRemovedVertices = 0; - int NbRemovedEdges = 0; - int NbRemovedWires = 0; - int NbRemovedFaces = 0; - int NbRemovedShells = 0; - int NbRemovedSolids = 0; - int NbRemovedCompounds = 0; - int NbRemovedCompSolids = 0; - int NbRemovedSurfaces = 0; - int NbRemovedCurves = 0; - int NbNodesBefore = 0; - int NbNodesAfter = 0; + uint32_t NbRemovedVertices = 0; + uint32_t NbRemovedEdges = 0; + uint32_t NbRemovedWires = 0; + uint32_t NbRemovedFaces = 0; + uint32_t NbRemovedShells = 0; + uint32_t NbRemovedSolids = 0; + uint32_t NbRemovedCompounds = 0; + uint32_t NbRemovedCompSolids = 0; + uint32_t NbRemovedSurfaces = 0; + uint32_t NbRemovedCurves = 0; + uint32_t NbNodesBefore = 0; + uint32_t NbNodesAfter = 0; + uint32_t NbUnmappedActiveDefs = + 0; //!< Active defs not present in any remap (orphans + drop-outs). }; //! Run compaction with default options. @@ -67,7 +75,6 @@ public: [[nodiscard]] Standard_EXPORT static Result Perform(BRepGraph& theGraph, const Options& theOptions); -private: BRepGraph_Compact() = delete; }; diff --git a/opencascade/BRepGraph_Copy.hxx b/opencascade/BRepGraph_Copy.hxx index edf8d5e2d..27ed54cbb 100644 --- a/opencascade/BRepGraph_Copy.hxx +++ b/opencascade/BRepGraph_Copy.hxx @@ -16,8 +16,7 @@ #include #include -#include - +#include #include //! @brief Graph-to-graph deep copy. @@ -25,19 +24,23 @@ //! Produces a new BRepGraph from an existing one in a single bottom-up pass, //! avoiding the 5-7 traversals of BRepTools_Modifier used by BRepBuilderAPI_Copy. //! -//! Two modes: -//! - theCopyGeom = true (deep): geometry handles are cloned, result is fully independent. -//! - theCopyGeom = false (light): geometry handles are shared, only topology is duplicated. +//! Two copy modes: +//! - External: source and target are different graphs. Target receives the copied data. +//! - Self-copy: source and target are the same graph. The specified sub-graph is +//! duplicated with new entity IDs; shared dependencies (geometry, vertices referenced +//! from outside the sub-graph) are preserved. +//! +//! Geometry and mesh policies are controlled by the GeomPolicy and MeshPolicy enums. //! -//! @note Unlike in-place mutation algorithms (Sewing, Deduplicate) which return a -//! Result struct with diagnostics, Copy and Transform return a BRepGraph directly -//! because they produce new graphs. Check IsDone() on the returned graph for success. +//! @note Check the return value for success: Perform returns bool, +//! CopyNode returns the mapped root NodeId (invalid on failure). //! //! ## Typical usage //! @code //! BRepGraph aGraph; -//! BRepGraph_Builder::Add(aGraph, myShape); -//! BRepGraph aCopy = BRepGraph_Copy::Perform(aGraph); +//! aGraph.Shapes().Add(myShape); +//! BRepGraph aCopy; +//! BRepGraph_Copy::Perform(aGraph, aCopy); //! TopoDS_Shape aShape = aCopy.Shapes().Shape(); //! @endcode class BRepGraph_Copy @@ -45,33 +48,78 @@ class BRepGraph_Copy public: DEFINE_STANDARD_ALLOC - //! Copy the entire graph. - //! @param[in] theGraph a pre-built BRepGraph (must have IsDone() == true) - //! @param[in] theCopyGeom if true (default), geometry handles are deep-copied; - //! if false, geometry is shared (only topology is duplicated) - //! @return a new BRepGraph with IsDone() == true on success, - //! or an empty graph with IsDone() == false on failure - [[nodiscard]] Standard_EXPORT static BRepGraph Perform(const BRepGraph& theGraph, - const bool theCopyGeom = true); + //! Policy for handling geometry handles (Geom_Curve, Geom_Surface, Geom2d_Curve). + enum class GeomPolicy + { + Copy, //!< Deep-clone geometry handles; result is fully independent + Share, //!< Reuse source geometry handles; only topology is duplicated + Drop //!< Pure topology: edges carry no curves, faces carry no surfaces + }; - //! Copy a single node sub-graph of any kind (Face, Shell, Solid, Wire, Edge, Vertex, etc.). - //! The new graph contains only the specified node and all entities it references. - //! @param[in] theGraph a pre-built BRepGraph - //! @param[in] theNodeId node identifier (any kind) - //! @param[in] theCopyGeom if true, geometry handles are deep-copied - //! @param[in] theCopyMesh if true, cached mesh entries are propagated to the result; - //! if false, mesh references are dropped on copied faces - //! @param[in] theReserveCache if true, pre-allocates transient cache - //! @return a new BRepGraph containing only the specified sub-graph - [[nodiscard]] Standard_EXPORT static BRepGraph CopyNode(const BRepGraph& theGraph, - const BRepGraph_NodeId theNodeId, - const bool theCopyGeom = true, - const bool theCopyMesh = true, - const bool theReserveCache = false); + //! Policy for handling mesh data (Poly_Triangulation, Poly_Polygon3D, + //! Poly_PolygonOnTriangulation). + enum class MeshPolicy + { + Copy, //!< Deep-clone mesh data; independent result + Share, //!< Reuse source mesh handle references; no cloning + Drop //!< Discard all mesh data on copied entities + }; -private: - //! Pre-allocate transient cache for lock-free parallel access. - static void reserveTransientCache(BRepGraph& theGraph); + //! Policy for handling transient runtime cache services. + enum class CachePolicy + { + Drop, //!< Do not copy runtime cache services or entries. + CopyFresh //!< Copy fresh, remappable runtime cache entries. + }; + + //! Copy the entire source graph into the target graph. + //! + //! Self-copy (theSourceGraph == theTargetGraph): + //! Identity no-op, returns true immediately. + //! + //! External copy to empty target (theTargetGraph.IsEmpty()): + //! Uses identity-mapped fast path (old index == new index). + //! + //! External copy to non-empty target: + //! Uses explicit mapping; IDs in theTargetGraph will differ from theSourceGraph. + //! Entities from theSourceGraph are appended to theTargetGraph. + //! + //! @param[in] theSourceGraph a pre-built BRepGraph (must not be empty) + //! @param[in,out] theTargetGraph destination graph (may already contain data) + //! @param[in] theGeomPolicy geometry handle policy (default: Copy) + //! @param[in] theMeshPolicy mesh data policy (default: Copy) + //! @return true on success, false on failure (empty source) + Standard_EXPORT static bool Perform(const BRepGraph& theSourceGraph, + BRepGraph& theTargetGraph, + GeomPolicy theGeomPolicy = GeomPolicy::Copy, + MeshPolicy theMeshPolicy = MeshPolicy::Copy, + CachePolicy theCachePolicy = CachePolicy::Drop); + + //! Copy a single node sub-graph of any kind (Face, Shell, Solid, Wire, Edge, Vertex, etc.). + //! The target graph receives the specified node and all entities it references. + //! + //! External copy (theSourceGraph != theTargetGraph): + //! New entities are appended to theTargetGraph. Entities already present + //! in theTargetGraph are reused (not duplicated). + //! + //! Self-copy (theSourceGraph == theTargetGraph): + //! The specified sub-graph is duplicated with new entity IDs within the same graph. + //! Shared dependencies (vertices, edges referenced from outside the sub-graph) + //! are preserved as-is. + //! + //! @param[in] theSourceGraph a pre-built BRepGraph + //! @param[in,out] theTargetGraph destination graph (may already contain data) + //! @param[in] theNodeId node identifier (any kind) + //! @param[in] theGeomPolicy geometry handle policy (default: Copy) + //! @param[in] theMeshPolicy mesh data policy (default: Copy) + //! @return the mapped root NodeId in theTargetGraph, or invalid NodeId on failure + [[nodiscard]] Standard_EXPORT static BRepGraph_NodeId CopyNode( + const BRepGraph& theSourceGraph, + BRepGraph& theTargetGraph, + const BRepGraph_NodeId theNodeId, + GeomPolicy theGeomPolicy = GeomPolicy::Copy, + MeshPolicy theMeshPolicy = MeshPolicy::Copy, + CachePolicy theCachePolicy = CachePolicy::Drop); BRepGraph_Copy() = delete; }; diff --git a/opencascade/BRepGraph_CopyRemap.hxx b/opencascade/BRepGraph_CopyRemap.hxx new file mode 100644 index 000000000..e9dfc0f8e --- /dev/null +++ b/opencascade/BRepGraph_CopyRemap.hxx @@ -0,0 +1,113 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_CopyRemap_HeaderFile +#define _BRepGraph_CopyRemap_HeaderFile + +#include +#include +#include +#include + +#include + +class BRepGraph; + +//! Immutable context passed to layer copy callbacks. +//! +//! The structural copy algorithm owns remap construction. Layers receive this +//! context and decide how to copy their own representation without exposing layer +//! details back to BRepGraph_Copy. +class BRepGraph_CopyRemap +{ +public: + DEFINE_STANDARD_ALLOC + + //! Distinguishes copy vs. compact migration semantics. + enum class Mode : std::uint8_t + { + Copy = 0, //!< Full graph copy: source and target are distinct graphs. + Compact = 1 //!< In-place compaction: layers migrate into the same (rebuilt) graph. + }; + + //! Distinguishes explicit item map vs. identity mapping. + enum class MappingKind : std::uint8_t + { + Explicit = 0, //!< Use theItemRemap for source->target resolution. + Identity = 1 //!< Source and target ids are identical (full identity copy). + }; + + using ItemMap = NCollection_FlatDataMap; + + BRepGraph_CopyRemap(const BRepGraph& theSourceGraph, + BRepGraph& theTargetGraph, + const ItemMap& theItemRemap, + const Mode theMode) noexcept; + + //! Identity-mapping constructor for full identity copy into an empty target. + //! Source item ids are returned directly as target item ids after validation. + BRepGraph_CopyRemap(const BRepGraph& theSourceGraph, + BRepGraph& theTargetGraph, + MappingKind theMappingKind, + Mode theMode) noexcept; + + //! Migration mode of this context. + [[nodiscard]] Mode CopyMode() const noexcept { return myMode; } + + //! True if this is a compaction migration (not a full copy). + [[nodiscard]] bool IsCompact() const noexcept { return myMode == Mode::Compact; } + + //! Source graph the copied layer is attached to. + [[nodiscard]] const BRepGraph& SourceGraph() const noexcept { return *mySourceGraph; } + + //! Target graph whose structural contents have already been copied. + [[nodiscard]] BRepGraph& TargetGraph() const noexcept { return *myTargetGraph; } + + //! Target graph as const. + [[nodiscard]] const BRepGraph& TargetGraphConst() const noexcept { return *myTargetGraph; } + + //! Source item id -> target item id map for copied definitions, refs, and reps. + [[nodiscard]] const ItemMap& Items() const noexcept { return *myItemRemap; } + + //! Return the target item for a source item, or an invalid item if not copied. + [[nodiscard]] Standard_EXPORT BRepGraph_ItemId + TargetItem(const BRepGraph_ItemId theSourceItem) const; + + //! Return the target item for a source item, or an invalid item id. + [[nodiscard]] Standard_EXPORT BRepGraph_ItemId + TargetItemOrInvalid(const BRepGraph_ItemId theSourceItem) const; + + //! Return true if the source item has a valid copied target item. + [[nodiscard]] Standard_EXPORT bool HasTargetItem(const BRepGraph_ItemId theSourceItem) const; + + //! Return source UID for a source item. + [[nodiscard]] Standard_EXPORT BRepGraph_ItemUID + SourceUID(const BRepGraph_ItemId theSourceItem) const; + + //! Return target UID for a target item. + [[nodiscard]] Standard_EXPORT BRepGraph_ItemUID + TargetUID(const BRepGraph_ItemId theTargetItem) const; + + //! Return target UID for a source item by source->target remap. + [[nodiscard]] Standard_EXPORT BRepGraph_ItemUID + TargetUIDFromSource(const BRepGraph_ItemId theSourceItem) const; + +private: + const BRepGraph* mySourceGraph = nullptr; + BRepGraph* myTargetGraph = nullptr; + const ItemMap* myItemRemap = nullptr; + Mode myMode = Mode::Copy; + MappingKind myMappingKind = MappingKind::Explicit; +}; + +#endif // _BRepGraph_CopyRemap_HeaderFile diff --git a/opencascade/BRepGraph_Data.hxx b/opencascade/BRepGraph_Data.hxx index 162a44844..9c21a7249 100644 --- a/opencascade/BRepGraph_Data.hxx +++ b/opencascade/BRepGraph_Data.hxx @@ -14,36 +14,19 @@ #ifndef _BRepGraph_Data_HeaderFile #define _BRepGraph_Data_HeaderFile -#include #include +#include +#include #include -#include -#include -#include #include #include -#include -#include -#include #include -#include #include -#include #include -#include -#include -#include - -#include -#include -#include -#include - -#include - #include -#include + +class BRepGraph; //! @brief Internal storage for BRepGraph (PIMPL). //! @@ -51,108 +34,23 @@ //! Access via myIncStorage.Edges, myIncStorage.Faces, etc. struct BRepGraph_Data { - occ::handle myAllocator; - //! Incidence-table storage - sole source of truth for all topology data, - //! original shapes, TShape->NodeId mapping, and UIDs. + //! original shapes, TShape->NodeId mapping, UIDs, and UID reverse indexes. BRepGraphInc_Storage myIncStorage; - //! UID system. - std::atomic myNextUIDCounter{ - 1}; //!< Starts at 1; counter=0 is BRepGraph_UID invalid sentinel. - std::atomic myGeneration{0}; - Standard_GUID myGraphGUID; //!< Random graph identity, generated at BRepGraph_Builder::Add(). - - //! History subsystem. - BRepGraph_History myHistoryLog; - - bool myIsDone = false; - - //! Root product identifiers: products not referenced by any active occurrence. - //! Maintained incrementally by Editor/EditorView mutations. - NCollection_DynamicArray myRootProductIds; - - //! When true, markModified() only increments OwnGen + SubtreeGen and appends to - //! myDeferredModified - no mutex acquisition and no upward propagation. - std::atomic myDeferredMode{false}; - - //! Propagation wave counter. Incremented at the start of each - //! markModified() / markRefModified() call. markParentModified() - //! compares entity.LastPropWave against this to skip already-visited - //! parents in the same propagation wave (O(1) re-visit guard). - std::atomic myPropagationWave{0}; + //! Registered graph layers. + BRepGraph_LayerRegistry myLayerRegistry; - //! Recursion depth of EditorView::GenOps::RemoveSubgraph. Outermost call (depth==0) - //! triggers a single reverse-index rebuild after cascade so individual cascade-prune - //! steps avoid maintaining per-kind unbinds for every removed node. - uint32_t myRemoveSubgraphDepth = 0; + //! Registered transient cache services. + BRepGraph_CacheRegistry myCacheRegistry; - //! NodeIds accumulated during deferred mode. Processed by EndDeferredInvalidation(). - NCollection_DynamicArray myDeferredModified; - - //! RefIds accumulated during deferred mode. Processed by EndDeferredInvalidation(). - NCollection_DynamicArray myDeferredRefModified; - - //! Gen-validated shape cache entry. - struct CachedShape - { - TopoDS_Shape Shape; - uint32_t StoredSubtreeGen = 0; - }; - - //! Thread-safe cache of reconstructed shapes with SubtreeGen validation. - mutable NCollection_DataMap myCurrentShapes; - mutable std::shared_mutex myCurrentShapesMutex; - - //! Lazy reverse lookup index for entity UIDs. - mutable NCollection_DataMap myUIDToNodeId; - mutable std::shared_mutex myUIDToNodeIdMutex; - mutable uint32_t myUIDToNodeIdGeneration = 0; - mutable bool myUIDToNodeIdDirty = true; - - //! Lazy reverse lookup index for reference UIDs. - mutable NCollection_DataMap myRefUIDToRefId; - mutable std::shared_mutex myRefUIDToRefIdMutex; - mutable uint32_t myRefUIDToRefIdGeneration = 0; - mutable bool myRefUIDToRefIdDirty = true; - - //! Cached mesh data storage (algorithm-derived, non-mutating). - //! Holds triangulation/polygon rep references written by BRepGraphMesh. - //! Does NOT trigger markModified() or mutation tracking. - BRepGraph_MeshCacheStorage myMeshCache; - - using ReconstructCache = NCollection_DataMap; - - //! Cached view objects (pointers set to owning BRepGraph in its constructor). + //! Stable top-level views. Nested views store graph-data context only. BRepGraph::TopoView myTopoView{nullptr}; BRepGraph::UIDsView myUIDsView{nullptr}; - BRepGraph::CacheView myCacheView{nullptr}; BRepGraph::RefsView myRefsView{nullptr}; BRepGraph::ShapesView myShapesView{nullptr}; BRepGraph::EditorView myEditorView{nullptr}; BRepGraph::MeshView myMeshView{nullptr}; - - BRepGraph_Data() - : myAllocator(new NCollection_IncAllocator), - myIncStorage(myAllocator), - myCurrentShapes(1, myAllocator), - myUIDToNodeId(1, myAllocator), - myRefUIDToRefId(1, myAllocator) - { - myHistoryLog.SetAllocator(myAllocator); - } - - explicit BRepGraph_Data(const occ::handle& theAlloc) - : myAllocator(!theAlloc.IsNull() - ? theAlloc - : occ::handle(new NCollection_IncAllocator)), - myIncStorage(myAllocator), - myCurrentShapes(1, myAllocator), - myUIDToNodeId(1, myAllocator), - myRefUIDToRefId(1, myAllocator) - { - myHistoryLog.SetAllocator(myAllocator); - } }; #endif // _BRepGraph_Data_HeaderFile diff --git a/opencascade/BRepGraph_Deduplicate.hxx b/opencascade/BRepGraph_Deduplicate.hxx index 2387356bb..e725884c5 100644 --- a/opencascade/BRepGraph_Deduplicate.hxx +++ b/opencascade/BRepGraph_Deduplicate.hxx @@ -15,9 +15,8 @@ #define _BRepGraph_Deduplicate_HeaderFile #include - #include -#include +#include #include #include @@ -46,23 +45,26 @@ public: //! Result counters for diagnostics and tests. struct Result { - int NbCanonicalSurfaces = 0; - int NbCanonicalCurves = 0; - int NbSurfaceRewrites = 0; - int NbCurveRewrites = 0; - int NbNullifiedSurfaces = 0; - int NbNullifiedCurves = 0; - int NbHistoryRecords = 0; - bool IsEntityMergeApplied = false; + uint32_t NbCanonicalSurfaces = 0; + uint32_t NbCanonicalCurves = 0; + uint32_t NbSurfaceRewrites = 0; + uint32_t NbCurveRewrites = 0; + uint32_t NbNullifiedSurfaces = 0; + uint32_t NbNullifiedCurves = 0; + uint32_t NbHistoryRecords = 0; + bool IsEntityMergeApplied = false; //! Topology definition merge counters (active when MergeEntitiesWhenSafe = true). - int NbMergedVertices = 0; - int NbMergedEdges = 0; - int NbMergedWires = 0; - int NbMergedFaces = 0; + uint32_t NbMergedVertices = 0; + uint32_t NbMergedEdges = 0; + uint32_t NbMergedWires = 0; + uint32_t NbMergedFaces = 0; + uint32_t NbReorderedWires = 0; + uint32_t NbToleranceOrderedWires = 0; + uint32_t NbPartialOrderedWires = 0; - NCollection_DynamicArray AffectedFaces; //!< Faces whose SurfNodeId changed. - NCollection_DynamicArray AffectedEdges; //!< Edges whose CurveNodeId changed. + NCollection_LinearVector AffectedFaces; //!< Faces whose SurfNodeId changed. + NCollection_LinearVector AffectedEdges; //!< Edges whose CurveNodeId changed. }; //! Run deduplication on a built graph. @@ -77,8 +79,10 @@ public: [[nodiscard]] Standard_EXPORT static Result Perform(BRepGraph& theGraph, const Options& theOptions); -private: BRepGraph_Deduplicate() = delete; + +private: + static void CanonicalizeWireOrders(BRepGraph& theGraph, Result& theResult); }; #endif // _BRepGraph_Deduplicate_HeaderFile diff --git a/opencascade/BRepGraph_DeferredScope.hxx b/opencascade/BRepGraph_DeferredScope.hxx index 5f6a1cfc0..2808e6827 100644 --- a/opencascade/BRepGraph_DeferredScope.hxx +++ b/opencascade/BRepGraph_DeferredScope.hxx @@ -23,8 +23,8 @@ //! followed by CommitMutation validation. Guarantees exception-safe cleanup: //! when this guard owns deferred mode, it is always closed and boundary checks //! are executed at scope exit. EndDeferredInvalidation() batch-propagates -//! SubtreeGen upward, then CommitMutation() validates reverse-index consistency -//! and active-entity counts. +//! SubtreeGen upward, then CommitMutation() validates relation consistency and +//! active-entity counts. //! //! Re-entrant: if deferred mode is already active (e.g., nested guard), //! the inner guard is a no-op. Only the outermost guard flushes and commits, @@ -55,10 +55,12 @@ public: myOwnsScope(!theGraph.Editor().IsDeferredMode()) { if (myOwnsScope) + { myGraph.Editor().BeginDeferredInvalidation(); + } } - //! End deferred invalidation and validate reverse index + active counts. + //! End deferred invalidation and validate relations + active counts. ~BRepGraph_DeferredScope() { if (myOwnsScope) diff --git a/opencascade/BRepGraph_DefsIterator.hxx b/opencascade/BRepGraph_DefsIterator.hxx index 3ea84451e..3ac79067d 100644 --- a/opencascade/BRepGraph_DefsIterator.hxx +++ b/opencascade/BRepGraph_DefsIterator.hxx @@ -17,8 +17,9 @@ #include #include #include - #include +#include +#include //! @brief Single-level typed iterators over active child definitions. //! @@ -44,21 +45,11 @@ struct BaseTraits using RefEntry = RefEntryT; using ChildId = ChildIdT; using ChildDef = ChildDefT; -}; -template -inline const BRepGraphInc::BaseDef* childBaseDef(const BRepGraph& theGraph, - const ChildIdT theChildId) -{ - return theGraph.Topo().Gen().TopoEntity(BRepGraph_NodeId(theChildId)); -} - -inline const BRepGraphInc::BaseDef* childBaseDef(const BRepGraph& theGraph, - const BRepGraph_NodeId theChildId) -{ - return theGraph.Topo().Gen().TopoEntity(theChildId); -} + static constexpr bool THE_IS_DIRECT = std::is_same_v; +}; +//! Traits for iterating over shell children of a solid. struct ShellOfSolidTraits : public BaseTraits& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Solids().Definition(theParent).ShellRefIds; + return theGraph.Topo().Solids().Relations(theParent).ShellRefIds; } static const BRepGraphInc::ShellRef& Ref(const BRepGraph& theGraph, const RefId theRefId) @@ -84,7 +74,7 @@ struct ShellOfSolidTraits : public BaseTraits& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Shells().Definition(theParent).FaceRefIds; + return theGraph.Topo().Shells().Relations(theParent).FaceRefIds; } static const BRepGraphInc::FaceRef& Ref(const BRepGraph& theGraph, const RefId theRefId) @@ -118,7 +108,7 @@ struct FaceOfShellTraits : public BaseTraits -{ - static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) - { - return theParent.IsValid(theGraph.Topo().Shells().Nb()) - && !theGraph.Topo().Shells().Definition(theParent).IsRemoved; - } - - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, - const ParentId theParent) - { - return theGraph.Topo().Shells().Definition(theParent).AuxChildRefIds; - } - - static const BRepGraphInc::ChildRef& Ref(const BRepGraph& theGraph, const RefId theRefId) - { - return theGraph.Refs().Children().Entry(theRefId); - } - - static ChildId ChildIdOf(const BRepGraph&, const BRepGraphInc::ChildRef& theRef) - { - return theRef.ChildDefId; - } - - static const ChildDef& Child(const BRepGraph& theGraph, const ChildId theChildId) - { - return *theGraph.Topo().Gen().TopoEntity(theChildId); - } -}; - +//! Traits for iterating over wire children of a face. struct WireOfFaceTraits : public BaseTraits& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Faces().Definition(theParent).WireRefIds; + return theGraph.Topo().Faces().Relations(theParent).WireRefIds; } static const BRepGraphInc::WireRef& Ref(const BRepGraph& theGraph, const RefId theRefId) @@ -186,7 +142,7 @@ struct WireOfFaceTraits : public BaseTraits -{ - static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) - { - return theParent.IsValid(theGraph.Topo().Faces().Nb()) - && !theGraph.Topo().Faces().Definition(theParent).IsRemoved; - } - - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, - const ParentId theParent) - { - return theGraph.Topo().Faces().Definition(theParent).VertexRefIds; - } - - static const BRepGraphInc::VertexRef& Ref(const BRepGraph& theGraph, const RefId theRefId) - { - return theGraph.Refs().Vertices().Entry(theRefId); - } - - static ChildId ChildIdOf(const BRepGraph&, const BRepGraphInc::VertexRef& theRef) - { - return theRef.VertexDefId; - } - - static const ChildDef& Child(const BRepGraph& theGraph, const ChildId theChildId) - { - return theGraph.Topo().Vertices().Definition(theChildId); - } -}; - +//! Traits for iterating over coedge children of a wire (direct, no ref indirection). struct CoEdgeOfWireTraits : public BaseTraits { static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) { - return theParent.IsValid(theGraph.Topo().Wires().Nb()) - && !theGraph.Topo().Wires().Definition(theParent).IsRemoved; + return theParent.IsValid(theGraph.Topo().Wires().Nb()) && !theParent.IsRemoved(theGraph); } - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Wires().Definition(theParent).CoEdgeRefIds; - } - - static const BRepGraphInc::CoEdgeRef& Ref(const BRepGraph& theGraph, const RefId theRefId) - { - return theGraph.Refs().CoEdges().Entry(theRefId); + return theGraph.Topo().Wires().Relations(theParent).CoEdgeIds; } - static ChildId ChildIdOf(const BRepGraph&, const BRepGraphInc::CoEdgeRef& theRef) + static const BRepGraphInc::CoEdgeDef& Ref(const BRepGraph& theGraph, const RefId theRefId) { - return theRef.CoEdgeDefId; + return theGraph.Topo().CoEdges().Definition(theRefId); } static const ChildDef& Child(const BRepGraph& theGraph, const ChildId theChildId) @@ -263,43 +180,37 @@ struct CoEdgeOfWireTraits : public BaseTraits { static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) { - return theParent.IsValid(theGraph.Topo().Wires().Nb()) - && !theGraph.Topo().Wires().Definition(theParent).IsRemoved; + return theParent.IsValid(theGraph.Topo().Wires().Nb()) && !theParent.IsRemoved(theGraph); } - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Wires().Definition(theParent).CoEdgeRefIds; + return theGraph.Topo().Wires().Relations(theParent).CoEdgeIds; } - static const BRepGraphInc::CoEdgeRef& Ref(const BRepGraph& theGraph, const RefId theRefId) + static const BRepGraphInc::CoEdgeDef& Ref(const BRepGraph& theGraph, const RefId theRefId) { - return theGraph.Refs().CoEdges().Entry(theRefId); + return theGraph.Topo().CoEdges().Definition(theRefId); } - static ChildId ChildIdOf(const BRepGraph& theGraph, const BRepGraphInc::CoEdgeRef& theRef) + static ChildId ChildIdOf(const BRepGraph& theGraph, const BRepGraphInc::CoEdgeDef& theRef) { - const BRepGraph_CoEdgeId aCoEdgeId = theRef.CoEdgeDefId; - if (!aCoEdgeId.IsValid(theGraph.Topo().CoEdges().Nb())) - { - return ChildId(); - } - - const BRepGraphInc::CoEdgeDef& aCoEdge = theGraph.Topo().CoEdges().Definition(aCoEdgeId); - if (aCoEdge.IsRemoved) + const BRepGraph_EdgeId aEdgeId = theRef.ChildEdgeId; + if (!aEdgeId.IsValid(theGraph.Topo().Edges().Nb()) || aEdgeId.IsRemoved(theGraph)) { return ChildId(); } - return aCoEdge.EdgeDefId; + return aEdgeId; } static const ChildDef& Child(const BRepGraph& theGraph, const ChildId theChildId) @@ -308,6 +219,7 @@ struct EdgeOfWireTraits : public BaseTraits& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().CompSolids().Definition(theParent).SolidRefIds; + return theGraph.Topo().CompSolids().Relations(theParent).SolidRefIds; } static const BRepGraphInc::SolidRef& Ref(const BRepGraph& theGraph, const RefId theRefId) @@ -333,7 +244,7 @@ struct SolidOfCompSolidTraits : public BaseTraits -{ - static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) - { - return theParent.IsValid(theGraph.Topo().Solids().Nb()) - && !theGraph.Topo().Solids().Definition(theParent).IsRemoved; - } - - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, - const ParentId theParent) - { - return theGraph.Topo().Solids().Definition(theParent).AuxChildRefIds; - } - - static const BRepGraphInc::ChildRef& Ref(const BRepGraph& theGraph, const RefId theRefId) - { - return theGraph.Refs().Children().Entry(theRefId); - } - - static ChildId ChildIdOf(const BRepGraph&, const BRepGraphInc::ChildRef& theRef) - { - return theRef.ChildDefId; - } - - static const ChildDef& Child(const BRepGraph& theGraph, const ChildId theChildId) - { - return *theGraph.Topo().Gen().TopoEntity(theChildId); - } -}; - +//! Traits for iterating over child nodes of a compound. struct ChildOfCompoundTraits : public BaseTraits& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Compounds().Definition(theParent).ChildRefIds; + return theGraph.Topo().Compounds().Relations(theParent).ChildRefIds; } static const BRepGraphInc::ChildRef& Ref(const BRepGraph& theGraph, const RefId theRefId) @@ -401,7 +278,7 @@ struct ChildOfCompoundTraits : public BaseTraits& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Products().Definition(theParent).OccurrenceRefIds; + return theGraph.Topo().Products().Relations(theParent).OccurrenceRefIds; } static const BRepGraphInc::OccurrenceRef& Ref(const BRepGraph& theGraph, const RefId theRefId) @@ -435,7 +312,7 @@ struct OccurrenceOfProductTraits : public BaseTraits(myRefIds->Size()); + if constexpr (std::is_convertible_v) + { + myNbRefs = theGraph.Topo().Gen().Nb(BRepGraph_NodeId(RefId()).NodeKind); + } + else + { + myNbRefs = theGraph.Refs().Gen().Nb(BRepGraph_RefId(RefId()).RefKind); + } + + if constexpr (TraitsT::THE_IS_DIRECT) + { + myNbChildren = myNbRefs; + } + else + { + if constexpr (!std::is_same_v) + { + myNbChildren = theGraph.Topo().Gen().Nb(BRepGraph_NodeId(ChildId()).NodeKind); + } + } skipRemoved(); } @@ -471,16 +368,59 @@ public: void Next() { ++myIndex; + // Fast-path: check if the very next element is already valid. + if (myRefIds != nullptr && myIndex < myLength) + { + const RefId aRefId = myRefIds->Value(static_cast(myIndex)); + if (aRefId.IsValid(myNbRefs) && !aRefId.IsRemoved(myGraph)) + { + if constexpr (TraitsT::THE_IS_DIRECT) + { + myCurrentChild = ChildId(aRefId); + return; + } + else + { + const typename TraitsT::RefEntry& aRef = TraitsT::Ref(myGraph, aRefId); + const ChildId aChildId = TraitsT::ChildIdOf(myGraph, aRef); + if constexpr (std::is_same_v) + { + if (myGraph.Topo().Gen().IsActive(aChildId)) + { + myCurrentChild = aChildId; + return; + } + } + else if (aChildId.IsValid(myNbChildren) && !aChildId.IsRemoved(myGraph)) + { + myCurrentChild = aChildId; + return; + } + } + } + } + // Slow-path: full scan for next valid element. skipRemoved(); } [[nodiscard]] ChildId CurrentId() const { - return TraitsT::ChildIdOf(myGraph, - TraitsT::Ref(myGraph, myRefIds->Value(static_cast(myIndex)))); + Standard_ASSERT_VOID(More(), "DefsOfParent::CurrentId() called on exhausted iterator"); + return myCurrentChild; + } + + [[nodiscard]] const ChildDef& Current() const + { + Standard_ASSERT_VOID(More(), "DefsOfParent::Current() called on exhausted iterator"); + return TraitsT::Child(myGraph, CurrentId()); } - [[nodiscard]] const ChildDef& Current() const { return TraitsT::Child(myGraph, CurrentId()); } + //! Returns the reference/coedge entry that carries the current child relation. + [[nodiscard]] RefId CurrentRefId() const + { + return myRefIds != nullptr && myIndex < myLength ? myRefIds->Value(static_cast(myIndex)) + : RefId(); + } [[nodiscard]] uint32_t Index() const { return myIndex; } @@ -498,14 +438,31 @@ private: { while (myRefIds != nullptr && myIndex < myLength) { - const typename TraitsT::RefEntry& aRef = - TraitsT::Ref(myGraph, myRefIds->Value(static_cast(myIndex))); - if (!aRef.IsRemoved) + const RefId aRefId = myRefIds->Value(static_cast(myIndex)); + if (aRefId.IsValid(myNbRefs) && !aRefId.IsRemoved(myGraph)) { - const BRepGraphInc::BaseDef* aChildDef = - childBaseDef(myGraph, TraitsT::ChildIdOf(myGraph, aRef)); - if (aChildDef != nullptr && !aChildDef->IsRemoved) + const ChildId aChildId = [&]() { + if constexpr (TraitsT::THE_IS_DIRECT) + { + return ChildId(aRefId); + } + else + { + const typename TraitsT::RefEntry& aRef = TraitsT::Ref(myGraph, aRefId); + return TraitsT::ChildIdOf(myGraph, aRef); + } + }(); + if constexpr (std::is_same_v) + { + if (myGraph.Topo().Gen().IsActive(aChildId)) + { + myCurrentChild = aChildId; + return; + } + } + else if (aChildId.IsValid(myNbChildren) && !aChildId.IsRemoved(myGraph)) { + myCurrentChild = aChildId; return; } } @@ -514,14 +471,17 @@ private: } const BRepGraph& myGraph; - const NCollection_DynamicArray* myRefIds = nullptr; - uint32_t myIndex = 0; - uint32_t myLength = 0; + const NCollection_LinearVector* myRefIds = nullptr; + ChildId myCurrentChild{}; + uint32_t myIndex = 0; + uint32_t myLength = 0; + uint32_t myNbRefs = 0; + uint32_t myNbChildren = 0; }; -//! @brief Direct active vertex children of an edge. +//! @brief Direct active boundary vertex children of an edge. //! -//! Iteration order is start vertex, end vertex, then internal/external vertices. +//! Iteration order is start vertex, then end vertex. class DefsVertexOfEdge { public: @@ -531,14 +491,15 @@ public: DefsVertexOfEdge(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdgeId) : myGraph(theGraph) { - if (!theEdgeId.IsValid(theGraph.Topo().Edges().Nb()) - || theGraph.Topo().Edges().Definition(theEdgeId).IsRemoved) + if (!theEdgeId.IsValid(theGraph.Topo().Edges().Nb()) || theEdgeId.IsRemoved(theGraph)) { return; } - myEdge = &theGraph.Topo().Edges().Definition(theEdgeId); - myLength = 2u + static_cast(myEdge->InternalVertexRefIds.Size()); + myEdge = &theGraph.Topo().Edges().Definition(theEdgeId); + myLength = 2u; + myNbVertexRefs = theGraph.Refs().Vertices().Nb(); + myNbVertices = theGraph.Topo().Vertices().Nb(); skipRemoved(); } @@ -552,14 +513,22 @@ public: [[nodiscard]] ChildId CurrentId() const { - return myGraph.Refs().Vertices().Entry(currentRefId()).VertexDefId; + Standard_ASSERT_VOID(More(), "DefsVertexOfEdge::CurrentId() called on exhausted iterator"); + return myGraph.Refs().Vertices().Entry(currentRefId()).ChildVertexId; } [[nodiscard]] const ChildDef& Current() const { + Standard_ASSERT_VOID(More(), "DefsVertexOfEdge::Current() called on exhausted iterator"); return myGraph.Topo().Vertices().Definition(CurrentId()); } + //! Returns the start/end vertex reference entry that carries the current child relation. + [[nodiscard]] BRepGraph_VertexRefId CurrentRefId() const + { + return More() ? currentRefId() : BRepGraph_VertexRefId(); + } + [[nodiscard]] uint32_t Index() const { return myIndex; } //! Returns an STL-compatible iterator for range-based for loops. @@ -578,11 +547,7 @@ private: { return myEdge->StartVertexRefId; } - if (theIndex == 1) - { - return myEdge->EndVertexRefId; - } - return myEdge->InternalVertexRefIds.Value(static_cast(theIndex - 2)); + return myEdge->EndVertexRefId; } [[nodiscard]] BRepGraph_VertexRefId currentRefId() const { return refIdAt(myIndex); } @@ -592,27 +557,26 @@ private: while (myEdge != nullptr && myIndex < myLength) { const BRepGraph_VertexRefId aRefId = refIdAt(myIndex); - if (aRefId.IsValid()) + if (aRefId.IsValid(myNbVertexRefs) && !myGraph.Refs().Gen().IsRemoved(aRefId)) { const BRepGraphInc::VertexRef& aRef = myGraph.Refs().Vertices().Entry(aRefId); - if (!aRef.IsRemoved) + if (!aRef.ChildVertexId.IsValid(myNbVertices) || aRef.ChildVertexId.IsRemoved(myGraph)) { - const BRepGraphInc::BaseDef* aChildDef = - myGraph.Topo().Gen().TopoEntity(BRepGraph_NodeId(aRef.VertexDefId)); - if (aChildDef != nullptr && !aChildDef->IsRemoved) - { - return; - } + ++myIndex; + continue; } + return; } ++myIndex; } } const BRepGraph& myGraph; - const BRepGraphInc::EdgeDef* myEdge = nullptr; - uint32_t myIndex = 0; - uint32_t myLength = 0; + const BRepGraphInc::EdgeDef* myEdge = nullptr; + uint32_t myIndex = 0; + uint32_t myLength = 0; + uint32_t myNbVertexRefs = 0; + uint32_t myNbVertices = 0; }; } // namespace BRepGraph_DefsIterator @@ -621,18 +585,12 @@ using BRepGraph_DefsShellOfSolid = BRepGraph_DefsIterator::DefsOfParent; using BRepGraph_DefsFaceOfShell = BRepGraph_DefsIterator::DefsOfParent; -using BRepGraph_DefsChildOfShell = - BRepGraph_DefsIterator::DefsOfParent; using BRepGraph_DefsEdgeOfWire = BRepGraph_DefsIterator::DefsOfParent; using BRepGraph_DefsWireOfFace = BRepGraph_DefsIterator::DefsOfParent; -using BRepGraph_DefsVertexOfFace = - BRepGraph_DefsIterator::DefsOfParent; using BRepGraph_DefsCoEdgeOfWire = BRepGraph_DefsIterator::DefsOfParent; -using BRepGraph_DefsChildOfSolid = - BRepGraph_DefsIterator::DefsOfParent; using BRepGraph_DefsSolidOfCompSolid = BRepGraph_DefsIterator::DefsOfParent; using BRepGraph_DefsChildOfCompound = @@ -641,4 +599,4 @@ using BRepGraph_DefsOccurrenceOfProduct = BRepGraph_DefsIterator::DefsOfParent; using BRepGraph_DefsVertexOfEdge = BRepGraph_DefsIterator::DefsVertexOfEdge; -#endif // _BRepGraph_DefsIterator_HeaderFile \ No newline at end of file +#endif // _BRepGraph_DefsIterator_HeaderFile diff --git a/opencascade/BRepGraph_EditorView.hxx b/opencascade/BRepGraph_EditorView.hxx index 66787020b..784697860 100644 --- a/opencascade/BRepGraph_EditorView.hxx +++ b/opencascade/BRepGraph_EditorView.hxx @@ -15,11 +15,16 @@ #define _BRepGraph_EditorView_HeaderFile #include +#include #include +#include #include +#include #include #include #include +#include +#include #include #include #include @@ -45,8 +50,9 @@ class Poly_PolygonOnTriangulation; //! faces, shells, solids, compounds) and assembly nodes (products, occurrences) //! without an existing TopoDS_Shape. //! - Field-level RAII-scoped mutation via Mut*() guards (Edges().Mut, Faces().Mut, -//! Products().Mut, Occurrences().Mut, Reps().MutSurface, etc.) with automatic cache invalidation -//! and upward SubtreeGen propagation on guard destruction. +//! Products().Mut, Occurrences().Mut, Edges().Mut, Faces().Mut, +//! etc.) with automatic cache invalidation and upward SubtreeGen propagation on +//! guard destruction. //! - Incremental shape appending, soft-deletion of nodes, and deferred invalidation //! mode for batched structural edit loops under external serialization. //! Obtained via BRepGraph::Editor(). @@ -54,7 +60,8 @@ class Poly_PolygonOnTriangulation; //! Each Ops class is accessed via a non-const reference accessor: //! theGraph.Editor().Vertices().Add(...) //! theGraph.Editor().Edges().Add(...) -//! theGraph.Editor().CoEdges().SetPCurve(...) +//! theGraph.Editor().CoEdges().Add(edge, face, curve2d, first, last, ori) +//! theGraph.Editor().Products().Add(shapeRoot, placement) //! theGraph.Editor().Gen().RemoveNode(...) //! //! Contract notes: @@ -71,99 +78,6 @@ class Poly_PolygonOnTriangulation; class BRepGraph::EditorView { public: - //! Representation mutation guards (Surface, Curve3D, Curve2D, Triangulation, - //! Polygon3D, Polygon2D, PolygonOnTri). All `Mut*()` accessors raise - //! `Standard_ProgramError` for null, out-of-range, or removed typed ids. - //! Access via `BRepGraph::EditorView::Reps()`. - class RepOps - { - public: - //! Return scoped mutable surface representation guard. - [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard MutSurface( - const BRepGraph_SurfaceRepId theSurface); - //! Return scoped mutable 3D curve representation guard. - [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard MutCurve3D( - const BRepGraph_Curve3DRepId theCurve); - //! Return scoped mutable 2D curve representation guard. - [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard MutCurve2D( - const BRepGraph_Curve2DRepId theCurve); - //! Return scoped mutable triangulation representation guard. - [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard - MutTriangulation(const BRepGraph_TriangulationRepId theTriangulation); - //! Return scoped mutable 3D polygon representation guard. - [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard MutPolygon3D( - const BRepGraph_Polygon3DRepId thePolygon); - //! Return scoped mutable 2D polygon representation guard. - [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard MutPolygon2D( - const BRepGraph_Polygon2DRepId thePolygon); - //! Return scoped mutable polygon-on-triangulation representation guard. - [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard MutPolygonOnTri( - const BRepGraph_PolygonOnTriRepId thePolygon); - - //! Set the surface handle on a SurfaceRep. - Standard_EXPORT void SetSurface(const BRepGraph_SurfaceRepId theRep, - const occ::handle& theSurface); - Standard_EXPORT void SetSurface(BRepGraph_MutGuard& theMut, - const occ::handle& theSurface); - - //! Set the 3D curve handle on a Curve3DRep. - Standard_EXPORT void SetCurve3D(const BRepGraph_Curve3DRepId theRep, - const occ::handle& theCurve); - Standard_EXPORT void SetCurve3D(BRepGraph_MutGuard& theMut, - const occ::handle& theCurve); - - //! Set the 2D curve handle on a Curve2DRep. - Standard_EXPORT void SetCurve2D(const BRepGraph_Curve2DRepId theRep, - const occ::handle& theCurve); - Standard_EXPORT void SetCurve2D(BRepGraph_MutGuard& theMut, - const occ::handle& theCurve); - - //! Set the triangulation handle on a TriangulationRep. - Standard_EXPORT void SetTriangulation(const BRepGraph_TriangulationRepId theRep, - const occ::handle& theTri); - Standard_EXPORT void SetTriangulation( - BRepGraph_MutGuard& theMut, - const occ::handle& theTri); - - //! Set the polygon handle on a Polygon3DRep. - Standard_EXPORT void SetPolygon3D(const BRepGraph_Polygon3DRepId theRep, - const occ::handle& thePolygon); - Standard_EXPORT void SetPolygon3D(BRepGraph_MutGuard& theMut, - const occ::handle& thePolygon); - - //! Set the polygon handle on a Polygon2DRep. - Standard_EXPORT void SetPolygon2D(const BRepGraph_Polygon2DRepId theRep, - const occ::handle& thePolygon); - Standard_EXPORT void SetPolygon2D(BRepGraph_MutGuard& theMut, - const occ::handle& thePolygon); - - //! Set the polygon-on-triangulation handle on a PolygonOnTriRep. - Standard_EXPORT void SetPolygonOnTri( - const BRepGraph_PolygonOnTriRepId theRep, - const occ::handle& thePolygon); - Standard_EXPORT void SetPolygonOnTri( - BRepGraph_MutGuard& theMut, - const occ::handle& thePolygon); - - //! Set the triangulation rep id linked to a PolygonOnTriRep. - Standard_EXPORT void SetPolygonOnTriTriangulationId( - const BRepGraph_PolygonOnTriRepId theRep, - const BRepGraph_TriangulationRepId theTriRep); - Standard_EXPORT void SetPolygonOnTriTriangulationId( - BRepGraph_MutGuard& theMut, - const BRepGraph_TriangulationRepId theTriRep); - - private: - friend class EditorView; - - explicit RepOps(BRepGraph* theGraph) - : myGraph(theGraph) - { - } - - BRepGraph* myGraph; - }; - //! @brief Vertex creation operations. class VertexOps { @@ -204,31 +118,19 @@ public: const double theTolerance); //! Set the orientation of a vertex reference. - Standard_EXPORT void SetRefOrientation(const BRepGraph_VertexRefId theVertexRef, - const TopAbs_Orientation theOrientation); + Standard_EXPORT void SetRefOrientation(const BRepGraph_VertexRefId theVertexRef, + const BRepGraphInc::ParityOrientation theOrientation); //! Set the orientation inside a batched mutation scope. Standard_EXPORT void SetRefOrientation(BRepGraph_MutGuard& theMut, - const TopAbs_Orientation theOrientation); - - //! Set the local location of a vertex reference and fire immediate notification. - //! @param[in] theVertexRef typed vertex reference identifier - //! @param[in] theLoc new local location - Standard_EXPORT void SetRefLocalLocation(const BRepGraph_VertexRefId theVertexRef, - const TopLoc_Location& theLoc); - - //! Set the local location of a vertex reference inside a batched mutation scope. - //! @param[in] theMut active mutable vertex reference guard - //! @param[in] theLoc new local location - Standard_EXPORT void SetRefLocalLocation(BRepGraph_MutGuard& theMut, - const TopLoc_Location& theLoc); + const BRepGraphInc::ParityOrientation theOrientation); //! Rewire a vertex reference to a different vertex def (rebinds VertexToEdges if parent is //! Edge). - Standard_EXPORT void SetRefVertexDefId(const BRepGraph_VertexRefId theVertexRef, - const BRepGraph_VertexId theVertex); - Standard_EXPORT void SetRefVertexDefId(BRepGraph_MutGuard& theMut, - const BRepGraph_VertexId theVertex); + Standard_EXPORT void SetRefChildVertexId(const BRepGraph_VertexRefId theVertexRef, + const BRepGraph_VertexId theVertex); + Standard_EXPORT void SetRefChildVertexId(BRepGraph_MutGuard& theMut, + const BRepGraph_VertexId theVertex); private: friend class EditorView; @@ -261,18 +163,6 @@ public: const double theLast, const double theTolerance); - //! Add an internal or external direct vertex usage to an edge definition. - //! The vertex is stored in EdgeDef.InternalVertexRefIds; boundary start/end - //! vertices remain owned by StartVertexRefId and EndVertexRefId. - //! @param[in] theEdgeEntity typed edge definition identifier - //! @param[in] theVertexEntity typed vertex definition identifier - //! @param[in] theOri orientation of the direct vertex usage on the edge - //! @return typed vertex reference identifier, or invalid if inputs are not active - [[nodiscard]] Standard_EXPORT BRepGraph_VertexRefId - AddInternalVertex(const BRepGraph_EdgeId theEdgeEntity, - const BRepGraph_VertexId theVertexEntity, - const TopAbs_Orientation theOri = TopAbs_INTERNAL); - //! Split a single edge definition at a vertex and 3D-curve parameter. //! Creates two new EdgeDef slots, splits all PCurve nodes at the corresponding //! 2D parameter, and updates every wire that contained the original edge. @@ -287,53 +177,40 @@ public: BRepGraph_EdgeId& theSubA, BRepGraph_EdgeId& theSubB); - //! Detach one exact direct vertex ref from an edge definition. - //! Supports both boundary fixed slots (StartVertexRefId / EndVertexRefId) and - //! entries stored in EdgeDef.InternalVertexRefIds. - //! @param[in] theEdgeDefId edge definition identifier + //! Detach one exact edge-owned vertex ref from an edge definition. + //! Supports only the persisted boundary slots (StartVertexRefId / + //! EndVertexRefId). Supplemental direct-vertex usages are stored in + //! BRepGraph_LayerTopoSupplement and are not removed through this API. + //! @param[in] theChildEdgeId edge definition identifier //! @param[in] theVertexRefId exact edge-owned vertex reference identifier //! @return true if the active edge-owned usage was removed - [[nodiscard]] Standard_EXPORT bool RemoveVertex(const BRepGraph_EdgeId theEdgeDefId, + [[nodiscard]] Standard_EXPORT bool RemoveVertex(const BRepGraph_EdgeId theChildEdgeId, const BRepGraph_VertexRefId theVertexRefId); //! Remap one edge-owned vertex reference to point at a different vertex //! definition, preserving the existing orientation and local location. //! Intended for boundary-vertex substitution without a full edge rebuild //! (e.g. stitching shared endpoints after a ShapeFix pass). - //! @param[in] theEdgeDefId edge owning the vertex reference - //! @param[in] theOldVertexRefId exact vertex reference to remap (boundary or internal) - //! @param[in] theNewVertexDefId replacement vertex definition + //! @param[in] theChildEdgeId edge owning the vertex reference + //! @param[in] theOldVertexRefId exact boundary vertex reference to remap + //! @param[in] theNewChildVertexId replacement vertex definition //! @return typed id of the newly created vertex reference, or invalid if //! any input was inactive or the old ref did not belong to this edge [[nodiscard]] Standard_EXPORT BRepGraph_VertexRefId - ReplaceVertex(const BRepGraph_EdgeId theEdgeDefId, + ReplaceVertex(const BRepGraph_EdgeId theChildEdgeId, const BRepGraph_VertexRefId theOldVertexRefId, - const BRepGraph_VertexId theNewVertexDefId); + const BRepGraph_VertexId theNewChildVertexId); //! Return scoped mutable edge definition guard. [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard Mut( const BRepGraph_EdgeId theEdge); - //! Returns true iff the edge appears as a seam on the given face (two CoEdges - //! of theEdge share theFace). - //! @param[in] theEdge typed edge definition identifier - //! @param[in] theFace typed face definition identifier - //! @return true if the edge is a seam on the given face - [[nodiscard]] Standard_EXPORT bool IsSeamOnFace(const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace) const; - - //! Set the geometric regularity (C^k) for an edge across a pair of faces in - //! BRepGraph_LayerRegularity. theFace1 == theFace2 sets the seam continuity - //! across the closed-surface seam line. Requires the layer to be registered. - //! @param[in] theEdge typed edge definition identifier - //! @param[in] theFace1 first face (or seam face when theFace2 == theFace1) - //! @param[in] theFace2 second face - //! @param[in] theContinuity continuity (GeomAbs_Shape) - //! @return true if written; false if the layer is not registered - Standard_EXPORT bool SetRegularity(const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace1, - const BRepGraph_FaceId theFace2, - const GeomAbs_Shape theContinuity); + //! Reverse the edge: swap StartVertexRefId and EndVertexRefId. Used by + //! healing/sewing when a caller wants the edge's boundary order flipped. + //! Does not alter the parametric range (callers needing reparametrization + //! should follow up with SetParamRange). + //! @param[in] theEdge edge definition identifier + Standard_EXPORT void Reverse(const BRepGraph_EdgeId theEdge); //! Set the tolerance of an edge definition and fire immediate notification. //! @param[in] theEdge typed edge definition identifier @@ -354,46 +231,38 @@ public: const double theFirst, const double theLast); - //! Set the SameParameter flag of an edge definition. - Standard_EXPORT void SetSameParameter(const BRepGraph_EdgeId theEdge, - const bool theSameParameter); - Standard_EXPORT void SetSameParameter(BRepGraph_MutGuard& theMut, - const bool theSameParameter); - - //! Set the SameRange flag of an edge definition. - Standard_EXPORT void SetSameRange(const BRepGraph_EdgeId theEdge, const bool theSameRange); - Standard_EXPORT void SetSameRange(BRepGraph_MutGuard& theMut, - const bool theSameRange); - - //! Set the IsDegenerate flag of an edge definition. - Standard_EXPORT void SetDegenerate(const BRepGraph_EdgeId theEdge, const bool theIsDegenerate); - Standard_EXPORT void SetDegenerate(BRepGraph_MutGuard& theMut, - const bool theIsDegenerate); - - //! Set the Curve3DRep id bound to an edge (invalid id clears the binding). - Standard_EXPORT void SetCurve3DRepId(const BRepGraph_EdgeId theEdge, - const BRepGraph_Curve3DRepId theRep); - Standard_EXPORT void SetCurve3DRepId(BRepGraph_MutGuard& theMut, - const BRepGraph_Curve3DRepId theRep); - - //! Set the Polygon3DRep id bound to an edge (invalid id clears the binding). - Standard_EXPORT void SetPolygon3DRepId(const BRepGraph_EdgeId theEdge, - const BRepGraph_Polygon3DRepId theRep); - Standard_EXPORT void SetPolygon3DRepId(BRepGraph_MutGuard& theMut, - const BRepGraph_Polygon3DRepId theRep); - - //! Set the IsClosed flag (StartVertex == EndVertex topology) of an edge. - Standard_EXPORT void SetIsClosed(const BRepGraph_EdgeId theEdge, const bool theIsClosed); - Standard_EXPORT void SetIsClosed(BRepGraph_MutGuard& theMut, - const bool theIsClosed); - - //! Set the start vertex-ref id (rebinds VertexToEdges). Caller maintains reverse indices. + //! Set the 3D curve on an edge. Creates an owned EdgeCurve3DRep record + //! and an associated Curve3DRep for edge geometry access. + //! @param[in] theEdge edge definition identifier + //! @param[in] theCurve 3D curve geometry (must not be null) + //! @param[in] theFirst first curve parameter + //! @param[in] theLast last curve parameter + Standard_EXPORT void SetCurve(const BRepGraph_EdgeId theEdge, + const occ::handle& theCurve, + const double theFirst, + const double theLast); + + //! Clear the 3D curve on an edge. Removes the owned use record binding. + //! @param[in] theEdge edge definition identifier + Standard_EXPORT void ClearCurve(const BRepGraph_EdgeId theEdge); + + //! Set the persistent 3D polygon on an edge. Creates an owned EdgePolygon3DRep record. + //! @param[in] theEdge edge definition identifier + //! @param[in] thePolygon 3D polygon (must not be null) + Standard_EXPORT void SetPersistentPolygon3D(const BRepGraph_EdgeId theEdge, + const occ::handle& thePolygon); + + //! Clear the persistent 3D polygon on an edge. + //! @param[in] theEdge edge definition identifier + Standard_EXPORT void ClearPersistentPolygon3D(const BRepGraph_EdgeId theEdge); + + //! Set the start vertex-ref id and rebind the vertex-to-edge relation. Standard_EXPORT void SetStartVertexRefId(const BRepGraph_EdgeId theEdge, const BRepGraph_VertexRefId theVertexRef); Standard_EXPORT void SetStartVertexRefId(BRepGraph_MutGuard& theMut, const BRepGraph_VertexRefId theVertexRef); - //! Set the end vertex-ref id (rebinds VertexToEdges). Caller maintains reverse indices. + //! Set the end vertex-ref id and rebind the vertex-to-edge relation. Standard_EXPORT void SetEndVertexRefId(const BRepGraph_EdgeId theEdge, const BRepGraph_VertexRefId theVertexRef); Standard_EXPORT void SetEndVertexRefId(BRepGraph_MutGuard& theMut, @@ -414,16 +283,6 @@ public: class CoEdgeOps { public: - //! Create a new Curve2DRep in storage and return its typed identifier. - //! Use this when assigning a new PCurve to an existing CoEdge entity - //! via Editor().MutCoEdge() inside a larger mutation sequence. - //! For one-shot creation and binding of a face-context PCurve, use - //! AddPCurve(). - //! @param[in] theCurve2d the 2D parametric curve handle - //! @return typed Curve2DRep identifier, or invalid if the curve is null - [[nodiscard]] Standard_EXPORT BRepGraph_Curve2DRepId - CreateCurve2DRep(const occ::handle& theCurve2d); - //! Assign or clear the PCurve bound to an existing coedge. //! Creates a new Curve2DRep for non-null curves and stores its id on the coedge. //! Pass a null handle to clear the stored PCurve binding. @@ -432,35 +291,41 @@ public: Standard_EXPORT void SetPCurve(const BRepGraph_CoEdgeId theCoEdge, const occ::handle& theCurve2d); - //! Attach a PCurve to an edge for a given face context. - //! Creates a new CoEdge entity with Curve2DRep and updates reverse indices. + //! Create a new CoEdge entity linking an edge with an orientation. + //! The CoEdge is free-floating (no parent wire); bind it to a wire + //! via WireOps::Add(). + //! @param[in] theEdge typed edge definition identifier + //! @param[in] theOrientation orientation of the edge in the wire + //! @return typed coedge identifier, or invalid if the edge is invalid + [[nodiscard]] Standard_EXPORT BRepGraph_CoEdgeId + Add(const BRepGraph_EdgeId theEdge, const BRepGraphInc::ParityOrientation theOrientation); + + //! Create a new CoEdge entity with a PCurve for a given edge-face pair. + //! Creates a new CoEdge entity with Curve2DRep and updates relation tables. //! This always appends a new CoEdge entry for the edge-face pair; callers //! should avoid duplicate creation unless multiple bindings are intentional //! for the modeled topology. - //! Prefer this route when the caller needs to add a face-context PCurve in - //! one operation. For editing an already identified CoEdge inside a larger - //! mutation sequence, use CreateCurve2DRep() with Editor().MutCoEdge(). + //! For editing an already identified CoEdge inside a larger + //! mutation sequence, use CoEdges().SetPCurve(). //! @param[in] theEdgeEntity typed edge definition identifier //! @param[in] theFaceEntity typed face definition identifier //! @param[in] theCurve2d 2D curve geometry //! @param[in] theFirst first curve parameter //! @param[in] theLast last curve parameter //! @param[in] theEdgeOrientation edge orientation on the face - Standard_EXPORT void AddPCurve(const BRepGraph_EdgeId theEdgeEntity, - const BRepGraph_FaceId theFaceEntity, - const occ::handle& theCurve2d, - const double theFirst, - const double theLast, - const TopAbs_Orientation theEdgeOrientation = TopAbs_FORWARD); + //! @return typed coedge identifier, or invalid if inputs are not active + [[nodiscard]] Standard_EXPORT BRepGraph_CoEdgeId + Add(const BRepGraph_EdgeId theEdgeEntity, + const BRepGraph_FaceId theFaceEntity, + const occ::handle& theCurve2d, + const double theFirst, + const double theLast, + const BRepGraphInc::ParityOrientation theEdgeOrientation = TopAbs_FORWARD); //! Return scoped mutable coedge definition guard. [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard Mut( const BRepGraph_CoEdgeId theCoEdge); - //! Return scoped mutable coedge reference guard. - [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard MutRef( - const BRepGraph_CoEdgeRefId theCoEdgeRef); - //! Set the parametric range of a coedge definition and fire immediate notification. //! @param[in] theCoEdge typed coedge definition identifier //! @param[in] theFirst new first parameter value @@ -477,83 +342,61 @@ public: double theFirst, double theLast); - //! Set the local location of a coedge reference and fire immediate notification. - //! @param[in] theCoEdgeRef typed coedge reference identifier - //! @param[in] theLoc new local location - Standard_EXPORT void SetRefLocalLocation(const BRepGraph_CoEdgeRefId theCoEdgeRef, - const TopLoc_Location& theLoc); - - //! Set the local location of a coedge reference inside a batched mutation scope. - //! @param[in] theMut active mutable coedge reference guard - //! @param[in] theLoc new local location - Standard_EXPORT void SetRefLocalLocation(BRepGraph_MutGuard& theMut, - const TopLoc_Location& theLoc); - - //! Rewire a coedge reference to a different coedge def (rebinds CoEdgeToWires + EdgeToWires). - Standard_EXPORT void SetRefCoEdgeDefId(const BRepGraph_CoEdgeRefId theCoEdgeRef, - const BRepGraph_CoEdgeId theCoEdge); - Standard_EXPORT void SetRefCoEdgeDefId(BRepGraph_MutGuard& theMut, - const BRepGraph_CoEdgeId theCoEdge); - //! Set the orientation of a coedge definition. - Standard_EXPORT void SetOrientation(const BRepGraph_CoEdgeId theCoEdge, - const TopAbs_Orientation theOrientation); + Standard_EXPORT void SetOrientation(const BRepGraph_CoEdgeId theCoEdge, + const BRepGraphInc::ParityOrientation theOrientation); Standard_EXPORT void SetOrientation(BRepGraph_MutGuard& theMut, - const TopAbs_Orientation theOrientation); - - //! Set the UV box (UV1 = at ParamFirst, UV2 = at ParamLast) of a coedge definition. - Standard_EXPORT void SetUVBox(const BRepGraph_CoEdgeId theCoEdge, - const gp_Pnt2d& theUV1, - const gp_Pnt2d& theUV2); - Standard_EXPORT void SetUVBox(BRepGraph_MutGuard& theMut, - const gp_Pnt2d& theUV1, - const gp_Pnt2d& theUV2); - - //! Continuity is a property of (Edge, Face1, Face2) and lives in - //! BRepGraph_LayerRegularity. Use EditorView::EdgeOps::SetRegularity to write, - //! BRepGraph_Tool::Edge::Continuity to read. - - //! Set the Curve2DRep id bound to a coedge (invalid id clears the binding). - Standard_EXPORT void SetCurve2DRepId(const BRepGraph_CoEdgeId theCoEdge, - const BRepGraph_Curve2DRepId theRep); - Standard_EXPORT void SetCurve2DRepId(BRepGraph_MutGuard& theMut, - const BRepGraph_Curve2DRepId theRep); - - //! Set the Polygon2DRep id bound to a coedge. - Standard_EXPORT void SetPolygon2DRepId(const BRepGraph_CoEdgeId theCoEdge, - const BRepGraph_Polygon2DRepId theRep); - Standard_EXPORT void SetPolygon2DRepId(BRepGraph_MutGuard& theMut, - const BRepGraph_Polygon2DRepId theRep); - - //! Set the PolygonOnTriRep id bound to a coedge. - Standard_EXPORT void SetPolygonOnTriRepId(const BRepGraph_CoEdgeId theCoEdge, - const BRepGraph_PolygonOnTriRepId theRep); - Standard_EXPORT void SetPolygonOnTriRepId(BRepGraph_MutGuard& theMut, - const BRepGraph_PolygonOnTriRepId theRep); - - //! Drop face-bound parametric payload (PCurve, param range, continuity, UVs) + const BRepGraphInc::ParityOrientation theOrientation); + + //! Set the PCurve on a coedge. Creates an owned CoEdgeCurve2DRep record. + //! @param[in] theCoEdge coedge definition identifier + //! @param[in] theCurve2d 2D curve geometry (must not be null) + //! @param[in] theFirst first curve parameter + //! @param[in] theLast last curve parameter + Standard_EXPORT void SetPCurve(const BRepGraph_CoEdgeId theCoEdge, + const occ::handle& theCurve2d, + const double theFirst, + const double theLast); + + //! Clear the PCurve on a coedge. + //! @param[in] theCoEdge coedge definition identifier + Standard_EXPORT void ClearPCurve(const BRepGraph_CoEdgeId theCoEdge); + + //! Set the persistent 2D polygon on a coedge. + //! @param[in] theCoEdge coedge definition identifier + //! @param[in] thePolygon 2D polygon (must not be null) + Standard_EXPORT void SetPersistentPolygon2D(const BRepGraph_CoEdgeId theCoEdge, + const occ::handle& thePolygon); + + //! Set the persistent polygon-on-triangulation on a coedge. + //! The triangulation is resolved via CoEdgeDef.FaceId -> FaceDef.TriangulationRepId. + //! @param[in] theCoEdge coedge definition identifier + //! @param[in] thePolygon polygon-on-triangulation (must not be null) + Standard_EXPORT void SetPersistentPolygonOnTri( + const BRepGraph_CoEdgeId theCoEdge, + const occ::handle& thePolygon); + + //! Drop face-bound parametric representation (PCurve, param range, continuity, UVs) //! while keeping structural links - used when the owning face is removed. - Standard_EXPORT void ClearPCurveBinding(const BRepGraph_CoEdgeId theCoEdge); - Standard_EXPORT void ClearPCurveBinding(BRepGraph_MutGuard& theMut); + Standard_EXPORT void ResetPCurveBinding(const BRepGraph_CoEdgeId theCoEdge); + Standard_EXPORT void ResetPCurveBinding(BRepGraph_MutGuard& theMut); //! Set the seam-pair id linking two coedges of a seam edge (invalid breaks the link). // To establish seam-ness, ensure two CoEdges exist on the same (Edge, Face) // with opposite orientations; the seam relation is then queryable via // BRepGraph_Tool::CoEdge::SeamPair. - //! Rewire a coedge to a different parent edge (rebinds EdgeToCoEdges, EdgeToWires, - //! EdgeToFaces). Caller maintains reverse indices. - Standard_EXPORT void SetEdgeDefId(const BRepGraph_CoEdgeId theCoEdge, - const BRepGraph_EdgeId theEdge); - Standard_EXPORT void SetEdgeDefId(BRepGraph_MutGuard& theMut, - const BRepGraph_EdgeId theEdge); + //! Rewire a coedge to a different child edge and rebind edge parent/use relations. + Standard_EXPORT void SetChildEdgeId(const BRepGraph_CoEdgeId theCoEdge, + const BRepGraph_EdgeId theEdge); + Standard_EXPORT void SetChildEdgeId(BRepGraph_MutGuard& theMut, + const BRepGraph_EdgeId theEdge); - //! Rewire a coedge to a different owning face (rebinds EdgeToFaces). Caller maintains reverse - //! indices. - Standard_EXPORT void SetFaceDefId(const BRepGraph_CoEdgeId theCoEdge, - const BRepGraph_FaceId theFace); - Standard_EXPORT void SetFaceDefId(BRepGraph_MutGuard& theMut, - const BRepGraph_FaceId theFace); + //! Rewire a coedge to a different owning face and rebind edge-to-face relations. + Standard_EXPORT void SetFaceId(const BRepGraph_CoEdgeId theCoEdge, + const BRepGraph_FaceId theFace); + Standard_EXPORT void SetFaceId(BRepGraph_MutGuard& theMut, + const BRepGraph_FaceId theFace); private: friend class EditorView; @@ -570,36 +413,113 @@ public: class WireOps { public: - //! Add a wire definition to the graph. - //! Each pair is (EdgeDefId, OrientationInWire). - //! @param[in] theEdges ordered edge entries + //! Status returned by wire coedge-order prechecks. + enum class CoEdgeOrderStatus + { + Ready, //!< Input is valid and already connected in given order. + Reordered, //!< Input is valid after internal canonical reordering. + AlreadyCurrent, //!< Input equals current stored order; mutation can be skipped. + AlreadyContained, //!< Append precheck found the coedge already in the wire. + Empty, //!< Input contains no coedges. + InvalidWire, //!< Wire id is invalid or removed. + SizeMismatch, //!< Input size differs from current wire coedge count. + DuplicateCoEdge, //!< Input repeats a coedge id. + InvalidCoEdge, //!< Input references an invalid, removed, or incomplete coedge. + CoEdgeAlreadyBound, //!< Add precheck found a coedge already owned by a wire. + CoEdgeNotOwnedByWire, //!< Set-order precheck found a coedge not owned by the wire. + NotPermutation, //!< Set-order input is not a permutation of current coedges. + Disconnected //!< Coedges cannot form a connected chain. + }; + + //! Status returned by wire edge-replacement prechecks. + enum class ReplaceEdgeStatus + { + Ready, //!< Replacement is valid and preserves wire connectivity. + AlreadyCurrent, //!< Old and new edge are the same and no mutation is needed. + InvalidWire, //!< Wire id is invalid or removed. + InvalidOldEdge, //!< Old edge id is invalid, removed, or not used by the wire. + InvalidNewEdge, //!< New edge id is invalid or removed. + Disconnected //!< Replacement would break the ordered coedge chain. + }; + + //! Precheck free-floating CoEdges for WireOps::Add(). + //! @param[in] theCoEdgeIds candidate coedge identifiers + //! @return status describing whether the input can form a wire + [[nodiscard]] Standard_EXPORT CoEdgeOrderStatus + CheckCoEdgeOrder(const NCollection_Array1& theCoEdgeIds) const; + + //! Precheck owned CoEdges for WireOps::SetCoEdgeOrder(). + //! @param[in] theWire wire definition identifier + //! @param[in] theCoEdgeIds candidate coedge identifiers + //! @return status describing whether the input can replace the stored order + [[nodiscard]] Standard_EXPORT CoEdgeOrderStatus + CheckCoEdgeOrder(const BRepGraph_WireId theWire, + const NCollection_Array1& theCoEdgeIds) const; + + //! Precheck appending a free CoEdge to an existing wire. + //! @param[in] theWire wire definition identifier + //! @param[in] theCoEdgeId free coedge candidate + //! @return status describing whether the append can preserve connected order + [[nodiscard]] Standard_EXPORT CoEdgeOrderStatus + CheckAppendCoEdge(const BRepGraph_WireId theWire, const BRepGraph_CoEdgeId theCoEdgeId) const; + + //! Precheck replacing one edge by another in an existing wire. + //! @param[in] theWire wire definition identifier + //! @param[in] theOldEdge edge currently used by one or more wire coedges + //! @param[in] theNewEdge replacement edge + //! @param[in] theReversed if true, replacement coedge orientation is reversed + //! @return status describing whether replacement preserves connected order + [[nodiscard]] Standard_EXPORT ReplaceEdgeStatus + CheckReplaceEdge(const BRepGraph_WireId theWire, + const BRepGraph_EdgeId theOldEdge, + const BRepGraph_EdgeId theNewEdge, + const bool theReversed) const; + + //! Add a wire definition from pre-created CoEdges. + //! Each CoEdge must be free-floating (no parent wire yet). + //! The method binds all CoEdges to the new wire and updates relation tables. + //! @param[in] theCoEdgeIds ordered coedge identifiers //! @return typed wire definition identifier, or invalid if any referenced - //! edge entry is invalid - [[nodiscard]] Standard_EXPORT BRepGraph_WireId Add( - const NCollection_DynamicArray>& theEdges); + //! coedge is invalid or already bound to a wire + [[nodiscard]] Standard_EXPORT BRepGraph_WireId + Add(const NCollection_Array1& theCoEdgeIds); //! Replace one edge with another in a wire definition. //! Updates the CoEdge's EdgeIdx to point to the new edge, adjusts orientation - //! if theReversed, and incrementally updates reverse indices. - //! @param[in] theWireDefId wire definition identifier + //! if theReversed, and incrementally updates relation tables. + //! @param[in] theChildWireId wire definition identifier //! @param[in] theOldEdgeEntity edge to replace //! @param[in] theNewEdgeEntity replacement edge //! @param[in] theReversed if true, reverse the orientation of the replacement - Standard_EXPORT void ReplaceEdge(const BRepGraph_WireId theWireDefId, + Standard_EXPORT void ReplaceEdge(const BRepGraph_WireId theChildWireId, const BRepGraph_EdgeId theOldEdgeEntity, const BRepGraph_EdgeId theNewEdgeEntity, const bool theReversed); - //! Detach one exact coedge ref from a wire definition. - //! Use BRepGraph_RefsCoEdgeOfWire::CurrentId() when removing from a wire - //! iterator. The method removes the exact CoEdgeRef entry, erases it from - //! the wire's ordered ref sequence, updates reverse indices, and prunes the - //! CoEdge node when it has no other active usages. - //! @param[in] theWireDefId wire definition identifier - //! @param[in] theCoEdgeRefId exact wire-owned coedge reference identifier + //! Detach one exact coedge entry from a wire definition. + //! Use BRepGraph_CoEdgesOfWire::CurrentId() when removing from a wire + //! iterator. The method removes the exact ordered coedge entry, updates + //! relation tables, and prunes the CoEdge node when it has no other active + //! usages. + //! @param[in] theChildWireId wire definition identifier + //! @param[in] theCoEdgeId exact wire-owned coedge identifier //! @return true if the active wire-owned usage was removed - [[nodiscard]] Standard_EXPORT bool RemoveCoEdge(const BRepGraph_WireId theWireDefId, - const BRepGraph_CoEdgeRefId theCoEdgeRefId); + [[nodiscard]] Standard_EXPORT bool RemoveCoEdge(const BRepGraph_WireId theChildWireId, + const BRepGraph_CoEdgeId theCoEdgeId); + + //! Reverse the wire: flip the order of the wire's CoEdgeIds and flip each + //! owned CoEdge's orientation. Used by healing/sewing to invert a loop. + //! @param[in] theWire wire definition identifier + Standard_EXPORT void Reverse(const BRepGraph_WireId theWire); + + //! Replace the ordered CoEdge relation vector with a permutation of its + //! current content. + //! @param[in] theWire wire definition identifier + //! @param[in] theCoEdgeIds new ordered CoEdge identifiers + //! @return true if the order was accepted and applied + [[nodiscard]] Standard_EXPORT bool SetCoEdgeOrder( + const BRepGraph_WireId theWire, + const NCollection_Array1& theCoEdgeIds); //! Return scoped mutable wire definition guard. [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard Mut( @@ -609,45 +529,17 @@ public: [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard MutRef( const BRepGraph_WireRefId theWireRef); - //! Set the IsClosed flag of a wire definition and fire immediate notification. - //! @param[in] theWire typed wire definition identifier - //! @param[in] theIsClosed new closed state - Standard_EXPORT void SetIsClosed(const BRepGraph_WireId theWire, bool theIsClosed); - - //! Set the IsClosed flag of a wire definition inside a batched mutation scope. - //! @param[in] theMut active mutable wire guard - //! @param[in] theIsClosed new closed state - Standard_EXPORT void SetIsClosed(BRepGraph_MutGuard& theMut, - bool theIsClosed); - - //! Set the local location of a wire reference and fire immediate notification. - //! @param[in] theWireRef typed wire reference identifier - //! @param[in] theLoc new local location - Standard_EXPORT void SetRefLocalLocation(const BRepGraph_WireRefId theWireRef, - const TopLoc_Location& theLoc); - - //! Set the local location of a wire reference inside a batched mutation scope. - //! @param[in] theMut active mutable wire reference guard - //! @param[in] theLoc new local location - Standard_EXPORT void SetRefLocalLocation(BRepGraph_MutGuard& theMut, - const TopLoc_Location& theLoc); - - //! Set the IsOuter flag on a wire reference. - Standard_EXPORT void SetRefIsOuter(const BRepGraph_WireRefId theWireRef, const bool theIsOuter); - Standard_EXPORT void SetRefIsOuter(BRepGraph_MutGuard& theMut, - const bool theIsOuter); - //! Set the orientation of a wire reference. - Standard_EXPORT void SetRefOrientation(const BRepGraph_WireRefId theWireRef, - const TopAbs_Orientation theOrientation); + Standard_EXPORT void SetRefOrientation(const BRepGraph_WireRefId theWireRef, + const BRepGraphInc::ParityOrientation theOrientation); Standard_EXPORT void SetRefOrientation(BRepGraph_MutGuard& theMut, - const TopAbs_Orientation theOrientation); + const BRepGraphInc::ParityOrientation theOrientation); //! Rewire a wire reference to a different wire def (rebinds WireToFaces if parent is Face). - Standard_EXPORT void SetRefWireDefId(const BRepGraph_WireRefId theWireRef, - const BRepGraph_WireId theWire); - Standard_EXPORT void SetRefWireDefId(BRepGraph_MutGuard& theMut, - const BRepGraph_WireId theWire); + Standard_EXPORT void SetRefChildWireId(const BRepGraph_WireRefId theWireRef, + const BRepGraph_WireId theWire); + Standard_EXPORT void SetRefChildWireId(BRepGraph_MutGuard& theMut, + const BRepGraph_WireId theWire); private: friend class EditorView; @@ -672,39 +564,31 @@ public: //! @return typed face definition identifier, or invalid if any referenced //! wire id is out of range or removed [[nodiscard]] Standard_EXPORT BRepGraph_FaceId - Add(const occ::handle& theSurface, - const BRepGraph_WireId theOuterWire, - const NCollection_DynamicArray& theInnerWires, - const double theTolerance); - - //! Add a direct INTERNAL/EXTERNAL vertex usage to a face definition. - //! @param[in] theFaceEntity typed face definition identifier - //! @param[in] theVertexEntity typed vertex definition identifier - //! @param[in] theOri orientation of the direct vertex usage on the face - //! @return typed vertex reference identifier, or invalid if inputs are not active - [[nodiscard]] Standard_EXPORT BRepGraph_VertexRefId - AddVertex(const BRepGraph_FaceId theFaceEntity, - const BRepGraph_VertexId theVertexEntity, - const TopAbs_Orientation theOri = TopAbs_INTERNAL); - - //! Detach one exact direct vertex ref from a face definition. - //! Use BRepGraph_RefsVertexOfFace::CurrentId() when removing from a face - //! direct-vertex iterator. - //! @param[in] theFaceDefId face definition identifier - //! @param[in] theVertexRefId exact face-owned vertex reference identifier - //! @return true if the active face-owned usage was removed - [[nodiscard]] Standard_EXPORT bool RemoveVertex(const BRepGraph_FaceId theFaceDefId, - const BRepGraph_VertexRefId theVertexRefId); + Add(const occ::handle& theSurface, + const BRepGraph_WireId theOuterWire, + const NCollection_Array1& theInnerWires, + const double theTolerance); + + //! Append a wire usage to an existing face definition. + //! @param[in] theFaceEntity typed face definition identifier + //! @param[in] theWireEntity typed wire definition identifier + //! @param[in] theOri orientation of the wire usage on the face + //! @return typed wire reference identifier, or invalid if inputs are not + //! active + [[nodiscard]] Standard_EXPORT BRepGraph_WireRefId + Append(const BRepGraph_FaceId theFaceEntity, + const BRepGraph_WireId theWireEntity, + const BRepGraphInc::ParityOrientation theOri = TopAbs_FORWARD); //! Detach one exact wire ref from a face definition. //! Use BRepGraph_RefsWireOfFace::CurrentId() when removing from a face //! iterator. The method removes the exact WireRef entry, erases it from - //! the face's ordered ref sequence, rebuilds reverse indices, and prunes the + //! the face's ordered ref sequence, updates relation tables, and prunes the //! Wire subtree when it has no other active usages. - //! @param[in] theFaceDefId face definition identifier + //! @param[in] theFaceId face definition identifier //! @param[in] theWireRefId exact face-owned wire reference identifier //! @return true if the active face-owned usage was removed - [[nodiscard]] Standard_EXPORT bool RemoveWire(const BRepGraph_FaceId theFaceDefId, + [[nodiscard]] Standard_EXPORT bool RemoveWire(const BRepGraph_FaceId theFaceId, const BRepGraph_WireRefId theWireRefId); //! Return scoped mutable face definition guard. @@ -726,63 +610,46 @@ public: Standard_EXPORT void SetTolerance(BRepGraph_MutGuard& theMut, double theTolerance); - //! Set the NaturalRestriction flag of a face definition and fire immediate notification. - //! @param[in] theFace typed face definition identifier - //! @param[in] theNaturalRestriction new flag value - Standard_EXPORT void SetNaturalRestriction(const BRepGraph_FaceId theFace, - bool theNaturalRestriction); - - //! Set the NaturalRestriction flag inside a batched mutation scope. - //! @param[in] theMut active mutable face guard - //! @param[in] theNaturalRestriction new flag value - Standard_EXPORT void SetNaturalRestriction(BRepGraph_MutGuard& theMut, - bool theNaturalRestriction); - - //! Set the triangulation representation id and fire immediate notification. - //! Pass an invalid id to clear the triangulation binding. - //! @param[in] theFace typed face definition identifier - //! @param[in] theRep new triangulation rep identifier (may be invalid to clear) - Standard_EXPORT void SetTriangulationRep(const BRepGraph_FaceId theFace, - const BRepGraph_TriangulationRepId theRep); - - Standard_EXPORT void SetTriangulationRep(BRepGraph_MutGuard& theMut, - const BRepGraph_TriangulationRepId theRep); - - //! Set the SurfaceRep id bound to a face (invalid id clears the binding). - Standard_EXPORT void SetSurfaceRepId(const BRepGraph_FaceId theFace, - const BRepGraph_SurfaceRepId theRep); - Standard_EXPORT void SetSurfaceRepId(BRepGraph_MutGuard& theMut, - const BRepGraph_SurfaceRepId theRep); + //! Set the surface on a face. Creates an owned FaceSurfaceRep record + //! and an associated SurfaceRep for face geometry access. + //! @param[in] theFace face definition identifier + //! @param[in] theSurface surface geometry (must not be null) + Standard_EXPORT void SetSurface(const BRepGraph_FaceId theFace, + const occ::handle& theSurface); + + //! Clear the surface on a face. Removes the owned use record binding. + //! @param[in] theFace face definition identifier + Standard_EXPORT void ClearSurface(const BRepGraph_FaceId theFace); + + //! Set the persistent triangulation on a face. Creates an owned FaceTriangulationRep record. + //! Also creates a TriangulationRep for backward compatibility. + //! @param[in] theFace face definition identifier + //! @param[in] theTriangulation triangulation mesh (must not be null) + Standard_EXPORT void SetPersistentTriangulation( + const BRepGraph_FaceId theFace, + const occ::handle& theTriangulation); + + //! Clear the persistent triangulation on a face. + //! @param[in] theFace face definition identifier + Standard_EXPORT void ClearPersistentTriangulation(const BRepGraph_FaceId theFace); //! Set the orientation of a face reference and fire immediate notification. //! @param[in] theFaceRef typed face reference identifier //! @param[in] theOrientation new orientation value - Standard_EXPORT void SetRefOrientation(const BRepGraph_FaceRefId theFaceRef, - TopAbs_Orientation theOrientation); + Standard_EXPORT void SetRefOrientation(const BRepGraph_FaceRefId theFaceRef, + BRepGraphInc::ParityOrientation theOrientation); //! Set the orientation of a face reference inside a batched mutation scope. //! @param[in] theMut active mutable face reference guard //! @param[in] theOrientation new orientation value Standard_EXPORT void SetRefOrientation(BRepGraph_MutGuard& theMut, - TopAbs_Orientation theOrientation); - - //! Set the local location of a face reference and fire immediate notification. - //! @param[in] theFaceRef typed face reference identifier - //! @param[in] theLoc new local location - Standard_EXPORT void SetRefLocalLocation(const BRepGraph_FaceRefId theFaceRef, - const TopLoc_Location& theLoc); - - //! Set the local location of a face reference inside a batched mutation scope. - //! @param[in] theMut active mutable face reference guard - //! @param[in] theLoc new local location - Standard_EXPORT void SetRefLocalLocation(BRepGraph_MutGuard& theMut, - const TopLoc_Location& theLoc); + BRepGraphInc::ParityOrientation theOrientation); //! Rewire a face reference to a different face def (rebinds FaceToShells if parent is Shell). - Standard_EXPORT void SetRefFaceDefId(const BRepGraph_FaceRefId theFaceRef, - const BRepGraph_FaceId theFace); - Standard_EXPORT void SetRefFaceDefId(BRepGraph_MutGuard& theMut, - const BRepGraph_FaceId theFace); + Standard_EXPORT void SetRefFaceId(const BRepGraph_FaceRefId theFaceRef, + const BRepGraph_FaceId theFace); + Standard_EXPORT void SetRefFaceId(BRepGraph_MutGuard& theMut, + const BRepGraph_FaceId theFace); private: friend class EditorView; @@ -803,46 +670,48 @@ public: //! @return typed shell definition identifier [[nodiscard]] Standard_EXPORT BRepGraph_ShellId Add(); - //! Link a face to a shell. + //! Append a face to a shell. //! Appends FaceRef and stores its FaceRefId in shell FaceRefIds. //! @param[in] theShellEntity typed shell definition identifier //! @param[in] theFaceEntity typed face definition identifier //! @param[in] theOri orientation of the face in the shell //! @return typed face reference identifier, or invalid if inputs are not active - Standard_EXPORT BRepGraph_FaceRefId AddFace(const BRepGraph_ShellId theShellEntity, - const BRepGraph_FaceId theFaceEntity, - const TopAbs_Orientation theOri = TopAbs_FORWARD); + Standard_EXPORT BRepGraph_FaceRefId + Append(const BRepGraph_ShellId theShellEntity, + const BRepGraph_FaceId theFaceEntity, + const BRepGraphInc::ParityOrientation theOri = TopAbs_FORWARD); - //! Link an auxiliary non-face child to a shell. - //! Supported child kinds are Wire and Edge. + //! Batch-append multiple faces to a shell. + //! Two-pass: validates all inputs first, then links all. //! @param[in] theShellEntity typed shell definition identifier - //! @param[in] theChildEntity typed child definition identifier - //! @param[in] theOri orientation of the child in the shell - //! @return typed child reference identifier, or invalid if inputs are not active - [[nodiscard]] Standard_EXPORT BRepGraph_ChildRefId - AddChild(const BRepGraph_ShellId theShellEntity, - const BRepGraph_NodeId theChildEntity, - const TopAbs_Orientation theOri = TopAbs_FORWARD); + //! @param[in] theFaceIds face definition identifiers to append + //! @param[in] theOrientations optional parity orientations (empty = all FORWARD) + //! @return array of created face reference ids, empty on validation failure + [[nodiscard]] Standard_EXPORT NCollection_Array1 Append( + const BRepGraph_ShellId theShellEntity, + const NCollection_Array1& theFaceIds, + const NCollection_Array1& theOrientations = + NCollection_Array1()); //! Detach one exact face ref from a shell definition. //! Use BRepGraph_RefsFaceOfShell::CurrentId() when removing from a shell //! iterator. The method removes the exact FaceRef entry, erases it from the - //! shell's ordered ref sequence, rebuilds reverse indices, and prunes the + //! shell's ordered ref sequence, updates relation tables, and prunes the //! Face subtree when it has no other active usages. - //! @param[in] theShellDefId shell definition identifier + //! @param[in] theChildShellId shell definition identifier //! @param[in] theFaceRefId exact shell-owned face reference identifier //! @return true if the active shell-owned usage was removed - [[nodiscard]] Standard_EXPORT bool RemoveFace(const BRepGraph_ShellId theShellDefId, + [[nodiscard]] Standard_EXPORT bool RemoveFace(const BRepGraph_ShellId theChildShellId, const BRepGraph_FaceRefId theFaceRefId); - //! Detach one exact child ref from a shell auxiliary-child sequence. - //! Use BRepGraph_RefsChildOfShell::CurrentId() when removing from a shell - //! aux-child iterator. - //! @param[in] theShellDefId shell definition identifier - //! @param[in] theChildRefId exact shell-owned child reference identifier - //! @return true if the active shell-owned usage was removed - [[nodiscard]] Standard_EXPORT bool RemoveChild(const BRepGraph_ShellId theShellDefId, - const BRepGraph_ChildRefId theChildRefId); + //! Batch-remove multiple face refs from a shell definition. + //! All-or-nothing: validates all inputs first, then removes all. + //! @param[in] theShellId shell definition identifier + //! @param[in] theFaceRefs face reference identifiers to remove + //! @return true if all refs were successfully removed + [[nodiscard]] Standard_EXPORT bool RemoveFaces( + const BRepGraph_ShellId theShellId, + const NCollection_Array1& theFaceRefs); //! Return scoped mutable shell definition guard. [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard Mut( @@ -852,39 +721,19 @@ public: [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard MutRef( const BRepGraph_ShellRefId theShellRef); - //! Set the local location of a shell reference and fire immediate notification. - //! @param[in] theShellRef typed shell reference identifier - //! @param[in] theLoc new local location - Standard_EXPORT void SetRefLocalLocation(const BRepGraph_ShellRefId theShellRef, - const TopLoc_Location& theLoc); - - //! Set the local location of a shell reference inside a batched mutation scope. - //! @param[in] theMut active mutable shell reference guard - //! @param[in] theLoc new local location - Standard_EXPORT void SetRefLocalLocation(BRepGraph_MutGuard& theMut, - const TopLoc_Location& theLoc); - //! Set the orientation of a shell reference. - Standard_EXPORT void SetRefOrientation(const BRepGraph_ShellRefId theShellRef, - const TopAbs_Orientation theOrientation); + Standard_EXPORT void SetRefOrientation(const BRepGraph_ShellRefId theShellRef, + const BRepGraphInc::ParityOrientation theOrientation); //! Set the orientation inside a batched mutation scope. Standard_EXPORT void SetRefOrientation(BRepGraph_MutGuard& theMut, - const TopAbs_Orientation theOrientation); - - //! Rewire a shell reference to a different shell def (rebinds ShellToSolids if parent is - //! Solid). - Standard_EXPORT void SetRefShellDefId(const BRepGraph_ShellRefId theShellRef, - const BRepGraph_ShellId theShell); - Standard_EXPORT void SetRefShellDefId(BRepGraph_MutGuard& theMut, - const BRepGraph_ShellId theShell); - - //! Set the IsClosed flag of a shell definition. - Standard_EXPORT void SetIsClosed(const BRepGraph_ShellId theShell, const bool theIsClosed); + const BRepGraphInc::ParityOrientation theOrientation); - //! Set the IsClosed flag inside a batched mutation scope. - Standard_EXPORT void SetIsClosed(BRepGraph_MutGuard& theMut, - const bool theIsClosed); + //! Rewire a shell reference to a different shell def (rebinds ShellToSolid if parent is Solid). + Standard_EXPORT void SetRefChildShellId(const BRepGraph_ShellRefId theShellRef, + const BRepGraph_ShellId theShell); + Standard_EXPORT void SetRefChildShellId(BRepGraph_MutGuard& theMut, + const BRepGraph_ShellId theShell); private: friend class EditorView; @@ -905,46 +754,48 @@ public: //! @return typed solid definition identifier [[nodiscard]] Standard_EXPORT BRepGraph_SolidId Add(); - //! Link a shell to a solid. + //! Append a shell to a solid. //! Appends ShellRef and stores its ShellRefId in solid ShellRefIds. //! @param[in] theSolidEntity typed solid definition identifier //! @param[in] theShellEntity typed shell definition identifier //! @param[in] theOri orientation of the shell in the solid //! @return typed shell reference identifier, or invalid if inputs are not active - Standard_EXPORT BRepGraph_ShellRefId AddShell(const BRepGraph_SolidId theSolidEntity, - const BRepGraph_ShellId theShellEntity, - const TopAbs_Orientation theOri = TopAbs_FORWARD); + Standard_EXPORT BRepGraph_ShellRefId + Append(const BRepGraph_SolidId theSolidEntity, + const BRepGraph_ShellId theShellEntity, + const BRepGraphInc::ParityOrientation theOri = TopAbs_FORWARD); - //! Link an auxiliary non-shell child to a solid. - //! Supported child kinds are Edge and Vertex. + //! Batch-append multiple shells to a solid. + //! Two-pass: validates all inputs first, then links all. //! @param[in] theSolidEntity typed solid definition identifier - //! @param[in] theChildEntity typed child definition identifier - //! @param[in] theOri orientation of the child in the solid - //! @return typed child reference identifier, or invalid if inputs are not active - [[nodiscard]] Standard_EXPORT BRepGraph_ChildRefId - AddChild(const BRepGraph_SolidId theSolidEntity, - const BRepGraph_NodeId theChildEntity, - const TopAbs_Orientation theOri = TopAbs_FORWARD); + //! @param[in] theShellIds shell definition identifiers to append + //! @param[in] theOrientations optional parity orientations (empty = all FORWARD) + //! @return array of created shell reference ids, empty on validation failure + [[nodiscard]] Standard_EXPORT NCollection_Array1 Append( + const BRepGraph_SolidId theSolidEntity, + const NCollection_Array1& theShellIds, + const NCollection_Array1& theOrientations = + NCollection_Array1()); //! Detach one exact shell ref from a solid definition. //! Use BRepGraph_RefsShellOfSolid::CurrentId() when removing from a solid //! iterator. The method removes the exact ShellRef entry, erases it from the - //! solid's ordered ref sequence, rebuilds reverse indices, and prunes the + //! solid's ordered ref sequence, updates relation tables, and prunes the //! Shell subtree when it has no other active usages. - //! @param[in] theSolidDefId solid definition identifier + //! @param[in] theChildSolidId solid definition identifier //! @param[in] theShellRefId exact solid-owned shell reference identifier //! @return true if the active solid-owned usage was removed - [[nodiscard]] Standard_EXPORT bool RemoveShell(const BRepGraph_SolidId theSolidDefId, + [[nodiscard]] Standard_EXPORT bool RemoveShell(const BRepGraph_SolidId theChildSolidId, const BRepGraph_ShellRefId theShellRefId); - //! Detach one exact child ref from a solid auxiliary-child sequence. - //! Use BRepGraph_RefsChildOfSolid::CurrentId() when removing from a solid - //! aux-child iterator. - //! @param[in] theSolidDefId solid definition identifier - //! @param[in] theChildRefId exact solid-owned child reference identifier - //! @return true if the active solid-owned usage was removed - [[nodiscard]] Standard_EXPORT bool RemoveChild(const BRepGraph_SolidId theSolidDefId, - const BRepGraph_ChildRefId theChildRefId); + //! Batch-remove multiple shell refs from a solid definition. + //! All-or-nothing: validates all inputs first, then removes all. + //! @param[in] theSolidId solid definition identifier + //! @param[in] theShellRefs shell reference identifiers to remove + //! @return true if all refs were successfully removed + [[nodiscard]] Standard_EXPORT bool RemoveShells( + const BRepGraph_SolidId theSolidId, + const NCollection_Array1& theShellRefs); //! Return scoped mutable solid definition guard. [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard Mut( @@ -954,32 +805,20 @@ public: [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard MutRef( const BRepGraph_SolidRefId theSolidRef); - //! Set the local location of a solid reference and fire immediate notification. - //! @param[in] theSolidRef typed solid reference identifier - //! @param[in] theLoc new local location - Standard_EXPORT void SetRefLocalLocation(const BRepGraph_SolidRefId theSolidRef, - const TopLoc_Location& theLoc); - - //! Set the local location of a solid reference inside a batched mutation scope. - //! @param[in] theMut active mutable solid reference guard - //! @param[in] theLoc new local location - Standard_EXPORT void SetRefLocalLocation(BRepGraph_MutGuard& theMut, - const TopLoc_Location& theLoc); - //! Set the orientation of a solid reference. - Standard_EXPORT void SetRefOrientation(const BRepGraph_SolidRefId theSolidRef, - const TopAbs_Orientation theOrientation); + Standard_EXPORT void SetRefOrientation(const BRepGraph_SolidRefId theSolidRef, + const BRepGraphInc::ParityOrientation theOrientation); //! Set the orientation inside a batched mutation scope. Standard_EXPORT void SetRefOrientation(BRepGraph_MutGuard& theMut, - const TopAbs_Orientation theOrientation); + const BRepGraphInc::ParityOrientation theOrientation); //! Rewire a solid reference to a different solid def (rebinds SolidToCompSolid if parent is //! CompSolid). - Standard_EXPORT void SetRefSolidDefId(const BRepGraph_SolidRefId theSolidRef, - const BRepGraph_SolidId theSolid); - Standard_EXPORT void SetRefSolidDefId(BRepGraph_MutGuard& theMut, - const BRepGraph_SolidId theSolid); + Standard_EXPORT void SetRefChildSolidId(const BRepGraph_SolidRefId theSolidRef, + const BRepGraph_SolidId theSolid); + Standard_EXPORT void SetRefChildSolidId(BRepGraph_MutGuard& theMut, + const BRepGraph_SolidId theSolid); private: friend class EditorView; @@ -996,11 +835,11 @@ public: class CompoundOps { public: - //! Add a compound definition with child definitions. - //! @param[in] theChildEntities child definition NodeIds + //! Add a compound entity with ordered child usages. + //! @param[in] theChildEntities child node identifiers //! @return typed compound definition identifier [[nodiscard]] Standard_EXPORT BRepGraph_CompoundId - Add(const NCollection_DynamicArray& theChildEntities); + Add(const NCollection_Array1& theChildEntities); //! Append a single child to an existing compound definition. //! @param[in] theCompoundEntity typed compound definition identifier @@ -1008,14 +847,26 @@ public: //! @param[in] theOri orientation of the child in the compound //! @return typed child reference identifier, or invalid if inputs are not active [[nodiscard]] Standard_EXPORT BRepGraph_ChildRefId - AddChild(const BRepGraph_CompoundId theCompoundEntity, - const BRepGraph_NodeId theChildEntity, - const TopAbs_Orientation theOri = TopAbs_FORWARD); + Append(const BRepGraph_CompoundId theCompoundEntity, + const BRepGraph_NodeId theChildEntity, + const BRepGraphInc::ParityOrientation theOri = TopAbs_FORWARD); + + //! Batch-append multiple children to an existing compound definition. + //! Two-pass: validates all inputs first, then links all. + //! @param[in] theCompoundEntity typed compound definition identifier + //! @param[in] theChildIds child node identifiers to append + //! @param[in] theOrientations optional parity orientations (empty = all FORWARD) + //! @return array of created child reference ids, empty on validation failure + [[nodiscard]] Standard_EXPORT NCollection_Array1 Append( + const BRepGraph_CompoundId theCompoundEntity, + const NCollection_Array1& theChildIds, + const NCollection_Array1& theOrientations = + NCollection_Array1()); //! Detach one exact child ref from a compound definition. //! Use BRepGraph_RefsChildOfParent::CurrentId() when removing from a compound //! iterator. The method removes the exact ChildRef entry, erases it from the - //! compound's ordered ref sequence, rebuilds reverse indices, and prunes the + //! compound's ordered ref sequence, updates relation tables, and prunes the //! child subtree when it has no other active usages. //! @param[in] theCompoundDefId compound definition identifier //! @param[in] theChildRefId exact compound-owned child reference identifier @@ -1023,10 +874,26 @@ public: [[nodiscard]] Standard_EXPORT bool RemoveChild(const BRepGraph_CompoundId theCompoundDefId, const BRepGraph_ChildRefId theChildRefId); + //! Batch-remove multiple child refs from a compound definition. + //! All-or-nothing: validates all inputs first, then removes all. + //! @param[in] theCompoundId compound definition identifier + //! @param[in] theChildRefs child reference identifiers to remove + //! @return true if all refs were successfully removed + [[nodiscard]] Standard_EXPORT bool RemoveChildren( + const BRepGraph_CompoundId theCompoundId, + const NCollection_Array1& theChildRefs); + //! Return scoped mutable compound definition guard. [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard Mut( const BRepGraph_CompoundId theCompound); + //! Replace the child node of an existing child reference in a compound. + //! Delegates to Gen().SetChildRefChildNodeId(). + //! @param[in] theChildRef typed child reference identifier + //! @param[in] theNewChild new child node identifier + Standard_EXPORT void ReplaceChild(const BRepGraph_ChildRefId theChildRef, + const BRepGraph_NodeId theNewChild); + private: friend class EditorView; @@ -1042,11 +909,11 @@ public: class CompSolidOps { public: - //! Add a compsolid definition with child solid definitions. - //! @param[in] theSolidEntities typed child solid definition identifiers + //! Add a compsolid entity with ordered solid usages. + //! @param[in] theSolidEntities typed child solid identifiers //! @return typed compsolid definition identifier [[nodiscard]] Standard_EXPORT BRepGraph_CompSolidId - Add(const NCollection_DynamicArray& theSolidEntities); + Add(const NCollection_Array1& theSolidEntities); //! Append a single solid to an existing compsolid definition. //! @param[in] theCompSolidEntity typed compsolid definition identifier @@ -1054,25 +921,53 @@ public: //! @param[in] theOri orientation of the solid in the compsolid //! @return typed solid reference identifier, or invalid if inputs are not active [[nodiscard]] Standard_EXPORT BRepGraph_SolidRefId - AddSolid(const BRepGraph_CompSolidId theCompSolidEntity, - const BRepGraph_SolidId theSolidEntity, - const TopAbs_Orientation theOri = TopAbs_FORWARD); + Append(const BRepGraph_CompSolidId theCompSolidEntity, + const BRepGraph_SolidId theSolidEntity, + const BRepGraphInc::ParityOrientation theOri = TopAbs_FORWARD); + + //! Batch-append multiple solids to an existing compsolid definition. + //! Two-pass: validates all inputs first, then links all. + //! @param[in] theCompSolidEntity typed compsolid definition identifier + //! @param[in] theSolidIds solid definition identifiers to append + //! @param[in] theOrientations optional parity orientations (empty = all FORWARD) + //! @return array of created solid reference ids, empty on validation failure + [[nodiscard]] Standard_EXPORT NCollection_Array1 Append( + const BRepGraph_CompSolidId theCompSolidEntity, + const NCollection_Array1& theSolidIds, + const NCollection_Array1& theOrientations = + NCollection_Array1()); //! Detach one exact solid ref from a compsolid definition. //! Use BRepGraph_RefsSolidOfCompSolid::CurrentId() when removing from a //! compsolid iterator. The method removes the exact SolidRef entry, erases it - //! from the compsolid's ordered ref sequence, rebuilds reverse indices, and + //! from the compsolid's ordered ref sequence, updates relation tables, and //! prunes the Solid subtree when it has no other active usages. - //! @param[in] theCompSolidDefId compsolid definition identifier + //! @param[in] theCompChildSolidId compsolid definition identifier //! @param[in] theSolidRefId exact compsolid-owned solid reference identifier //! @return true if the active compsolid-owned usage was removed - [[nodiscard]] Standard_EXPORT bool RemoveSolid(const BRepGraph_CompSolidId theCompSolidDefId, + [[nodiscard]] Standard_EXPORT bool RemoveSolid(const BRepGraph_CompSolidId theCompChildSolidId, const BRepGraph_SolidRefId theSolidRefId); + //! Batch-remove multiple solid refs from a compsolid definition. + //! All-or-nothing: validates all inputs first, then removes all. + //! @param[in] theCompSolidId compsolid definition identifier + //! @param[in] theSolidRefs solid reference identifiers to remove + //! @return true if all refs were successfully removed + [[nodiscard]] Standard_EXPORT bool RemoveSolids( + const BRepGraph_CompSolidId theCompSolidId, + const NCollection_Array1& theSolidRefs); + //! Return scoped mutable comp-solid definition guard. [[nodiscard]] Standard_EXPORT BRepGraph_MutGuard Mut( const BRepGraph_CompSolidId theCompSolid); + //! Replace the solid of an existing solid reference in a compsolid. + //! Delegates to Solids().SetRefChildSolidId(). + //! @param[in] theSolidRef typed solid reference identifier + //! @param[in] theNewSolid new solid definition identifier + Standard_EXPORT void ReplaceSolid(const BRepGraph_SolidRefId theSolidRef, + const BRepGraph_SolidId theNewSolid); + private: friend class EditorView; @@ -1085,24 +980,31 @@ public: }; //! @brief Product and assembly low-level reconstruction primitives. - //! Wire two existing entities together; for shape ingestion use BRepGraph_Builder::Add(). + //! Wire two existing entities together; for shape ingestion use BRepGraph::ShapesView::Add(). class ProductOps { public: //! Create a Product wrapping an existing topology root via an Occurrence. + //! The product is NOT added to document roots; call AppendDocumentRoot() explicitly + //! when this Product is a document root. //! @param[in] theShapeRoot root topology NodeId for the part //! @param[in] thePlacement local placement stored on the root OccurrenceRef //! @return typed product definition identifier, or invalid if the root is //! not an active topology definition node [[nodiscard]] Standard_EXPORT BRepGraph_ProductId - LinkProductToTopology(const BRepGraph_NodeId theShapeRoot, - const TopLoc_Location& thePlacement = TopLoc_Location()); + Add(const BRepGraph_NodeId theShapeRoot, + const TopLoc_Location& thePlacement = TopLoc_Location()); - //! Create a Product with no direct shape root; can later own child occurrences. + //! Create an empty Product with no direct shape root; can later own child occurrences. + //! The product is NOT added to document roots; call AppendDocumentRoot() explicitly + //! when this Product is a document root. //! @return typed product definition identifier - [[nodiscard]] Standard_EXPORT BRepGraph_ProductId CreateEmptyProduct(); + [[nodiscard]] Standard_EXPORT BRepGraph_ProductId Add(); + + //! Add an active Product to document roots if it is not already listed. + Standard_EXPORT void AppendDocumentRoot(const BRepGraph_ProductId theProductId); - //! Link two existing Products via a fresh Occurrence. + //! Append two existing Products via a fresh Occurrence. //! @param[in] theParentProduct typed parent product identifier //! @param[in] theReferencedProduct typed child product identifier being instantiated //! @param[in] thePlacement local placement relative to parent @@ -1110,16 +1012,27 @@ public: //! @param[out] theOutOccurrenceRefId optional out: typed ref id of the inserted OccurrenceRef //! @return typed occurrence definition identifier, or invalid if the chain is not active [[nodiscard]] Standard_EXPORT BRepGraph_OccurrenceId - LinkProducts(const BRepGraph_ProductId theParentProduct, - const BRepGraph_ProductId theReferencedProduct, - const TopLoc_Location& thePlacement, - const BRepGraph_OccurrenceId theParentOccurrence = BRepGraph_OccurrenceId(), - BRepGraph_OccurrenceRefId* theOutOccurrenceRefId = nullptr); + Append(const BRepGraph_ProductId theParentProduct, + const BRepGraph_ProductId theReferencedProduct, + const TopLoc_Location& thePlacement, + const BRepGraph_OccurrenceId theParentOccurrence = BRepGraph_OccurrenceId(), + BRepGraph_OccurrenceRefId* theOutOccurrenceRefId = nullptr); + + //! Batch-append multiple child products to a parent product via fresh Occurrences. + //! Two-pass: validates all inputs first, then links all. + //! @param[in] theParentProduct typed parent product identifier + //! @param[in] theChildProducts child product identifiers to instantiate + //! @param[in] thePlacements local placements per child (must match child count) + //! @return array of created occurrence reference ids, empty on validation failure + [[nodiscard]] Standard_EXPORT NCollection_Array1 Append( + const BRepGraph_ProductId theParentProduct, + const NCollection_Array1& theChildProducts, + const NCollection_Array1& thePlacements); //! Detach one exact occurrence ref from a product definition. //! Use BRepGraph_RefsOccurrenceOfProduct::CurrentId() when removing from a //! product iterator. The method removes the exact OccurrenceRef entry, erases - //! it from the product's ordered ref sequence, rebuilds reverse indices, and + //! it from the product's ordered ref sequence, updates relation tables, and //! prunes the occurrence subtree when it has no other active usages. //! @param[in] theProductDefId product definition identifier //! @param[in] theOccurrenceRefId exact product-owned occurrence reference identifier @@ -1128,6 +1041,15 @@ public: const BRepGraph_ProductId theProductDefId, const BRepGraph_OccurrenceRefId theOccurrenceRefId); + //! Batch-remove multiple occurrence refs from a product definition. + //! All-or-nothing: validates all inputs first, then removes all. + //! @param[in] theProductId product definition identifier + //! @param[in] theOccurrenceRefs occurrence reference identifiers to remove + //! @return true if all refs were successfully removed + [[nodiscard]] Standard_EXPORT bool RemoveOccurrences( + const BRepGraph_ProductId theProductId, + const NCollection_Array1& theOccurrenceRefs); + //! Detach the scalar shape-root ownership from a product definition. //! If no other active product owns the same topology root afterward, the root //! subgraph is pruned as orphaned. The product loses its direct shape root; @@ -1178,19 +1100,21 @@ public: const TopLoc_Location& theLoc); //! Set the child node referenced by an occurrence definition. - //! The child kind must be a topology root or a Product - invalid kinds are - //! accepted but the resulting graph will fail Validate. - Standard_EXPORT void SetChildDefId(const BRepGraph_OccurrenceId theOccurrence, - const BRepGraph_NodeId theChildDefId); + //! Invalid or removed occurrence ids are ignored. The child must be an + //! active topology node or an active Product; invalid, removed, and + //! Occurrence child ids are ignored. + Standard_EXPORT void SetChildNodeId(const BRepGraph_OccurrenceId theOccurrence, + const BRepGraph_NodeId theChildNodeId); - //! Set the child node id inside a batched mutation scope. - Standard_EXPORT void SetChildDefId(BRepGraph_MutGuard& theMut, - const BRepGraph_NodeId theChildDefId); + //! Set the child node id inside a batched mutation scope. Invalid, removed, + //! and Occurrence child ids are ignored. + Standard_EXPORT void SetChildNodeId(BRepGraph_MutGuard& theMut, + const BRepGraph_NodeId theChildNodeId); //! Rewire an occurrence reference to a different occurrence def (rebinds ProductToOccurrences). - Standard_EXPORT void SetRefOccurrenceDefId(const BRepGraph_OccurrenceRefId theOccurrenceRef, - const BRepGraph_OccurrenceId theOccurrence); - Standard_EXPORT void SetRefOccurrenceDefId( + Standard_EXPORT void SetRefChildOccurrenceId(const BRepGraph_OccurrenceRefId theOccurrenceRef, + const BRepGraph_OccurrenceId theOccurrence); + Standard_EXPORT void SetRefChildOccurrenceId( BRepGraph_MutGuard& theMut, const BRepGraph_OccurrenceId theOccurrence); @@ -1213,15 +1137,19 @@ public: //! @param[in] theNode node to remove Standard_EXPORT void RemoveNode(const BRepGraph_NodeId theNode); - //! Mark a node as removed with a known replacement (sewing/deduplicate). + //! Replace a node by another active node and mark the old node as removed. //! For Edge nodes: all CoEdges referencing the removed edge are reparented to - //! the replacement edge (EdgeIdx updated, reverse index rebound). This prevents + //! the replacement edge (ChildEdgeId updated, relation entries rebound). This prevents //! orphaned CoEdges that would disappear from CoEdgesOfEdge() queries. - //! Layers are notified with both old and replacement NodeIds for data migration. + //! If the replacement is active, layers receive OnNodeReplaced(theNode, + //! theReplacement) for structural data migration. If the replacement is invalid + //! or inactive, the operation falls back to OnNodeRemoved(theNode), matching pure + //! deletion. Semantic history records are not inferred here; algorithms should + //! record operation-specific history. //! @param[in] theNode node to remove //! @param[in] theReplacement node that replaces theNode - Standard_EXPORT void RemoveNode(const BRepGraph_NodeId theNode, - const BRepGraph_NodeId theReplacement); + Standard_EXPORT void ReplaceNode(const BRepGraph_NodeId theNode, + const BRepGraph_NodeId theReplacement); //! Mark a node and all its descendants as removed (cascading soft deletion). //! @param[in] theNode root node to remove @@ -1250,13 +1178,6 @@ public: const BRepGraph_RefId theRef, const bool theToPruneOrphanedChild); - //! Mark a representation entry as removed (soft deletion). - //! Invalid or already-removed ids are ignored. - //! Owning topology entities are marked modified so generation-based caches - //! and read helpers observe the representation as absent. - //! @param[in] theRep representation to remove - Standard_EXPORT void RemoveRep(const BRepGraph_RepId theRep); - //! Return scoped mutable child reference guard. ChildRef is generic (the //! child node can be of any kind), so its Mut accessor lives on the //! cross-kind Gen() rather than on a per-kind Ops. @@ -1270,18 +1191,20 @@ public: const TopLoc_Location& theLoc); //! Set the orientation of a child reference. - Standard_EXPORT void SetChildRefOrientation(const BRepGraph_ChildRefId theChildRef, - const TopAbs_Orientation theOrientation); + Standard_EXPORT void SetChildRefOrientation( + const BRepGraph_ChildRefId theChildRef, + const BRepGraphInc::ParityOrientation theOrientation); //! Set the orientation inside a batched mutation scope. - Standard_EXPORT void SetChildRefOrientation(BRepGraph_MutGuard& theMut, - const TopAbs_Orientation theOrientation); + Standard_EXPORT void SetChildRefOrientation( + BRepGraph_MutGuard& theMut, + const BRepGraphInc::ParityOrientation theOrientation); //! Rewire a child reference to a different child def (rebinds CompoundsOf). - Standard_EXPORT void SetChildRefChildDefId(const BRepGraph_ChildRefId theChildRef, - const BRepGraph_NodeId theChild); - Standard_EXPORT void SetChildRefChildDefId(BRepGraph_MutGuard& theMut, - const BRepGraph_NodeId theChild); + Standard_EXPORT void SetChildRefChildNodeId(const BRepGraph_ChildRefId theChildRef, + const BRepGraph_NodeId theChild); + Standard_EXPORT void SetChildRefChildNodeId(BRepGraph_MutGuard& theMut, + const BRepGraph_NodeId theChild); //! Set the local location of a child reference inside a batched mutation scope. //! @param[in] theMut active mutable child reference guard @@ -1299,11 +1222,23 @@ public: ModifierT&& theModifier, const TCollection_AsciiString& theOpLabel) { - NCollection_DynamicArray aReplacements = - std::forward(theModifier)(*myGraph, theTarget); + auto aProducedReplacements = std::forward(theModifier)(*myGraph, theTarget); + NCollection_LinearVector aReplacements(aProducedReplacements.Size()); + for (const BRepGraph_NodeId& aNode : aProducedReplacements) + { + aReplacements.Append(aNode); + } applyModificationImpl(theTarget, std::move(aReplacements), theOpLabel); } + //! Clean up forward references to removed nodes in relation tables and + //! references. After one or more RemoveNode calls, other entities may + //! still hold stale child references pointing to removed nodes. This method + //! marks those stale references as removed, detaches them from parent + //! arrays, and updates relation entries for consistency. + //! @post ValidateRelations() passes. + Standard_EXPORT void CleanupRemovedReferences(); + private: friend class EditorView; @@ -1314,7 +1249,7 @@ public: Standard_EXPORT void applyModificationImpl( const BRepGraph_NodeId theTarget, - NCollection_DynamicArray&& theReplacements, + NCollection_LinearVector&& theReplacements, const TCollection_AsciiString& theOpLabel); BRepGraph* myGraph; @@ -1357,8 +1292,11 @@ public: //! Return generic node, reference, and representation removal operations. [[nodiscard]] GenOps& Gen() { return myGenOps; } - //! Return representation (surface, curve, triangulation, polygon) mutation operations. - [[nodiscard]] RepOps& Reps() { return myRepOps; } + //! Return runtime supplement attachment operations. + [[nodiscard]] BRepGraph_SupplementEditor Supplement() + { + return BRepGraph_SupplementEditor(*myGraph); + } //! Begin deferred invalidation mode. //! While active, markModified() only increments OwnGen + SubtreeGen and @@ -1393,7 +1331,7 @@ public: }; //! Finalize a batch of mutations. - //! Validates reverse-index consistency and asserts active entity counts + //! Validates relation consistency and asserts active entity counts //! match actual entity state. //! Call this after manual batch mutation loops, or rely on //! BRepGraph_DeferredScope to call it automatically at scope exit. @@ -1403,7 +1341,7 @@ public: //! @param[out] theIssues optional destination for detailed issues //! @return true if no issues were found [[nodiscard]] Standard_EXPORT bool ValidateMutationBoundary( - NCollection_DynamicArray* const theIssues = nullptr) const; + NCollection_LinearVector* const theIssues = nullptr) const; private: friend class BRepGraph; @@ -1422,9 +1360,49 @@ private: myCompSolidOps(theGraph), myProductOps(theGraph), myOccurrenceOps(theGraph), - myGenOps(theGraph), - myRepOps(theGraph) + myGenOps(theGraph) + { + } + + [[nodiscard]] Standard_EXPORT bool isOwned(const BRepGraph_ItemId theItem) const; + + [[nodiscard]] bool isOwned(const BRepGraph_NodeId theNode) const + { + return isOwned(BRepGraph_ItemId(theNode)); + } + + [[nodiscard]] bool isOwned(const BRepGraph_RefId theRef) const + { + return isOwned(BRepGraph_ItemId(theRef)); + } + + Standard_EXPORT void requireUnlocked(const BRepGraph_ItemId theItem, + const char* theOperation) const; + + void requireUnlocked(const BRepGraph_NodeId theNode, const char* theOperation) const + { + requireUnlocked(BRepGraph_ItemId(theNode), theOperation); + } + + void requireUnlocked(const BRepGraph_RefId theRef, const char* theOperation) const + { + requireUnlocked(BRepGraph_ItemId(theRef), theOperation); + } + + //! Verify no active MutGuard holds the given item. + //! Used by structural operations (Remove*, Replace*, Add*) to prevent + //! topology changes while a guard is active on the target item. + Standard_EXPORT void requireNoActiveGuard(const BRepGraph_ItemId theItem, + const char* theOperation) const; + + void requireNoActiveGuard(const BRepGraph_NodeId theNode, const char* theOperation) const + { + requireNoActiveGuard(BRepGraph_ItemId(theNode), theOperation); + } + + void requireNoActiveGuard(const BRepGraph_RefId theRef, const char* theOperation) const { + requireNoActiveGuard(BRepGraph_ItemId(theRef), theOperation); } BRepGraph* myGraph; @@ -1440,7 +1418,6 @@ private: ProductOps myProductOps; OccurrenceOps myOccurrenceOps; GenOps myGenOps; - RepOps myRepOps; }; #endif // _BRepGraph_EditorView_HeaderFile diff --git a/opencascade/BRepGraph_History.hxx b/opencascade/BRepGraph_History.hxx deleted file mode 100644 index 931992fbb..000000000 --- a/opencascade/BRepGraph_History.hxx +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraph_History_HeaderFile -#define _BRepGraph_History_HeaderFile - -#include -#include -#include -#include -#include -#include -#include - -class BRepGraph; - -//! Extracted history subsystem for BRepGraph. -//! -//! BRepGraph_History maintains an append-only log of modification events -//! and bidirectional lookup maps (original <-> derived) for efficient -//! history queries. Recording can be toggled on/off at runtime. -class BRepGraph_History -{ - friend class BRepGraph; - -public: - DEFINE_STANDARD_ALLOC - - //! Record a modification: theOriginal was replaced by theReplacements. - //! @param[in] theOpLabel human-readable operation name - //! @param[in] theOriginal node id before the operation - //! @param[in] theReplacements node ids after the operation - Standard_EXPORT void Record(const TCollection_AsciiString& theOpLabel, - const BRepGraph_NodeId theOriginal, - const NCollection_DynamicArray& theReplacements); - - //! Record a batch of 1-to-1 modifications in a single history event. - //! theOriginals[i] was replaced by theReplacements[i]. - //! More efficient than calling Record() in a loop: creates one HistoryRecord - //! and updates the bidirectional maps with minimal overhead. - //! @param[in] theOpLabel human-readable operation name - //! @param[in] theOriginals node ids before the operation - //! @param[in] theReplacements node ids after the operation (same length) - //! @param[in] theExtraInfo optional diagnostic info stored on the record - Standard_EXPORT void RecordBatch( - const TCollection_AsciiString& theOpLabel, - const NCollection_DynamicArray& theOriginals, - const NCollection_DynamicArray& theReplacements, - const TCollection_AsciiString& theExtraInfo = TCollection_AsciiString()); - - //! Walk backwards from a modified node to its original. - //! Follows the reverse map recursively until a root is reached. - //! @param[in] theModified node id to trace back - //! @return the root original node id, or theModified itself if not found - [[nodiscard]] Standard_EXPORT BRepGraph_NodeId - FindOriginal(const BRepGraph_NodeId theModified) const; - - //! Walk forwards from an original node to all derived nodes. - //! Follows the forward map recursively, collecting all leaves. - //! @param[in] theOriginal node id to trace forward - //! @return all transitively derived node ids - [[nodiscard]] Standard_EXPORT NCollection_DynamicArray FindDerived( - const BRepGraph_NodeId theOriginal) const; - - //! Number of recorded history events. - //! @return record count - [[nodiscard]] Standard_EXPORT size_t NbRecords() const; - - //! Access a record by index (0-based). - //! @param[in] theRecordIdx zero-based index into the records vector - //! @return the history record at the given index - [[nodiscard]] Standard_EXPORT const BRepGraph_HistoryRecord& Record( - const size_t theRecordIdx) const; - - //! Enable or disable history recording. - //! @param[in] theVal true to enable, false to disable - Standard_EXPORT void SetEnabled(const bool theVal); - - //! Query whether history recording is enabled. - //! @return true if recording is active - [[nodiscard]] Standard_EXPORT bool IsEnabled() const; - - //! Clear all records and lookup maps. - Standard_EXPORT void Clear(); - - //! Set the allocator for internal containers. - //! Must be called before any Record/RecordBatch calls. - //! @param[in] theAlloc allocator to use for internal maps - Standard_EXPORT void SetAllocator(const occ::handle& theAlloc); - -private: - occ::handle myAllocator; - - NCollection_DynamicArray myRecords; - - //! Reverse map: derived node -> original node. - NCollection_DataMap myDerivedToOriginal; - - //! Forward map: original node -> vector of derived nodes. - NCollection_DataMap> - myOriginalToDerived; - - bool myEnabled = true; -}; - -#endif // _BRepGraph_History_HeaderFile diff --git a/opencascade/BRepGraph_HistoryRecord.hxx b/opencascade/BRepGraph_HistoryRecord.hxx deleted file mode 100644 index 3724eab98..000000000 --- a/opencascade/BRepGraph_HistoryRecord.hxx +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraph_HistoryRecord_HeaderFile -#define _BRepGraph_HistoryRecord_HeaderFile - -#include - -#include -#include -#include - -//! One atomic modification event recorded in the graph's history log. -//! -//! A HistoryRecord captures what happened during a single call to -//! BRepGraph::ApplyModification(): -//! - OperationName identifies the algorithm ("Sewing", "FilletEdge", ...). -//! - SequenceNumber provides total ordering of events. -//! - Mapping records the topological fate of each affected node: -//! original -> [replacement1, replacement2, ...] (split) -//! original -> [same_node] (modified in place) -//! original -> [] (deleted) -//! -//! The history log is append-only within a graph's lifetime. -struct BRepGraph_HistoryRecord -{ - TCollection_AsciiString OperationName; - size_t SequenceNumber = 0; - - //! Key: original node id before the operation. - //! Value: sequence of replacement node ids after the operation. - NCollection_DataMap> Mapping; - - //! Optional extra info for diagnostic/debugging purposes. - //! E.g., merge tolerance, canonical source index. - TCollection_AsciiString ExtraInfo; -}; - -#endif // _BRepGraph_HistoryRecord_HeaderFile diff --git a/opencascade/BRepGraph_ItemId.hxx b/opencascade/BRepGraph_ItemId.hxx new file mode 100644 index 000000000..53a358619 --- /dev/null +++ b/opencascade/BRepGraph_ItemId.hxx @@ -0,0 +1,172 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_ItemId_HeaderFile +#define _BRepGraph_ItemId_HeaderFile + +#include +#include +#include +#include +#include + +#include +#include +#include + +//! Generic BRepGraph item identifier covering definitions and references. +//! Use-records are NOT included - they are session-local, not graph identity. +class BRepGraph_ItemId +{ +public: + //! Addressed graph item domain. + enum class Domain : uint8_t + { + None, + Node, + Reference + }; + + //! Construct an invalid item id. + BRepGraph_ItemId() = default; + + //! Construct a node item id. + BRepGraph_ItemId(const BRepGraph_NodeId theNode) + { + if (theNode.IsValid()) + { + myDomain = Domain::Node; + myIndex = theNode.Index; + myKind = static_cast(theNode.NodeKind); + } + } + + //! Construct a reference item id. + BRepGraph_ItemId(const BRepGraph_RefId theRef) + { + if (theRef.IsValid()) + { + myDomain = Domain::Reference; + myIndex = theRef.Index; + myKind = static_cast(theRef.RefKind); + } + } + + //! Return true if this item addresses a graph object. + [[nodiscard]] bool IsValid() const noexcept + { + if (myIndex == THE_INVALID_INDEX) + { + return false; + } + + switch (myDomain) + { + case Domain::Node: + return BRepGraph_NodeId::IsValidKind(static_cast(myKind)); + case Domain::Reference: + return BRepGraph_RefId::IsValidKind(static_cast(myKind)); + case Domain::None: + return false; + } + return false; + } + + //! Return the addressed domain. + [[nodiscard]] Domain ItemDomain() const noexcept { return myDomain; } + + //! Return true if this item addresses a definition node. + [[nodiscard]] bool IsNode() const noexcept { return myDomain == Domain::Node; } + + //! Return true if this item addresses a reference entry. + [[nodiscard]] bool IsReference() const noexcept { return myDomain == Domain::Reference; } + + //! Convert to node id. Returns invalid id for non-node items. + [[nodiscard]] BRepGraph_NodeId NodeId() const noexcept + { + return IsNode() && BRepGraph_NodeId::IsValidKind(static_cast(myKind)) + ? BRepGraph_NodeId(static_cast(myKind), myIndex) + : BRepGraph_NodeId(); + } + + //! Convert to reference id. Returns invalid id for non-reference items. + [[nodiscard]] BRepGraph_RefId RefId() const noexcept + { + return IsReference() && BRepGraph_RefId::IsValidKind(static_cast(myKind)) + ? BRepGraph_RefId(static_cast(myKind), myIndex) + : BRepGraph_RefId(); + } + + //! Return node kind. Valid only when IsNode() is true. + [[nodiscard]] BRepGraph_NodeId::Kind NodeKind() const noexcept + { + Standard_ASSERT_RETURN( + IsNode() && BRepGraph_NodeId::IsValidKind(static_cast(myKind)), + "BRepGraph_ItemId::NodeKind(): item is not a valid node", + BRepGraph_NodeId::Kind::Solid); + return static_cast(myKind); + } + + //! Return reference kind. Valid only when IsReference() is true. + [[nodiscard]] BRepGraph_RefId::Kind RefKind() const noexcept + { + Standard_ASSERT_RETURN( + IsReference() && BRepGraph_RefId::IsValidKind(static_cast(myKind)), + "BRepGraph_ItemId::RefKind(): item is not a valid reference", + BRepGraph_RefId::Kind::Shell); + return static_cast(myKind); + } + + //! Return item kind encoded in its own domain enum space. + [[nodiscard]] uint8_t RawKind() const noexcept { return myKind; } + + //! Return item kind encoded in its own domain enum space. + [[nodiscard]] uint8_t Kind() const noexcept { return RawKind(); } + + //! Return item per-kind index. + [[nodiscard]] uint32_t Index() const noexcept { return myIndex; } + + friend bool operator==(const BRepGraph_ItemId& theLeft, const BRepGraph_ItemId& theRight) noexcept + { + return theLeft.myDomain == theRight.myDomain && theLeft.myKind == theRight.myKind + && theLeft.myIndex == theRight.myIndex; + } + + friend bool operator!=(const BRepGraph_ItemId& theLeft, const BRepGraph_ItemId& theRight) noexcept + { + return !(theLeft == theRight); + } + +private: + static constexpr uint32_t THE_INVALID_INDEX = std::numeric_limits::max(); + + Domain myDomain = Domain::None; + uint32_t myIndex = THE_INVALID_INDEX; + uint8_t myKind = 0; +}; + +//! std::hash specialization for BRepGraph_ItemId. +template <> +struct std::hash +{ + size_t operator()(const BRepGraph_ItemId& theId) const noexcept + { + size_t aCombination[3]; + aCombination[0] = opencascade::hash(static_cast(theId.ItemDomain())); + aCombination[1] = opencascade::hash(static_cast(theId.RawKind())); + aCombination[2] = opencascade::hash(theId.Index()); + return opencascade::hashBytes(aCombination, sizeof(aCombination)); + } +}; + +#endif // _BRepGraph_ItemId_HeaderFile diff --git a/opencascade/BRepGraph_ItemUID.hxx b/opencascade/BRepGraph_ItemUID.hxx new file mode 100644 index 000000000..51678b2a2 --- /dev/null +++ b/opencascade/BRepGraph_ItemUID.hxx @@ -0,0 +1,189 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_ItemUID_HeaderFile +#define _BRepGraph_ItemUID_HeaderFile + +#include +#include +#include +#include + +#include +#include +#include +#include + +//! Durable BRepGraph item identity covering definition nodes and reference entries. +//! +//! BRepGraph_ItemId is a transient structural address. BRepGraph_ItemUID is the persistent +//! identity assigned at item creation and kept stable across compaction and vector reordering. +//! Representation/use records are not addressed here because they do not have persisted identity. +class BRepGraph_ItemUID +{ +public: + //! Addressed persistent identity domain. + enum class Domain : uint8_t + { + None, + Node, + Reference + }; + + //! Construct an invalid UID. + BRepGraph_ItemUID() = default; + + //! Construct a node UID. + static BRepGraph_ItemUID Node(const BRepGraph_NodeId::Kind theKind, const size_t theCounter) + { + return BRepGraph_ItemUID(Domain::Node, static_cast(theKind), theCounter); + } + + //! Construct a reference UID. + static BRepGraph_ItemUID Reference(const BRepGraph_RefId::Kind theKind, const size_t theCounter) + { + return BRepGraph_ItemUID(Domain::Reference, static_cast(theKind), theCounter); + } + + //! Return an invalid sentinel UID. + static BRepGraph_ItemUID Invalid() { return BRepGraph_ItemUID(); } + + //! Return true if this UID has a non-sentinel counter and a valid domain/kind pair. + [[nodiscard]] bool IsValid() const noexcept + { + if (myCounter == 0) + { + return false; + } + + switch (myDomain) + { + case Domain::Node: + return BRepGraph_NodeId::IsValidKind(static_cast(myKind)); + case Domain::Reference: + return BRepGraph_RefId::IsValidKind(static_cast(myKind)); + case Domain::None: + return false; + } + return false; + } + + //! Return the addressed identity domain. + [[nodiscard]] Domain ItemDomain() const noexcept { return myDomain; } + + [[nodiscard]] bool IsNode() const noexcept { return myDomain == Domain::Node; } + + [[nodiscard]] bool IsReference() const noexcept { return myDomain == Domain::Reference; } + + //! Return node kind. Valid only for node UIDs. + [[nodiscard]] BRepGraph_NodeId::Kind NodeKind() const noexcept + { + Standard_ASSERT_RETURN( + IsNode() && BRepGraph_NodeId::IsValidKind(static_cast(myKind)), + "BRepGraph_ItemUID::NodeKind(): UID is not a valid node UID", + BRepGraph_NodeId::Kind::Solid); + return static_cast(myKind); + } + + //! Return reference kind. Valid only for reference UIDs. + [[nodiscard]] BRepGraph_RefId::Kind RefKind() const noexcept + { + Standard_ASSERT_RETURN( + IsReference() && BRepGraph_RefId::IsValidKind(static_cast(myKind)), + "BRepGraph_ItemUID::RefKind(): UID is not a valid reference UID", + BRepGraph_RefId::Kind::Shell); + return static_cast(myKind); + } + + //! Return item kind encoded in its own domain enum space. + [[nodiscard]] uint8_t RawKind() const noexcept { return myKind; } + + //! Return the graph-wide monotonic UID counter. + [[nodiscard]] size_t Counter() const noexcept { return myCounter; } + + friend bool operator==(const BRepGraph_ItemUID& theLeft, + const BRepGraph_ItemUID& theRight) noexcept + { + if (theLeft.myCounter == 0 || theRight.myCounter == 0) + { + return (theLeft.myCounter == 0) == (theRight.myCounter == 0); + } + return theLeft.myDomain == theRight.myDomain && theLeft.myKind == theRight.myKind + && theLeft.myCounter == theRight.myCounter; + } + + friend bool operator!=(const BRepGraph_ItemUID& theLeft, + const BRepGraph_ItemUID& theRight) noexcept + { + return !(theLeft == theRight); + } + + friend bool operator<(const BRepGraph_ItemUID& theLeft, + const BRepGraph_ItemUID& theRight) noexcept + { + if (theLeft.myDomain != theRight.myDomain) + { + return static_cast(theLeft.myDomain) < static_cast(theRight.myDomain); + } + if (theLeft.myKind != theRight.myKind) + { + return theLeft.myKind < theRight.myKind; + } + return theLeft.myCounter < theRight.myCounter; + } + + //! Compute a hash value compatible with operator==. + [[nodiscard]] size_t HashValue() const noexcept + { + if (myCounter == 0) + { + return opencascade::hash(0); + } + + size_t aCombination[3]; + aCombination[0] = opencascade::hash(static_cast(myDomain)); + aCombination[1] = opencascade::hash(static_cast(myKind)); + aCombination[2] = opencascade::hash(myCounter); + return opencascade::hashBytes(aCombination, sizeof(aCombination)); + } + +private: + BRepGraph_ItemUID(const Domain theDomain, const uint8_t theKind, const size_t theCounter) + : myCounter(0), + myDomain(theDomain), + myKind(theKind) + { + Standard_ASSERT_VOID(theCounter > 0, "BRepGraph_ItemUID: counter must be > 0 for valid UIDs"); + Standard_ASSERT_VOID(theCounter <= std::numeric_limits::max(), + "BRepGraph_ItemUID: counter exceeds 32-bit storage"); + if (theCounter > 0 && theCounter <= std::numeric_limits::max()) + { + myCounter = static_cast(theCounter); + } + } + + uint32_t myCounter = 0; //!< 0 = invalid sentinel; valid counters start at 1. + Domain myDomain = Domain::None; //!< Identity domain. + uint8_t myKind = 0; //!< Kind encoded in the selected domain enum space. +}; + +static_assert(sizeof(BRepGraph_ItemUID) <= 8, "BRepGraph_ItemUID must stay compact"); + +//! std::hash specialization for NCollection_DefaultHasher support. +template <> +struct std::hash +{ + size_t operator()(const BRepGraph_ItemUID& theUID) const noexcept { return theUID.HashValue(); } +}; + +#endif // _BRepGraph_ItemUID_HeaderFile diff --git a/opencascade/BRepGraph_Iterator.hxx b/opencascade/BRepGraph_Iterator.hxx index c356dd90e..72acda757 100644 --- a/opencascade/BRepGraph_Iterator.hxx +++ b/opencascade/BRepGraph_Iterator.hxx @@ -16,10 +16,8 @@ #include #include - #include -#include #include //! @brief Type-safe, allocation-free iterator over BRepGraph definition nodes. @@ -39,16 +37,6 @@ //! @endcode namespace BRepGraph_IteratorDetail { -//! SFINAE helper: detect whether NodeType has an IsRemoved member (BaseDef types do). -template -struct HasIsRemoved : std::false_type -{ -}; - -template -struct HasIsRemoved().IsRemoved)>> : std::true_type -{ -}; //! Compile-time traits mapping from definition type to typed NodeId, //! count accessor, and definition accessor. @@ -60,7 +48,7 @@ struct NodeTraits { using TypedId = BRepGraph_SolidId; - static int Count(const BRepGraph& theGraph) { return theGraph.Topo().Solids().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Topo().Solids().Nb(); } static const BRepGraphInc::SolidDef& Get(const BRepGraph& theGraph, const TypedId theId) { @@ -73,7 +61,7 @@ struct NodeTraits { using TypedId = BRepGraph_ShellId; - static int Count(const BRepGraph& theGraph) { return theGraph.Topo().Shells().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Topo().Shells().Nb(); } static const BRepGraphInc::ShellDef& Get(const BRepGraph& theGraph, const TypedId theId) { @@ -86,7 +74,7 @@ struct NodeTraits { using TypedId = BRepGraph_FaceId; - static int Count(const BRepGraph& theGraph) { return theGraph.Topo().Faces().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Topo().Faces().Nb(); } static const BRepGraphInc::FaceDef& Get(const BRepGraph& theGraph, const TypedId theId) { @@ -99,7 +87,7 @@ struct NodeTraits { using TypedId = BRepGraph_WireId; - static int Count(const BRepGraph& theGraph) { return theGraph.Topo().Wires().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Topo().Wires().Nb(); } static const BRepGraphInc::WireDef& Get(const BRepGraph& theGraph, const TypedId theId) { @@ -112,7 +100,7 @@ struct NodeTraits { using TypedId = BRepGraph_EdgeId; - static int Count(const BRepGraph& theGraph) { return theGraph.Topo().Edges().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Topo().Edges().Nb(); } static const BRepGraphInc::EdgeDef& Get(const BRepGraph& theGraph, const TypedId theId) { @@ -125,7 +113,7 @@ struct NodeTraits { using TypedId = BRepGraph_VertexId; - static int Count(const BRepGraph& theGraph) { return theGraph.Topo().Vertices().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Topo().Vertices().Nb(); } static const BRepGraphInc::VertexDef& Get(const BRepGraph& theGraph, const TypedId theId) { @@ -138,7 +126,7 @@ struct NodeTraits { using TypedId = BRepGraph_ProductId; - static int Count(const BRepGraph& theGraph) { return theGraph.Topo().Products().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Topo().Products().Nb(); } static const BRepGraphInc::ProductDef& Get(const BRepGraph& theGraph, const TypedId theId) { @@ -151,7 +139,7 @@ struct NodeTraits { using TypedId = BRepGraph_OccurrenceId; - static int Count(const BRepGraph& theGraph) { return theGraph.Topo().Occurrences().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Topo().Occurrences().Nb(); } static const BRepGraphInc::OccurrenceDef& Get(const BRepGraph& theGraph, const TypedId theId) { @@ -164,7 +152,7 @@ struct NodeTraits { using TypedId = BRepGraph_CoEdgeId; - static int Count(const BRepGraph& theGraph) { return theGraph.Topo().CoEdges().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Topo().CoEdges().Nb(); } static const BRepGraphInc::CoEdgeDef& Get(const BRepGraph& theGraph, const TypedId theId) { @@ -177,7 +165,7 @@ struct NodeTraits { using TypedId = BRepGraph_CompoundId; - static int Count(const BRepGraph& theGraph) { return theGraph.Topo().Compounds().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Topo().Compounds().Nb(); } static const BRepGraphInc::CompoundDef& Get(const BRepGraph& theGraph, const TypedId theId) { @@ -190,7 +178,7 @@ struct NodeTraits { using TypedId = BRepGraph_CompSolidId; - static int Count(const BRepGraph& theGraph) { return theGraph.Topo().CompSolids().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Topo().CompSolids().Nb(); } static const BRepGraphInc::CompSolidDef& Get(const BRepGraph& theGraph, const TypedId theId) { @@ -255,10 +243,12 @@ private: //! Advance past any nodes marked as removed. void skipRemoved() { - if constexpr (!TheFullTraverse && BRepGraph_IteratorDetail::HasIsRemoved::value) + if constexpr (!TheFullTraverse) { - while (myCurrent < myLength && Current().IsRemoved) + while (myCurrent < myLength && myCurrent.IsRemoved(myGraph)) + { ++myCurrent; + } } } @@ -312,7 +302,7 @@ public: { } - [[nodiscard]] bool More() const { return myIndex < myRoots.Length(); } + [[nodiscard]] bool More() const { return myIndex < myRoots.Size(); } void Next() { ++myIndex; } @@ -326,8 +316,8 @@ public: NCollection_ForwardRangeSentinel end() const { return NCollection_ForwardRangeSentinel{}; } private: - const NCollection_DynamicArray& myRoots; - int myIndex = 0; + const NCollection_LinearVector& myRoots; + size_t myIndex = 0; }; #endif // _BRepGraph_Iterator_HeaderFile diff --git a/opencascade/BRepGraph_Layer.hxx b/opencascade/BRepGraph_Layer.hxx index e5db1c5aa..73520ec07 100644 --- a/opencascade/BRepGraph_Layer.hxx +++ b/opencascade/BRepGraph_Layer.hxx @@ -14,17 +14,21 @@ #ifndef _BRepGraph_Layer_HeaderFile #define _BRepGraph_Layer_HeaderFile +#include +#include +#include #include #include +#include #include -#include +#include #include #include #include #include +#include -class BRepGraph; class BRepGraph_LayerRegistry; //! @brief Abstract base class for named attribute layers. @@ -67,27 +71,40 @@ public: //! Layer identity (unique within a graph). [[nodiscard]] virtual const TCollection_AsciiString& Name() const = 0; - //! Called when a node is soft-removed. - //! @param[in] theNode the removed node - //! @param[in] theReplacement if valid, the node that replaces theNode - //! (e.g., sewing edge merge, deduplicate). If invalid, pure deletion. - //! Layers should migrate data from theNode to theReplacement when valid, - //! otherwise discard or archive removed-node data. - //! Implementations must validate theReplacement before dereferencing - //! graph data through it. + //! Called when a node is soft-removed without a replacement. + //! @param[in] theNode the removed node + //! Layers should discard or archive data associated with it. //! @warning Layer callbacks must not throw. They are called from noexcept //! notification paths (MutGuard destructors, deferred invalidation flush). - virtual void OnNodeRemoved(const BRepGraph_NodeId theNode, - const BRepGraph_NodeId theReplacement) noexcept = 0; - - //! Called after Compact with a unified old->new remap map. - //! Layer must remap all internal NodeId references using this map. - //! The map covers all node kinds (Vertex through CompSolid and future extensions). - //! Nodes absent from the map were removed during compaction - layers should - //! drop data associated with those nodes. - //! @param[in] theRemapMap maps old NodeId to new NodeId for all surviving nodes - virtual void OnCompact( - const NCollection_DataMap& theRemapMap) noexcept = 0; + Standard_EXPORT virtual void OnNodeRemoved(const BRepGraph_NodeId theNode) noexcept; + + //! Dispatch a generic item removal to the matching typed removal callback. + //! This is a non-virtual convenience entry point; typed callbacks remain the + //! extension points for derived layers. + //! @param[in] theItem the removed definition or reference + Standard_EXPORT void OnItemRemoved(const BRepGraph_ItemId theItem) noexcept; + + //! Called when a node is soft-removed and replaced by another node. + //! @param[in] theOldNode the removed node + //! @param[in] theNewNode the node that replaces theOldNode + //! Layers that store node-keyed data should migrate from + //! theOldNode to theNewNode when the replacement kind is + //! compatible. This is a structural lifecycle event, not an + //! algorithmic history record. + //! @warning Layer callbacks must not throw. They are called from noexcept + //! notification paths (MutGuard destructors, deferred invalidation flush). + Standard_EXPORT virtual void OnNodeReplaced(const BRepGraph_NodeId theOldNode, + const BRepGraph_NodeId theNewNode) noexcept; + + //! Copy this source layer data into another graph. + //! The source graph is the graph this layer is attached to (Graph()). + //! @param[in] theCopy source graph, target graph, and source item id -> target item id remap + //! @note Missing source items were not copied; persistent layers should skip dependent records. + //! @note For BRepGraph_CopyRemap::Mode::Compact, the layer is being migrated in-place after + //! structural compaction. UID/ItemUID records and ref/rep entries should be remapped through + //! the item map. Stale entries (absent from the remap) should be dropped. + //! @warning This callback may allocate and is intentionally not noexcept. + Standard_EXPORT virtual void CopyTo(const BRepGraph_CopyRemap& theCopy) const = 0; //! Mark all cached values dirty (bulk invalidation). virtual void InvalidateAll() noexcept = 0; @@ -95,8 +112,6 @@ public: //! Clear all stored data. virtual void Clear() noexcept = 0; - // --- Modification event subscription --- - //! Return a bitmask of BRepGraph_NodeId::Kind values this layer subscribes to. //! Only modification events matching subscribed kinds are dispatched. //! Default: 0 (no subscription - no modification events received). @@ -110,14 +125,20 @@ public: //! @param[in] theNode the modified node Standard_EXPORT virtual void OnNodeModified(const BRepGraph_NodeId theNode) noexcept; + //! Dispatch a generic item modification to the matching typed modification callback. + //! This is a non-virtual convenience entry point; typed callbacks remain the + //! extension points for derived layers. + //! @param[in] theItem the modified definition or reference + Standard_EXPORT void OnItemModified(const BRepGraph_ItemId theItem) noexcept; + //! Called after EndDeferredInvalidation() with all nodes modified during //! the deferred scope. Only dispatched if at least one modified node's kind - //! matches SubscribedKinds(). The vector may contain nodes of kinds not + //! matches SubscribedKinds(). The array may contain nodes of kinds not //! subscribed to - layers should filter internally if needed. //! Default: no-op. //! @param[in] theModifiedNodes all modified, non-removed nodes Standard_EXPORT virtual void OnNodesModified( - const NCollection_DynamicArray& theModifiedNodes) noexcept; + const NCollection_Array1& theModifiedNodes) noexcept; //! Convenience: return bitmask bit for a given Kind. static int KindBit(const BRepGraph_NodeId::Kind theKind) @@ -125,8 +146,6 @@ public: return 1 << static_cast(theKind); } - // --- Reference modification event subscription --- - //! Return a bitmask of BRepGraph_RefId::Kind values this layer subscribes to. //! Only modification events matching subscribed ref kinds are dispatched. //! Default: 0 (no subscription). Must be constant for the layer's lifetime. @@ -148,14 +167,12 @@ public: //! Called after EndDeferredInvalidation() with all refs modified during //! the deferred scope. Only dispatched if at least one modified ref's kind - //! matches SubscribedRefKinds(). The vector may contain refs of kinds not + //! matches SubscribedRefKinds(). The array may contain refs of kinds not //! subscribed to - layers should filter internally if needed. //! Default: no-op. - //! @param[in] theModifiedRefs all modified, non-removed refs - //! @param[in] theModifiedRefKindsMask bitwise OR of all modified ref kinds + //! @param[in] theModifiedRefs all modified, non-removed refs Standard_EXPORT virtual void OnRefsModified( - const NCollection_DynamicArray& theModifiedRefs, - const int theModifiedRefKindsMask) noexcept; + const NCollection_Array1& theModifiedRefs) noexcept; //! Convenience: return bitmask bit for a given RefId::Kind. static int RefKindBit(const BRepGraph_RefId::Kind theKind) @@ -163,34 +180,74 @@ public: return 1 << static_cast(theKind); } - // --- Revision + owning-graph access --- - //! Monotonic revision counter incremented by touch() on every observable //! state change. Consumers compare stored revisions to detect staleness in O(1). //! Derived layers MUST call touch() from their mutators. [[nodiscard]] uint64_t Revision() const noexcept { return myRevision; } - //! Owning graph, set by the registry on RegisterLayer() and cleared on Unregister(). - //! Nullptr before registration or after unregistration. - [[nodiscard]] const BRepGraph* OwningGraph() const noexcept { return myOwningGraph; } +protected: + Standard_EXPORT BRepGraph_Layer(); - //! Mutable accessor for layers that drive graph mutations (e.g. meshing). - [[nodiscard]] BRepGraph* OwningMutableGraph() const noexcept + //! Bump the revision counter. + void touch() noexcept { ++myRevision; } + + //! True while this layer is registered in a live graph registry. + [[nodiscard]] bool IsAttached() const noexcept { return myGraph != nullptr; } + + //! Attached graph for read-only layer services. Raises Standard_ProgramError if detached. + [[nodiscard]] Standard_EXPORT const BRepGraph& Graph() const; + + //! Attached mutable graph for graph-owned service layers. Returns null if detached. + [[nodiscard]] BRepGraph* AttachedGraph() const noexcept { return myGraph; } + + template + [[nodiscard]] static BRepGraph_NodeId::Typed RemappedItem( + const BRepGraph_CopyRemap& theCopy, + const BRepGraph_NodeId::Typed theId) { - return const_cast(myOwningGraph); + if (!theId.IsValid()) + { + return BRepGraph_NodeId::Typed(); + } + const BRepGraph_ItemId aMapped = theCopy.TargetItem(BRepGraph_ItemId(theId)); + if (!aMapped.IsNode()) + { + return BRepGraph_NodeId::Typed(); + } + return BRepGraph_NodeId::Typed::FromNodeId(aMapped.NodeId()); } -protected: - //! Bump the revision counter. - void touch() noexcept { ++myRevision; } + template + [[nodiscard]] static BRepGraph_RefId::Typed RemappedItem( + const BRepGraph_CopyRemap& theCopy, + const BRepGraph_RefId::Typed theId) + { + if (!theId.IsValid()) + { + return BRepGraph_RefId::Typed(); + } + const BRepGraph_ItemId aMapped = theCopy.TargetItem(BRepGraph_ItemId(theId)); + if (!aMapped.IsReference()) + { + return BRepGraph_RefId::Typed(); + } + return BRepGraph_RefId::Typed::FromRefId(aMapped.RefId()); + } + + //! Called after the layer is attached to a graph registry. + Standard_EXPORT virtual void OnAttached() noexcept; + + //! Called before the layer is detached from a graph registry. + Standard_EXPORT virtual void OnDetached() noexcept; private: friend class ::BRepGraph_LayerRegistry; - void setOwningGraph(const BRepGraph* theGraph) noexcept { myOwningGraph = theGraph; } + Standard_EXPORT void attachGraph(BRepGraph* theGraph) noexcept; + Standard_EXPORT void detachContext() noexcept; - const BRepGraph* myOwningGraph = nullptr; - uint64_t myRevision = 0; + BRepGraph* myGraph = nullptr; + uint64_t myRevision = 0; public: DEFINE_STANDARD_RTTIEXT(BRepGraph_Layer, Standard_Transient) diff --git a/opencascade/BRepGraph_LayerDeferred.hxx b/opencascade/BRepGraph_LayerDeferred.hxx new file mode 100644 index 000000000..165b0abeb --- /dev/null +++ b/opencascade/BRepGraph_LayerDeferred.hxx @@ -0,0 +1,324 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_LayerDeferred_HeaderFile +#define _BRepGraph_LayerDeferred_HeaderFile + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +//! Base layer for postponed graph item loading. +//! +//! The layer stores provider-neutral deferred representation records and owns the lock +//! state through BRepGraph_LayerLock. Format-specific loaders, such as ODE or +//! STEP, should derive from this class or use the same representation contract rather +//! than storing deferred ownership in topology definitions. +class BRepGraph_LayerDeferred : public BRepGraph_Layer +{ +public: + //! Constructor for generic deferred layers. + Standard_EXPORT BRepGraph_LayerDeferred(); + + //! Representation category. + enum class RepresentationKind + { + Unknown, + Geometry, + Mesh, + Topology, + Assembly, + Parametric + }; + + //! One postponed representation attached to a graph item. + struct Representation + { + static constexpr uint32_t THE_INVALID_SOURCE_INDEX = std::numeric_limits::max(); + + RepresentationKind Kind = RepresentationKind::Unknown; + uint32_t Role = 0; + TCollection_AsciiString Name; + uint32_t SourceIndex = THE_INVALID_SOURCE_INDEX; + }; + + //! Deferred ownership entry for one graph item. + struct Entry + { + //! Small fixed representation list. Deferred graph items have a bounded number of + //! persisted representations, so avoid one heap allocation per item. + class RepresentationStorage + { + public: + static constexpr size_t THE_MAX_REPRESENTATIONS_PER_ITEM = 8; + + RepresentationStorage() = default; + + RepresentationStorage(const RepresentationStorage& theOther) { copyFrom(theOther); } + + RepresentationStorage(RepresentationStorage&& theOther) noexcept { moveFrom(theOther); } + + Standard_EXPORT RepresentationStorage& operator=(const RepresentationStorage& theOther); + Standard_EXPORT RepresentationStorage& operator=(RepresentationStorage&& theOther) noexcept; + + ~RepresentationStorage() { Clear(); } + + [[nodiscard]] size_t Size() const { return mySize; } + + [[nodiscard]] bool IsEmpty() const { return mySize == 0; } + + [[nodiscard]] Standard_EXPORT bool ContainsKind(const RepresentationKind theKind) const; + + [[nodiscard]] const Representation& Value(const size_t theIndex) const + { + Standard_ASSERT_RAISE(theIndex < mySize, "Deferred representation index is out of range"); + return *representationPtr(theIndex); + } + + [[nodiscard]] Representation& ChangeValue(const size_t theIndex) + { + Standard_ASSERT_RAISE(theIndex < mySize, "Deferred representation index is out of range"); + return *representationPtr(theIndex); + } + + [[nodiscard]] const Representation& First() const + { + Standard_ASSERT_RAISE(mySize > 0, "Deferred representation list is empty"); + return *representationPtr(0); + } + + Standard_EXPORT void Append(const Representation& theRepresentation); + + Standard_EXPORT void Clear(); + + private: + [[nodiscard]] const Representation* representationPtr(const size_t theIndex) const + { + return reinterpret_cast(&myRepresentationStorage[theIndex]); + } + + [[nodiscard]] Representation* representationPtr(const size_t theIndex) + { + return reinterpret_cast(&myRepresentationStorage[theIndex]); + } + + Standard_EXPORT void copyFrom(const RepresentationStorage& theOther); + Standard_EXPORT void moveFrom(RepresentationStorage& theOther); + + using RepresentationSlot = + std::aligned_storage_t; + + RepresentationSlot myRepresentationStorage[THE_MAX_REPRESENTATIONS_PER_ITEM]; + size_t mySize = 0; + }; + + TCollection_AsciiString Provider; + TCollection_AsciiString SourceKey; + RepresentationStorage Representations; + }; + + //! Return fixed layer type GUID. + [[nodiscard]] Standard_EXPORT static const Standard_GUID& GetID(); + + //! Return this layer type GUID. + [[nodiscard]] Standard_EXPORT const Standard_GUID& ID() const override; + + //! Return deferred entry for an item, or null if none exists. + [[nodiscard]] Standard_EXPORT const Entry* FindDeferred(const BRepGraph_ItemId theItem) const; + + //! Return deferred entry for a node, or null if none exists. + [[nodiscard]] const Entry* FindDeferred(const BRepGraph_NodeId theNode) const + { + return FindDeferred(BRepGraph_ItemId(theNode)); + } + + //! Return deferred entry for a reference, or null if none exists. + [[nodiscard]] const Entry* FindDeferred(const BRepGraph_RefId theRef) const + { + return FindDeferred(BRepGraph_ItemId(theRef)); + } + + //! Return true if an item has deferred representations. + [[nodiscard]] Standard_EXPORT bool HasDeferred(const BRepGraph_ItemId theItem) const; + + //! Return true if a node has deferred representations. + [[nodiscard]] bool HasDeferred(const BRepGraph_NodeId theNode) const + { + return HasDeferred(BRepGraph_ItemId(theNode)); + } + + //! Return true if a reference has deferred representations. + [[nodiscard]] bool HasDeferred(const BRepGraph_RefId theRef) const + { + return HasDeferred(BRepGraph_ItemId(theRef)); + } + + //! Register one postponed representation and lock the item. + Standard_EXPORT void RegisterDeferred(const BRepGraph_ItemId theItem, + const TCollection_AsciiString& theProvider, + const TCollection_AsciiString& theSourceKey, + const RepresentationKind theRepresentationKind, + const TCollection_AsciiString& theRepresentationName, + const uint32_t theSourceIndex); + + //! Register postponed representations for one item and lock the item once. + Standard_EXPORT void RegisterDeferredRepresentations(const BRepGraph_ItemId theItem, + const TCollection_AsciiString& theProvider, + const TCollection_AsciiString& theSourceKey, + const Representation* theRepresentations, + const size_t theNbRepresentations); + + //! Register postponed representations for a new item and lock it once. + //! + //! This is a trusted bulk-load fast path: the caller must ensure the item is valid, + //! has no existing deferred entry, and `theRepresentations` contains no duplicates. + Standard_EXPORT void RegisterDeferredRepresentationsDirect( + const BRepGraph_ItemId theItem, + const TCollection_AsciiString& theProvider, + const TCollection_AsciiString& theSourceKey, + const Representation* theRepresentations, + const size_t theNbRepresentations); + + //! Register one postponed node representation and lock the node. + void RegisterDeferred(const BRepGraph_NodeId theNode, + const TCollection_AsciiString& theProvider, + const TCollection_AsciiString& theSourceKey, + const RepresentationKind theRepresentationKind, + const TCollection_AsciiString& theRepresentationName, + const uint32_t theSourceIndex) + { + RegisterDeferred(BRepGraph_ItemId(theNode), + theProvider, + theSourceKey, + theRepresentationKind, + theRepresentationName, + theSourceIndex); + } + + //! Register one postponed reference representation and lock the reference. + void RegisterDeferred(const BRepGraph_RefId theRef, + const TCollection_AsciiString& theProvider, + const TCollection_AsciiString& theSourceKey, + const RepresentationKind theRepresentationKind, + const TCollection_AsciiString& theRepresentationName, + const uint32_t theSourceIndex) + { + RegisterDeferred(BRepGraph_ItemId(theRef), + theProvider, + theSourceKey, + theRepresentationKind, + theRepresentationName, + theSourceIndex); + } + + //! Remove all deferred representations for an item and unlock it. + Standard_EXPORT void UnregisterDeferred(const BRepGraph_ItemId theItem); + + //! Remove all deferred representations for a node and unlock it. + void UnregisterDeferred(const BRepGraph_NodeId theNode) + { + UnregisterDeferred(BRepGraph_ItemId(theNode)); + } + + //! Remove all deferred representations for a reference and unlock it. + void UnregisterDeferred(const BRepGraph_RefId theRef) + { + UnregisterDeferred(BRepGraph_ItemId(theRef)); + } + + //! Return true if at least one item has deferred representations. + [[nodiscard]] bool HasDeferredItems() const { return myEntries.Extent() != 0; } + + //! Return first deferred entry with at least one representation of the requested kind, or null. + [[nodiscard]] Standard_EXPORT const Entry* FindFirstDeferred( + const RepresentationKind theKind, + BRepGraph_ItemId* theItem = nullptr) const; + + //! Reserve deferred and lock layer buckets for bulk registration. + Standard_EXPORT void ReserveDeferredItems(const size_t theNbItems); + + //! Begin bulk deferred registration. Revision updates are postponed until EndBulkRegistration(). + Standard_EXPORT void BeginBulkRegistration(); + + //! Finish bulk deferred registration and publish one revision update if anything changed. + Standard_EXPORT void EndBulkRegistration(); + + //! Visit deferred entries. Callback receives item id and an entry copy; returning false stops. + template + void ForEachDeferred(VisitorT&& theVisitor) const + { + for (NCollection_DataMap::Iterator anIt(myEntries); anIt.More();) + { + const BRepGraph_ItemId anItem = anIt.Key(); + const Entry anEntry = anIt.Value(); + anIt.Next(); + if (!theVisitor(anItem, anEntry)) + { + break; + } + } + } + + //! Visit deferred entries with at least one representation of the requested kind. + //! Callback receives item id and an entry copy; returning false stops. + template + void ForEachDeferred(const RepresentationKind theKind, VisitorT&& theVisitor) const + { + for (NCollection_DataMap::Iterator anIt(myEntries); anIt.More();) + { + if (!anIt.Value().Representations.ContainsKind(theKind)) + { + anIt.Next(); + continue; + } + + const BRepGraph_ItemId anItem = anIt.Key(); + const Entry anEntry = anIt.Value(); + anIt.Next(); + if (!theVisitor(anItem, anEntry)) + { + break; + } + } + } + + Standard_EXPORT const TCollection_AsciiString& Name() const override; + Standard_EXPORT void OnNodeRemoved(const BRepGraph_NodeId theNode) noexcept override; + Standard_EXPORT void OnNodeReplaced(const BRepGraph_NodeId theOldNode, + const BRepGraph_NodeId theNewNode) noexcept override; + Standard_EXPORT void CopyTo(const BRepGraph_CopyRemap& theCopy) const override; + Standard_EXPORT void OnRefRemoved(const BRepGraph_RefId theRef) noexcept override; + Standard_EXPORT void InvalidateAll() noexcept override; + Standard_EXPORT void Clear() noexcept override; + + DEFINE_STANDARD_RTTIEXT(BRepGraph_LayerDeferred, BRepGraph_Layer) + +private: + void removeItem(const BRepGraph_ItemId theItem) noexcept; + void lockItem(const BRepGraph_ItemId theItem); + void unlockItem(const BRepGraph_ItemId theItem); + +private: + NCollection_DataMap myEntries; + uint32_t myBulkRegistrationDepth = 0; + bool myHasBulkChanges = false; +}; + +#endif // _BRepGraph_LayerDeferred_HeaderFile diff --git a/opencascade/BRepGraph_LayerHistory.hxx b/opencascade/BRepGraph_LayerHistory.hxx new file mode 100644 index 000000000..f994c2c70 --- /dev/null +++ b/opencascade/BRepGraph_LayerHistory.hxx @@ -0,0 +1,422 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_LayerHistory_HeaderFile +#define _BRepGraph_LayerHistory_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class BRepGraph; +class BRepTools_History; + +//! History layer for BRepGraph. +//! +//! BRepGraph_LayerHistory maintains an append-only log of modification events +//! and per-kind lookup maps for efficient queries. Four event kinds are +//! tracked (see #BRepGraph_LayerHistory::Kind): +//! - **Modified**: input -> { modified images } (default). +//! - **Generated**: input -> { generated images } (new entities born +//! from the input but not sharing its identity). +//! - **Deleted**: input has been consumed and has no image in the +//! result. +//! - **Replaced**: input was structurally detached and replaced by another +//! node; this maps as Modified and also marks the input as deleted. +//! +//! Recording can be toggled on/off at runtime. Graph-owned history is registered +//! as a layer and accessed through #Ensure / #Find; algorithms wrapping OCCT's +//! `BRepTools_History` can import results through #Absorb. +class BRepGraph_LayerHistory : public BRepGraph_Layer +{ +public: + //! Classification of a history event. + enum class Kind : std::uint8_t + { + Modified = 0, //!< Default; input persists into the result(s). + Generated = 1, //!< Output entity is freshly produced from the input. + Deleted = 2, //!< Input has no image in the result. + Replaced = 3 //!< Input was detached and continued by replacement(s). + }; + + //! One atomic modification event recorded in the graph's history log. + struct Event + { + Event() = default; + + TCollection_AsciiString OperationName; + size_t SequenceNumber = 0; + Kind RecordKind = Kind::Modified; + + //! Key: original node id before the operation. + //! Value: sequence of replacement node ids after the operation. + NCollection_DataMap> Mapping; + + //! UID-keyed mapping for cross-graph history records. + NCollection_DataMap> UidMapping; + + //! ItemUID-keyed mapping for durable all-domain history records. + NCollection_DataMap> + ItemUidMapping; + + //! Optional diagnostic representation. + TCollection_AsciiString ExtraInfo; + }; + + //! Default constructor. + Standard_EXPORT BRepGraph_LayerHistory(); + + //! Stable layer GUID. + Standard_EXPORT static const Standard_GUID& GetID(); + + //! Layer type identity. + [[nodiscard]] Standard_EXPORT const Standard_GUID& ID() const override; + + //! Layer display name. + [[nodiscard]] Standard_EXPORT const TCollection_AsciiString& Name() const override; + + //! Record a modification: theOriginal was replaced by theReplacements. + //! + //! @note When @p theReplacements is empty the record is auto-downgraded to + //! Kind::Deleted and @p theOriginal is added to the deleted set, + //! regardless of @p theKind. Use #RecordDeleted directly for the + //! deletion case to avoid relying on this implicit conversion. + //! @param[in] theOpLabel human-readable operation name + //! @param[in] theOriginal node id before the operation + //! @param[in] theReplacements node ids after the operation + //! @param[in] theKind classification of this record (default Modified) + Standard_EXPORT void Record( + const TCollection_AsciiString& theOpLabel, + const BRepGraph_NodeId theOriginal, + const NCollection_Array1& theReplacements, + const BRepGraph_LayerHistory::Kind theKind = BRepGraph_LayerHistory::Kind::Modified); + + //! Record a batch of 1-to-1 modifications in a single history event. + //! Each original is paired with the replacement at the same logical position. + //! More efficient than calling Record() in a loop: creates one HistoryRecord + //! and updates the per-kind maps with minimal overhead. + //! @param[in] theOpLabel human-readable operation name + //! @param[in] theOriginals node ids before the operation + //! @param[in] theReplacements node ids after the operation (same length) + //! @param[in] theExtraInfo optional diagnostic info stored on the record + //! @param[in] theKind classification of this record (default Modified) + Standard_EXPORT void RecordBatch( + const TCollection_AsciiString& theOpLabel, + const NCollection_Array1& theOriginals, + const NCollection_Array1& theReplacements, + const TCollection_AsciiString& theExtraInfo = TCollection_AsciiString(), + const BRepGraph_LayerHistory::Kind theKind = BRepGraph_LayerHistory::Kind::Modified); + + //! Record that a collection of inputs has been consumed by the operation + //! and has no image in the result. Each input is appended to the + //! deleted set and emits a single audit record with empty replacements. + //! @param[in] theOpLabel human-readable operation name + //! @param[in] theDeleted node ids that have been removed + Standard_EXPORT void RecordDeleted(const TCollection_AsciiString& theOpLabel, + const NCollection_Array1& theDeleted); + + //! Record replacements: each original is logically removed/detached and + //! continued by the corresponding replacement. Replaced records participate + //! in modified-image queries and also mark originals as deleted. + Standard_EXPORT void RecordReplaced(const TCollection_AsciiString& theOpLabel, + const BRepGraph_NodeId theOriginal, + const BRepGraph_NodeId theReplacement); + + //! Record a batch of 1-to-1 replacements in a single history event. + Standard_EXPORT void RecordReplacedBatch( + const TCollection_AsciiString& theOpLabel, + const NCollection_Array1& theOriginals, + const NCollection_Array1& theReplacements, + const TCollection_AsciiString& theExtraInfo = TCollection_AsciiString()); + + //! Record a UID-keyed modification/generation event. + //! + //! This is the durable-history path for operations whose source and result + //! identities may live in different BRepGraph instances. Existing NodeId + //! records remain available for in-graph algorithms; UID records are queried + //! directly by cross-graph consumers. + Standard_EXPORT void RecordUid( + const TCollection_AsciiString& theOpLabel, + const BRepGraph_UID& theOriginal, + const NCollection_Array1& theReplacements, + const BRepGraph_LayerHistory::Kind theKind = BRepGraph_LayerHistory::Kind::Modified); + + //! Record UID-keyed deletions. + Standard_EXPORT void RecordDeletedUid(const TCollection_AsciiString& theOpLabel, + const NCollection_Array1& theDeleted); + + //! Record an all-domain ItemUID-keyed modification/generation event. + Standard_EXPORT void RecordItemUid( + const TCollection_AsciiString& theOpLabel, + const BRepGraph_ItemUID& theOriginal, + const NCollection_Array1& theReplacements, + const BRepGraph_LayerHistory::Kind theKind = BRepGraph_LayerHistory::Kind::Modified); + + //! Record ItemUID-keyed deletions. + Standard_EXPORT void RecordDeletedItemUid( + const TCollection_AsciiString& theOpLabel, + const NCollection_Array1& theDeleted); + + //! Import a BRepTools_History into this graph-native history log. + //! + //! Iterates @p theInputs, queries @p theSource for Modified / Generated / + //! IsRemoved, translates each TopoDS_Shape image to a NodeId via + //! @p theOutputs, and emits the corresponding records. + //! + //! Semantics: + //! - For every input shape whose Modified() list is non-empty: + //! emit a Modified record. + //! - For every input shape whose Generated() list is non-empty: + //! emit a Generated record. + //! - For every input shape with IsRemoved() == true: accumulate into + //! a single Deleted record (IsRemoved takes precedence over + //! Modified/Generated to handle a known OCCT bug where a shape can + //! appear in both the removed set and the generated map). + //! + //! Output TopoDS_Shapes that do not appear in @p theOutputs are silently + //! dropped (expected for subshapes merged into a parent compound whose + //! identity is preserved at a higher level). + //! + //! @param[in] theInputs TopoDS_Shape -> NodeId for every input subshape + //! that should be tracked + //! @param[in] theOutputs TopoDS_Shape -> NodeId for every subshape added + //! to the graph by this operation (typically from + //! BRepGraph::ShapesView::Add with TrackAddedNodes) + //! @param[in] theSource BRepTools_History from the OCCT algorithm. + //! Null is accepted (no-op). + //! @param[in] theOpLabel record label written into every emitted record + Standard_EXPORT void Absorb( + const NCollection_DataMap& theInputs, + const NCollection_DataMap& theOutputs, + const occ::handle& theSource, + const TCollection_AsciiString& theOpLabel); + + //! Import a BRepTools_History using persistent UIDs from source/result graphs. + //! + //! This overload is the canonical bridge for cross-graph algorithms: input + //! shapes are resolved in @p theInputGraph, output shapes are resolved in + //! @p theOutputGraph, and the resulting history is stored by UID. + Standard_EXPORT void Absorb( + const BRepGraph& theInputGraph, + const BRepGraph& theOutputGraph, + const NCollection_DataMap& theInputs, + const NCollection_DataMap& theOutputs, + const occ::handle& theSource, + const TCollection_AsciiString& theOpLabel); + + //! Walk backwards from a modified node to its original. + //! Follows the reverse map recursively until a root is reached. + //! @param[in] theModified node id to trace back + //! @return the root original node id, or theModified itself if not found + [[nodiscard]] Standard_EXPORT BRepGraph_NodeId + FindOriginal(const BRepGraph_NodeId theModified) const; + + //! Walk forwards from an original node to all derived nodes, including + //! both Modified and Generated descendants. Follows the forward maps + //! recursively, collecting every transitively-reachable descendant + //! (intermediate nodes and leaves alike, but not @p theOriginal itself). + //! @param[in] theOriginal node id to trace forward + //! @return all transitively derived node ids in breadth-first order + [[nodiscard]] Standard_EXPORT NCollection_LinearVector FindDerived( + const BRepGraph_NodeId theOriginal) const; + + //! Direct lookup of the Modified images of @p theOriginal, non-recursive. + //! @param[in] theOriginal node id to query + //! @return pointer to the stored vector, or nullptr if @p theOriginal has + //! no Modified record (note: nullptr does not imply IsDeleted). + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector* FindModified( + const BRepGraph_NodeId theOriginal) const; + + //! Direct lookup of the Generated images of @p theOriginal, non-recursive. + //! @param[in] theOriginal node id to query + //! @return pointer to the stored vector, or nullptr if @p theOriginal has + //! no Generated record. + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector* FindGenerated( + const BRepGraph_NodeId theOriginal) const; + + //! Test whether @p theOriginal was deleted by some recorded operation. + //! @param[in] theOriginal node id to query + //! @return true if @p theOriginal is in the deleted set + [[nodiscard]] Standard_EXPORT bool IsDeleted(const BRepGraph_NodeId theOriginal) const; + + //! Borrowed access to the full deleted set. + //! @return reference to the deleted-node set + [[nodiscard]] Standard_EXPORT const NCollection_FlatMap& DeletedNodes() const; + + //! UID-keyed Modified images stored directly in this history. + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector* FindModified( + const BRepGraph_UID& theUID) const; + + //! Direct lookup of all immediate node origins of @p theDerived. + //! A derived entity can have more than one parent in reconstructive algorithms. + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector* FindOriginals( + const BRepGraph_NodeId theDerived) const; + + //! UID-keyed Generated images stored directly in this history. + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector* FindGenerated( + const BRepGraph_UID& theUID) const; + + //! UID-keyed deletion test stored directly in this history. + [[nodiscard]] Standard_EXPORT bool IsDeleted(const BRepGraph_UID& theUID) const; + + //! UID-keyed deleted set stored directly in this history. + [[nodiscard]] Standard_EXPORT const NCollection_FlatMap& DeletedUids() const; + + //! Test whether @p theUID was registered as an operation input. + [[nodiscard]] Standard_EXPORT bool HasKnownInput(const BRepGraph_UID& theUID) const; + + //! ItemUID-keyed Modified images stored directly in this history. + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector* FindModified( + const BRepGraph_ItemUID& theUID) const; + + //! ItemUID-keyed Generated images stored directly in this history. + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector* FindGenerated( + const BRepGraph_ItemUID& theUID) const; + + //! ItemUID-keyed deletion test stored directly in this history. + [[nodiscard]] Standard_EXPORT bool IsDeleted(const BRepGraph_ItemUID& theUID) const; + + //! ItemUID-keyed deleted set stored directly in this history. + [[nodiscard]] Standard_EXPORT const NCollection_FlatMap& DeletedItemUids() + const; + + //! Test whether @p theUID was registered as an operation input. + [[nodiscard]] Standard_EXPORT bool HasKnownInput(const BRepGraph_ItemUID& theUID) const; + + //! UID-keyed convenience: Modified images of the input identified by + //! @p theUID, resolved against @p theGraph. Returns an empty vector if + //! the UID cannot be resolved or has no Modified record. + //! @param[in] theGraph graph used to translate UID <-> NodeId + //! @param[in] theUID UID of the input entity + //! @return UIDs of the modified images (in record-insertion order) + [[nodiscard]] Standard_EXPORT NCollection_LinearVector FindModified( + const BRepGraph& theGraph, + const BRepGraph_UID& theUID) const; + + //! UID-keyed convenience: Generated images. See #FindModified for the + //! resolution contract. + //! @param[in] theGraph graph used to translate UID <-> NodeId + //! @param[in] theUID UID of the input entity + //! @return UIDs of the generated images (in record-insertion order) + [[nodiscard]] Standard_EXPORT NCollection_LinearVector FindGenerated( + const BRepGraph& theGraph, + const BRepGraph_UID& theUID) const; + + //! UID-keyed convenience: deletion test. + //! @param[in] theGraph graph used to resolve the UID + //! @param[in] theUID UID of the input entity + //! @return true if the resolved NodeId is in the deleted set + [[nodiscard]] Standard_EXPORT bool IsDeleted(const BRepGraph& theGraph, + const BRepGraph_UID& theUID) const; + + //! UID-keyed convenience: dump the full deleted set as UIDs. + //! @param[in] theGraph graph used to translate NodeId -> UID + //! @return UIDs of all deleted entities (insertion order is not stable) + [[nodiscard]] Standard_EXPORT NCollection_LinearVector DeletedUids( + const BRepGraph& theGraph) const; + + //! Number of recorded history events. + //! @return record count + [[nodiscard]] Standard_EXPORT size_t NbRecords() const; + + //! Access a record by index (0-based). + //! @param[in] theRecordIdx zero-based index into the records vector + //! @return the history record at the given index + [[nodiscard]] Standard_EXPORT const Event& Record(const size_t theRecordIdx) const; + + //! Enable or disable history recording. + //! @param[in] theVal true to enable, false to disable + Standard_EXPORT void SetEnabled(const bool theVal); + + //! Query whether history recording is enabled. + //! @return true if recording is active + [[nodiscard]] Standard_EXPORT bool IsEnabled() const; + + //! Clear all records and lookup maps. + Standard_EXPORT void Clear() noexcept override; + + //! Layer removal callback. Records pure graph deletions when enabled. + Standard_EXPORT void OnNodeRemoved(const BRepGraph_NodeId theNode) noexcept override; + + //! Copy history records whose source items have copied target items. + Standard_EXPORT void CopyTo(const BRepGraph_CopyRemap& theCopy) const override; + + //! Clear derived caches by dropping collected history. + Standard_EXPORT void InvalidateAll() noexcept override; + + DEFINE_STANDARD_RTTIEXT(BRepGraph_LayerHistory, BRepGraph_Layer) + +private: + //! Rebuild all lookup caches from myRecords. + void rebuildCaches(); + + NCollection_DynamicArray myRecords; + + //! Full reverse map: derived node -> all immediate original nodes. + NCollection_DataMap> + myDerivedToOriginals; + + //! Forward map: original node -> vector of Modified images. + NCollection_DataMap> + myOriginalToModified; + + //! Forward map: original node -> vector of Generated images. + NCollection_DataMap> + myOriginalToGenerated; + + //! Flat set of inputs that have been consumed (no image in the result). + NCollection_FlatMap myDeleted; + + //! UID-keyed forward map: original UID -> Modified image UIDs. + NCollection_DataMap> + myUidOriginalToModified; + + //! UID-keyed forward map: original UID -> Generated image UIDs. + NCollection_DataMap> + myUidOriginalToGenerated; + + //! UID-keyed operation inputs, including inputs with no images. + NCollection_FlatMap myUidKnownInputs; + + //! UID-keyed consumed inputs. + NCollection_FlatMap myUidDeleted; + + //! ItemUID-keyed forward map: original UID -> Modified image UIDs. + NCollection_DataMap> + myItemUidOriginalToModified; + + //! ItemUID-keyed forward map: original UID -> Generated image UIDs. + NCollection_DataMap> + myItemUidOriginalToGenerated; + + //! ItemUID-keyed operation inputs, including inputs with no images. + NCollection_FlatMap myItemUidKnownInputs; + + //! ItemUID-keyed consumed inputs. + NCollection_FlatMap myItemUidDeleted; + + bool myEnabled = true; +}; + +#endif // _BRepGraph_LayerHistory_HeaderFile diff --git a/opencascade/BRepGraph_LayerIterator.hxx b/opencascade/BRepGraph_LayerIterator.hxx index eeac605c9..d50cec632 100644 --- a/opencascade/BRepGraph_LayerIterator.hxx +++ b/opencascade/BRepGraph_LayerIterator.hxx @@ -50,16 +50,13 @@ public: void Next() { ++myCurrent; } //! Return the current layer handle. - [[nodiscard]] const occ::handle& Value() const - { - return myRegistry->Layer(myCurrent); - } + [[nodiscard]] occ::handle Value() const { return myRegistry->Layer(myCurrent); } //! Return the current slot index in the registry. - [[nodiscard]] int Slot() const { return myCurrent; } + [[nodiscard]] uint32_t Slot() const { return myCurrent; } //! Number of layers in the registry. - [[nodiscard]] int NbLayers() const { return myCount; } + [[nodiscard]] uint32_t NbLayers() const { return myCount; } //! STL range-for support. NCollection_ForwardRangeIterator begin() @@ -72,8 +69,8 @@ public: private: const BRepGraph_LayerRegistry* myRegistry; - int myCount; - int myCurrent; + uint32_t myCount; + uint32_t myCurrent; }; #endif // _BRepGraph_LayerIterator_HeaderFile diff --git a/opencascade/BRepGraph_LayerLock.hxx b/opencascade/BRepGraph_LayerLock.hxx new file mode 100644 index 000000000..0ad756efd --- /dev/null +++ b/opencascade/BRepGraph_LayerLock.hxx @@ -0,0 +1,200 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_LayerLock_HeaderFile +#define _BRepGraph_LayerLock_HeaderFile + +#include +#include +#include +#include + +//! Owner metadata layer for owned BRepGraph items. +//! +//! Uses a root-based ownership model: only the highest owned item per group +//! is stored in the map. All descendants receive the fast IsOwned bit-flag +//! via automatic downward propagation. Owner lookup traverses upward to +//! find the root entry. +//! +//! Overlapping roots are forbidden: SetOwner rejects if the item is already +//! covered by an ancestor root with a different GUID. +//! +//! HasOwner() checks the IsOwned bit-flag (O(1)). +//! FindOwnerId() traverses upward to find the root entry (O(depth)). +class BRepGraph_LayerLock : public BRepGraph_Layer +{ +public: + //! Scoped permission for an owner layer to edit one item it owns. + //! + //! The scope traverses upward to find the root owner for GUID verification, + //! then temporarily clears the fast owned bit on the specific item so existing + //! editor mutation APIs can be reused by the owning layer. + class ScopedOwnerEdit + { + public: + Standard_EXPORT ScopedOwnerEdit(BRepGraph_LayerLock& theLayer, + const BRepGraph_ItemId theItem, + const Standard_GUID& theOwnerId); + Standard_EXPORT ~ScopedOwnerEdit(); + + ScopedOwnerEdit(const ScopedOwnerEdit&) = delete; + ScopedOwnerEdit& operator=(const ScopedOwnerEdit&) = delete; + + Standard_EXPORT ScopedOwnerEdit(ScopedOwnerEdit&& theOther) noexcept; + Standard_EXPORT ScopedOwnerEdit& operator=(ScopedOwnerEdit&& theOther) noexcept; + + private: + BRepGraph_LayerLock* myLayer = nullptr; + BRepGraph_ItemId myItem; + bool myIsActive = false; + }; + + //! Create lock-owner storage. + Standard_EXPORT BRepGraph_LayerLock(); + + //! Return fixed layer type GUID. + [[nodiscard]] Standard_EXPORT static const Standard_GUID& GetID(); + + //! Return this layer type GUID. + [[nodiscard]] Standard_EXPORT const Standard_GUID& ID() const override; + + //! Return owner ID for an item. + //! Traverses upward for nodes/refs to find the root owner entry. + //! @return true when the item has a resolved owner and @p theOwnerId was filled. + [[nodiscard]] Standard_EXPORT bool FindOwnerId(const BRepGraph_ItemId theItem, + Standard_GUID& theOwnerId) const; + + //! Return owner ID for a node. + [[nodiscard]] bool FindOwnerId(const BRepGraph_NodeId theNode, Standard_GUID& theOwnerId) const + { + return FindOwnerId(BRepGraph_ItemId(theNode), theOwnerId); + } + + //! Return owner ID for a reference. + [[nodiscard]] bool FindOwnerId(const BRepGraph_RefId theRef, Standard_GUID& theOwnerId) const + { + return FindOwnerId(BRepGraph_ItemId(theRef), theOwnerId); + } + + //! Return true if an item's IsOwned bit-flag is set. + //! This is an O(1) check. Use FindOwnerId() to resolve the actual owner GUID. + [[nodiscard]] Standard_EXPORT bool HasOwner(const BRepGraph_ItemId theItem) const; + + //! Return true if a node's IsOwned bit-flag is set. + [[nodiscard]] bool HasOwner(const BRepGraph_NodeId theNode) const + { + return HasOwner(BRepGraph_ItemId(theNode)); + } + + //! Return true if a reference's IsOwned bit-flag is set. + [[nodiscard]] bool HasOwner(const BRepGraph_RefId theRef) const + { + return HasOwner(BRepGraph_ItemId(theRef)); + } + + //! Register an owner ID and set the graph item's ownership flag. + //! For nodes, propagates the IsOwned bit-flag to all descendants. + //! Rejects if the item is already covered by an ancestor root with a different GUID. + Standard_EXPORT void SetOwner(const BRepGraph_ItemId theItem, const Standard_GUID& theOwnerId); + + //! Register an owner ID and set the graph item's ownership flag. + //! Returns true when owner storage changed. Revision update can be deferred by bulk callers. + Standard_EXPORT bool SetOwner(const BRepGraph_ItemId theItem, + const Standard_GUID& theOwnerId, + const bool theToUpdateRevision); + + //! Register an owner ID and set the node ownership flag. + void SetOwner(const BRepGraph_NodeId theNode, const Standard_GUID& theOwnerId) + { + SetOwner(BRepGraph_ItemId(theNode), theOwnerId); + } + + //! Register an owner ID and set the reference ownership flag. + void SetOwner(const BRepGraph_RefId theRef, const Standard_GUID& theOwnerId) + { + SetOwner(BRepGraph_ItemId(theRef), theOwnerId); + } + + //! Remove an owner and clear the graph item's ownership flag. + //! For node roots, clears the IsOwned bit-flag on all descendants. + Standard_EXPORT void UnsetOwner(const BRepGraph_ItemId theItem); + + //! Remove an owner and clear the graph item's ownership flag if owner ID matches. + Standard_EXPORT void UnsetOwner(const BRepGraph_ItemId theItem, const Standard_GUID& theOwnerId); + + //! Remove an owner and clear the node ownership flag. + void UnsetOwner(const BRepGraph_NodeId theNode) { UnsetOwner(BRepGraph_ItemId(theNode)); } + + //! Remove an owner and clear the reference ownership flag. + void UnsetOwner(const BRepGraph_RefId theRef) { UnsetOwner(BRepGraph_ItemId(theRef)); } + + //! Return true if at least one root entry exists. + [[nodiscard]] bool HasOwners() const + { + return myNodeOwners.Extent() != 0 || myRefOwners.Extent() != 0; + } + + //! Reserve owner map buckets for bulk registration. + Standard_EXPORT void ReserveOwners(const size_t theNbOwners); + + //! Mark owner metadata changed after a bulk update. + Standard_EXPORT void TouchOwners(); + + Standard_EXPORT const TCollection_AsciiString& Name() const override; + Standard_EXPORT void OnNodeRemoved(const BRepGraph_NodeId theNode) noexcept override; + Standard_EXPORT void OnNodeReplaced(const BRepGraph_NodeId theOldNode, + const BRepGraph_NodeId theNewNode) noexcept override; + Standard_EXPORT void CopyTo(const BRepGraph_CopyRemap& theCopy) const override; + Standard_EXPORT void OnRefRemoved(const BRepGraph_RefId theRef) noexcept override; + Standard_EXPORT void InvalidateAll() noexcept override; + Standard_EXPORT void Clear() noexcept override; + + DEFINE_STANDARD_RTTIEXT(BRepGraph_LayerLock, BRepGraph_Layer) + +private: + //! Set or clear the IsOwned bit-flag on a single item. + Standard_EXPORT void setItemOwned(const BRepGraph_ItemId theItem, const bool theIsOwned) const; + + //! Propagate the IsOwned bit-flag to all descendants of a root node. + //! Walks nodes via ChildExplorer, refs via CurrentRef(), and reps via definition fields. + void expandOwnership(const BRepGraph_NodeId theRoot, const bool theIsOwned); + + //! Rebuild fast IsOwned bit-flags from remaining root maps. + void rebuildOwnedFlagsFromRoots(); + + //! Find the root node entry that covers a given node. + //! Checks direct map entry first, then traverses upward via ParentExplorer. + [[nodiscard]] bool findRootNodeId(const BRepGraph_NodeId theNode, + BRepGraph_ItemId& theRootItem) const; + + //! Find the root entry that covers a given ref. + //! Checks direct map entry first, then traverses via parent node. + [[nodiscard]] bool findRootRefId(const BRepGraph_RefId theRef, + BRepGraph_ItemId& theRootItem) const; + + //! Get the parent node of a ref from its storage struct. + [[nodiscard]] BRepGraph_NodeId parentNodeId(const BRepGraph_RefId theRef) const; + + //! Check if an item is already covered by an ancestor root. + //! Returns true if an ancestor root exists. If so, fills theRootOwnerId. + [[nodiscard]] bool isCoveredByAncestor(const BRepGraph_ItemId theItem, + Standard_GUID& theRootOwnerId) const; + + //! Remove a root entry from the appropriate map and clear its bit-flag. + void removeRootEntry(const BRepGraph_ItemId theItem) noexcept; + + NCollection_FlatDataMap myNodeOwners; + NCollection_FlatDataMap myRefOwners; +}; + +#endif // _BRepGraph_LayerLock_HeaderFile diff --git a/opencascade/BRepGraph_LayerParam.hxx b/opencascade/BRepGraph_LayerParam.hxx deleted file mode 100644 index 6afa5467c..000000000 --- a/opencascade/BRepGraph_LayerParam.hxx +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraph_LayerParam_HeaderFile -#define _BRepGraph_LayerParam_HeaderFile - -#include - -#include -#include -#include - -//! @brief Persistent vertex point-representation store: point-on-curve, -//! point-on-surface, and point-on-PCurve parameters per vertex. -//! -//! Mirrors classical BRep_PointRepresentation entries on TVertex: each vertex -//! may carry parameters identifying its location on incident edges, faces, or -//! coedges (PCurves). The layer is the single source of truth for these -//! parameters in BRepGraph. -//! -//! ## Lifetime policy -//! The layer is **persistent metadata**: stored values survive arbitrary -//! mutations to the referenced vertices, edges, faces, and coedges. Only the -//! following events discard data: -//! - OnNodeRemoved - the referenced node is gone; entries naming it are -//! dropped (or migrated when a replacement is provided). -//! - OnCompact - ids are remapped; entries pointing to removed nodes drop. -//! - InvalidateAll() / Clear() - explicit caller request. -//! The layer does NOT subscribe to OnNodeModified: a tolerance bump, parameter -//! range adjustment, or NaturalRestriction toggle on a referenced node leaves -//! point-representation data intact. Callers that change geometry are -//! responsible for refreshing affected entries. -class BRepGraph_LayerParam : public BRepGraph_Layer -{ -public: - //! Return fixed layer type GUID. - [[nodiscard]] Standard_EXPORT static const Standard_GUID& GetID(); - - //! Return this layer type GUID. - [[nodiscard]] Standard_EXPORT const Standard_GUID& ID() const override; - - struct PointOnCurveEntry - { - double Parameter = 0.0; - BRepGraph_EdgeId EdgeDefId; - }; - - struct PointOnSurfaceEntry - { - double ParameterU = 0.0; - double ParameterV = 0.0; - BRepGraph_FaceId FaceDefId; - }; - - struct PointOnPCurveEntry - { - double Parameter = 0.0; - BRepGraph_CoEdgeId CoEdgeDefId; - }; - - struct VertexParams - { - NCollection_DynamicArray PointsOnCurve; - NCollection_DynamicArray PointsOnSurface; - NCollection_DynamicArray PointsOnPCurve; - - [[nodiscard]] bool IsEmpty() const - { - return PointsOnCurve.IsEmpty() && PointsOnSurface.IsEmpty() && PointsOnPCurve.IsEmpty(); - } - }; - - Standard_EXPORT const VertexParams* FindVertexParams(const BRepGraph_VertexId theVertex) const; - - Standard_EXPORT bool FindPointOnCurve(const BRepGraph_VertexId theVertex, - const BRepGraph_EdgeId theEdge, - double* const theParameter = nullptr) const; - - Standard_EXPORT bool FindPointOnSurface(const BRepGraph_VertexId theVertex, - const BRepGraph_FaceId theFace, - gp_Pnt2d* const theUV = nullptr) const; - - Standard_EXPORT bool FindPointOnPCurve(const BRepGraph_VertexId theVertex, - const BRepGraph_CoEdgeId theCoEdge, - double* const theParameter = nullptr) const; - - Standard_EXPORT uint32_t NbPointsOnCurve(const BRepGraph_VertexId theVertex) const; - Standard_EXPORT uint32_t NbPointsOnSurface(const BRepGraph_VertexId theVertex) const; - Standard_EXPORT uint32_t NbPointsOnPCurve(const BRepGraph_VertexId theVertex) const; - - [[nodiscard]] bool HasBindings() const { return myVertexParams.Extent() != 0; } - - Standard_EXPORT void SetPointOnCurve(const BRepGraph_VertexId theVertex, - const BRepGraph_EdgeId theEdge, - const double theParameter); - - Standard_EXPORT void SetPointOnSurface(const BRepGraph_VertexId theVertex, - const BRepGraph_FaceId theFace, - const double theParameterU, - const double theParameterV); - - Standard_EXPORT void SetPointOnPCurve(const BRepGraph_VertexId theVertex, - const BRepGraph_CoEdgeId theCoEdge, - const double theParameter); - - Standard_EXPORT const TCollection_AsciiString& Name() const override; - Standard_EXPORT void OnNodeRemoved(const BRepGraph_NodeId theNode, - const BRepGraph_NodeId theReplacement) noexcept override; - Standard_EXPORT void OnCompact( - const NCollection_DataMap& theRemapMap) noexcept override; - Standard_EXPORT void InvalidateAll() noexcept override; - Standard_EXPORT void Clear() noexcept override; - - DEFINE_STANDARD_RTTIEXT(BRepGraph_LayerParam, BRepGraph_Layer) - -private: - void removeVertexBindings(const BRepGraph_VertexId theVertex) noexcept; - void invalidateEdgeBindings(const BRepGraph_EdgeId theEdge) noexcept; - void invalidateFaceBindings(const BRepGraph_FaceId theFace) noexcept; - void invalidateCoEdgeBindings(const BRepGraph_CoEdgeId theCoEdge) noexcept; - void migrateVertexBindings(const BRepGraph_VertexId theOldVertex, - const BRepGraph_VertexId theNewVertex) noexcept; - void migrateEdgeBindings(const BRepGraph_EdgeId theOldEdge, - const BRepGraph_EdgeId theNewEdge) noexcept; - void migrateFaceBindings(const BRepGraph_FaceId theOldFace, - const BRepGraph_FaceId theNewFace) noexcept; - void migrateCoEdgeBindings(const BRepGraph_CoEdgeId theOldCoEdge, - const BRepGraph_CoEdgeId theNewCoEdge) noexcept; - - VertexParams& changeVertexParams(const BRepGraph_VertexId theVertex); - void bindEdgeToVertex(const BRepGraph_EdgeId theEdge, const BRepGraph_VertexId theVertex); - void bindFaceToVertex(const BRepGraph_FaceId theFace, const BRepGraph_VertexId theVertex); - void bindCoEdgeToVertex(const BRepGraph_CoEdgeId theCoEdge, const BRepGraph_VertexId theVertex); - void unbindEdgeFromVertex(const BRepGraph_EdgeId theEdge, - const BRepGraph_VertexId theVertex) noexcept; - void unbindFaceFromVertex(const BRepGraph_FaceId theFace, - const BRepGraph_VertexId theVertex) noexcept; - void unbindCoEdgeFromVertex(const BRepGraph_CoEdgeId theCoEdge, - const BRepGraph_VertexId theVertex) noexcept; - void removePointOnCurve(const BRepGraph_VertexId theVertex, - const BRepGraph_EdgeId theEdge) noexcept; - void removePointOnSurface(const BRepGraph_VertexId theVertex, - const BRepGraph_FaceId theFace) noexcept; - void removePointOnPCurve(const BRepGraph_VertexId theVertex, - const BRepGraph_CoEdgeId theCoEdge) noexcept; - -private: - NCollection_DataMap myVertexParams; - NCollection_DataMap> - myEdgeToVertices; - NCollection_DataMap> - myFaceToVertices; - NCollection_DataMap> - myCoEdgeToVertices; -}; - -#endif // _BRepGraph_LayerParam_HeaderFile diff --git a/opencascade/BRepGraph_LayerParametric.hxx b/opencascade/BRepGraph_LayerParametric.hxx new file mode 100644 index 000000000..a6743d0cf --- /dev/null +++ b/opencascade/BRepGraph_LayerParametric.hxx @@ -0,0 +1,130 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_LayerParametric_HeaderFile +#define _BRepGraph_LayerParametric_HeaderFile + +#include + +#include +#include + +class BRepGraph_LayerLock; + +//! @brief Base layer for graph-owned parametric generators. +//! +//! The class defines the common instance identity, generation flags, mesh +//! quality controls, and graph access helpers shared by higher-level parametric +//! layers. +//! Concrete layers such as BRepGraphPrim box, plane, or loft generators build +//! their own parameter schema and manifest storage on top of this base. +class BRepGraph_LayerParametric : public BRepGraph_Layer +{ +public: + //! Controls which graph artifacts should be created or refreshed. + enum class GenerationFlag : uint32_t + { + Topology = 0x01, //!< Create or preserve topological nodes and references. + Geometry = 0x02, //!< Bind analytic reps; absence keeps generated topology mesh-only. + Mesh = 0x04 //!< Create or preserve triangulation representations. + }; + + //! High-level mesh quality hint shared by parametric generators. + enum class MeshQuality : uint8_t + { + VeryCoarse, //!< Minimal preview-oriented detail. + Coarse, //!< Low detail for fast authoring feedback. + Medium, //!< Balanced default-quality detail. + Fine, //!< High-quality detail for closer inspection. + VeryFine //!< Maximum detail requested by the caller. + }; + + //! Result of adding a new parametric instance to a graph. + struct AddResult + { + uint32_t Instance = THE_INVALID_INSTANCE; //!< Created instance identifier. + BRepGraph_NodeId Root; //!< Root topology node of the created subtree. + }; + + //! Reserved sentinel used when an operation does not create an instance. + static constexpr uint32_t THE_INVALID_INSTANCE = std::numeric_limits::max(); + + //! Default generation mode builds topology and analytic geometry only. + static constexpr uint32_t THE_DEFAULT_GENERATION_FLAGS = + static_cast(GenerationFlag::Topology) + | static_cast(GenerationFlag::Geometry); + + //! Convert one generation flag into its bit-mask value. + //! @param[in] theFlag generation flag to convert + //! @return bit-mask value for the requested generation flag + [[nodiscard]] static constexpr uint32_t GenerationMask(const GenerationFlag theFlag) + { + return static_cast(theFlag); + } + + //! Return true when the flag mask contains the requested generation flag. + //! @param[in] theFlags generation mask built from GenerationFlag bits + //! @param[in] theFlag generation flag to test + //! @return true when the flag is present in the mask + [[nodiscard]] static constexpr bool HasGenerationFlag(const uint32_t theFlags, + const GenerationFlag theFlag) + { + return (theFlags & GenerationMask(theFlag)) != 0; + } + + //! Select one integer value from a mesh-quality ladder. + //! @param[in] theQuality requested shared mesh quality + //! @param[in] theVeryCoarse value for MeshQuality::VeryCoarse + //! @param[in] theCoarse value for MeshQuality::Coarse + //! @param[in] theMedium value for MeshQuality::Medium + //! @param[in] theFine value for MeshQuality::Fine + //! @param[in] theVeryFine value for MeshQuality::VeryFine + //! @return selected value for the requested quality + [[nodiscard]] static constexpr uint32_t MeshQualityValue(const MeshQuality theQuality, + const uint32_t theVeryCoarse, + const uint32_t theCoarse, + const uint32_t theMedium, + const uint32_t theFine, + const uint32_t theVeryFine) + { + switch (theQuality) + { + case MeshQuality::VeryCoarse: + return theVeryCoarse; + case MeshQuality::Coarse: + return theCoarse; + case MeshQuality::Medium: + return theMedium; + case MeshQuality::Fine: + return theFine; + case MeshQuality::VeryFine: + return theVeryFine; + } + return theMedium; + } + +protected: + //! Return the attached graph and raise if the layer is detached. + //! @return attached graph for mutation operations + [[nodiscard]] Standard_EXPORT BRepGraph* graphForMutation() const; + + //! Return the ownership layer used by parametric generators. + //! @param[in] theGraph graph whose ownership layer should be returned + //! @return ownership layer handle + [[nodiscard]] Standard_EXPORT occ::handle lockLayer( + BRepGraph& theGraph) const; + + DEFINE_STANDARD_RTTIEXT(BRepGraph_LayerParametric, BRepGraph_Layer) +}; + +#endif // _BRepGraph_LayerParametric_HeaderFile diff --git a/opencascade/BRepGraph_LayerRegistry.hxx b/opencascade/BRepGraph_LayerRegistry.hxx index 8b02b2a84..030d5f805 100644 --- a/opencascade/BRepGraph_LayerRegistry.hxx +++ b/opencascade/BRepGraph_LayerRegistry.hxx @@ -14,14 +14,20 @@ #ifndef _BRepGraph_LayerRegistry_HeaderFile #define _BRepGraph_LayerRegistry_HeaderFile +#include #include #include - #include -#include +#include +#include #include #include +#include +#include +#include +#include + //! @brief Dense GUID-keyed runtime registry of graph layers. //! //! Stores registered layers in a compact vector for O(1) slot access and a @@ -31,23 +37,17 @@ class BRepGraph_LayerRegistry public: DEFINE_STANDARD_ALLOC - BRepGraph_LayerRegistry() = default; + Standard_EXPORT BRepGraph_LayerRegistry(); BRepGraph_LayerRegistry(const BRepGraph_LayerRegistry&) = delete; BRepGraph_LayerRegistry& operator=(const BRepGraph_LayerRegistry&) = delete; - BRepGraph_LayerRegistry(BRepGraph_LayerRegistry&&) noexcept = default; - BRepGraph_LayerRegistry& operator=(BRepGraph_LayerRegistry&&) noexcept = default; - - //! Bind the owning graph. Propagates to every registered layer. - Standard_EXPORT void SetOwningGraph(BRepGraph* theGraph) noexcept; - - //! Owning graph bound via SetOwningGraph(), or nullptr. - [[nodiscard]] BRepGraph* OwningGraph() const noexcept { return myOwningGraph; } + Standard_EXPORT BRepGraph_LayerRegistry(BRepGraph_LayerRegistry&& theOther) noexcept; + Standard_EXPORT BRepGraph_LayerRegistry& operator=(BRepGraph_LayerRegistry&& theOther) noexcept; //! Register a layer. Replaces an existing layer with the same GUID. - //! @return slot index in the internal dense vector, or -1 for null input. - Standard_EXPORT int RegisterLayer(const occ::handle& theLayer); + //! @return slot index in the internal dense vector. + Standard_EXPORT uint32_t RegisterLayer(const occ::handle& theLayer); //! Remove a layer by GUID. Standard_EXPORT void UnregisterLayer(const Standard_GUID& theGUID); @@ -59,48 +59,103 @@ public: //! Typed convenience lookup by layer GUID. template [[nodiscard]] occ::handle FindLayer() const + { + return Find(); + } + + //! Typed lookup by layer GUID. + template + [[nodiscard]] occ::handle Find() const { return occ::down_cast(FindLayer(T::GetID())); } - //! Return current slot for a GUID, or -1 if not registered. - [[nodiscard]] Standard_EXPORT int FindSlot(const Standard_GUID& theGUID) const; + //! Return an existing layer or create and register a default one. + //! Template convenience wrapper: extracts GUID and calls ensureLayer. + template + [[nodiscard]] occ::handle Ensure() + { + return occ::down_cast( + ensureLayer(T::GetID(), []() -> occ::handle { return new T(); })); + } + + //! Return current slot for a GUID. + [[nodiscard]] Standard_EXPORT bool FindSlot(const Standard_GUID& theGUID, + uint32_t& theSlot) const; - //! Return layer by slot index. - [[nodiscard]] Standard_EXPORT const occ::handle& Layer(const int theSlot) const; + //! Return layer by slot index, or null handle if the slot is out of range. + [[nodiscard]] Standard_EXPORT occ::handle Layer(uint32_t theSlot) const; //! Number of registered layers. - [[nodiscard]] int NbLayers() const { return myLayers.Length(); } + [[nodiscard]] uint32_t NbLayers() const + { + std::shared_lock aLock(myMutex); + return static_cast(myLayers.Size()); + } //! True if any registered layer subscribes to node modification events. - [[nodiscard]] bool HasModificationSubscribers() const { return mySubscribedKindsMask != 0; } + [[nodiscard]] bool HasModificationSubscribers() const + { + return mySubscribedKindsMask.load(std::memory_order_acquire) != 0; + } //! Bitwise OR of all registered layer node subscription masks. - [[nodiscard]] int SubscribedKindsMask() const { return mySubscribedKindsMask; } + [[nodiscard]] int SubscribedKindsMask() const + { + return static_cast(mySubscribedKindsMask.load(std::memory_order_acquire)); + } //! Dispatch OnNodeRemoved to all registered layers. - Standard_EXPORT void DispatchOnNodeRemoved(const BRepGraph_NodeId theNode, - const BRepGraph_NodeId theReplacement) noexcept; + Standard_EXPORT void DispatchOnNodeRemoved(const BRepGraph_NodeId theNode) noexcept; + + //! Dispatch generic item removal to all registered layers. + Standard_EXPORT void DispatchOnItemRemoved(const BRepGraph_ItemId theItem) noexcept; + + //! Dispatch OnNodeReplaced to all registered layers. + Standard_EXPORT void DispatchOnNodeReplaced(const BRepGraph_NodeId theOldNode, + const BRepGraph_NodeId theNewNode) noexcept; //! Dispatch OnNodeModified to subscribed layers. Standard_EXPORT void DispatchNodeModified(const BRepGraph_NodeId theNode) noexcept; + //! Dispatch generic item modification through the matching typed subscription path. + Standard_EXPORT void DispatchItemModified(const BRepGraph_ItemId theItem) noexcept; + //! Dispatch OnNodesModified to subscribed layers. Standard_EXPORT void DispatchNodesModified( - const NCollection_DynamicArray& theModifiedNodes, - const int theModifiedKindsMask) noexcept; - - //! Dispatch OnCompact to all registered layers. - Standard_EXPORT void DispatchOnCompact( - const NCollection_DataMap& theRemapMap) noexcept; - - // --- Reference dispatch --- + const NCollection_Array1& theModifiedNodes, + const int theModifiedKindsMask) noexcept; + + //! Ask every registered source layer to copy itself into the target graph. + //! For Mode::Compact, layers are unregistered first and CopyTo creates fresh instances. + //! @param[in] theTargetGraph target graph to receive layer data + //! @param[in] theItemRemap source -> target item id mapping + //! @param[in] theMode Copy or Compact semantics + Standard_EXPORT void CopyLayersTo( + BRepGraph& theTargetGraph, + const NCollection_FlatDataMap& theItemRemap, + const BRepGraph_CopyRemap::Mode theMode) const; + + //! Ask every registered source layer to copy itself using identity mapping. + //! Source item ids are the same as target item ids (full identity copy). + //! @param[in] theTargetGraph target graph to receive layer data + //! @param[in] theMappingKind identity or explicit mapping + //! @param[in] theMode Copy or Compact semantics + Standard_EXPORT void CopyLayersTo(BRepGraph& theTargetGraph, + BRepGraph_CopyRemap::MappingKind theMappingKind, + BRepGraph_CopyRemap::Mode theMode) const; //! True if any registered layer subscribes to reference modification events. - [[nodiscard]] bool HasRefModificationSubscribers() const { return mySubscribedRefKindsMask != 0; } + [[nodiscard]] bool HasRefModificationSubscribers() const + { + return mySubscribedRefKindsMask.load(std::memory_order_acquire) != 0; + } //! Bitwise OR of all registered layer reference subscription masks. - [[nodiscard]] int SubscribedRefKindsMask() const { return mySubscribedRefKindsMask; } + [[nodiscard]] int SubscribedRefKindsMask() const + { + return static_cast(mySubscribedRefKindsMask.load(std::memory_order_acquire)); + } //! Dispatch OnRefRemoved to all registered layers (unconditional - not filtered). Standard_EXPORT void DispatchOnRefRemoved(const BRepGraph_RefId theRef) noexcept; @@ -110,24 +165,49 @@ public: //! Dispatch OnRefsModified to subscribed layers (deferred/batch mode). Standard_EXPORT void DispatchRefsModified( - const NCollection_DynamicArray& theModifiedRefs, - const int theModifiedRefKindsMask) noexcept; + const NCollection_Array1& theModifiedRefs, + const int theModifiedRefKindsMask) noexcept; - //! Clear all registered layer payloads without unregistering them. + //! Clear all registered layer data without unregistering services. Standard_EXPORT void ClearAll() noexcept; - //! Invalidate all registered layer payloads. + //! Invalidate all registered layer data. Standard_EXPORT void InvalidateAll() noexcept; private: + friend class ::BRepGraph; + friend struct ::BRepGraph_Data; + + //! Attach this registry to graph owner. Propagates context to registered layers. + Standard_EXPORT void Attach(BRepGraph* theGraph) noexcept; + + //! Clear the graph data binding. + Standard_EXPORT void Detach() noexcept; + + [[nodiscard]] Standard_EXPORT occ::handle findLayerLocked( + const Standard_GUID& theGUID) const; + + //! Return an existing layer or create and register a default one. + //! Uses double-checked locking: shared lock for fast path (layer exists), + //! exclusive lock only for creation (rare, first-call only). + [[nodiscard]] Standard_EXPORT occ::handle ensureLayer( + const Standard_GUID& theGUID, + const std::function()>& theFactory); + + [[nodiscard]] Standard_EXPORT occ::handle layerAt(uint32_t theSlot) const; + + Standard_EXPORT uint32_t registerLayerLocked(const occ::handle& theLayer); + Standard_EXPORT void recomputeSubscribedKindsMask(); + Standard_EXPORT void detachAllLocked() noexcept; private: - NCollection_DynamicArray> myLayers; + NCollection_LinearVector> myLayers; NCollection_DataMap myGuidToSlot; - uint32_t mySubscribedKindsMask = 0; - uint32_t mySubscribedRefKindsMask = 0; - BRepGraph* myOwningGraph = nullptr; + std::atomic mySubscribedKindsMask{0}; + std::atomic mySubscribedRefKindsMask{0}; + BRepGraph* myGraph = nullptr; + mutable std::shared_mutex myMutex; }; #endif // _BRepGraph_LayerRegistry_HeaderFile diff --git a/opencascade/BRepGraph_LayerRegularity.hxx b/opencascade/BRepGraph_LayerRegularity.hxx deleted file mode 100644 index 0b420f97f..000000000 --- a/opencascade/BRepGraph_LayerRegularity.hxx +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraph_LayerRegularity_HeaderFile -#define _BRepGraph_LayerRegularity_HeaderFile - -#include - -#include -#include -#include - -//! @brief Persistent edge-continuity store, keyed by (edge, F1, F2). -//! -//! Each entry holds the geometric continuity (C^k / G^k) across the face pair -//! at a given edge. F1 == F2 represents seam continuity across a closed -//! surface's seam line; F1 != F2 represents inter-face regularity. The schema -//! mirrors classical BRep_Tool::Continuity(edge, F1, F2). -//! -//! ## Lifetime policy -//! The layer is **persistent metadata**: stored values survive arbitrary -//! mutations to the referenced edges and faces. Only the following events -//! discard data: -//! - OnNodeRemoved(edge|face) - the referenced node is gone; entries naming -//! it are dropped (or migrated when a replacement is provided). -//! - OnCompact - ids are remapped; entries pointing to removed nodes drop. -//! - InvalidateAll() / Clear() - explicit caller request. -//! In particular, this layer does NOT subscribe to OnNodeModified: a tolerance -//! bump or NaturalRestriction toggle leaves stored continuity intact. Callers -//! that change the underlying geometry are responsible for refreshing affected -//! entries (typically via SetRegularity, removeRegularity, or InvalidateAll). -class BRepGraph_LayerRegularity : public BRepGraph_Layer -{ -public: - //! Return fixed layer type GUID. - [[nodiscard]] Standard_EXPORT static const Standard_GUID& GetID(); - - //! Return this layer type GUID. - [[nodiscard]] Standard_EXPORT const Standard_GUID& ID() const override; - - struct RegularityEntry - { - BRepGraph_FaceId FaceEntity1; - BRepGraph_FaceId FaceEntity2; - GeomAbs_Shape Continuity = GeomAbs_C0; - }; - - struct EdgeRegularities - { - NCollection_DynamicArray Entries; - - [[nodiscard]] bool IsEmpty() const { return Entries.IsEmpty(); } - }; - - Standard_EXPORT const EdgeRegularities* FindEdgeRegularities( - const BRepGraph_EdgeId theEdge) const; - - Standard_EXPORT bool FindContinuity(const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace1, - const BRepGraph_FaceId theFace2, - GeomAbs_Shape* const theContinuity = nullptr) const; - - Standard_EXPORT uint32_t NbRegularities(const BRepGraph_EdgeId theEdge) const; - Standard_EXPORT GeomAbs_Shape MaxContinuity(const BRepGraph_EdgeId theEdge) const; - - [[nodiscard]] bool HasBindings() const { return myEdgeRegularities.Extent() != 0; } - - Standard_EXPORT void SetRegularity(const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace1, - const BRepGraph_FaceId theFace2, - const GeomAbs_Shape theContinuity); - - //! Copy all regularity entries from one edge to another. - Standard_EXPORT void CopyRegularities(const BRepGraph_EdgeId theSourceEdge, - const BRepGraph_EdgeId theTargetEdge); - - //! Remove all regularity entries bound to the edge. - Standard_EXPORT void RemoveRegularities(const BRepGraph_EdgeId theEdge) noexcept; - - Standard_EXPORT const TCollection_AsciiString& Name() const override; - Standard_EXPORT void OnNodeRemoved(const BRepGraph_NodeId theNode, - const BRepGraph_NodeId theReplacement) noexcept override; - Standard_EXPORT void OnCompact( - const NCollection_DataMap& theRemapMap) noexcept override; - Standard_EXPORT void InvalidateAll() noexcept override; - Standard_EXPORT void Clear() noexcept override; - - DEFINE_STANDARD_RTTIEXT(BRepGraph_LayerRegularity, BRepGraph_Layer) - -private: - void normalizeFacePair(BRepGraph_FaceId& theFace1, BRepGraph_FaceId& theFace2) const noexcept; - EdgeRegularities& changeEdgeRegularities(const BRepGraph_EdgeId theEdge); - void bindFaceToEdge(const BRepGraph_FaceId theFace, const BRepGraph_EdgeId theEdge); - void unbindFaceFromEdge(const BRepGraph_FaceId theFace, const BRepGraph_EdgeId theEdge) noexcept; - void removeRegularity(const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace1, - const BRepGraph_FaceId theFace2) noexcept; - void removeEdgeBindings(const BRepGraph_EdgeId theEdge) noexcept; - void invalidateFaceBindings(const BRepGraph_FaceId theFace) noexcept; - void migrateEdgeBindings(const BRepGraph_EdgeId theOldEdge, - const BRepGraph_EdgeId theNewEdge) noexcept; - void migrateFaceBindings(const BRepGraph_FaceId theOldFace, - const BRepGraph_FaceId theNewFace) noexcept; - -private: - NCollection_DataMap myEdgeRegularities; - NCollection_DataMap> myFaceToEdges; -}; - -#endif // _BRepGraph_LayerRegularity_HeaderFile diff --git a/opencascade/BRepGraph_LayerTopoSupplement.hxx b/opencascade/BRepGraph_LayerTopoSupplement.hxx new file mode 100644 index 000000000..df44a7528 --- /dev/null +++ b/opencascade/BRepGraph_LayerTopoSupplement.hxx @@ -0,0 +1,137 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_LayerTopoSupplement_HeaderFile +#define _BRepGraph_LayerTopoSupplement_HeaderFile + +#include +#include +#include +#include + +//! @brief Runtime-only storage for supplemental TopoDS topology fragments. +//! +//! This layer stores non-core topology extracted from a source shape and +//! attached to supported core graph owners. These attachments are not +//! serialized and are intended only to preserve live +//! `TopoDS -> Graph -> TopoDS` behavior. +class BRepGraph_LayerTopoSupplement : public BRepGraph_Layer +{ +public: + //! @brief Semantic role of one supplemental attachment. + enum class AttachmentKind + { + VertexSupplementShape, + EdgeInternalVertex, + FaceDirectVertex, + SolidAuxShape, + ShellAuxShape, + CompSolidAuxShape, + CompoundAuxShape, + GenericSupplementShape + }; + + //! @brief Stored runtime attachment record. + struct Entry + { + BRepGraph_NodeId BaseOwner; + uint64_t LocalUid = 0; + AttachmentKind Kind = AttachmentKind::GenericSupplementShape; + TopoDS_Shape Shape; + }; + + //! @brief Return the fixed layer type GUID. + [[nodiscard]] Standard_EXPORT static const Standard_GUID& GetID(); + + //! @brief Return the runtime type GUID for this layer instance. + [[nodiscard]] Standard_EXPORT const Standard_GUID& ID() const override; + + //! @brief Return a short stable layer name for diagnostics and registry lookup. + [[nodiscard]] Standard_EXPORT const TCollection_AsciiString& Name() const override; + + //! @brief Find one attachment entry by its layer-local uid. + //! @param[in] theUid layer-local attachment uid + //! @return pointer to the entry, or `nullptr` when not found + [[nodiscard]] Standard_EXPORT const Entry* FindByUid(uint64_t theUid) const; + + //! @brief Return all attachment uids currently owned by one core node. + //! @param[in] theOwner core topology owner node + //! @return owner-local insertion-ordered list of attachment uids + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& AttachedTo( + BRepGraph_NodeId theOwner) const; + + //! @brief Add one supplemental shape attachment to a supported core owner node. + //! Supported owner kinds are vertex, edge, face, shell, solid, compsolid, and compound. + //! @param[in] theOwner active core topology owner + //! @param[in] theKind semantic attachment kind + //! @param[in] theShape attached supplemental shape + //! @return non-zero layer-local uid on success, `0` on rejection + Standard_EXPORT uint64_t AddAttachment(BRepGraph_NodeId theOwner, + AttachmentKind theKind, + const TopoDS_Shape& theShape); + + //! @brief Add one supplemental shape attachment with an explicitly preserved uid. + //! Supported owner kinds are vertex, edge, face, shell, solid, compsolid, and compound. + //! @param[in] theOwner active core topology owner + //! @param[in] theUid layer-local attachment uid to preserve + //! @param[in] theKind semantic attachment kind + //! @param[in] theShape attached supplemental shape + //! @return `true` on success, `false` when the uid or input is rejected + Standard_EXPORT bool AddAttachmentWithUid(BRepGraph_NodeId theOwner, + uint64_t theUid, + AttachmentKind theKind, + const TopoDS_Shape& theShape); + + //! @brief Remove one supplemental attachment by uid. + //! @param[in] theUid layer-local attachment uid + //! @return `true` when the attachment existed and was removed + Standard_EXPORT bool RemoveAttachment(uint64_t theUid); + + //! @brief Validate internal owner/uid bookkeeping invariants. + //! @throws Standard_ProgramError on inconsistent internal state + Standard_EXPORT void Validate() const; + + //! @brief Drop all attachments owned by a removed node. + //! @param[in] theNode removed core node + Standard_EXPORT void OnNodeRemoved(const BRepGraph_NodeId theNode) noexcept override; + + //! @brief Migrate attachments from one owner node to another compatible node. + //! @param[in] theOldNode previous owner node + //! @param[in] theNewNode replacement owner node + Standard_EXPORT void OnNodeReplaced(const BRepGraph_NodeId theOldNode, + const BRepGraph_NodeId theNewNode) noexcept override; + + //! @brief Copy remapped attachments to the target graph. + Standard_EXPORT void CopyTo(const BRepGraph_CopyRemap& theCopy) const override; + + //! @brief Invalidate all cached state in the layer. + Standard_EXPORT void InvalidateAll() noexcept override; + + //! @brief Remove every stored supplemental attachment. + Standard_EXPORT void Clear() noexcept override; + + DEFINE_STANDARD_RTTIEXT(BRepGraph_LayerTopoSupplement, BRepGraph_Layer) + +private: + //! @brief Remove all attachments belonging to one owner node. + //! @param[in] theOwner owner node to erase + void removeOwner(BRepGraph_NodeId theOwner) noexcept; + +private: + NCollection_DataMap myEntries; + NCollection_DataMap> myOwnerToUids; + NCollection_LinearVector myEmptyUids; + uint64_t myNextUid = 1; +}; + +#endif // _BRepGraph_LayerTopoSupplement_HeaderFile diff --git a/opencascade/BRepGraph_MeshCache.hxx b/opencascade/BRepGraph_MeshCache.hxx deleted file mode 100644 index 95f8c2131..000000000 --- a/opencascade/BRepGraph_MeshCache.hxx +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraph_MeshCache_HeaderFile -#define _BRepGraph_MeshCache_HeaderFile - -#include -#include - -#include -#include - -//! @brief Cached mesh data storage for BRepGraph. -//! -//! Stores mesh RepId references (triangulations for faces, polygons for edges -//! and coedges) separately from topology definitions. This cache holds -//! algorithm-derived mesh data written by BRepGraphMesh, as opposed to -//! persistent mesh data stored in definition structs (imported from STEP, etc.). -//! -//! Priority rule: cached mesh takes precedence over persistent mesh in -//! definitions. Persistent mesh is the fallback when no fresh cache exists. -//! -//! Freshness is validated by comparing StoredOwnGen against the entity's -//! current OwnGen. A mismatch means the geometry changed since meshing, -//! so the cached mesh is stale. -//! -//! Writing to the cache does NOT trigger markModified() or mutation tracking. -//! -//! ### Invalidation contract -//! The cache relies on the following invariants upheld by BRepGraph mutations: -//! 1. Any `Editor().Faces().Mut(FaceId)` guard bumps `FaceDef.OwnGen` on scope -//! exit, invalidating cached face mesh entries. -//! 2. `markRepModified(SurfaceRepId | TriangulationRepId)` iterates every Face -//! referencing the rep and calls `markModified(FaceId)`, so geometry edits -//! through `Editor().Reps().MutSurface/MutTriangulation()` also invalidate -//! cached face meshes. -//! 3. `markRepModified(TriangulationRepId)` additionally scans the cache itself -//! (not just persistent `FaceDef.TriangulationRepId`) so that cached-only -//! triangulations are bumped along with their owning Face's `OwnGen`. -//! Edge/CoEdge caches follow the analogous pattern for `EdgeDef`/`CoEdgeDef` -//! and the corresponding `Polygon3D`/`Polygon2D`/`PolygonOnTri` reps. -namespace BRepGraph_MeshCache -{ - -//! Cached mesh entry for a face: triangulation rep references. -struct FaceMeshEntry -{ - NCollection_DynamicArray TriangulationRepIds; - int ActiveTriangulationIndex = -1; - uint32_t StoredOwnGen = 0; //!< OwnGen of FaceDef at write time - - //! True if this entry contains mesh data. - [[nodiscard]] bool IsPresent() const { return !TriangulationRepIds.IsEmpty(); } - - //! Convenience: active triangulation rep id, or invalid. - [[nodiscard]] BRepGraph_TriangulationRepId ActiveTriangulationRepId() const - { - if (ActiveTriangulationIndex >= 0 && ActiveTriangulationIndex < TriangulationRepIds.Length()) - return TriangulationRepIds.Value(ActiveTriangulationIndex); - return BRepGraph_TriangulationRepId(); - } - - //! Reset all fields to default (absent) state. - void Reset() - { - TriangulationRepIds.Clear(); - ActiveTriangulationIndex = -1; - StoredOwnGen = 0; - } -}; - -//! Cached mesh entry for a coedge: polygon-on-triangulation and polygon-2D rep references. -struct CoEdgeMeshEntry -{ - BRepGraph_Polygon2DRepId Polygon2DRepId; - NCollection_DynamicArray PolygonOnTriRepIds; - uint32_t StoredOwnGen = 0; //!< OwnGen of CoEdgeDef at write time - - //! True if this entry contains mesh data. - [[nodiscard]] bool IsPresent() const - { - return Polygon2DRepId.IsValid() || !PolygonOnTriRepIds.IsEmpty(); - } - - //! Reset all fields to default (absent) state. - void Reset() - { - Polygon2DRepId = BRepGraph_Polygon2DRepId(); - PolygonOnTriRepIds.Clear(); - StoredOwnGen = 0; - } -}; - -//! Cached mesh entry for an edge: polygon-3D rep reference. -struct EdgeMeshEntry -{ - BRepGraph_Polygon3DRepId Polygon3DRepId; - uint32_t StoredOwnGen = 0; //!< OwnGen of EdgeDef at write time - - //! True if this entry contains mesh data. - [[nodiscard]] bool IsPresent() const { return Polygon3DRepId.IsValid(); } - - //! Reset all fields to default (absent) state. - void Reset() - { - Polygon3DRepId = BRepGraph_Polygon3DRepId(); - StoredOwnGen = 0; - } -}; - -} // namespace BRepGraph_MeshCache - -//! @brief Storage backend for cached mesh data. -//! -//! Dense vectors indexed by per-kind entity index (same pattern as DefStore). -//! Entries with StoredOwnGen == 0 are absent (no cached mesh data). -//! Thread safety: parallel writes to different indices are safe (no contention). -class BRepGraph_MeshCacheStorage -{ -public: - //! Check if a face has a cached mesh entry (StoredOwnGen != 0). - [[nodiscard]] bool HasFaceMesh(const BRepGraph_FaceId theFace) const; - - //! Find face mesh entry, or nullptr if absent. - [[nodiscard]] const BRepGraph_MeshCache::FaceMeshEntry* FindFaceMesh( - const BRepGraph_FaceId theFace) const; - - //! Get or create a face mesh entry. Creates with default values if absent. - [[nodiscard]] BRepGraph_MeshCache::FaceMeshEntry& ChangeFaceMesh(const BRepGraph_FaceId theFace); - - //! Clear the face mesh entry (reset to absent). - void ClearFaceMesh(const BRepGraph_FaceId theFace); - - //! Check if a coedge has a cached mesh entry. - [[nodiscard]] bool HasCoEdgeMesh(const BRepGraph_CoEdgeId theCoEdge) const; - - //! Find coedge mesh entry, or nullptr if absent. - [[nodiscard]] const BRepGraph_MeshCache::CoEdgeMeshEntry* FindCoEdgeMesh( - const BRepGraph_CoEdgeId theCoEdge) const; - - //! Get or create a coedge mesh entry. - [[nodiscard]] BRepGraph_MeshCache::CoEdgeMeshEntry& ChangeCoEdgeMesh( - const BRepGraph_CoEdgeId theCoEdge); - - //! Clear the coedge mesh entry. - void ClearCoEdgeMesh(const BRepGraph_CoEdgeId theCoEdge); - - //! Check if an edge has a cached mesh entry. - [[nodiscard]] bool HasEdgeMesh(const BRepGraph_EdgeId theEdge) const; - - //! Find edge mesh entry, or nullptr if absent. - [[nodiscard]] const BRepGraph_MeshCache::EdgeMeshEntry* FindEdgeMesh( - const BRepGraph_EdgeId theEdge) const; - - //! Get or create an edge mesh entry. - [[nodiscard]] BRepGraph_MeshCache::EdgeMeshEntry& ChangeEdgeMesh(const BRepGraph_EdgeId theEdge); - - //! Clear the edge mesh entry. - void ClearEdgeMesh(const BRepGraph_EdgeId theEdge); - - //! Clear all cached mesh data. - void Clear(); - - //! Remap cache entries after compaction. - //! @param[in] theNodeRemapMap old NodeId -> new NodeId mapping - void OnCompact(const NCollection_DataMap& theNodeRemapMap); - -private: - //! Ensure vector has at least theIndex+1 elements. - template - static void ensureSize(NCollection_DynamicArray& theVec, const size_t theIndex); - - NCollection_DynamicArray myFaceMeshes; - NCollection_DynamicArray myCoEdgeMeshes; - NCollection_DynamicArray myEdgeMeshes; -}; - -#endif // _BRepGraph_MeshCache_HeaderFile diff --git a/opencascade/BRepGraph_MeshView.hxx b/opencascade/BRepGraph_MeshView.hxx index c7961a4b5..c3d1eb2a4 100644 --- a/opencascade/BRepGraph_MeshView.hxx +++ b/opencascade/BRepGraph_MeshView.hxx @@ -15,182 +15,600 @@ #define _BRepGraph_MeshView_HeaderFile #include -#include -#include +#include +#include +#include +#include +#include -namespace BRepGraph_MeshCache -{ -struct FaceMeshEntry; -struct CoEdgeMeshEntry; -struct EdgeMeshEntry; -} // namespace BRepGraph_MeshCache - -namespace BRepGraphInc -{ -struct TriangulationRep; -struct Polygon3DRep; -struct Polygon2DRep; -struct PolygonOnTriRep; -} // namespace BRepGraphInc - -//! @brief Read-only view over mesh data with cache-first, persistent-fallback priority. +//! @brief Read/write view over mesh data. //! -//! Provides mesh queries that check the mesh cache (algorithm-derived mesh -//! from BRepGraphMesh) first, falling back to persistent mesh stored in -//! topology definitions (imported from STEP, etc.). +//! Splits mesh access into three explicit sub-views: +//! - `Cache()` - reads from the BRepGraphMesh cache only (algorithm-derived, +//! freshness-checked against the entity's OwnGen). +//! - `Persistent()` - reads from definition-resident mesh (FaceDef.TriangulationRepId, +//! EdgeDef.Polygon3DRepId, CoEdgeDef.Polygon2DRepId, +//! CoEdgeDef.PolygonOnTriRepId). +//! - `Editor()` - cache mutations (append/clear). Persistent rep creation lives on +//! `BRepGraph::Editor().Edges()`, `BRepGraph::Editor().CoEdges()`, +//! `BRepGraph::Editor().Faces()` since reps back the topology defs. +//! - `Poly()` - mesh element count queries (shared by all paths). //! -//! For mesh cache writes and rep creation, use BRepGraph_Tool::Mesh. +//! There is no fallback path that mixes cache and persistent - callers pick the +//! source explicitly. //! -//! Obtained via BRepGraph::Mesh(). +//! Obtained via `BRepGraph::Mesh()` (const) or `BRepGraph::Mesh()` (non-const for Editor). class BRepGraph::MeshView { public: - //! @brief Face mesh queries (cache-first, persistent fallback). - class FaceOps + //! Cache reads. Each accessor returns data only if a fresh cache entry exists + //! for the given entity (matched against its current OwnGen). + class CacheView { public: - //! Check if face has any mesh data (cached or persistent). - [[nodiscard]] Standard_EXPORT bool HasTriangulation(const BRepGraph_FaceId theFace) const; - - //! Active triangulation rep id (cached if fresh, else persistent). - //! @return valid TriangulationRepId, or invalid if no mesh available - [[nodiscard]] Standard_EXPORT BRepGraph_TriangulationRepId - ActiveTriangulationRepId(const BRepGraph_FaceId theFace) const; - - //! Direct access to cached face mesh entry (null if absent or stale). - [[nodiscard]] Standard_EXPORT const BRepGraph_MeshCache::FaceMeshEntry* CachedMesh( - const BRepGraph_FaceId theFace) const; + class FaceOps + { + public: + //! True if a fresh cached triangulation is present. + //! @param[in] theFace typed face definition identifier + //! @return true if Entry() would return non-null + [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_FaceId theFace) const; + + //! Cached triangulation handle. + //! @param[in] theFace typed face definition identifier + //! @return triangulation handle, or null handle if absent + [[nodiscard]] Standard_EXPORT const occ::handle& Triangulation( + const BRepGraph_FaceId theFace) const; + + //! Raw cached face mesh entry, or nullptr if absent or stale. + //! @param[in] theFace typed face definition identifier + //! @return cache entry pointer, or nullptr + [[nodiscard]] Standard_EXPORT const BRepGraph_CacheMesh::FaceMeshEntry* Entry( + const BRepGraph_FaceId theFace) const; + + private: + friend class CacheView; + + explicit FaceOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; + }; + + class EdgeOps + { + public: + //! True if a fresh cached Polygon3D is bound to the edge. + //! @param[in] theEdge typed edge definition identifier + //! @return true if a fresh Polygon3D is present in cache + [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_EdgeId theEdge) const; + + //! Cached Polygon3D handle. + //! @param[in] theEdge typed edge definition identifier + //! @return polygon-3D handle, or null handle if absent + [[nodiscard]] Standard_EXPORT const occ::handle& Polygon3D( + const BRepGraph_EdgeId theEdge) const; + + //! Raw cached edge mesh entry, or nullptr if absent or stale. + //! @param[in] theEdge typed edge definition identifier + //! @return cache entry pointer, or nullptr + [[nodiscard]] Standard_EXPORT const BRepGraph_CacheMesh::EdgeMeshEntry* Entry( + const BRepGraph_EdgeId theEdge) const; + + private: + friend class CacheView; + + explicit EdgeOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; + }; + + class CoEdgeOps + { + public: + //! True if a fresh cached entry exists (any of polygon-2D / polygon-on-tri). + //! @param[in] theCoEdge typed coedge definition identifier + //! @return true if a fresh cache entry exists + [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_CoEdgeId theCoEdge) const; + + //! Return coedge entry if Polygon2D is fresh, nullptr otherwise. + //! @param[in] theCoEdge typed coedge definition identifier + //! @return cache entry pointer, or nullptr + [[nodiscard]] Standard_EXPORT const BRepGraph_CacheMesh::CoEdgeMeshEntry* FindPolygon2D( + const BRepGraph_CoEdgeId theCoEdge) const; + + //! Return coedge entry if PolygonsOnTri is fresh, nullptr otherwise. + //! @param[in] theCoEdge typed coedge definition identifier + //! @return cache entry pointer, or nullptr + [[nodiscard]] Standard_EXPORT const BRepGraph_CacheMesh::CoEdgeMeshEntry* FindPolygonOnTri( + const BRepGraph_CoEdgeId theCoEdge) const; + + //! Raw coedge entry access (no freshness filtering). Returns nullptr if + //! the entry has no representation. For internal/testing use. + //! @param[in] theCoEdge typed coedge definition identifier + //! @return cache entry pointer, or nullptr if absent + [[nodiscard]] Standard_EXPORT const BRepGraph_CacheMesh::CoEdgeMeshEntry* FindRaw( + const BRepGraph_CoEdgeId theCoEdge) const; + + private: + friend class CacheView; + + explicit CoEdgeOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; + }; + + //! Grouped face cache queries. + [[nodiscard]] const FaceOps& Faces() const { return myFaces; } + + //! Grouped edge cache queries. + [[nodiscard]] const EdgeOps& Edges() const { return myEdges; } + + //! Grouped coedge cache queries. + [[nodiscard]] const CoEdgeOps& CoEdges() const { return myCoEdges; } private: friend class MeshView; - explicit FaceOps(const BRepGraph* theGraph) - : myGraph(theGraph) + explicit CacheView(BRepGraph* theGraph) + : myFaces(theGraph), + myEdges(theGraph), + myCoEdges(theGraph) { } - [[nodiscard]] bool isFresh(const BRepGraph_FaceId theFace, const uint32_t theStoredGen) const; - - const BRepGraph* myGraph; + FaceOps myFaces; + EdgeOps myEdges; + CoEdgeOps myCoEdges; }; - //! @brief Edge mesh queries (cache-first, persistent fallback). - class EdgeOps + //! Persistent reads. Resolves data through the rep id stored on the entity's + //! definition (FaceDef / EdgeDef / CoEdgeDef). Independent of the cache. + class PersistentView { public: - //! Check if edge has polygon-3D mesh data (cached or persistent). - [[nodiscard]] Standard_EXPORT bool HasPolygon3D(const BRepGraph_EdgeId theEdge) const; + class FaceOps + { + public: + //! True if FaceDef.TriangulationRepId is valid and the rep is not removed. + //! @param[in] theFace typed face definition identifier + //! @return true if a persistent triangulation is bound + [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_FaceId theFace) const; + + //! Persistent triangulation handle. + //! @param[in] theFace typed face definition identifier + //! @return triangulation handle, or null handle if absent + [[nodiscard]] Standard_EXPORT const occ::handle& Triangulation( + const BRepGraph_FaceId theFace) const; + + private: + friend class PersistentView; + + explicit FaceOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; + }; + + class EdgeOps + { + public: + //! True if EdgeDef.Polygon3DRepId is bound (dominant kind on edges). + //! @param[in] theEdge typed edge definition identifier + //! @return true if a persistent Polygon3D is bound + [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_EdgeId theEdge) const; + + //! Persistent Polygon3D handle. + //! @param[in] theEdge typed edge definition identifier + //! @return polygon-3D handle, or null handle if absent + [[nodiscard]] Standard_EXPORT const occ::handle& Polygon3D( + const BRepGraph_EdgeId theEdge) const; + + //! True if the (edge, face) coedge has a polygon-on-triangulation. + //! @param[in] theEdge typed edge definition identifier + //! @param[in] theFace typed face definition identifier + //! @return true if persistent polygon-on-triangulation is bound + [[nodiscard]] Standard_EXPORT bool HasPolygonOnTriangulation( + const BRepGraph_EdgeId theEdge, + const BRepGraph_FaceId theFace) const; + + //! Polygon-on-triangulation for the (edge, face) coedge. + //! @param[in] theEdge typed edge definition identifier + //! @param[in] theFace typed face definition identifier + //! @return polygon-on-triangulation handle, or null handle if absent + [[nodiscard]] Standard_EXPORT const occ::handle& + PolygonOnTriangulation(const BRepGraph_EdgeId theEdge, + const BRepGraph_FaceId theFace) const; + + private: + friend class PersistentView; + + explicit EdgeOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; + }; + + class CoEdgeOps + { + public: + //! True if CoEdgeDef.Polygon2DRepId is bound (dominant kind on coedges). + //! @param[in] theCoEdge typed coedge definition identifier + //! @return true if a persistent polygon-on-surface is bound + [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_CoEdgeId theCoEdge) const; + + //! Persistent polygon-on-surface (2D polygon) bound to the coedge. + //! @param[in] theCoEdge typed coedge definition identifier + //! @return polygon-2D handle, or null handle if absent + [[nodiscard]] Standard_EXPORT const occ::handle& PolygonOnSurface( + const BRepGraph_CoEdgeId theCoEdge) const; + + //! True if CoEdgeDef.PolygonOnTriRepId is bound. + //! @param[in] theCoEdge typed coedge definition identifier + //! @return true if persistent polygon-on-triangulation is bound + [[nodiscard]] Standard_EXPORT bool HasPolygonOnTriangulation( + const BRepGraph_CoEdgeId theCoEdge) const; + + //! Persistent polygon-on-triangulation bound to the coedge. + //! @param[in] theCoEdge typed coedge definition identifier + //! @return polygon-on-triangulation handle, or null handle if absent + [[nodiscard]] Standard_EXPORT const occ::handle& + PolygonOnTriangulation(const BRepGraph_CoEdgeId theCoEdge) const; + + private: + friend class PersistentView; + + explicit CoEdgeOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; + }; + + //! Grouped face persistent queries. + [[nodiscard]] const FaceOps& Faces() const { return myFaces; } + + //! Grouped edge persistent queries. + [[nodiscard]] const EdgeOps& Edges() const { return myEdges; } + + //! Grouped coedge persistent queries. + [[nodiscard]] const CoEdgeOps& CoEdges() const { return myCoEdges; } + + private: + friend class MeshView; - //! Polygon3D rep id (cached if fresh, else persistent). - [[nodiscard]] Standard_EXPORT BRepGraph_Polygon3DRepId - Polygon3DRepId(const BRepGraph_EdgeId theEdge) const; + explicit PersistentView(BRepGraph* theGraph) + : myFaces(theGraph), + myEdges(theGraph), + myCoEdges(theGraph) + { + } - //! Direct access to cached edge mesh entry (null if absent or stale). - [[nodiscard]] Standard_EXPORT const BRepGraph_MeshCache::EdgeMeshEntry* CachedMesh( - const BRepGraph_EdgeId theEdge) const; + FaceOps myFaces; + EdgeOps myEdges; + CoEdgeOps myCoEdges; + }; + + //! Resolves mesh data by checking the cache first and the persistent (def-resident) + //! source second. Callers that do not care which source supplies the data go + //! through this view; callers that do care use Cache() or Persistent() directly. + class EffectiveView + { + public: + class FaceOps + { + public: + //! True if the face has a triangulation in either cache or persistent storage. + //! @param[in] theFace typed face definition identifier + //! @return true if any triangulation is reachable + [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_FaceId theFace) const; + + //! Cached triangulation handle (cache first, persistent fallback). + //! @param[in] theFace typed face definition identifier + //! @return triangulation handle, or null handle if absent + [[nodiscard]] Standard_EXPORT const occ::handle& Triangulation( + const BRepGraph_FaceId theFace) const; + + private: + friend class EffectiveView; + + explicit FaceOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; + }; + + class EdgeOps + { + public: + //! True if the edge has a Polygon3D in either cache or persistent storage. + //! @param[in] theEdge typed edge definition identifier + //! @return true if any Polygon3D is reachable + [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_EdgeId theEdge) const; + + //! Polygon3D handle (cache first, persistent fallback). + //! @param[in] theEdge typed edge definition identifier + //! @return polygon-3D handle, or null handle if absent + [[nodiscard]] Standard_EXPORT const occ::handle& Polygon3D( + const BRepGraph_EdgeId theEdge) const; + + private: + friend class EffectiveView; + + explicit EdgeOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; + }; + + class CoEdgeOps + { + public: + //! True if the coedge has any polygon-2D / polygon-on-tri in either source. + //! @param[in] theCoEdge typed coedge definition identifier + //! @return true if any coedge mesh data is reachable + [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_CoEdgeId theCoEdge) const; + + //! True if a polygon-on-surface (2D) is reachable in either source. + //! @param[in] theCoEdge typed coedge definition identifier + //! @return true if a polygon-2D is bound on either side + [[nodiscard]] Standard_EXPORT bool HasPolygonOnSurface( + const BRepGraph_CoEdgeId theCoEdge) const; + + //! Polygon-on-surface (2D) handle (cache first, persistent fallback). + //! @param[in] theCoEdge typed coedge definition identifier + //! @return polygon-2D handle, or null handle if absent + [[nodiscard]] Standard_EXPORT const occ::handle& PolygonOnSurface( + const BRepGraph_CoEdgeId theCoEdge) const; + + //! True if a polygon-on-triangulation is reachable in either source. + //! @param[in] theCoEdge typed coedge definition identifier + //! @return true if a polygon-on-tri is bound on either side + [[nodiscard]] Standard_EXPORT bool HasPolygonOnTriangulation( + const BRepGraph_CoEdgeId theCoEdge) const; + + //! Polygon-on-triangulation handle (cache first, persistent fallback). + //! @param[in] theCoEdge typed coedge definition identifier + //! @return polygon-on-tri handle, or null handle if absent + [[nodiscard]] Standard_EXPORT const occ::handle& + PolygonOnTriangulation(const BRepGraph_CoEdgeId theCoEdge) const; + + private: + friend class EffectiveView; + + explicit CoEdgeOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; + }; + + //! Grouped face effective queries. + [[nodiscard]] const FaceOps& Faces() const { return myFaces; } + + //! Grouped edge effective queries. + [[nodiscard]] const EdgeOps& Edges() const { return myEdges; } + + //! Grouped coedge effective queries. + [[nodiscard]] const CoEdgeOps& CoEdges() const { return myCoEdges; } private: friend class MeshView; - explicit EdgeOps(const BRepGraph* theGraph) - : myGraph(theGraph) + explicit EffectiveView(BRepGraph* theGraph) + : myFaces(theGraph), + myEdges(theGraph), + myCoEdges(theGraph) { } - [[nodiscard]] bool isFresh(const BRepGraph_EdgeId theEdge, const uint32_t theStoredGen) const; - - const BRepGraph* myGraph; + FaceOps myFaces; + EdgeOps myEdges; + CoEdgeOps myCoEdges; }; - //! @brief CoEdge mesh queries (cache-first, persistent fallback). - class CoEdgeOps + //! Cache mutation surface. Mutates the BRepGraphMesh cache only - does not + //! touch persistent definition data. Persistent rep creation/edit lives on + //! `BRepGraph::Editor().Edges()`, `BRepGraph::Editor().CoEdges()`, + //! `BRepGraph::Editor().Faces()`. + class EditorView { public: - //! Check if coedge has cached mesh data (polygon-on-tri or polygon-2D). - [[nodiscard]] Standard_EXPORT bool HasMesh(const BRepGraph_CoEdgeId theCoEdge) const; + class FaceOps + { + public: + //! Set the cached triangulation for a face. + //! @param[in] theFace typed face definition identifier + //! @param[in] theTriangulation triangulation to store (null clears) + Standard_EXPORT void SetCachedTriangulation( + const BRepGraph_FaceId theFace, + const occ::handle& theTriangulation); + + //! Clear the face's cached mesh entry (no effect if absent). + //! @param[in] theFace typed face definition identifier + Standard_EXPORT void Clear(const BRepGraph_FaceId theFace); + + private: + friend class EditorView; + + explicit FaceOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; + }; + + class EdgeOps + { + public: + //! Bind a Polygon3D to the edge's cached entry. + //! @param[in] theEdge typed edge definition identifier + //! @param[in] thePolygon3D polygon-3D handle (null clears the cached binding) + Standard_EXPORT void SetCachedPolygon3D(const BRepGraph_EdgeId theEdge, + const occ::handle& thePolygon3D); + + //! Clear the edge's cached mesh entry. + //! @param[in] theEdge typed edge definition identifier + Standard_EXPORT void Clear(const BRepGraph_EdgeId theEdge); + + private: + friend class EditorView; + + explicit EdgeOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; + }; + + class CoEdgeOps + { + public: + //! Append a polygon-on-triangulation to the coedge's cached list. + //! @param[in] theCoEdge typed coedge definition identifier + //! @param[in] thePolygonOnTri polygon-on-tri to append + Standard_EXPORT void AppendCachedPolygonOnTri( + const BRepGraph_CoEdgeId theCoEdge, + const occ::handle& thePolygonOnTri); - //! Direct access to cached coedge mesh entry (null if absent or stale). - [[nodiscard]] Standard_EXPORT const BRepGraph_MeshCache::CoEdgeMeshEntry* CachedMesh( - const BRepGraph_CoEdgeId theCoEdge) const; + //! Bind a polygon-2D to the coedge's cached entry. + //! @param[in] theCoEdge typed coedge definition identifier + //! @param[in] thePolygon2D polygon-2D handle (null clears the cached binding) + Standard_EXPORT void SetCachedPolygon2D(const BRepGraph_CoEdgeId theCoEdge, + const occ::handle& thePolygon2D); + + //! Clear the coedge's cached mesh entry. + //! @param[in] theCoEdge typed coedge definition identifier + Standard_EXPORT void Clear(const BRepGraph_CoEdgeId theCoEdge); + + private: + friend class EditorView; + + explicit CoEdgeOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; + }; + + //! Grouped face cache mutations. + [[nodiscard]] FaceOps& Faces() { return myFaces; } + + //! Grouped edge cache mutations. + [[nodiscard]] EdgeOps& Edges() { return myEdges; } + + //! Grouped coedge cache mutations. + [[nodiscard]] CoEdgeOps& CoEdges() { return myCoEdges; } + + //! Promote all currently fresh default-slot cache mesh entries to persistent mesh reps. + Standard_EXPORT void PromoteToPersistent(); private: friend class MeshView; - explicit CoEdgeOps(const BRepGraph* theGraph) - : myGraph(theGraph) + explicit EditorView(BRepGraph* theGraph) + : myGraph(theGraph), + myFaces(theGraph), + myEdges(theGraph), + myCoEdges(theGraph) { } - [[nodiscard]] bool isFresh(const BRepGraph_CoEdgeId theCoEdge, - const uint32_t theStoredGen) const; - - const BRepGraph* myGraph; + BRepGraph* myGraph; + FaceOps myFaces; + EdgeOps myEdges; + CoEdgeOps myCoEdges; }; - //! @brief Polygonal and triangulation representation queries. + //! @brief Polygonal and triangulation count queries. class PolyOps { public: - [[nodiscard]] Standard_EXPORT int NbTriangulations() const; - [[nodiscard]] Standard_EXPORT int NbPolygons3D() const; - [[nodiscard]] Standard_EXPORT int NbPolygons2D() const; - [[nodiscard]] Standard_EXPORT int NbPolygonsOnTri() const; - - [[nodiscard]] Standard_EXPORT int NbActiveTriangulations() const; - [[nodiscard]] Standard_EXPORT int NbActivePolygons3D() const; - [[nodiscard]] Standard_EXPORT int NbActivePolygons2D() const; - [[nodiscard]] Standard_EXPORT int NbActivePolygonsOnTri() const; - - [[nodiscard]] Standard_EXPORT const BRepGraphInc::TriangulationRep& TriangulationRep( - const BRepGraph_TriangulationRepId theRep) const; - [[nodiscard]] Standard_EXPORT const BRepGraphInc::Polygon3DRep& Polygon3DRep( - const BRepGraph_Polygon3DRepId theRep) const; - [[nodiscard]] Standard_EXPORT const BRepGraphInc::Polygon2DRep& Polygon2DRep( - const BRepGraph_Polygon2DRepId theRep) const; - [[nodiscard]] Standard_EXPORT const BRepGraphInc::PolygonOnTriRep& PolygonOnTriRep( - const BRepGraph_PolygonOnTriRepId theRep) const; + //! Total number of face triangulation slots (including removed). + [[nodiscard]] Standard_EXPORT uint32_t NbFaceTriangulations() const; + //! Total number of edge polygon-3D slots (including removed). + [[nodiscard]] Standard_EXPORT uint32_t NbEdgePolygons3D() const; + //! Total number of coedge polygon-2D slots (including removed). + [[nodiscard]] Standard_EXPORT uint32_t NbCoEdgePolygons2D() const; + //! Total number of coedge polygon-on-triangulation slots (including removed). + [[nodiscard]] Standard_EXPORT uint32_t NbCoEdgePolygonsOnTri() const; + + //! Number of non-removed face triangulation entries. + [[nodiscard]] Standard_EXPORT uint32_t NbActiveTriangulations() const; + //! Number of non-removed edge polygon-3D entries. + [[nodiscard]] Standard_EXPORT uint32_t NbActivePolygons3D() const; + //! Number of non-removed coedge polygon-2D entries. + [[nodiscard]] Standard_EXPORT uint32_t NbActivePolygons2D() const; + //! Number of non-removed coedge polygon-on-triangulation entries. + [[nodiscard]] Standard_EXPORT uint32_t NbActivePolygonsOnTri() const; private: friend class MeshView; - explicit PolyOps(const BRepGraph* theGraph) + explicit PolyOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; - //! Grouped face mesh queries. - [[nodiscard]] const FaceOps& Faces() const { return myFaces; } + //! Cache-only reads. + [[nodiscard]] const CacheView& Cache() const { return myCache; } + + //! Persistent (definition-resident) reads. + [[nodiscard]] const PersistentView& Persistent() const { return myPersistent; } - //! Grouped edge mesh queries. - [[nodiscard]] const EdgeOps& Edges() const { return myEdges; } + //! Effective reads - cache first, persistent fallback. Use when source is irrelevant. + [[nodiscard]] const EffectiveView& Effective() const { return myEffective; } - //! Grouped coedge mesh queries. - [[nodiscard]] const CoEdgeOps& CoEdges() const { return myCoEdges; } + //! Cache mutations. + [[nodiscard]] EditorView& Editor() { return myEditor; } - //! Grouped polygonal representation queries. + //! Polygon/triangulation count queries. [[nodiscard]] const PolyOps& Poly() const { return myPoly; } private: friend class BRepGraph; friend struct BRepGraph_Data; - explicit MeshView(const BRepGraph* theGraph) + explicit MeshView(BRepGraph* theGraph) : myGraph(theGraph), - myFaces(theGraph), - myEdges(theGraph), - myCoEdges(theGraph), - myPoly(theGraph) + myPoly(theGraph), + myCache(theGraph), + myPersistent(theGraph), + myEffective(theGraph), + myEditor(theGraph) { } - const BRepGraph* myGraph; - FaceOps myFaces; - EdgeOps myEdges; - CoEdgeOps myCoEdges; - PolyOps myPoly; + BRepGraph* myGraph; + PolyOps myPoly; + CacheView myCache; + PersistentView myPersistent; + EffectiveView myEffective; + EditorView myEditor; }; #endif // _BRepGraph_MeshView_HeaderFile diff --git a/opencascade/BRepGraph_MutGuard.hxx b/opencascade/BRepGraph_MutGuard.hxx index 8857bddf8..4417a0455 100644 --- a/opencascade/BRepGraph_MutGuard.hxx +++ b/opencascade/BRepGraph_MutGuard.hxx @@ -14,47 +14,46 @@ #ifndef _BRepGraph_MutGuard_HeaderFile #define _BRepGraph_MutGuard_HeaderFile +#include #include #include -#include +#include #include #include -class BRepGraph; - //! @brief RAII scope token batching mutation notifications for a single entity. //! //! Obtained via BRepGraph::Editor().().Mut() / MutRef() / MutSurface() etc. //! Reads via `operator->()` / `operator*()`; writes via Editor's typed setters //! (or `Internal()` for in-tree structural remaps). Any call to `Internal()` //! flags the guard dirty and the destructor fires `markModified` / -//! `markRefModified` / `markRepModified` once on scope exit. +//! `markRefModified` once on scope exit. //! -//! Move-only; non-copyable. After a move, the source guard becomes inert. +//! The guard registers itself as active on the guarded item at construction +//! and deregisters on destruction. This prevents double-mutation: attempting +//! to acquire a second guard on the same item while the first is still alive +//! will throw. Move-only; after a move, the source guard becomes inert and +//! does not deregister. //! //! Compile-time dispatch selects the ID type and notification method: //! - For types derived from BRepGraphInc::BaseDef: BRepGraph_NodeId + markModified() //! - For types derived from BRepGraphInc::BaseRef: BRepGraph_RefId + markRefModified() -//! - For types derived from BRepGraphInc::BaseRep: BRepGraph_RepId + markRepModified() //! //! @code //! { //! BRepGraph_MutGuard anEdge = //! theGraph.Editor().Edges().Mut(BRepGraph_EdgeId(42)); -//! theGraph.Editor().Edges().SetTolerance (anEdge, 0.5); -//! theGraph.Editor().Edges().SetSameParameter (anEdge, true); -//! } // markModified called once here +//! theGraph.Editor().Edges().SetTolerance(anEdge, 0.5); +//! } // markModified called once here, guard deregistered //! @endcode template class BRepGraph_MutGuard { static_assert(std::is_base_of_v - || std::is_base_of_v - || std::is_base_of_v, - "BRepGraph_MutGuard: T must derive from BaseDef, BaseRef, or BaseRep"); + || std::is_base_of_v, + "BRepGraph_MutGuard: T must derive from BaseDef or BaseRef"); - //! Entity-provided identifier alias. using TypeId = typename T::TypeId; //! Call the appropriate notification method on the graph. @@ -63,11 +62,13 @@ class BRepGraph_MutGuard try { if constexpr (std::is_base_of_v) + { myGraph->markModified(myId, *myEntity); + } else if constexpr (std::is_base_of_v) - myGraph->markRefModified(myId, *myEntity); - else - myGraph->markRepModified(myId); + { + myGraph->markRefModified(myId); + } } catch (...) { @@ -76,51 +77,81 @@ class BRepGraph_MutGuard public: //! Construct a guard over a mutable entity. - //! @param[in] theGraph owning graph (used for notification on destruction) - //! @param[in] theEntity pointer to the mutable entity - //! @param[in] theId identity for notification - BRepGraph_MutGuard(BRepGraph* theGraph, T* theEntity, const TypeId theId) - : myGraph(theGraph), + //! Registers the item via the storage bit-plane. The Mut() factory pre-validates + //! that no guard is active, so this assertion should never fire in normal use. + //! @param[in] theGraph owning graph (used for notification) + //! @param[in] theStorage storage instance (for bit-plane guard tracking) + //! @param[in] theEntity pointer to the mutable entity + //! @param[in] theId identity for notification and guard registration + BRepGraph_MutGuard(BRepGraph& theGraph, + BRepGraphInc_Storage& theStorage, + T* theEntity, + const TypeId theId) + : myGraph(&theGraph), + myStorage(&theStorage), myEntity(theEntity), myId(theId), myDirty(false) { + Standard_ProgramError_Raise_if(myStorage->IsGuarded(BRepGraph_ItemId(myId)), + "BRepGraph_MutGuard: guard already active on this item"); + myStorage->SetGuarded(BRepGraph_ItemId(myId)); } - //! Destructor: notifies the graph if the guard owns an entity AND - //! at least one setter (or `MarkDirty`) flagged it modified. + //! Destructor: clears the guard bit-plane and notifies the graph if the + //! guard owns an entity AND at least one setter (or `MarkDirty`) flagged it modified. + //! Guard clearance happens BEFORE notification so that markModified() propagation + //! does not see a stale guard registration on the same item. ~BRepGraph_MutGuard() { - if (myGraph != nullptr && myDirty) + if (myEntity != nullptr) { - notify(); + myStorage->ClearGuarded(BRepGraph_ItemId(myId)); + if (myDirty) + { + notify(); + } } } + //! Move constructor: transfers guard ownership. The source becomes inert + //! and will not deregister on its destruction. BRepGraph_MutGuard(BRepGraph_MutGuard&& theOther) noexcept : myGraph(theOther.myGraph), + myStorage(theOther.myStorage), myEntity(theOther.myEntity), myId(theOther.myId), myDirty(theOther.myDirty) { - theOther.myGraph = nullptr; - theOther.myEntity = nullptr; - theOther.myDirty = false; + theOther.myEntity = nullptr; + theOther.myDirty = false; + theOther.myGraph = nullptr; + theOther.myStorage = nullptr; } + //! Move assignment: deregisters current guard (if active), then transfers + //! ownership from the source. The source becomes inert. BRepGraph_MutGuard& operator=(BRepGraph_MutGuard&& theOther) noexcept { if (this != &theOther) { - if (myGraph != nullptr && myDirty) - notify(); - myGraph = theOther.myGraph; - myEntity = theOther.myEntity; - myId = theOther.myId; - myDirty = theOther.myDirty; - theOther.myGraph = nullptr; - theOther.myEntity = nullptr; - theOther.myDirty = false; + if (myEntity != nullptr) + { + myStorage->ClearGuarded(BRepGraph_ItemId(myId)); + if (myDirty) + { + notify(); + } + } + myGraph = theOther.myGraph; + myStorage = theOther.myStorage; + myEntity = theOther.myEntity; + myId = theOther.myId; + myDirty = theOther.myDirty; + theOther.myEntity = nullptr; + theOther.myDirty = false; + theOther.myGraph = nullptr; + theOther.myStorage = nullptr; } return *this; } @@ -153,8 +184,8 @@ public: //! Identity for notification. [[nodiscard]] TypeId Id() const noexcept { return myId; } - //! Owning graph pointer (nullptr after move). - [[nodiscard]] BRepGraph* Graph() const noexcept { return myGraph; } + //! Owning graph handle. + [[nodiscard]] BRepGraph& Graph() const { return *myGraph; } //! Flag the guarded entity as modified without writing through `Internal()`. //! Use when an external mutation (e.g. in-place geometry transform on a shared @@ -173,10 +204,11 @@ public: } private: - BRepGraph* myGraph; //!< Owning graph (nullptr after move). - T* myEntity; //!< Mutable entity pointer; access via Editor setters. - TypeId myId; //!< Identity for notification. - bool myDirty; //!< True once a setter has modified the entity in this scope. + BRepGraph* myGraph; //!< Owning graph, non-owning. + BRepGraphInc_Storage* myStorage; //!< Storage instance for bit-plane guard tracking, non-owning. + T* myEntity; //!< Mutable entity pointer; access via Editor setters. + TypeId myId; //!< Identity for notification and guard registration. + bool myDirty; //!< True once a setter has modified the entity in this scope. }; #endif // _BRepGraph_MutGuard_HeaderFile diff --git a/opencascade/BRepGraph_NodeId.hxx b/opencascade/BRepGraph_NodeId.hxx index acc73de38..5fa40031a 100644 --- a/opencascade/BRepGraph_NodeId.hxx +++ b/opencascade/BRepGraph_NodeId.hxx @@ -23,6 +23,8 @@ #include #include +class BRepGraph; + //! Lightweight typed index into a per-kind node vector inside BRepGraph. //! //! The pair (NodeKind, Index) forms a unique node identifier within one graph @@ -54,11 +56,32 @@ struct BRepGraph_NodeId Occurrence = 11 //!< Placed instance of a product within a parent product }; + //! True if the kind value is one of the supported node kinds. + static bool IsValidKind(const Kind theKind) + { + switch (theKind) + { + case Kind::Solid: + case Kind::Shell: + case Kind::Face: + case Kind::Wire: + case Kind::Edge: + case Kind::Vertex: + case Kind::Compound: + case Kind::CompSolid: + case Kind::CoEdge: + case Kind::Product: + case Kind::Occurrence: + return true; + } + return false; + } + //! @brief Compile-time typed wrapper around BRepGraph_NodeId. //! //! Provides compile-time kind safety: a Typed //! cannot be accidentally used where a Typed is expected. - //! Implicitly converts to BRepGraph_NodeId for backward compatibility. + //! Implicitly converts to BRepGraph_NodeId for API continuity. //! //! @tparam TheKind the BRepGraph_NodeId::Kind this typed id represents template @@ -97,11 +120,17 @@ struct BRepGraph_NodeId [[nodiscard]] static Typed Invalid() { return Typed(); } //! True if this id points to an allocated node slot. - [[nodiscard]] bool IsValid() const { return Index != THE_INVALID_INDEX; } + [[nodiscard]] bool IsValid() const + { + return BRepGraph_NodeId::IsValidKind(TheKind) && Index != THE_INVALID_INDEX; + } //! True if this id points to an allocated slot within [0, theMaxCount). //! UINT32_MAX (invalid sentinel) always fails this check for any realistic count. - [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const { return Index < theMaxCount; } + [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const + { + return IsValid() && Index < theMaxCount; + } //! True if this id is within the dense range exposed by a provider with Nb(). template @@ -127,7 +156,11 @@ struct BRepGraph_NodeId //! @param[in] theId untyped NodeId to convert static Typed FromNodeId(const BRepGraph_NodeId theId) { - Standard_ASSERT_VOID(theId.NodeKind == TheKind, "NodeId kind mismatch"); + Standard_ASSERT_RETURN(theId.NodeKind == TheKind, "NodeId kind mismatch", Typed()); + if (!theId.IsValid()) + { + return Typed(); + } return Typed(theId.Index); } @@ -192,15 +225,30 @@ struct BRepGraph_NodeId { return theRhs != theLhs; } + + //! Return true if this node has been soft-removed in the given graph. + [[nodiscard]] bool IsRemoved(const BRepGraph& theGraph) const + { + return BRepGraph_NodeId(*this).IsRemoved(theGraph); + } + + //! Return true if this node has an active owner in the given graph. + [[nodiscard]] bool IsOwned(const BRepGraph& theGraph) const + { + return BRepGraph_NodeId(*this).IsOwned(theGraph); + } }; //! True if the kind is a core topology kind (Solid..CoEdge). - static bool IsTopologyKind(const Kind theKind) { return static_cast(theKind) <= 8; } + static bool IsTopologyKind(const Kind theKind) + { + return IsValidKind(theKind) && theKind >= Kind::Solid && theKind <= Kind::CoEdge; + } //! True if the kind is an assembly kind (Product or Occurrence). static bool IsAssemblyKind(const Kind theKind) { - return theKind == Kind::Product || theKind == Kind::Occurrence; + return IsValidKind(theKind) && (theKind == Kind::Product || theKind == Kind::Occurrence); } //! Total number of dense kind slots used by per-kind arrays. @@ -239,11 +287,14 @@ struct BRepGraph_NodeId } //! True if this id points to an allocated node slot. - [[nodiscard]] bool IsValid() const { return Index != THE_INVALID_INDEX; } + [[nodiscard]] bool IsValid() const { return IsValidKind(NodeKind) && Index != THE_INVALID_INDEX; } //! True if this id points to an allocated slot within [0, theMaxCount). //! UINT32_MAX (invalid sentinel) always fails this check for any realistic count. - [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const { return Index < theMaxCount; } + [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const + { + return IsValid() && Index < theMaxCount; + } //! True if this id is within the dense range exposed by a provider with Nb(). template @@ -271,7 +322,9 @@ struct BRepGraph_NodeId bool operator<(const BRepGraph_NodeId& theOther) const { if (NodeKind != theOther.NodeKind) + { return static_cast(NodeKind) < static_cast(theOther.NodeKind); + } return Index < theOther.Index; } @@ -340,6 +393,12 @@ struct BRepGraph_NodeId Standard_ASSERT_VOID(false, "BRepGraph_NodeId::Visit: unhandled Kind"); return std::forward(theFunc)(Typed()); } + + //! Return true if this node has been soft-removed in the given graph. + [[nodiscard]] Standard_EXPORT bool IsRemoved(const BRepGraph& theGraph) const; + + //! Return true if this node has an active owner in the given graph. + [[nodiscard]] Standard_EXPORT bool IsOwned(const BRepGraph& theGraph) const; }; // Convenience type aliases for typed NodeIds. diff --git a/opencascade/BRepGraph_ParallelPolicy.hxx b/opencascade/BRepGraph_ParallelPolicy.hxx index 1523f4fbf..56fb23ae5 100644 --- a/opencascade/BRepGraph_ParallelPolicy.hxx +++ b/opencascade/BRepGraph_ParallelPolicy.hxx @@ -31,9 +31,9 @@ public: //! Simple workload estimate for an execution phase. struct Workload { - int PrimaryItems = 0; //!< Main loop range. - int AuxiliaryItems = 0; //!< Additional independent items participating in the phase. - int InteractionCount = 0; //!< Pairwise or adjacency work discovered for the phase. + uint32_t PrimaryItems = 0; //!< Main loop range. + uint32_t AuxiliaryItems = 0; //!< Additional independent items participating in the phase. + uint32_t InteractionCount = 0; //!< Pairwise or adjacency work discovered for the phase. }; //! Return the effective logical worker count reported by OSD_Parallel. @@ -51,36 +51,18 @@ public: //! Decide whether the estimated workload is large enough to amortize //! thread-pool launch and synchronization overhead. - [[nodiscard]] static bool ShouldRun(const bool theAllowParallel, - const int theWorkers, - const Workload& theWorkload) - { - if (!theAllowParallel || theWorkers <= 1) - { - return false; - } - - const int aPrimaryItems = std::max(theWorkload.PrimaryItems, 0); - if (aPrimaryItems <= 1) - { - return false; - } - - if (aPrimaryItems <= theWorkers) - { - return false; - } - - const int64_t aTotalWorkUnits = - static_cast(aPrimaryItems) - + static_cast(std::max(theWorkload.AuxiliaryItems, 0)) - + static_cast(std::max(theWorkload.InteractionCount, 0)); - const int64_t aRequiredWorkUnits = - static_cast(theWorkers) * static_cast(theWorkers); - return aTotalWorkUnits > aRequiredWorkUnits; - } + //! @param[in] theAllowParallel whether parallel mode is allowed by the caller + //! @param[in] theWorkers effective logical worker count + //! @param[in] theWorkload estimated workload for the phase + //! @return true if parallel execution should be used + [[nodiscard]] Standard_EXPORT static bool ShouldRun(const bool theAllowParallel, + const int theWorkers, + const Workload& theWorkload); //! Overload that queries the active worker count lazily. + //! @param[in] theAllowParallel whether parallel mode is allowed by the caller + //! @param[in] theWorkload estimated workload for the phase + //! @return true if parallel execution should be used [[nodiscard]] static bool ShouldRun(const bool theAllowParallel, const Workload& theWorkload) { return ShouldRun(theAllowParallel, WorkerCount(), theWorkload); diff --git a/opencascade/BRepGraph_ParentExplorer.hxx b/opencascade/BRepGraph_ParentExplorer.hxx index c356806b2..97a90cdaa 100644 --- a/opencascade/BRepGraph_ParentExplorer.hxx +++ b/opencascade/BRepGraph_ParentExplorer.hxx @@ -18,11 +18,9 @@ #include #include #include - #include #include #include - #include #include @@ -40,7 +38,8 @@ //! kind is visited as a distinct entity (no hidden collapses): //! Vertex -> Edge, Edge -> CoEdge, CoEdge -> Wire, Wire -> Face, //! Face -> Shell, Shell -> Solid, Solid -> CompSolid/Compound, -//! Product -> Occurrence, Occurrence -> Product (parent assembly). +//! topology root -> Occurrence, Product child -> Occurrence, +//! Occurrence -> parent Product. //! //! ## Traversal modes //! - **Recursive**: walks the full ancestor chain to the graph roots. @@ -72,9 +71,8 @@ public: //! Consolidated configuration for the explorer. //! - //! Prefer this struct over the historical constructor family. The overloads - //! remain supported but the `Config`-based constructor is the long-term - //! idiom: new options can be added as fields without another ctor overload. + //! The `Config`-based constructor is the preferred idiom: new options can be + //! added as fields without additional constructor overloads. //! //! @code //! BRepGraph_ParentExplorer::Config aConfig; @@ -100,15 +98,25 @@ public: const Config& theConfig); //! Explore all parents of the starting node. + //! @param[in] theGraph graph to walk + //! @param[in] theNode starting node whose ancestors are explored Standard_EXPORT BRepGraph_ParentExplorer(const BRepGraph& theGraph, const BRepGraph_NodeId theNode); //! Explore parents of the starting node using the given traversal mode. + //! @param[in] theGraph graph to walk + //! @param[in] theNode starting node whose ancestors are explored + //! @param[in] theMode traversal strategy (recursive or direct parents) Standard_EXPORT BRepGraph_ParentExplorer(const BRepGraph& theGraph, const BRepGraph_NodeId theNode, TraversalMode theMode); //! Explore all parents while pruning branches at the avoid kind. + //! @param[in] theGraph graph to walk + //! @param[in] theNode starting node whose ancestors are explored + //! @param[in] theAvoidKind node kind to avoid ascending through + //! @param[in] theEmitAvoidKind if true, emit matching avoid-kind ancestors once + //! @param[in] theMode traversal strategy Standard_EXPORT BRepGraph_ParentExplorer( const BRepGraph& theGraph, const BRepGraph_NodeId theNode, @@ -117,17 +125,30 @@ public: TraversalMode theMode = TraversalMode::Recursive); //! Explore only parents of the given kind. + //! @param[in] theGraph graph to walk + //! @param[in] theNode starting node whose ancestors are explored + //! @param[in] theTargetKind kind of nodes to emit Standard_EXPORT BRepGraph_ParentExplorer(const BRepGraph& theGraph, const BRepGraph_NodeId theNode, BRepGraph_NodeId::Kind theTargetKind); //! Explore only parents of the given kind using the given traversal mode. + //! @param[in] theGraph graph to walk + //! @param[in] theNode starting node whose ancestors are explored + //! @param[in] theTargetKind kind of nodes to emit + //! @param[in] theMode traversal strategy Standard_EXPORT BRepGraph_ParentExplorer(const BRepGraph& theGraph, const BRepGraph_NodeId theNode, BRepGraph_NodeId::Kind theTargetKind, TraversalMode theMode); //! Explore parents of the given kind while pruning branches at the avoid kind. + //! @param[in] theGraph graph to walk + //! @param[in] theNode starting node whose ancestors are explored + //! @param[in] theTargetKind kind of nodes to emit + //! @param[in] theAvoidKind node kind to avoid ascending through + //! @param[in] theEmitAvoidKind if true, emit matching avoid-kind ancestors once + //! @param[in] theMode traversal strategy Standard_EXPORT BRepGraph_ParentExplorer( const BRepGraph& theGraph, const BRepGraph_NodeId theNode, @@ -169,7 +190,7 @@ public: //! Some upward steps are structural and therefore have no parent-owned ref //! entry even though the parent itself is still emitted by the explorer. //! In those cases this method returns an invalid RefId, for example for - //! CoEdge->Edge, Product(part)->ShapeRoot and Occurrence->Product. + //! CoEdge->Edge and Occurrence->Product/topology-root. [[nodiscard]] Standard_EXPORT BRepGraph_RefId CurrentRef() const; //! Accumulated location at the starting node of the current branch. @@ -196,6 +217,7 @@ private: BRepGraph_NodeId Node; uint32_t NextParentIdx = 0; int StepToChild = -1; + BRepGraph_RefId RefToChild; TopLoc_Location AccLocation; TopAbs_Orientation AccOrientation = TopAbs_FORWARD; }; @@ -209,33 +231,42 @@ private: Standard_EXPORT void applyTransition(const BRepGraph_NodeId theParent, const BRepGraph_NodeId theChild, const int theStepToChild, + const BRepGraph_RefId theRefToChild, TopLoc_Location& theLocation, TopAbs_Orientation& theOrientation) const; [[nodiscard]] Standard_EXPORT int branchRootFrame() const; - Standard_EXPORT bool findNthProductWrapper(const BRepGraph_NodeId theNode, - const uint32_t theOrdinal, - BRepGraph_ProductId& theProduct) const; - - Standard_EXPORT bool findParentProduct(const BRepGraph_OccurrenceId theOccurrence, - BRepGraph_ProductId& theProduct) const; - Standard_EXPORT int findOccurrenceStep(const BRepGraph_ProductId theParentProduct, - const BRepGraph_OccurrenceId theOccurrence) const; - Standard_EXPORT int findCompoundChildStep(const BRepGraph_CompoundId theParent, - const BRepGraph_NodeId theChild) const; - Standard_EXPORT int findCompSolidSolidStep(const BRepGraph_CompSolidId theParent, - const BRepGraph_SolidId theChild) const; - Standard_EXPORT int findSolidChildStep(const BRepGraph_SolidId theParent, - const BRepGraph_NodeId theChild) const; - Standard_EXPORT int findShellChildStep(const BRepGraph_ShellId theParent, - const BRepGraph_NodeId theChild) const; - Standard_EXPORT int findFaceChildStep(const BRepGraph_FaceId theParent, - const BRepGraph_NodeId theChild) const; - Standard_EXPORT int findWireCoEdgeStep(const BRepGraph_WireId theParent, - const BRepGraph_CoEdgeId theChild) const; - Standard_EXPORT int findEdgeVertexStep(const BRepGraph_EdgeId theParent, - const BRepGraph_VertexId theChild) const; + Standard_EXPORT bool findNthOccurrenceWrapper(const BRepGraph_NodeId theNode, + const uint32_t theOrdinal, + BRepGraph_OccurrenceId& theOccurrence, + BRepGraph_OccurrenceRefId& theOccurrenceRef) const; + + Standard_EXPORT int findOccurrenceStep( + const BRepGraph_ProductId theParentProduct, + const BRepGraph_OccurrenceId theOccurrence, + BRepGraph_OccurrenceRefId* theOccurrenceRef = nullptr) const; + Standard_EXPORT int findCompoundChildStep(const BRepGraph_CompoundId theParent, + const BRepGraph_NodeId theChild) const; + Standard_EXPORT int findCompSolidSolidStep(const BRepGraph_CompSolidId theParent, + const BRepGraph_SolidId theChild) const; + Standard_EXPORT int findSolidChildStep(const BRepGraph_SolidId theParent, + const BRepGraph_NodeId theChild) const; + Standard_EXPORT int findShellChildStep(const BRepGraph_ShellId theParent, + const BRepGraph_NodeId theChild) const; + Standard_EXPORT int findFaceChildStep(const BRepGraph_FaceId theParent, + const BRepGraph_NodeId theChild) const; + Standard_EXPORT int findWireCoEdgeStep(const BRepGraph_WireId theParent, + const BRepGraph_CoEdgeId theChild) const; + Standard_EXPORT int findEdgeVertexStep(const BRepGraph_EdgeId theParent, + const BRepGraph_VertexId theChild) const; + + //! Try compound parents, then occurrence parents for the given node. + //! Returns true and fills theParent if a match is found at theRemainingIdx. + //! Returns false if no compound/occurrence parent exists at that index. + Standard_EXPORT bool nextCompoundOrOccurrenceParent(BRepGraph_NodeId theNode, + uint32_t theRemainingIdx, + StackFrame& theParent) const; static std::optional normalizeAvoidKind( const BRepGraph_NodeId theNode, @@ -288,4 +319,4 @@ private: bool myHasMore = false; }; -#endif // _BRepGraph_ParentExplorer_HeaderFile \ No newline at end of file +#endif // _BRepGraph_ParentExplorer_HeaderFile diff --git a/opencascade/BRepGraph_RefId.hxx b/opencascade/BRepGraph_RefId.hxx index 3c7c34f55..354f7b3a4 100644 --- a/opencascade/BRepGraph_RefId.hxx +++ b/opencascade/BRepGraph_RefId.hxx @@ -23,6 +23,8 @@ #include #include +class BRepGraph; + //! Lightweight typed index into a per-kind reference vector inside BRepGraph. //! //! The pair (Kind, Index) forms a unique reference identifier within one graph @@ -35,13 +37,29 @@ struct BRepGraph_RefId Shell = 0, //!< Shell reference entries (usage of shell definitions) Face = 1, //!< Face reference entries (usage of face definitions) Wire = 2, //!< Wire reference entries (usage of wire definitions) - CoEdge = 3, //!< CoEdge reference entries (usage of coedge definitions) - Vertex = 4, //!< Vertex reference entries (usage of vertex definitions) - Solid = 5, //!< Solid reference entries (usage of solid definitions) - Child = 6, //!< Generic child references (usage of mixed node definitions) - Occurrence = 7 //!< Occurrence references (usage of occurrence definitions) + Vertex = 3, //!< Vertex reference entries (usage of vertex definitions) + Solid = 4, //!< Solid reference entries (usage of solid definitions) + Child = 5, //!< Generic child references (usage of mixed node definitions) + Occurrence = 6 //!< Occurrence references (usage of occurrence definitions) }; + //! True if the kind value is one of the supported reference kinds. + static bool IsValidKind(const Kind theKind) + { + switch (theKind) + { + case Kind::Shell: + case Kind::Face: + case Kind::Wire: + case Kind::Vertex: + case Kind::Solid: + case Kind::Child: + case Kind::Occurrence: + return true; + } + return false; + } + //! @brief Compile-time typed wrapper around BRepGraph_RefId. //! //! Provides compile-time kind safety similarly to BRepGraph_NodeId::Typed. @@ -78,11 +96,17 @@ struct BRepGraph_RefId //! Invalid sentinel id. [[nodiscard]] static Typed Invalid() { return Typed(); } - [[nodiscard]] bool IsValid() const { return Index != THE_INVALID_INDEX; } + [[nodiscard]] bool IsValid() const + { + return BRepGraph_RefId::IsValidKind(TheKind) && Index != THE_INVALID_INDEX; + } //! True if this id points to an allocated slot within [0, theMaxCount). //! UINT32_MAX (invalid sentinel) always fails this check for any realistic count. - [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const { return Index < theMaxCount; } + [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const + { + return IsValid() && Index < theMaxCount; + } template [[nodiscard]] auto IsValidIn(const CountProviderT& theProvider) const @@ -102,7 +126,11 @@ struct BRepGraph_RefId static Typed FromRefId(const BRepGraph_RefId theRefId) { - Standard_ASSERT_VOID(theRefId.RefKind == TheKind, "RefId kind mismatch"); + Standard_ASSERT_RETURN(theRefId.RefKind == TheKind, "RefId kind mismatch", Typed()); + if (!theRefId.IsValid()) + { + return Typed(); + } return Typed(theRefId.Index); } @@ -165,12 +193,23 @@ struct BRepGraph_RefId { return theRhs != theLhs; } + + //! Return true if this reference entry has been soft-removed in the given graph. + [[nodiscard]] bool IsRemoved(const BRepGraph& theGraph) const + { + return BRepGraph_RefId(*this).IsRemoved(theGraph); + } + + //! Return true if this reference entry has an active owner in the given graph. + [[nodiscard]] bool IsOwned(const BRepGraph& theGraph) const + { + return BRepGraph_RefId(*this).IsOwned(theGraph); + } }; static bool IsTopologyRefKind(const Kind theKind) { - return static_cast(theKind) >= static_cast(Kind::Shell) - && static_cast(theKind) <= static_cast(Kind::Child); + return IsValidKind(theKind) && theKind >= Kind::Shell && theKind <= Kind::Child; } static constexpr uint32_t THE_START_INDEX = 0u; @@ -203,11 +242,14 @@ struct BRepGraph_RefId return BRepGraph_RefId(theKind, THE_INVALID_INDEX); } - [[nodiscard]] bool IsValid() const { return Index != THE_INVALID_INDEX; } + [[nodiscard]] bool IsValid() const { return IsValidKind(RefKind) && Index != THE_INVALID_INDEX; } //! True if this id points to an allocated slot within [0, theMaxCount). //! UINT32_MAX (invalid sentinel) always fails this check for any realistic count. - [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const { return Index < theMaxCount; } + [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const + { + return IsValid() && Index < theMaxCount; + } template [[nodiscard]] auto IsValidIn(const CountProviderT& theProvider) const @@ -233,7 +275,9 @@ struct BRepGraph_RefId bool operator<(const BRepGraph_RefId& theOther) const { if (RefKind != theOther.RefKind) + { return static_cast(RefKind) < static_cast(theOther.RefKind); + } return Index < theOther.Index; } @@ -281,8 +325,6 @@ struct BRepGraph_RefId return std::forward(theFunc)(Typed::FromRefId(theRefId)); case Kind::Wire: return std::forward(theFunc)(Typed::FromRefId(theRefId)); - case Kind::CoEdge: - return std::forward(theFunc)(Typed::FromRefId(theRefId)); case Kind::Vertex: return std::forward(theFunc)(Typed::FromRefId(theRefId)); case Kind::Solid: @@ -296,12 +338,17 @@ struct BRepGraph_RefId Standard_ASSERT_VOID(false, "BRepGraph_RefId::Visit: unhandled Kind"); return std::forward(theFunc)(Typed()); } + + //! Return true if this reference entry has been soft-removed in the given graph. + [[nodiscard]] Standard_EXPORT bool IsRemoved(const BRepGraph& theGraph) const; + + //! Return true if this reference entry has an active owner in the given graph. + [[nodiscard]] Standard_EXPORT bool IsOwned(const BRepGraph& theGraph) const; }; using BRepGraph_ShellRefId = BRepGraph_RefId::Typed; using BRepGraph_FaceRefId = BRepGraph_RefId::Typed; using BRepGraph_WireRefId = BRepGraph_RefId::Typed; -using BRepGraph_CoEdgeRefId = BRepGraph_RefId::Typed; using BRepGraph_VertexRefId = BRepGraph_RefId::Typed; using BRepGraph_SolidRefId = BRepGraph_RefId::Typed; using BRepGraph_ChildRefId = BRepGraph_RefId::Typed; diff --git a/opencascade/BRepGraph_RefTransientCache.hxx b/opencascade/BRepGraph_RefTransientCache.hxx deleted file mode 100644 index d88728106..000000000 --- a/opencascade/BRepGraph_RefTransientCache.hxx +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraph_RefTransientCache_HeaderFile -#define _BRepGraph_RefTransientCache_HeaderFile - -#include -#include - -#include - -#include -#include - -//! @brief Centralized transient cache for algorithm-computed per-reference values. -//! -//! Symmetric counterpart of BRepGraph_TransientCache, keyed by BRepGraph_RefId -//! instead of BRepGraph_NodeId. Freshness is tracked via BaseRef::OwnGen rather -//! than BaseDef::SubtreeGen, because references do not own subtrees. -//! -//! Shares the same BRepGraph_CacheKind descriptors and BRepGraph_CacheKindRegistry -//! as the node cache; the same kind GUID can address values in both caches. -//! -//! ## OwnGen-based freshness -//! Each stored slot records OwnGen at write time. On read, if the stored OwnGen -//! differs from the reference's current OwnGen the cached value is considered stale. -//! -//! ## Lifecycle -//! NOT a Layer. Cleared on BRepGraph_Builder::Add() and Compact(). No explicit removal callback -//! - stale data is auto-detected by OwnGen mismatch. -//! -//! ## Thread safety -//! After Reserve(), Get() and Set() for in-range indices bypass the mutex entirely. -//! Out-of-range access falls back to mutex-protected vector growth. -class BRepGraph_RefTransientCache -{ -public: - //! Number of BRepGraph_RefId::Kind enum values (Shell..Occurrence = 0..7). - static constexpr int THE_REF_KIND_COUNT = 8; - - //! Default number of cache-kind slots reserved after BRepGraph_Builder::Add(). - static constexpr int THE_DEFAULT_RESERVED_KIND_COUNT = 16; - - //! Per-slot storage: cached value handle + OwnGen stamp. - struct CacheSlot - { - occ::handle Value; - uint32_t StoredOwnGen = 0; - }; - - //! Store a cached value for a reference and cache kind. - //! @pre Reserve() must have been called for lock-free parallel access - //! on in-range entity indices; out-of-range access falls back to mutex. - Standard_EXPORT void Set(const BRepGraph_RefId theRef, - const occ::handle& theKind, - const occ::handle& theValue, - const uint32_t theCurrentOwnGen); - - //! Store a cached value using a pre-resolved kind slot index. - //! Bypasses BRepGraph_CacheKindRegistry lookup - use in hot parallel paths. - //! @param[in] theKindSlot slot from BRepGraph_CacheKindRegistry::Register() - Standard_EXPORT void Set(const BRepGraph_RefId theRef, - const int theKindSlot, - const occ::handle& theValue, - const uint32_t theCurrentOwnGen); - - //! Retrieve a cached value for a reference and cache kind. - //! Returns null handle if no value is stored or if OwnGen has changed. - [[nodiscard]] Standard_EXPORT occ::handle Get( - const BRepGraph_RefId theRef, - const occ::handle& theKind, - const uint32_t theCurrentOwnGen) const; - - //! Retrieve a cached value using a pre-resolved kind slot index. - [[nodiscard]] Standard_EXPORT occ::handle Get( - const BRepGraph_RefId theRef, - const int theKindSlot, - const uint32_t theCurrentOwnGen) const; - - //! Remove a cached value for a reference and cache kind. - [[nodiscard]] Standard_EXPORT bool Remove(const BRepGraph_RefId theRef, - const occ::handle& theKind); - - //! Remove a cached value using a pre-resolved cache-kind slot. - [[nodiscard]] Standard_EXPORT bool Remove(const BRepGraph_RefId theRef, const int theKindSlot); - - //! Collect fresh cache-kind slot indices for a reference (zero heap allocation). - //! Used internally by CacheView::CacheKindIterator. - //! @param[in] theRef reference to query - //! @param[in] theCurrentOwnGen freshness stamp to match - //! @param[out] theSlots output array (caller-allocated, must hold - //! THE_DEFAULT_RESERVED_KIND_COUNT) - //! @return number of populated slots written to theSlots - Standard_EXPORT int CollectCacheKindSlots(const BRepGraph_RefId theRef, - const uint32_t theCurrentOwnGen, - int theSlots[]) const; - - //! Pre-allocate storage for lock-free parallel access. - Standard_EXPORT void Reserve(const int theKindCount, const int theCounts[THE_REF_KIND_COUNT]); - - //! True if Reserve() has been called and storage is pre-allocated. - [[nodiscard]] bool IsReserved() const noexcept - { - return myIsReserved.load(std::memory_order_acquire); - } - - //! Clear all cached data. Called on BRepGraph_Builder::Add() and Compact(). - Standard_EXPORT void Clear() noexcept; - - //! Move constructor: transfers data, creates fresh mutex. - BRepGraph_RefTransientCache(BRepGraph_RefTransientCache&& theOther) noexcept - : myKinds(std::move(theOther.myKinds)), - myIsReserved(theOther.myIsReserved.load(std::memory_order_relaxed)) - { - theOther.myIsReserved.store(false, std::memory_order_relaxed); - } - - //! Move assignment: transfers data, mutex stays local. - BRepGraph_RefTransientCache& operator=(BRepGraph_RefTransientCache&& theOther) noexcept - { - if (this != &theOther) - { - myKinds = std::move(theOther.myKinds); - myIsReserved.store(theOther.myIsReserved.load(std::memory_order_relaxed), - std::memory_order_relaxed); - theOther.myIsReserved.store(false, std::memory_order_relaxed); - } - return *this; - } - - BRepGraph_RefTransientCache() = default; - BRepGraph_RefTransientCache(const BRepGraph_RefTransientCache&) = delete; - BRepGraph_RefTransientCache& operator=(const BRepGraph_RefTransientCache&) = delete; - -private: - //! Per-ref-kind dense vector of cache slots. - struct RefKindStore - { - NCollection_DynamicArray mySlots; - }; - - //! Per-cache-kind storage: one ref-kind store per reference kind. - struct CacheKindSlot - { - RefKindStore myRefKinds[THE_REF_KIND_COUNT]; - }; - - //! Ensure myKinds has capacity for the given cache-kind slot. - void ensureKind(const int theKindSlot); - - //! Access slot (mutable) - grows vector if needed. - CacheSlot& changeSlot(const BRepGraph_RefId theRef, const int theKindSlot); - - //! Access slot (const) - returns nullptr if out of range. - const CacheSlot* seekSlot(const BRepGraph_RefId theRef, const int theKindSlot) const; - - //! Outer vector indexed by cache-kind slot. - NCollection_DynamicArray myKinds; - - //! True after Reserve() - enables lock-free access for in-range slots. - std::atomic myIsReserved{false}; - - //! Protects structural modifications (vector growth) during concurrent access. - mutable std::shared_mutex myMutex; -}; - -#endif // _BRepGraph_RefTransientCache_HeaderFile diff --git a/opencascade/BRepGraph_RefUID.hxx b/opencascade/BRepGraph_RefUID.hxx index c19c57631..9056e87a3 100644 --- a/opencascade/BRepGraph_RefUID.hxx +++ b/opencascade/BRepGraph_RefUID.hxx @@ -15,87 +15,73 @@ #define _BRepGraph_RefUID_HeaderFile #include +#include +#include #include #include #include +#include -//! Unique reference identifier within a BRepGraph. +//! Unique reference-entry identifier within a BRepGraph. //! -//! Identity = (RefKind, Counter). Generation is excluded from equality/hash. -//! Counter 0 is an invalid sentinel. -//! -//! ## Serialization Contract -//! -//! Entity UIDs (BRepGraph_UID) and reference UIDs (BRepGraph_RefUID) share -//! a single monotonic counter (BRepGraph_Data::myNextUIDCounter). -//! To persist a BRepGraph across sessions: -//! 1. Write: for each reference entry, serialize (RefKind, Counter, OwnGen). -//! 2. Read: reconstruct reference entries, populate RefUID vectors with -//! deserialized (RefKind, Counter) values, set myNextUIDCounter to -//! max(all_entity_counters, all_ref_counters) + 1. -//! 3. myGeneration resets to 0 on load (session-scoped). -//! 4. VersionStamps from a previous session will correctly detect staleness -//! via Generation mismatch. +//! Identity = (RefKind, Counter). Counter 0 is an invalid sentinel. struct BRepGraph_RefUID { - BRepGraph_RefUID() - : myCounter(0), - myKind(BRepGraph_RefId::Kind::Shell), - myGeneration(0) - { - } + BRepGraph_RefId::Kind Kind = BRepGraph_RefId::Kind::Shell; + uint32_t Counter = 0; + + BRepGraph_RefUID() = default; - BRepGraph_RefUID(const BRepGraph_RefId::Kind theKind, - const size_t theCounter, - const uint32_t theGeneration) - : myCounter(theCounter), - myKind(theKind), - myGeneration(theGeneration) + BRepGraph_RefUID(const BRepGraph_RefId::Kind theKind, const uint32_t theCounter) + : Kind(theKind), + Counter(theCounter) { - Standard_ASSERT_VOID(theCounter > 0, "BRepGraph_RefUID: counter must be > 0 for valid UIDs"); } static BRepGraph_RefUID Invalid() { return BRepGraph_RefUID(); } - [[nodiscard]] bool IsValid() const { return myCounter > 0; } - - [[nodiscard]] BRepGraph_RefId::Kind Kind() const { return myKind; } + //! True if this UID has a valid kind and a non-zero counter. + [[nodiscard]] bool IsValid() const { return Counter > 0 && BRepGraph_RefId::IsValidKind(Kind); } - [[nodiscard]] size_t Counter() const { return myCounter; } - - [[nodiscard]] uint32_t Generation() const { return myGeneration; } - - bool operator==(const BRepGraph_RefUID& theOther) const + friend bool operator==(const BRepGraph_RefUID& theLeft, const BRepGraph_RefUID& theRight) noexcept { - if (myCounter == 0 || theOther.myCounter == 0) - return (myCounter == 0) == (theOther.myCounter == 0); - return myKind == theOther.myKind && myCounter == theOther.myCounter; + if (theLeft.Counter == 0 || theRight.Counter == 0) + { + return (theLeft.Counter == 0) == (theRight.Counter == 0); + } + return theLeft.Kind == theRight.Kind && theLeft.Counter == theRight.Counter; } - bool operator!=(const BRepGraph_RefUID& theOther) const { return !(*this == theOther); } + friend bool operator!=(const BRepGraph_RefUID& theLeft, const BRepGraph_RefUID& theRight) noexcept + { + return !(theLeft == theRight); + } - bool operator<(const BRepGraph_RefUID& theOther) const + friend bool operator<(const BRepGraph_RefUID& theLeft, const BRepGraph_RefUID& theRight) noexcept { - if (myKind != theOther.myKind) - return static_cast(myKind) < static_cast(theOther.myKind); - return myCounter < theOther.myCounter; + if (theLeft.Kind != theRight.Kind) + { + return static_cast(theLeft.Kind) < static_cast(theRight.Kind); + } + return theLeft.Counter < theRight.Counter; } - [[nodiscard]] size_t HashValue() const + [[nodiscard]] size_t HashValue() const noexcept { + if (Counter == 0) + { + return opencascade::hash(0); + } size_t aCombination[2]; - aCombination[0] = opencascade::hash(static_cast(myKind)); - aCombination[1] = opencascade::hash(myCounter); + aCombination[0] = opencascade::hash(static_cast(Kind)); + aCombination[1] = opencascade::hash(Counter); return opencascade::hashBytes(aCombination, sizeof(aCombination)); } - -private: - size_t myCounter; - BRepGraph_RefId::Kind myKind; - uint32_t myGeneration; }; +static_assert(sizeof(BRepGraph_RefUID) <= 8, "BRepGraph_RefUID must stay compact"); + template <> struct std::hash { diff --git a/opencascade/BRepGraph_RefsIterator.hxx b/opencascade/BRepGraph_RefsIterator.hxx index e259343ab..5ad680631 100644 --- a/opencascade/BRepGraph_RefsIterator.hxx +++ b/opencascade/BRepGraph_RefsIterator.hxx @@ -17,8 +17,10 @@ #include #include #include - +#include #include +#include +#include //! @brief Single-level typed iterators over active child reference ids. //! @@ -37,7 +39,7 @@ struct RefTraits { using RefId = BRepGraph_ShellRefId; - static int Count(const BRepGraph& theGraph) { return theGraph.Refs().Shells().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Refs().Shells().Nb(); } static const BRepGraphInc::ShellRef& Get(const BRepGraph& theGraph, const RefId theRefId) { @@ -50,7 +52,7 @@ struct RefTraits { using RefId = BRepGraph_FaceRefId; - static int Count(const BRepGraph& theGraph) { return theGraph.Refs().Faces().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Refs().Faces().Nb(); } static const BRepGraphInc::FaceRef& Get(const BRepGraph& theGraph, const RefId theRefId) { @@ -63,7 +65,7 @@ struct RefTraits { using RefId = BRepGraph_WireRefId; - static int Count(const BRepGraph& theGraph) { return theGraph.Refs().Wires().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Refs().Wires().Nb(); } static const BRepGraphInc::WireRef& Get(const BRepGraph& theGraph, const RefId theRefId) { @@ -71,25 +73,12 @@ struct RefTraits } }; -template <> -struct RefTraits -{ - using RefId = BRepGraph_CoEdgeRefId; - - static int Count(const BRepGraph& theGraph) { return theGraph.Refs().CoEdges().Nb(); } - - static const BRepGraphInc::CoEdgeRef& Get(const BRepGraph& theGraph, const RefId theRefId) - { - return theGraph.Refs().CoEdges().Entry(theRefId); - } -}; - template <> struct RefTraits { using RefId = BRepGraph_VertexRefId; - static int Count(const BRepGraph& theGraph) { return theGraph.Refs().Vertices().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Refs().Vertices().Nb(); } static const BRepGraphInc::VertexRef& Get(const BRepGraph& theGraph, const RefId theRefId) { @@ -102,7 +91,7 @@ struct RefTraits { using RefId = BRepGraph_SolidRefId; - static int Count(const BRepGraph& theGraph) { return theGraph.Refs().Solids().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Refs().Solids().Nb(); } static const BRepGraphInc::SolidRef& Get(const BRepGraph& theGraph, const RefId theRefId) { @@ -115,7 +104,7 @@ struct RefTraits { using RefId = BRepGraph_ChildRefId; - static int Count(const BRepGraph& theGraph) { return theGraph.Refs().Children().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Refs().Children().Nb(); } static const BRepGraphInc::ChildRef& Get(const BRepGraph& theGraph, const RefId theRefId) { @@ -128,7 +117,7 @@ struct RefTraits { using RefId = BRepGraph_OccurrenceRefId; - static int Count(const BRepGraph& theGraph) { return theGraph.Refs().Occurrences().Nb(); } + static uint32_t Count(const BRepGraph& theGraph) { return theGraph.Refs().Occurrences().Nb(); } static const BRepGraphInc::OccurrenceRef& Get(const BRepGraph& theGraph, const RefId theRefId) { @@ -187,7 +176,7 @@ private: { if constexpr (!TheFullTraverse) { - while (myCurrent < myLength && Current().IsRemoved) + while (myCurrent < myLength && myCurrent.IsRemoved(myGraph)) { ++myCurrent; } @@ -205,34 +194,24 @@ struct BaseTraits using ParentId = ParentIdT; using RefId = RefIdT; using RefEntry = RefEntryT; -}; - -template -inline const BRepGraphInc::BaseDef* childBaseDef(const BRepGraph& theGraph, - const ChildIdT theChildId) -{ - return theGraph.Topo().Gen().TopoEntity(BRepGraph_NodeId(theChildId)); -} -inline const BRepGraphInc::BaseDef* childBaseDef(const BRepGraph& theGraph, - const BRepGraph_NodeId theChildId) -{ - return theGraph.Topo().Gen().TopoEntity(theChildId); -} + static constexpr bool THE_IS_DIRECT = false; +}; struct ShellOfSolidTraits : public BaseTraits { + using ChildId = BRepGraph_ShellId; + static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) { - return theParent.IsValid(theGraph.Topo().Solids().Nb()) - && !theGraph.Topo().Solids().Definition(theParent).IsRemoved; + return theParent.IsValid(theGraph.Topo().Solids().Nb()) && !theParent.IsRemoved(theGraph); } - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Solids().Definition(theParent).ShellRefIds; + return theGraph.Topo().Solids().Relations(theParent).ShellRefIds; } static const BRepGraphInc::ShellRef& Ref(const BRepGraph& theGraph, const RefId theRefId) @@ -242,23 +221,24 @@ struct ShellOfSolidTraits static BRepGraph_ShellId ChildIdOf(const BRepGraph&, const BRepGraphInc::ShellRef& theRef) { - return theRef.ShellDefId; + return theRef.ChildShellId; } }; struct FaceOfShellTraits : public BaseTraits { + using ChildId = BRepGraph_FaceId; + static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) { - return theParent.IsValid(theGraph.Topo().Shells().Nb()) - && !theGraph.Topo().Shells().Definition(theParent).IsRemoved; + return theParent.IsValid(theGraph.Topo().Shells().Nb()) && !theParent.IsRemoved(theGraph); } - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Shells().Definition(theParent).FaceRefIds; + return theGraph.Topo().Shells().Relations(theParent).FaceRefIds; } static const BRepGraphInc::FaceRef& Ref(const BRepGraph& theGraph, const RefId theRefId) @@ -268,49 +248,24 @@ struct FaceOfShellTraits static BRepGraph_FaceId ChildIdOf(const BRepGraph&, const BRepGraphInc::FaceRef& theRef) { - return theRef.FaceDefId; - } -}; - -struct ChildOfShellTraits - : public BaseTraits -{ - static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) - { - return theParent.IsValid(theGraph.Topo().Shells().Nb()) - && !theGraph.Topo().Shells().Definition(theParent).IsRemoved; - } - - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, - const ParentId theParent) - { - return theGraph.Topo().Shells().Definition(theParent).AuxChildRefIds; - } - - static const BRepGraphInc::ChildRef& Ref(const BRepGraph& theGraph, const RefId theRefId) - { - return theGraph.Refs().Children().Entry(theRefId); - } - - static BRepGraph_NodeId ChildIdOf(const BRepGraph&, const BRepGraphInc::ChildRef& theRef) - { - return theRef.ChildDefId; + return theRef.ChildFaceId; } }; struct WireOfFaceTraits : public BaseTraits { + using ChildId = BRepGraph_WireId; + static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) { - return theParent.IsValid(theGraph.Topo().Faces().Nb()) - && !theGraph.Topo().Faces().Definition(theParent).IsRemoved; + return theParent.IsValid(theGraph.Topo().Faces().Nb()) && !theParent.IsRemoved(theGraph); } - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Faces().Definition(theParent).WireRefIds; + return theGraph.Topo().Faces().Relations(theParent).WireRefIds; } static const BRepGraphInc::WireRef& Ref(const BRepGraph& theGraph, const RefId theRefId) @@ -320,75 +275,48 @@ struct WireOfFaceTraits static BRepGraph_WireId ChildIdOf(const BRepGraph&, const BRepGraphInc::WireRef& theRef) { - return theRef.WireDefId; + return theRef.ChildWireId; } }; -struct VertexOfFaceTraits - : public BaseTraits +struct CoEdgeOfWireTraits + : public BaseTraits { - static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) - { - return theParent.IsValid(theGraph.Topo().Faces().Nb()) - && !theGraph.Topo().Faces().Definition(theParent).IsRemoved; - } - - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, - const ParentId theParent) - { - return theGraph.Topo().Faces().Definition(theParent).VertexRefIds; - } - - static const BRepGraphInc::VertexRef& Ref(const BRepGraph& theGraph, const RefId theRefId) - { - return theGraph.Refs().Vertices().Entry(theRefId); - } + using ChildId = BRepGraph_CoEdgeId; - static BRepGraph_VertexId ChildIdOf(const BRepGraph&, const BRepGraphInc::VertexRef& theRef) - { - return theRef.VertexDefId; - } -}; + static constexpr bool THE_IS_DIRECT = true; -struct CoEdgeOfWireTraits - : public BaseTraits -{ static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) { - return theParent.IsValid(theGraph.Topo().Wires().Nb()) - && !theGraph.Topo().Wires().Definition(theParent).IsRemoved; + return theParent.IsValid(theGraph.Topo().Wires().Nb()) && !theParent.IsRemoved(theGraph); } - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Wires().Definition(theParent).CoEdgeRefIds; + return theGraph.Topo().Wires().Relations(theParent).CoEdgeIds; } - static const BRepGraphInc::CoEdgeRef& Ref(const BRepGraph& theGraph, const RefId theRefId) + static const BRepGraphInc::CoEdgeDef& Ref(const BRepGraph& theGraph, const RefId theRefId) { - return theGraph.Refs().CoEdges().Entry(theRefId); - } - - static BRepGraph_CoEdgeId ChildIdOf(const BRepGraph&, const BRepGraphInc::CoEdgeRef& theRef) - { - return theRef.CoEdgeDefId; + return theGraph.Topo().CoEdges().Definition(theRefId); } }; struct SolidOfCompSolidTraits : public BaseTraits { + using ChildId = BRepGraph_SolidId; + static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) { - return theParent.IsValid(theGraph.Topo().CompSolids().Nb()) - && !theGraph.Topo().CompSolids().Definition(theParent).IsRemoved; + return theParent.IsValid(theGraph.Topo().CompSolids().Nb()) && !theParent.IsRemoved(theGraph); } - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().CompSolids().Definition(theParent).SolidRefIds; + return theGraph.Topo().CompSolids().Relations(theParent).SolidRefIds; } static const BRepGraphInc::SolidRef& Ref(const BRepGraph& theGraph, const RefId theRefId) @@ -398,49 +326,24 @@ struct SolidOfCompSolidTraits static BRepGraph_SolidId ChildIdOf(const BRepGraph&, const BRepGraphInc::SolidRef& theRef) { - return theRef.SolidDefId; - } -}; - -struct ChildOfSolidTraits - : public BaseTraits -{ - static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) - { - return theParent.IsValid(theGraph.Topo().Solids().Nb()) - && !theGraph.Topo().Solids().Definition(theParent).IsRemoved; - } - - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, - const ParentId theParent) - { - return theGraph.Topo().Solids().Definition(theParent).AuxChildRefIds; - } - - static const BRepGraphInc::ChildRef& Ref(const BRepGraph& theGraph, const RefId theRefId) - { - return theGraph.Refs().Children().Entry(theRefId); - } - - static BRepGraph_NodeId ChildIdOf(const BRepGraph&, const BRepGraphInc::ChildRef& theRef) - { - return theRef.ChildDefId; + return theRef.ChildSolidId; } }; struct ChildOfCompoundTraits : public BaseTraits { + using ChildId = BRepGraph_NodeId; + static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) { - return theParent.IsValid(theGraph.Topo().Compounds().Nb()) - && !theGraph.Topo().Compounds().Definition(theParent).IsRemoved; + return theParent.IsValid(theGraph.Topo().Compounds().Nb()) && !theParent.IsRemoved(theGraph); } - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Compounds().Definition(theParent).ChildRefIds; + return theGraph.Topo().Compounds().Relations(theParent).ChildRefIds; } static const BRepGraphInc::ChildRef& Ref(const BRepGraph& theGraph, const RefId theRefId) @@ -450,23 +353,24 @@ struct ChildOfCompoundTraits static BRepGraph_NodeId ChildIdOf(const BRepGraph&, const BRepGraphInc::ChildRef& theRef) { - return theRef.ChildDefId; + return theRef.ChildNodeId; } }; struct OccurrenceOfProductTraits : public BaseTraits { + using ChildId = BRepGraph_OccurrenceId; + static bool IsParentValid(const BRepGraph& theGraph, const ParentId theParent) { - return theParent.IsValid(theGraph.Topo().Products().Nb()) - && !theGraph.Topo().Products().Definition(theParent).IsRemoved; + return theParent.IsValid(theGraph.Topo().Products().Nb()) && !theParent.IsRemoved(theGraph); } - static const NCollection_DynamicArray& RefIds(const BRepGraph& theGraph, + static const NCollection_LinearVector& RefIds(const BRepGraph& theGraph, const ParentId theParent) { - return theGraph.Topo().Products().Definition(theParent).OccurrenceRefIds; + return theGraph.Topo().Products().Relations(theParent).OccurrenceRefIds; } static const BRepGraphInc::OccurrenceRef& Ref(const BRepGraph& theGraph, const RefId theRefId) @@ -477,7 +381,7 @@ struct OccurrenceOfProductTraits static BRepGraph_OccurrenceId ChildIdOf(const BRepGraph&, const BRepGraphInc::OccurrenceRef& theRef) { - return theRef.OccurrenceDefId; + return theRef.ChildOccurrenceId; } }; @@ -487,6 +391,7 @@ class RefsOfParent public: using ParentId = typename TraitsT::ParentId; using RefId = typename TraitsT::RefId; + using ChildId = typename TraitsT::ChildId; RefsOfParent(const BRepGraph& theGraph, const ParentId theParent) : myGraph(theGraph) @@ -498,6 +403,26 @@ public: myRefIds = &TraitsT::RefIds(theGraph, theParent); myLength = static_cast(myRefIds->Size()); + if constexpr (std::is_convertible_v) + { + myNbRefs = theGraph.Topo().Gen().Nb(BRepGraph_NodeId(RefId()).NodeKind); + } + else + { + myNbRefs = theGraph.Refs().Gen().Nb(BRepGraph_RefId(RefId()).RefKind); + } + + if constexpr (TraitsT::THE_IS_DIRECT) + { + myNbChildren = myNbRefs; + } + else + { + if constexpr (!std::is_same_v) + { + myNbChildren = theGraph.Topo().Gen().Nb(BRepGraph_NodeId(ChildId()).NodeKind); + } + } skipRemoved(); } @@ -506,10 +431,40 @@ public: void Next() { ++myIndex; + // Fast-path: check if the very next element is already valid. + if (myRefIds != nullptr && myIndex < myLength) + { + const RefId aRefId = myRefIds->Value(static_cast(myIndex)); + if (aRefId.IsValid(myNbRefs) && !aRefId.IsRemoved(myGraph)) + { + if constexpr (TraitsT::THE_IS_DIRECT) + { + return; + } + else + { + const typename TraitsT::RefEntry& aRef = TraitsT::Ref(myGraph, aRefId); + const auto aChildId = TraitsT::ChildIdOf(myGraph, aRef); + if constexpr (std::is_same_v) + { + if (myGraph.Topo().Gen().IsActive(aChildId)) + return; + } + else if (aChildId.IsValid(myNbChildren) && !aChildId.IsRemoved(myGraph)) + { + return; + } + } + } + } skipRemoved(); } - [[nodiscard]] RefId CurrentId() const { return myRefIds->Value(static_cast(myIndex)); } + [[nodiscard]] RefId CurrentId() const + { + Standard_ASSERT_VOID(More(), "RefsOfParent::CurrentId() called on exhausted iterator"); + return myRefIds->Value(static_cast(myIndex)); + } [[nodiscard]] uint32_t Index() const { return myIndex; } @@ -527,13 +482,28 @@ private: { while (myRefIds != nullptr && myIndex < myLength) { - const typename TraitsT::RefEntry& aRef = - TraitsT::Ref(myGraph, myRefIds->Value(static_cast(myIndex))); - if (!aRef.IsRemoved) + const RefId aRefId = myRefIds->Value(static_cast(myIndex)); + if (aRefId.IsValid(myNbRefs) && !aRefId.IsRemoved(myGraph)) { - const BRepGraphInc::BaseDef* aChildDef = - childBaseDef(myGraph, TraitsT::ChildIdOf(myGraph, aRef)); - if (aChildDef != nullptr && !aChildDef->IsRemoved) + const auto aChildId = [&]() { + if constexpr (TraitsT::THE_IS_DIRECT) + { + return aRefId; + } + else + { + const typename TraitsT::RefEntry& aRef = TraitsT::Ref(myGraph, aRefId); + return TraitsT::ChildIdOf(myGraph, aRef); + } + }(); + if constexpr (std::is_same_v) + { + if (myGraph.Topo().Gen().IsActive(aChildId)) + { + return; + } + } + else if (aChildId.IsValid(myNbChildren) && !aChildId.IsRemoved(myGraph)) { return; } @@ -543,14 +513,16 @@ private: } const BRepGraph& myGraph; - const NCollection_DynamicArray* myRefIds = nullptr; - uint32_t myIndex = 0; - uint32_t myLength = 0; + const NCollection_LinearVector* myRefIds = nullptr; + uint32_t myIndex = 0; + uint32_t myLength = 0; + uint32_t myNbRefs = 0; + uint32_t myNbChildren = 0; }; -//! @brief Direct active vertex reference ids of an edge. +//! @brief Direct active boundary vertex reference ids of an edge. //! -//! Iteration order is start vertex, end vertex, then internal/external vertices. +//! Iteration order is start vertex, then end vertex. class RefsVertexOfEdge { public: @@ -559,14 +531,15 @@ public: RefsVertexOfEdge(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdgeId) : myGraph(theGraph) { - if (!theEdgeId.IsValid(theGraph.Topo().Edges().Nb()) - || theGraph.Topo().Edges().Definition(theEdgeId).IsRemoved) + if (!theEdgeId.IsValid(theGraph.Topo().Edges().Nb()) || theEdgeId.IsRemoved(theGraph)) { return; } - myEdge = &theGraph.Topo().Edges().Definition(theEdgeId); - myLength = 2u + static_cast(myEdge->InternalVertexRefIds.Size()); + myEdge = &theGraph.Topo().Edges().Definition(theEdgeId); + myLength = 2u; + myNbVertexRefs = theGraph.Refs().Vertices().Nb(); + myNbVertices = theGraph.Topo().Vertices().Nb(); skipRemoved(); } @@ -598,11 +571,7 @@ private: { return myEdge->StartVertexRefId; } - if (theIndex == 1) - { - return myEdge->EndVertexRefId; - } - return myEdge->InternalVertexRefIds.Value(static_cast(theIndex - 2)); + return myEdge->EndVertexRefId; } void skipRemoved() @@ -610,27 +579,26 @@ private: while (myEdge != nullptr && myIndex < myLength) { const RefId aRefId = refIdAt(myIndex); - if (aRefId.IsValid()) + if (aRefId.IsValid(myNbVertexRefs) && !myGraph.Refs().Gen().IsRemoved(aRefId)) { const BRepGraphInc::VertexRef& aRef = myGraph.Refs().Vertices().Entry(aRefId); - if (!aRef.IsRemoved) + if (!aRef.ChildVertexId.IsValid(myNbVertices) || aRef.ChildVertexId.IsRemoved(myGraph)) { - const BRepGraphInc::BaseDef* aChildDef = - myGraph.Topo().Gen().TopoEntity(BRepGraph_NodeId(aRef.VertexDefId)); - if (aChildDef != nullptr && !aChildDef->IsRemoved) - { - return; - } + ++myIndex; + continue; } + return; } ++myIndex; } } const BRepGraph& myGraph; - const BRepGraphInc::EdgeDef* myEdge = nullptr; - uint32_t myIndex = 0; - uint32_t myLength = 0; + const BRepGraphInc::EdgeDef* myEdge = nullptr; + uint32_t myIndex = 0; + uint32_t myLength = 0; + uint32_t myNbVertexRefs = 0; + uint32_t myNbVertices = 0; }; } // namespace BRepGraph_RefsIterator @@ -639,16 +607,10 @@ using BRepGraph_RefsShellOfSolid = BRepGraph_RefsIterator::RefsOfParent; using BRepGraph_RefsFaceOfShell = BRepGraph_RefsIterator::RefsOfParent; -using BRepGraph_RefsChildOfShell = - BRepGraph_RefsIterator::RefsOfParent; using BRepGraph_RefsWireOfFace = BRepGraph_RefsIterator::RefsOfParent; -using BRepGraph_RefsVertexOfFace = - BRepGraph_RefsIterator::RefsOfParent; -using BRepGraph_RefsCoEdgeOfWire = +using BRepGraph_CoEdgesOfWire = BRepGraph_RefsIterator::RefsOfParent; -using BRepGraph_RefsChildOfSolid = - BRepGraph_RefsIterator::RefsOfParent; using BRepGraph_RefsSolidOfCompSolid = BRepGraph_RefsIterator::RefsOfParent; using BRepGraph_RefsChildOfCompound = @@ -660,7 +622,6 @@ using BRepGraph_RefsVertexOfEdge = BRepGraph_RefsIterator::RefsVertexOfEdge; using BRepGraph_ShellRefIterator = BRepGraph_RefsIterator::RefIterator; using BRepGraph_FaceRefIterator = BRepGraph_RefsIterator::RefIterator; using BRepGraph_WireRefIterator = BRepGraph_RefsIterator::RefIterator; -using BRepGraph_CoEdgeRefIterator = BRepGraph_RefsIterator::RefIterator; using BRepGraph_VertexRefIterator = BRepGraph_RefsIterator::RefIterator; using BRepGraph_SolidRefIterator = BRepGraph_RefsIterator::RefIterator; using BRepGraph_ChildRefIterator = BRepGraph_RefsIterator::RefIterator; @@ -673,8 +634,6 @@ using BRepGraph_FullFaceRefIterator = BRepGraph_RefsIterator::RefIterator; using BRepGraph_FullWireRefIterator = BRepGraph_RefsIterator::RefIterator; -using BRepGraph_FullCoEdgeRefIterator = - BRepGraph_RefsIterator::RefIterator; using BRepGraph_FullVertexRefIterator = BRepGraph_RefsIterator::RefIterator; using BRepGraph_FullSolidRefIterator = @@ -684,4 +643,4 @@ using BRepGraph_FullChildRefIterator = using BRepGraph_FullOccurrenceRefIterator = BRepGraph_RefsIterator::RefIterator; -#endif // _BRepGraph_RefsIterator_HeaderFile \ No newline at end of file +#endif // _BRepGraph_RefsIterator_HeaderFile diff --git a/opencascade/BRepGraph_RefsView.hxx b/opencascade/BRepGraph_RefsView.hxx index dc9d323e3..83b72526c 100644 --- a/opencascade/BRepGraph_RefsView.hxx +++ b/opencascade/BRepGraph_RefsView.hxx @@ -17,6 +17,7 @@ #include #include #include +#include //! @brief Read-only view for RefId/RefUID-based reference storage. //! @@ -24,13 +25,14 @@ //! - typed reference entry access (Shell, Face, ...) //! - reference counts //! - RefUID lookup and reverse lookup through BRepGraph::UIDs() -//! - stale tracking via BRepGraph_VersionStamp through BRepGraph::UIDs() +//! - freshness checks via BRepGraph_VersionStamp through BRepGraph::UIDs() //! //! Identity semantics: //! - RefId (kind + index) is graph-local and may change after Compact(). //! Use it for in-graph traversal and short-lived mutation logic. -//! - RefUID (kind + counter + generation) is stable across index remapping -//! and intended for longer-lived identity tracking. +//! - RefUID (kind + counter) is stable across index remapping and intended +//! for longer-lived identity tracking. Graph generation is carried by +//! BRepGraph_VersionStamp when freshness checks are needed. //! //! ## RefsView vs TopoView naming //! RefsView accessors take reference IDs (BRepGraph_ShellRefId, BRepGraph_FaceRefId) @@ -52,7 +54,7 @@ //! const BRepGraphInc::FaceRef& aFR = aRefs.Faces().Entry(aFaceRefId); //! if (aFR.IsRemoved) //! continue; -//! // use aFR.FaceDefId, aFR.Orientation, aFR.Location ... +//! // use aFR.FaceId, aFR.Orientation, aFR.Location ... //! } //! @endcode //! @@ -72,8 +74,8 @@ public: class ShellOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; [[nodiscard]] BRepGraph_ShellRefId StartId() const { return BRepGraph_ShellRefId::Start(); } @@ -81,26 +83,26 @@ public: [[nodiscard]] Standard_EXPORT const BRepGraphInc::ShellRef& Entry( const BRepGraph_ShellRefId theRefId) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& IdsOf( + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& IdsOf( const BRepGraph_SolidId theSolid) const; private: friend class RefsView; - explicit ShellOps(const BRepGraph* theGraph) + explicit ShellOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Face reference queries. class FaceOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; [[nodiscard]] BRepGraph_FaceRefId StartId() const { return BRepGraph_FaceRefId::Start(); } @@ -108,26 +110,26 @@ public: [[nodiscard]] Standard_EXPORT const BRepGraphInc::FaceRef& Entry( const BRepGraph_FaceRefId theRefId) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& IdsOf( + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& IdsOf( const BRepGraph_ShellId theShell) const; private: friend class RefsView; - explicit FaceOps(const BRepGraph* theGraph) + explicit FaceOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Wire reference queries. class WireOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; [[nodiscard]] BRepGraph_WireRefId StartId() const { return BRepGraph_WireRefId::Start(); } @@ -135,53 +137,26 @@ public: [[nodiscard]] Standard_EXPORT const BRepGraphInc::WireRef& Entry( const BRepGraph_WireRefId theRefId) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& IdsOf( + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& IdsOf( const BRepGraph_FaceId theFace) const; private: friend class RefsView; - explicit WireOps(const BRepGraph* theGraph) + explicit WireOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; - }; - - //! @brief Coedge reference queries. - class CoEdgeOps - { - public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; - - [[nodiscard]] BRepGraph_CoEdgeRefId StartId() const { return BRepGraph_CoEdgeRefId::Start(); } - - [[nodiscard]] BRepGraph_CoEdgeRefId EndId() const { return BRepGraph_CoEdgeRefId(Nb()); } - - [[nodiscard]] Standard_EXPORT const BRepGraphInc::CoEdgeRef& Entry( - const BRepGraph_CoEdgeRefId theRefId) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& IdsOf( - const BRepGraph_WireId theWire) const; - - private: - friend class RefsView; - - explicit CoEdgeOps(const BRepGraph* theGraph) - : myGraph(theGraph) - { - } - - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Vertex reference queries. class VertexOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; [[nodiscard]] BRepGraph_VertexRefId StartId() const { return BRepGraph_VertexRefId::Start(); } @@ -193,20 +168,20 @@ public: private: friend class RefsView; - explicit VertexOps(const BRepGraph* theGraph) + explicit VertexOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Solid reference queries. class SolidOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; [[nodiscard]] BRepGraph_SolidRefId StartId() const { return BRepGraph_SolidRefId::Start(); } @@ -214,26 +189,26 @@ public: [[nodiscard]] Standard_EXPORT const BRepGraphInc::SolidRef& Entry( const BRepGraph_SolidRefId theRefId) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& IdsOf( + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& IdsOf( const BRepGraph_CompSolidId theCompSolid) const; private: friend class RefsView; - explicit SolidOps(const BRepGraph* theGraph) + explicit SolidOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Generic child reference queries. class ChildOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; [[nodiscard]] BRepGraph_ChildRefId StartId() const { return BRepGraph_ChildRefId::Start(); } @@ -241,26 +216,28 @@ public: [[nodiscard]] Standard_EXPORT const BRepGraphInc::ChildRef& Entry( const BRepGraph_ChildRefId theRefId) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& IdsOf( + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& IdsOf( const BRepGraph_CompoundId theCompound) const; + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& + IdsReferencing(const BRepGraph_NodeId theChild) const; private: friend class RefsView; - explicit ChildOps(const BRepGraph* theGraph) + explicit ChildOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Occurrence reference queries. class OccurrenceOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; [[nodiscard]] BRepGraph_OccurrenceRefId StartId() const { @@ -274,18 +251,65 @@ public: [[nodiscard]] Standard_EXPORT const BRepGraphInc::OccurrenceRef& Entry( const BRepGraph_OccurrenceRefId theRefId) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& IdsOf( + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& IdsOf( const BRepGraph_ProductId theProduct) const; + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& + IdsReferencing(const BRepGraph_NodeId theChild) const; private: friend class RefsView; - explicit OccurrenceOps(const BRepGraph* theGraph) + explicit OccurrenceOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; + }; + + //! @brief Generic reference id queries. + class GenOps + { + public: + //! Return the number of references of the specified kind (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb(const BRepGraph_RefId::Kind theKind) const; + + //! Return true if the reference id kind and index are within storage bounds. + [[nodiscard]] Standard_EXPORT bool IsValid(const BRepGraph_RefId theRef) const; + + //! Return true if the reference id is valid and not soft-removed. + [[nodiscard]] Standard_EXPORT bool IsActive(const BRepGraph_RefId theRef) const; + + //! Return true if the specified typed RefId is invalid or marked removed. + [[nodiscard]] Standard_EXPORT bool IsRemoved(const BRepGraph_RefId theRef) const; + + //! Return the direct parent-owned RefId stored at the specified child step. + //! This is a structural lookup over the parent's raw ref arrays and does not + //! skip removed refs or refs targeting removed child defs. + [[nodiscard]] Standard_EXPORT BRepGraph_RefId RefAtStep(const BRepGraph_NodeId theParent, + const int theStep) const; + + //! Resolve the child definition node referenced by any typed RefId. + [[nodiscard]] Standard_EXPORT BRepGraph_NodeId ChildNode(const BRepGraph_RefId theRef) const; + + //! Return the local location carried by the specified typed RefId. + //! OccurrenceRef and invalid refs return identity. + [[nodiscard]] Standard_EXPORT TopLoc_Location LocalLocation(const BRepGraph_RefId theRef) const; + + //! Return the orientation carried by the specified typed RefId. + //! OccurrenceRef and invalid refs return TopAbs_FORWARD. + [[nodiscard]] Standard_EXPORT TopAbs_Orientation + Orientation(const BRepGraph_RefId theRef) const; + + private: + friend class RefsView; + + explicit GenOps(BRepGraph* theGraph) + : myGraph(theGraph) + { + } + + BRepGraph* myGraph; }; //! Grouped shell reference queries. @@ -297,9 +321,6 @@ public: //! Grouped wire reference queries. [[nodiscard]] const WireOps& Wires() const { return myWires; } - //! Grouped coedge reference queries. - [[nodiscard]] const CoEdgeOps& CoEdges() const { return myCoEdges; } - //! Grouped vertex reference queries. [[nodiscard]] const VertexOps& Vertices() const { return myVertices; } @@ -312,52 +333,35 @@ public: //! Grouped occurrence reference queries. [[nodiscard]] const OccurrenceOps& Occurrences() const { return myOccurrences; } - //! Return the direct parent-owned RefId stored at the specified child step. - //! This is a structural lookup over the parent's raw ref arrays and does not - //! skip removed refs or refs targeting removed child defs. - [[nodiscard]] Standard_EXPORT BRepGraph_RefId RefAtStep(const BRepGraph_NodeId theParent, - const int theStep) const; - - //! Resolve the child definition node referenced by any typed RefId. - [[nodiscard]] Standard_EXPORT BRepGraph_NodeId ChildNode(const BRepGraph_RefId theRef) const; - - //! Return true if the specified typed RefId is marked removed. - [[nodiscard]] Standard_EXPORT bool IsRemoved(const BRepGraph_RefId theRef) const; - - //! Return the local location carried by the specified typed RefId. - //! OccurrenceRef and invalid refs return identity. - [[nodiscard]] Standard_EXPORT TopLoc_Location LocalLocation(const BRepGraph_RefId theRef) const; - - //! Return the orientation carried by the specified typed RefId. - //! CoEdgeRef, OccurrenceRef, and invalid refs return TopAbs_FORWARD. - [[nodiscard]] Standard_EXPORT TopAbs_Orientation Orientation(const BRepGraph_RefId theRef) const; + //! Grouped generic reference id queries. + [[nodiscard]] const GenOps& Gen() const { return myGen; } private: friend class BRepGraph; friend struct BRepGraph_Data; - explicit RefsView(const BRepGraph* theGraph) + explicit RefsView(BRepGraph* theGraph) : myGraph(theGraph), myShells(theGraph), myFaces(theGraph), myWires(theGraph), - myCoEdges(theGraph), myVertices(theGraph), mySolids(theGraph), myChildren(theGraph), - myOccurrences(theGraph) + myOccurrences(theGraph), + myGen(theGraph) { } - const BRepGraph* myGraph; - ShellOps myShells; - FaceOps myFaces; - WireOps myWires; - CoEdgeOps myCoEdges; - VertexOps myVertices; - SolidOps mySolids; - ChildOps myChildren; - OccurrenceOps myOccurrences; + BRepGraph* myGraph; + ShellOps myShells; + FaceOps myFaces; + WireOps myWires; + VertexOps myVertices; + SolidOps mySolids; + ChildOps myChildren; + OccurrenceOps myOccurrences; + GenOps myGen; }; #endif // _BRepGraph_RefsView_HeaderFile diff --git a/opencascade/BRepGraph_RelatedIterator.hxx b/opencascade/BRepGraph_RelatedIterator.hxx index d3528fde2..839c46ee8 100644 --- a/opencascade/BRepGraph_RelatedIterator.hxx +++ b/opencascade/BRepGraph_RelatedIterator.hxx @@ -22,6 +22,7 @@ #include #include #include +#include //! @brief Single-level iterator over semantically related topology nodes. //! @see BRepGraph class comment "Iterator guide" for choosing between iterator types. @@ -50,14 +51,18 @@ public: SeamPair, //!< CoEdge -> CoEdge (seam twin) }; + //! Internal traversal stage tracking which sub-iteration is active. enum class Stage { - First, - Second, - Third, - Finished, + First, //!< Primary relation iteration. + Second, //!< Secondary relation iteration. + Third, //!< Tertiary relation iteration. + Finished, //!< All relations exhausted. }; + //! Construct an iterator over all semantically related nodes of the given source node. + //! @param[in] theGraph graph containing the node + //! @param[in] theNode source node whose relations are iterated BRepGraph_RelatedIterator(const BRepGraph& theGraph, const BRepGraph_NodeId theNode) : myGraph(&theGraph), myNode(theNode) @@ -65,8 +70,10 @@ public: advance(); } + //! True if another related node is available. [[nodiscard]] bool More() const { return myHasCurrent; } + //! Advance to the next related node. void Next() { if (!myHasCurrent) @@ -76,8 +83,10 @@ public: advance(); } + //! Return the current related node id. [[nodiscard]] const BRepGraph_NodeId& Current() const { return myCurrent; } + //! Return the relation kind explaining why the current node is related. [[nodiscard]] RelationKind CurrentRelation() const { return myRelation; } //! Returns an STL-compatible iterator for range-based for loops. @@ -90,18 +99,7 @@ public: NCollection_ForwardRangeSentinel end() const { return NCollection_ForwardRangeSentinel{}; } private: - [[nodiscard]] bool setCurrent(const BRepGraph_NodeId theNode, const RelationKind theRelation) - { - if (!theNode.IsValid() || myGraph->Topo().Gen().IsRemoved(theNode)) - { - return false; - } - - myCurrent = theNode; - myRelation = theRelation; - myHasCurrent = true; - return true; - } + [[nodiscard]] bool setCurrent(const BRepGraph_NodeId theNode, const RelationKind theRelation); template [[nodiscard]] bool advanceRefChildren(IteratorT theIterator, const RelationKind theRelation) @@ -113,8 +111,16 @@ private: continue; } - myIndex = theIterator.Index() + 1; - const BRepGraph_NodeId aChildNode = myGraph->Refs().ChildNode(theIterator.CurrentId()); + myIndex = theIterator.Index() + 1; + BRepGraph_NodeId aChildNode; + if constexpr (std::is_convertible_v) + { + aChildNode = myGraph->Refs().Gen().ChildNode(theIterator.CurrentId()); + } + else + { + aChildNode = BRepGraph_NodeId(theIterator.CurrentId()); + } return setCurrent(aChildNode, theRelation); } @@ -138,79 +144,9 @@ private: return false; } - [[nodiscard]] bool advanceFaceBoundaryEdge() - { - const BRepGraph_FaceId aFaceId = BRepGraph_FaceId::FromNodeId(myNode); - for (BRepGraph_DefsWireOfFace aWireIt(*myGraph, aFaceId); aWireIt.More(); aWireIt.Next()) - { - if (aWireIt.Index() < myIndex) - { - continue; - } - - for (BRepGraph_DefsEdgeOfWire anEdgeIt(*myGraph, aWireIt.CurrentId()); anEdgeIt.More(); - anEdgeIt.Next()) - { - if (aWireIt.Index() == myIndex && anEdgeIt.Index() < myInnerIndex) - { - continue; - } - - myIndex = aWireIt.Index(); - myInnerIndex = anEdgeIt.Index() + 1; - return setCurrent(BRepGraph_NodeId(anEdgeIt.CurrentId()), RelationKind::BoundaryEdge); - } - - myIndex = aWireIt.Index() + 1; - myInnerIndex = 0; - } - - return false; - } - - [[nodiscard]] bool advanceAdjacentFace() - { - const BRepGraph_FaceId aFaceId = BRepGraph_FaceId::FromNodeId(myNode); - for (BRepGraph_DefsWireOfFace aWireIt(*myGraph, aFaceId); aWireIt.More(); aWireIt.Next()) - { - if (aWireIt.Index() < myIndex) - { - continue; - } - - for (BRepGraph_DefsCoEdgeOfWire aCoEdgeIt(*myGraph, aWireIt.CurrentId()); aCoEdgeIt.More(); - aCoEdgeIt.Next()) - { - if (aWireIt.Index() == myIndex && aCoEdgeIt.Index() < myInnerIndex) - { - continue; - } + [[nodiscard]] bool advanceFaceBoundaryEdge(); - const NCollection_DynamicArray& aFaces = - myGraph->Topo().Edges().Faces(aCoEdgeIt.Current().EdgeDefId); - for (; myDeepIndex < static_cast(aFaces.Size()); ++myDeepIndex) - { - const BRepGraph_FaceId anAdjacentFaceId = aFaces.Value(static_cast(myDeepIndex)); - if (anAdjacentFaceId == aFaceId) - { - continue; - } - - myIndex = aWireIt.Index(); - myInnerIndex = aCoEdgeIt.Index(); - ++myDeepIndex; - return setCurrent(BRepGraph_NodeId(anAdjacentFaceId), RelationKind::AdjacentFace); - } - - myDeepIndex = 0; - } - - myIndex = aWireIt.Index() + 1; - myInnerIndex = 0; - } - - return false; - } + [[nodiscard]] bool advanceAdjacentFace(); [[nodiscard]] bool advanceEdgeVertex() { @@ -219,13 +155,16 @@ private: RelationKind::IncidentVertex); } - //! Advance through a reverse-index iterator (e.g. BRepGraph_FacesOfEdge). + //! Advance through a relation iterator (e.g. BRepGraph_FacesOfEdge). //! Constructs a ParentsOf starting at myIndex for O(1) amortized resumption. template - [[nodiscard]] bool advanceParents(const NCollection_DynamicArray& theParents, + [[nodiscard]] bool advanceParents(const NCollection_LinearVector& theParents, const RelationKind theRelation) { - BRepGraph_ReverseIterator::ParentsOf anIt(*myGraph, theParents, myIndex); + BRepGraph_ReverseIterator::ParentsOf> anIt( + *myGraph, + theParents, + myIndex); if (anIt.More()) { myIndex = anIt.Index() + 1; @@ -235,137 +174,19 @@ private: return false; } - void advance() + template + [[nodiscard]] bool advanceParentIterator(IteratorT theIterator, const RelationKind theRelation) { - myHasCurrent = false; - if (!myNode.IsValid() || myGraph->Topo().Gen().IsRemoved(myNode)) - { - return; - } - - for (;;) + if (theIterator.More()) { - switch (myNode.NodeKind) - { - // Container/assembly nodes have no topological relations. - // Use BRepGraph_ChildExplorer / BRepGraph_ParentExplorer for navigation. - case BRepGraph_NodeId::Kind::Solid: - case BRepGraph_NodeId::Kind::Shell: - case BRepGraph_NodeId::Kind::Compound: - case BRepGraph_NodeId::Kind::CompSolid: - case BRepGraph_NodeId::Kind::Product: - case BRepGraph_NodeId::Kind::Occurrence: - return; - case BRepGraph_NodeId::Kind::Face: { - if (myStage == Stage::First) - { - if (advanceFaceBoundaryEdge()) - { - return; - } - myStage = Stage::Second; - myIndex = 0; - myInnerIndex = 0; - myDeepIndex = 0; - } - if (myStage == Stage::Second) - { - if (advanceAdjacentFace()) - { - return; - } - myStage = Stage::Third; - myIndex = 0; - } - if (myStage == Stage::Third) - { - myStage = Stage::Finished; - return (void)setCurrent(BRepGraph_NodeId(myGraph->Topo().Faces().OuterWire( - BRepGraph_FaceId::FromNodeId(myNode))), - RelationKind::OuterWire); - } - return; - } - case BRepGraph_NodeId::Kind::Edge: { - if (myStage == Stage::First) - { - if (advanceParents(myGraph->Topo().Edges().Faces(BRepGraph_EdgeId::FromNodeId(myNode)), - RelationKind::ReferencedByFace)) - { - return; - } - myStage = Stage::Second; - myIndex = 0; - } - if (advanceEdgeVertex()) - { - return; - } - return; - } - case BRepGraph_NodeId::Kind::Wire: { - if (myStage == Stage::First) - { - if (advanceRefChildren( - BRepGraph_RefsCoEdgeOfWire(*myGraph, BRepGraph_WireId::FromNodeId(myNode)), - RelationKind::WireCoEdge)) - { - return; - } - myStage = Stage::Second; - myIndex = 0; - } - if (advanceParents(myGraph->Topo().Wires().Faces(BRepGraph_WireId::FromNodeId(myNode)), - RelationKind::OwningFace)) - { - return; - } - return; - } - case BRepGraph_NodeId::Kind::Vertex: { - if (advanceParents( - myGraph->Topo().Vertices().Edges(BRepGraph_VertexId::FromNodeId(myNode)), - RelationKind::IncidentEdge)) - { - return; - } - return; - } - case BRepGraph_NodeId::Kind::CoEdge: { - const BRepGraph_CoEdgeId aCoEdgeId = BRepGraph_CoEdgeId::FromNodeId(myNode); - if (myStage == Stage::First) - { - myStage = Stage::Second; - if (setCurrent(BRepGraph_NodeId(BRepGraph_Tool::CoEdge::EdgeOf(*myGraph, aCoEdgeId)), - RelationKind::ParentEdge)) - { - return; - } - } - if (myStage == Stage::Second) - { - myStage = Stage::Third; - if (setCurrent(BRepGraph_NodeId(BRepGraph_Tool::CoEdge::FaceOf(*myGraph, aCoEdgeId)), - RelationKind::OwningFace)) - { - return; - } - } - if (myStage == Stage::Third) - { - myStage = Stage::Finished; - if (setCurrent(BRepGraph_NodeId(BRepGraph_Tool::CoEdge::SeamPair(*myGraph, aCoEdgeId)), - RelationKind::SeamPair)) - { - return; - } - } - return; - } - } + myIndex = theIterator.Index() + 1; + return setCurrent(BRepGraph_NodeId(theIterator.CurrentId()), theRelation); } + return false; } + Standard_EXPORT void advance(); + private: const BRepGraph* myGraph; BRepGraph_NodeId myNode; @@ -378,4 +199,4 @@ private: bool myHasCurrent = false; }; -#endif // _BRepGraph_RelatedIterator_HeaderFile \ No newline at end of file +#endif // _BRepGraph_RelatedIterator_HeaderFile diff --git a/opencascade/BRepGraph_RepId.hxx b/opencascade/BRepGraph_RepId.hxx deleted file mode 100644 index 6a3570a61..000000000 --- a/opencascade/BRepGraph_RepId.hxx +++ /dev/null @@ -1,369 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraph_RepId_HeaderFile -#define _BRepGraph_RepId_HeaderFile - -#include -#include - -#include -#include -#include -#include -#include - -//! Lightweight typed index into a per-kind representation vector inside BRepGraph. -//! -//! The pair (Kind, Index) forms a unique representation identifier within one -//! graph instance. Default-constructed RepId has Index = UINT32_MAX (invalid). -//! -//! Representations are NOT topology nodes - they hold geometry or mesh data -//! referenced by topology entities. They do not participate in BFS traversal, -//! reverse index, or parent-child relationships. -//! -//! RepId is a value type: cheap to copy, compare, hash. -struct BRepGraph_RepId -{ - //! Categories of representation data. - enum class Kind : int - { - // Geometry (exact mathematical definition) - Surface = 0, //!< Geom_Surface for faces - Curve3D = 1, //!< Geom_Curve for edges - Curve2D = 2, //!< Geom2d_Curve for coedges (PCurve geometry) - - // Mesh (discrete approximation) - Triangulation = 3, //!< Poly_Triangulation for faces - Polygon3D = 4, //!< Poly_Polygon3D for edges - Polygon2D = 5, //!< Poly_Polygon2D for coedges (polygon-on-surface) - PolygonOnTri = 6, //!< Poly_PolygonOnTriangulation for coedges - - // Reserved 7-19 for future built-in types - // Custom plugin types start at 100+ - }; - - //! True if the kind is a geometry kind (Surface, Curve3D, Curve2D). - static bool IsGeometryKind(const Kind theKind) - { - return theKind == Kind::Surface || theKind == Kind::Curve3D || theKind == Kind::Curve2D; - } - - //! True if the kind is a mesh kind (Triangulation, Polygon3D, Polygon2D, PolygonOnTri). - static bool IsMeshKind(const Kind theKind) - { - return theKind == Kind::Triangulation || theKind == Kind::Polygon3D - || theKind == Kind::Polygon2D || theKind == Kind::PolygonOnTri; - } - - //! @brief Compile-time typed wrapper around BRepGraph_RepId. - //! - //! Provides compile-time kind safety: a Typed - //! cannot be accidentally used where a Typed is expected. - //! Implicitly converts to BRepGraph_RepId for backward compatibility. - //! - //! @tparam TheKind the BRepGraph_RepId::Kind this typed id represents - template - struct Typed - { - static constexpr uint32_t THE_START_INDEX = 0u; - static constexpr uint32_t THE_INVALID_INDEX = std::numeric_limits::max(); - - uint32_t Index; - - //! Default: invalid (Index = UINT32_MAX). - Typed() - : Index(THE_INVALID_INDEX) - { - } - - //! Construct from index. - explicit Typed(const uint32_t theIdx) - : Index(theIdx) - { - } - - //! Construct from an untyped representation id of the same kind. - explicit Typed(const BRepGraph_RepId theId) - : Typed(FromRepId(theId)) - { - } - - template = 0> - Typed(const Typed&) = delete; - - //! First valid id in a dense per-kind sequence. - [[nodiscard]] static Typed Start() { return Typed(THE_START_INDEX); } - - //! Invalid sentinel id. - [[nodiscard]] static Typed Invalid() { return Typed(); } - - //! True if this id points to an allocated representation slot. - [[nodiscard]] bool IsValid() const { return Index != THE_INVALID_INDEX; } - - //! True if this id points to an allocated slot within [0, theMaxCount). - //! UINT32_MAX (invalid sentinel) always fails this check for any realistic count. - [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const { return Index < theMaxCount; } - - //! True if this id is within the dense range exposed by a provider with Nb(). - template - [[nodiscard]] auto IsValidIn(const CountProviderT& theProvider) const - -> decltype(theProvider.Nb(), bool()) - { - return IsValid(theProvider.Nb()); - } - - //! True if this id is within the dense range exposed by a provider with Length(). - template - [[nodiscard]] auto IsValidIn(const CountProviderT& theProvider) const - -> decltype(theProvider.Size(), bool()) - { - return IsValid(static_cast(theProvider.Size())); - } - - //! Implicit conversion to untyped RepId. - operator BRepGraph_RepId() const { return BRepGraph_RepId(TheKind, Index); } - - //! Explicit conversion from untyped RepId. - //! Asserts that the Kind matches in debug builds. - //! @param[in] theId untyped RepId to convert - static Typed FromRepId(const BRepGraph_RepId theId) - { - Standard_ASSERT_VOID(theId.RepKind == TheKind, "RepId kind mismatch"); - return Typed(theId.Index); - } - - bool operator==(const Typed& theOther) const { return Index == theOther.Index; } - - bool operator!=(const Typed& theOther) const { return Index != theOther.Index; } - - bool operator<(const Typed& theOther) const { return Index < theOther.Index; } - - bool operator<=(const Typed& theOther) const { return Index <= theOther.Index; } - - bool operator>(const Typed& theOther) const { return Index > theOther.Index; } - - bool operator>=(const Typed& theOther) const { return Index >= theOther.Index; } - - //! Pre-increment (++id). - Typed& operator++() - { - Standard_ASSERT_VOID(Index != THE_INVALID_INDEX, "pre-increment on invalid id"); - ++Index; - return *this; - } - - //! Post-increment (id++). - Typed operator++(int) - { - Standard_ASSERT_VOID(Index != THE_INVALID_INDEX, "post-increment on invalid id"); - Typed aPrev = *this; - ++Index; - return aPrev; - } - - //! Advance by offset. - [[nodiscard]] Typed operator+(const uint32_t theOffset) const - { - return Typed(Index + theOffset); - } - - //! Retreat by offset. - [[nodiscard]] Typed operator-(const uint32_t theOffset) const - { - Standard_ASSERT_VOID(Index != THE_INVALID_INDEX && Index >= theOffset, - "retreat underflows index"); - return Typed(Index - theOffset); - } - - //! Comparison with untyped RepId (checks both Kind and Index). - bool operator==(const BRepGraph_RepId& theOther) const - { - return theOther.RepKind == TheKind && theOther.Index == Index; - } - - bool operator!=(const BRepGraph_RepId& theOther) const { return !(*this == theOther); } - - //! Allow reversed comparison: RepId == Typed. - friend bool operator==(const BRepGraph_RepId& theLhs, const Typed& theRhs) - { - return theRhs == theLhs; - } - - friend bool operator!=(const BRepGraph_RepId& theLhs, const Typed& theRhs) - { - return theRhs != theLhs; - } - }; - - static constexpr uint32_t THE_START_INDEX = 0u; - static constexpr uint32_t THE_INVALID_INDEX = std::numeric_limits::max(); - - Kind RepKind; - uint32_t Index; - - //! Default: invalid RepId (Index = UINT32_MAX). - //! RepKind is set to Kind::Surface but is meaningless when !IsValid(). - BRepGraph_RepId() - : RepKind(Kind::Surface), - Index(THE_INVALID_INDEX) - { - } - - BRepGraph_RepId(const Kind theKind, const uint32_t theIdx) - : RepKind(theKind), - Index(theIdx) - { - } - - //! First valid id in a dense sequence for the specified kind. - [[nodiscard]] static BRepGraph_RepId Start(const Kind theKind) - { - return BRepGraph_RepId(theKind, THE_START_INDEX); - } - - //! Invalid sentinel id for the specified kind. - [[nodiscard]] static BRepGraph_RepId Invalid(const Kind theKind = Kind::Surface) - { - return BRepGraph_RepId(theKind, THE_INVALID_INDEX); - } - - //! True if this id points to an allocated representation slot. - [[nodiscard]] bool IsValid() const { return Index != THE_INVALID_INDEX; } - - //! True if this id points to an allocated slot within [0, theMaxCount). - //! UINT32_MAX (invalid sentinel) always fails this check for any realistic count. - [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const { return Index < theMaxCount; } - - //! True if this id is within the dense range exposed by a provider with Nb(). - template - [[nodiscard]] auto IsValidIn(const CountProviderT& theProvider) const - -> decltype(theProvider.Nb(), bool()) - { - return IsValid(theProvider.Nb()); - } - - //! True if this id is within the dense range exposed by a provider with Size(). - template - [[nodiscard]] auto IsValidIn(const CountProviderT& theProvider) const - -> decltype(theProvider.Size(), bool()) - { - return IsValid(static_cast(theProvider.Size())); - } - - bool operator==(const BRepGraph_RepId& theOther) const - { - return RepKind == theOther.RepKind && Index == theOther.Index; - } - - bool operator!=(const BRepGraph_RepId& theOther) const { return !(*this == theOther); } - - bool operator<(const BRepGraph_RepId& theOther) const - { - if (RepKind != theOther.RepKind) - return static_cast(RepKind) < static_cast(theOther.RepKind); - return Index < theOther.Index; - } - - //! Pre-increment (++id). - BRepGraph_RepId& operator++() - { - Standard_ASSERT_VOID(Index != THE_INVALID_INDEX, "pre-increment on invalid id"); - ++Index; - return *this; - } - - //! Post-increment (id++). - BRepGraph_RepId operator++(int) - { - Standard_ASSERT_VOID(Index != THE_INVALID_INDEX, "post-increment on invalid id"); - BRepGraph_RepId aPrev = *this; - ++Index; - return aPrev; - } - - //! Advance by offset. - [[nodiscard]] BRepGraph_RepId operator+(const uint32_t theOffset) const - { - return BRepGraph_RepId(RepKind, Index + theOffset); - } - - //! Retreat by offset. - [[nodiscard]] BRepGraph_RepId operator-(const uint32_t theOffset) const - { - Standard_ASSERT_VOID(Index != THE_INVALID_INDEX && Index >= theOffset, - "retreat underflows index"); - return BRepGraph_RepId(RepKind, Index - theOffset); - } - - //! Dispatch a generic rep id to a callable taking the matching typed rep id. - template - static auto Visit(const BRepGraph_RepId theRepId, FuncT&& theFunc) - -> decltype(std::forward(theFunc)(Typed())) - { - switch (theRepId.RepKind) - { - case Kind::Surface: - return std::forward(theFunc)(Typed::FromRepId(theRepId)); - case Kind::Curve3D: - return std::forward(theFunc)(Typed::FromRepId(theRepId)); - case Kind::Curve2D: - return std::forward(theFunc)(Typed::FromRepId(theRepId)); - case Kind::Triangulation: - return std::forward(theFunc)(Typed::FromRepId(theRepId)); - case Kind::Polygon3D: - return std::forward(theFunc)(Typed::FromRepId(theRepId)); - case Kind::Polygon2D: - return std::forward(theFunc)(Typed::FromRepId(theRepId)); - case Kind::PolygonOnTri: - return std::forward(theFunc)(Typed::FromRepId(theRepId)); - } - - Standard_ASSERT_VOID(false, "BRepGraph_RepId::Visit: unhandled Kind"); - return std::forward(theFunc)(Typed()); - } -}; - -// Convenience type aliases for typed RepIds. -using BRepGraph_SurfaceRepId = BRepGraph_RepId::Typed; -using BRepGraph_Curve3DRepId = BRepGraph_RepId::Typed; -using BRepGraph_Curve2DRepId = BRepGraph_RepId::Typed; -using BRepGraph_TriangulationRepId = BRepGraph_RepId::Typed; -using BRepGraph_Polygon3DRepId = BRepGraph_RepId::Typed; -using BRepGraph_Polygon2DRepId = BRepGraph_RepId::Typed; -using BRepGraph_PolygonOnTriRepId = BRepGraph_RepId::Typed; - -//! std::hash specialization for NCollection_DefaultHasher support. -template <> -struct std::hash -{ - size_t operator()(const BRepGraph_RepId& theId) const noexcept - { - size_t aCombination[2]; - aCombination[0] = opencascade::hash(static_cast(theId.RepKind)); - aCombination[1] = opencascade::hash(theId.Index); - return opencascade::hashBytes(aCombination, sizeof(aCombination)); - } -}; - -//! std::hash specialization for BRepGraph_RepId::Typed. -template -struct std::hash> -{ - size_t operator()(const BRepGraph_RepId::Typed& theId) const noexcept - { - return std::hash{}(static_cast(theId)); - } -}; - -#endif // _BRepGraph_RepId_HeaderFile diff --git a/opencascade/BRepGraph_ReverseIterator.hxx b/opencascade/BRepGraph_ReverseIterator.hxx index 6374107bd..4906feebb 100644 --- a/opencascade/BRepGraph_ReverseIterator.hxx +++ b/opencascade/BRepGraph_ReverseIterator.hxx @@ -18,28 +18,27 @@ #include #include #include - #include +#include +#include -//! @brief Single-level typed iterators over parent definitions via reverse index. +//! @brief Single-level typed iterators over parent definitions via relation lists. //! -//! These iterators wrap the NCollection_DynamicArray returned by TopoView -//! reverse-index accessors (e.g. Edges().Faces(), Wires().Faces(), Vertices().Edges()). +//! These iterators wrap parent relation containers returned by TopoView accessors, +//! or derive parent definitions from const relation storage such as EdgeRelations::CoEdgeIds. //! They provide a typed, skip-removed iteration pattern consistent with the //! forward iterators in BRepGraph_DefsIterator and BRepGraph_RefsIterator. //! //! Usage: //! @code //! // Traditional iteration: -//! for (BRepGraph_FacesOfEdge anIt(aGraph, aGraph.Topo().Edges().Faces(anEdgeId)); -//! anIt.More(); anIt.Next()) +//! for (BRepGraph_FacesOfEdge anIt(aGraph, anEdgeId); anIt.More(); anIt.Next()) //! { //! const BRepGraph_FaceId aFaceId = anIt.CurrentId(); //! } //! //! // Range-based for: -//! for (const BRepGraph_FaceId aFaceId : -//! BRepGraph_FacesOfEdge(aGraph, aGraph.Topo().Edges().Faces(anEdgeId))) +//! for (const BRepGraph_FaceId aFaceId : BRepGraph_FacesOfEdge(aGraph, anEdgeId)) //! { //! // ... //! } @@ -172,29 +171,29 @@ struct DefTraits } }; -//! Typed iterator over a reverse-index vector of parent IDs. +//! Typed iterator over a relation vector of parent IDs. //! Skips removed parent definitions automatically in sequential iteration. //! Also provides indexed access (Length/Value) for callers that need //! random access into the underlying vector (e.g. BRepGraph_ParentExplorer). //! @tparam TypedIdT Typed ID such as BRepGraph_FaceId, BRepGraph_EdgeId, etc. -template +template > class ParentsOf { public: - ParentsOf(const BRepGraph& theGraph, const NCollection_DynamicArray& theParents) + ParentsOf(const BRepGraph& theGraph, const ContainerT& theParents) : myGraph(&theGraph), - myParents(&theParents) + myParents(&theParents), + myNbParents(theGraph.Topo().Gen().Nb(BRepGraph_NodeId(TypedIdT()).NodeKind)) { skipRemoved(); } //! Construct starting at a given vector index (for resumable iteration). //! Skips to the first non-removed entry at or after theStartIndex. - ParentsOf(const BRepGraph& theGraph, - const NCollection_DynamicArray& theParents, - const uint32_t theStartIndex) + ParentsOf(const BRepGraph& theGraph, const ContainerT& theParents, const uint32_t theStartIndex) : myGraph(&theGraph), myParents(&theParents), + myNbParents(theGraph.Topo().Gen().Nb(BRepGraph_NodeId(TypedIdT()).NodeKind)), myIndex(theStartIndex) { skipRemoved(); @@ -224,12 +223,9 @@ public: [[nodiscard]] uint32_t Index() const { return myIndex; } - //! Returns the total number of parent entries (including removed). - [[nodiscard]] int Length() const { return myParents->Length(); } - [[nodiscard]] size_t Size() const { return myParents->Size(); } - //! Returns the parent ID at the given index (does NOT check IsRemoved). + //! Returns the parent ID at the given bucket index (does NOT check removal status). [[nodiscard]] TypedIdT Value(const size_t theIndex) const { return myParents->Value(theIndex); } //! Returns an STL-compatible iterator for range-based for loops. @@ -244,11 +240,10 @@ public: private: void skipRemoved() { - while (myIndex < static_cast(myParents->Length())) + while (myIndex < static_cast(myParents->Size())) { - const BRepGraphInc::BaseDef* aDef = - myGraph->Topo().Gen().TopoEntity(myParents->Value(static_cast(myIndex))); - if (aDef != nullptr && !aDef->IsRemoved) + const TypedIdT aParentId = myParents->Value(static_cast(myIndex)); + if (aParentId.IsValid(myNbParents) && !aParentId.IsRemoved(*myGraph)) { return; } @@ -256,12 +251,139 @@ private: } } - const BRepGraph* myGraph = nullptr; - const NCollection_DynamicArray* myParents = nullptr; - uint32_t myIndex = 0; + const BRepGraph* myGraph = nullptr; + const ContainerT* myParents = nullptr; + uint32_t myNbParents = 0; + uint32_t myIndex = 0; }; -//! Result pair returned by RefsParentsOf: parent definition ID + the RefId +template +class EdgeParentsOf +{ +public: + using ParentId = typename TraitsT::ParentId; + + EdgeParentsOf(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge) + : myGraph(&theGraph), + myEdge(theEdge) + { + init(); + advance(); + } + + //! Construct starting at a given coedge relation index (for resumable iteration). + EdgeParentsOf(const BRepGraph& theGraph, + const BRepGraph_EdgeId theEdge, + const uint32_t theStartIndex) + : myGraph(&theGraph), + myEdge(theEdge), + myIndex(theStartIndex) + { + init(); + advance(); + } + + [[nodiscard]] bool More() const { return myHasCurrent; } + + void Next() + { + ++myIndex; + advance(); + } + + [[nodiscard]] ParentId CurrentId() const { return myCurrent; } + + [[nodiscard]] ParentId Current() const { return CurrentId(); } + + [[nodiscard]] const typename DefTraits::DefType& Definition() const + { + return DefTraits::Get(*myGraph, CurrentId()); + } + + [[nodiscard]] uint32_t Index() const { return myIndex; } + + NCollection_ForwardRangeIterator begin() + { + return NCollection_ForwardRangeIterator(this); + } + + NCollection_ForwardRangeSentinel end() const { return NCollection_ForwardRangeSentinel{}; } + +private: + void init() + { + if (!myEdge.IsValid(myGraph->Topo().Edges().Nb()) || myEdge.IsRemoved(*myGraph)) + { + return; + } + myNbParents = TraitsT::NbParents(*myGraph); + myCoEdges = &myGraph->Topo().Edges().CoEdges(myEdge); + } + + [[nodiscard]] ParentId parentAt(const uint32_t theIndex) const + { + if (myCoEdges == nullptr || theIndex >= static_cast(myCoEdges->Size())) + { + return ParentId(); + } + const BRepGraph_CoEdgeId aCoEdgeId = myCoEdges->Value(static_cast(theIndex)); + if (!aCoEdgeId.IsValid(myGraph->Topo().CoEdges().Nb()) || aCoEdgeId.IsRemoved(*myGraph)) + { + return ParentId(); + } + + const BRepGraphInc::CoEdgeDef& aCoEdge = myGraph->Topo().CoEdges().Definition(aCoEdgeId); + const ParentId aParent = TraitsT::ParentIdOf(aCoEdge); + if (!aParent.IsValid(myNbParents) || aParent.IsRemoved(*myGraph)) + { + return ParentId(); + } + return aParent; + } + + [[nodiscard]] bool isFirstOccurrence(const ParentId theParent, const uint32_t theIndex) const + { + for (uint32_t anIndex = 0; anIndex < theIndex; ++anIndex) + { + if (parentAt(anIndex) == theParent) + { + return false; + } + } + return true; + } + + void advance() + { + myHasCurrent = false; + if (myCoEdges == nullptr) + { + return; + } + + while (myIndex < static_cast(myCoEdges->Size())) + { + const ParentId aParent = parentAt(myIndex); + if (aParent.IsValid() && isFirstOccurrence(aParent, myIndex)) + { + myCurrent = aParent; + myHasCurrent = true; + return; + } + ++myIndex; + } + } + + const BRepGraph* myGraph = nullptr; + BRepGraph_EdgeId myEdge; + const NCollection_LinearVector* myCoEdges = nullptr; + ParentId myCurrent; + uint32_t myNbParents = 0; + uint32_t myIndex = 0; + bool myHasCurrent = false; +}; + +//! Result pair returned by parent-ref iterators: parent definition ID + the RefId //! in that parent which references the child. template struct ParentRef @@ -270,26 +392,38 @@ struct ParentRef RefIdT Ref; }; -//! Typed iterator over parent definitions via reverse index that also resolves -//! the specific RefId linking each parent to the child. -//! Requires a traits class to find the matching ref within each parent. +//! Typed iterator over parent ID relation lists that also resolves the specific +//! RefId linking each parent to the child by lookup in the parent definition. +//! Used only where the reverse relation stores parent IDs but no ref IDs. //! @tparam TraitsT Traits with: ParentId, ChildId, RefId types, //! FindRef(graph, parentId, childId) -> RefId (invalid if not found) template -class RefsParentsOf +class LookupParentRefsOf { public: - using ParentIdType = typename TraitsT::ParentId; - using ChildIdType = typename TraitsT::ChildId; - using RefIdType = typename TraitsT::RefId; - using ResultType = ParentRef; - - RefsParentsOf(const BRepGraph& theGraph, - const NCollection_DynamicArray& theParents, - const ChildIdType theChild) + using ParentIdType = typename TraitsT::ParentId; + using ChildIdType = typename TraitsT::ChildId; + using RefIdType = typename TraitsT::RefId; + using ResultType = ParentRef; + using ContainerType = typename TraitsT::ContainerType; + + LookupParentRefsOf(const BRepGraph& theGraph, + const ContainerType& theParents, + const ChildIdType theChild) : myGraph(&theGraph), myParents(&theParents), - myChild(theChild) + myChild(theChild), + myNbParents(theGraph.Topo().Gen().Nb(BRepGraph_NodeId(ParentIdType()).NodeKind)), + myNbRefs([&]() { + if constexpr (std::is_convertible_v) + { + return theGraph.Topo().Gen().Nb(BRepGraph_NodeId(RefIdType()).NodeKind); + } + else + { + return theGraph.Refs().Gen().Nb(BRepGraph_RefId(RefIdType()).RefKind); + } + }()) { advance(); } @@ -311,9 +445,9 @@ public: [[nodiscard]] uint32_t Index() const { return myIndex; } //! Returns an STL-compatible iterator for range-based for loops. - NCollection_ForwardRangeIterator begin() + NCollection_ForwardRangeIterator begin() { - return NCollection_ForwardRangeIterator(this); + return NCollection_ForwardRangeIterator(this); } //! Returns a sentinel marking the end of iteration. @@ -325,13 +459,11 @@ private: myHasCurrent = false; while (myIndex < static_cast(myParents->Size())) { - const ParentIdType aParentId = myParents->Value(static_cast(myIndex)); - const BRepGraphInc::BaseDef* aDef = - myGraph->Topo().Gen().TopoEntity(BRepGraph_NodeId(aParentId)); - if (aDef != nullptr && !aDef->IsRemoved) + const ParentIdType aParentId = myParents->Value(static_cast(myIndex)); + if (aParentId.IsValid(myNbParents) && !aParentId.IsRemoved(*myGraph)) { const RefIdType aRefId = TraitsT::FindRef(*myGraph, aParentId, myChild); - if (aRefId.IsValid()) + if (aRefId.IsValid(myNbRefs) && !aRefId.IsRemoved(*myGraph)) { myCurrent = ResultType{aParentId, aRefId}; myHasCurrent = true; @@ -342,93 +474,119 @@ private: } } - const BRepGraph* myGraph = nullptr; - const NCollection_DynamicArray* myParents = nullptr; - ChildIdType myChild; - ResultType myCurrent; - uint32_t myIndex = 0; - bool myHasCurrent = false; + const BRepGraph* myGraph = nullptr; + const ContainerType* myParents = nullptr; + ChildIdType myChild; + ResultType myCurrent; + uint32_t myNbParents = 0; + uint32_t myNbRefs = 0; + uint32_t myIndex = 0; + bool myHasCurrent = false; }; -// Traits for RefsParentsOf - each knows how to find the RefId -// linking a parent to a specific child definition. - -struct FaceOfWireRefTraits +template +class IdsOfRefs { - using ParentId = BRepGraph_FaceId; - using ChildId = BRepGraph_WireId; - using RefId = BRepGraph_WireRefId; +public: + using IdType = typename TraitsT::IdType; + using RefIdType = typename TraitsT::RefIdType; + using ContainerType = typename TraitsT::ContainerType; - static RefId FindRef(const BRepGraph& theGraph, - const BRepGraph_FaceId theParent, - const BRepGraph_WireId theChild) + IdsOfRefs(const BRepGraph& theGraph, const ContainerType& theRefs) + : myGraph(&theGraph), + myRefs(&theRefs), + myNbRefs(theGraph.Refs().Gen().Nb(BRepGraph_RefId(RefIdType()).RefKind)), + myNbIds(theGraph.Topo().Gen().Nb(BRepGraph_NodeId(IdType()).NodeKind)) { - for (BRepGraph_RefsWireOfFace aIt(theGraph, theParent); aIt.More(); aIt.Next()) - { - if (theGraph.Refs().ChildNode(aIt.CurrentId()) == BRepGraph_NodeId(theChild)) - { - return aIt.CurrentId(); - } - } - return RefId(); + advance(); } -}; -struct ShellOfFaceRefTraits -{ - using ParentId = BRepGraph_ShellId; - using ChildId = BRepGraph_FaceId; - using RefId = BRepGraph_FaceRefId; + IdsOfRefs(const BRepGraph& theGraph, const ContainerType& theRefs, const uint32_t theStartIndex) + : myGraph(&theGraph), + myRefs(&theRefs), + myNbRefs(theGraph.Refs().Gen().Nb(BRepGraph_RefId(RefIdType()).RefKind)), + myNbIds(theGraph.Topo().Gen().Nb(BRepGraph_NodeId(IdType()).NodeKind)), + myIndex(theStartIndex) + { + advance(); + } + + [[nodiscard]] bool More() const { return myHasCurrent; } + + void Next() + { + ++myIndex; + advance(); + } + + [[nodiscard]] IdType CurrentId() const { return myCurrent; } + + [[nodiscard]] IdType CurrentParentId() const { return CurrentId(); } - static RefId FindRef(const BRepGraph& theGraph, - const BRepGraph_ShellId theParent, - const BRepGraph_FaceId theChild) + [[nodiscard]] RefIdType CurrentRefId() const { return myCurrentRef; } + + [[nodiscard]] IdType Current() const { return CurrentId(); } + + [[nodiscard]] const typename DefTraits::DefType& Definition() const { - for (BRepGraph_RefsFaceOfShell aIt(theGraph, theParent); aIt.More(); aIt.Next()) - { - if (theGraph.Refs().ChildNode(aIt.CurrentId()) == BRepGraph_NodeId(theChild)) - { - return aIt.CurrentId(); - } - } - return RefId(); + return DefTraits::Get(*myGraph, CurrentId()); } -}; -struct SolidOfShellRefTraits -{ - using ParentId = BRepGraph_SolidId; - using ChildId = BRepGraph_ShellId; - using RefId = BRepGraph_ShellRefId; + [[nodiscard]] uint32_t Index() const { return myIndex; } - static RefId FindRef(const BRepGraph& theGraph, - const BRepGraph_SolidId theParent, - const BRepGraph_ShellId theChild) + NCollection_ForwardRangeIterator begin() { - for (BRepGraph_RefsShellOfSolid aIt(theGraph, theParent); aIt.More(); aIt.Next()) + return NCollection_ForwardRangeIterator(this); + } + + NCollection_ForwardRangeSentinel end() const { return NCollection_ForwardRangeSentinel{}; } + +private: + void advance() + { + myHasCurrent = false; + while (myIndex < static_cast(myRefs->Size())) { - if (theGraph.Refs().ChildNode(aIt.CurrentId()) == BRepGraph_NodeId(theChild)) + const RefIdType aRefId = myRefs->Value(static_cast(myIndex)); + if (aRefId.IsValid(myNbRefs) && !aRefId.IsRemoved(*myGraph)) { - return aIt.CurrentId(); + const IdType anId = TraitsT::Id(*myGraph, aRefId); + if (anId.IsValid(myNbIds) && !anId.IsRemoved(*myGraph)) + { + myCurrent = anId; + myCurrentRef = aRefId; + myHasCurrent = true; + return; + } } + ++myIndex; } - return RefId(); } + + const BRepGraph* myGraph = nullptr; + const ContainerType* myRefs = nullptr; + IdType myCurrent; + RefIdType myCurrentRef; + uint32_t myNbRefs = 0; + uint32_t myNbIds = 0; + uint32_t myIndex = 0; + bool myHasCurrent = false; }; -struct WireOfCoEdgeRefTraits +struct WireOfCoEdgeUsageTraits { - using ParentId = BRepGraph_WireId; - using ChildId = BRepGraph_CoEdgeId; - using RefId = BRepGraph_CoEdgeRefId; + using ParentId = BRepGraph_WireId; + using ChildId = BRepGraph_CoEdgeId; + using RefId = BRepGraph_CoEdgeId; + using ContainerType = NCollection_LinearVector; static RefId FindRef(const BRepGraph& theGraph, const BRepGraph_WireId theParent, const BRepGraph_CoEdgeId theChild) { - for (BRepGraph_RefsCoEdgeOfWire aIt(theGraph, theParent); aIt.More(); aIt.Next()) + for (BRepGraph_CoEdgesOfWire aIt(theGraph, theParent); aIt.More(); aIt.Next()) { - if (theGraph.Refs().ChildNode(aIt.CurrentId()) == BRepGraph_NodeId(theChild)) + if (aIt.CurrentId() == theChild) { return aIt.CurrentId(); } @@ -437,11 +595,33 @@ struct WireOfCoEdgeRefTraits } }; +struct WireFromEdgeCoEdgeTraits +{ + using ParentId = BRepGraph_WireId; + + static ParentId ParentIdOf(const BRepGraphInc::CoEdgeDef& theCoEdge) + { + return theCoEdge.ParentWireId; + } + + static uint32_t NbParents(const BRepGraph& theGraph) { return theGraph.Topo().Wires().Nb(); } +}; + +struct FaceFromEdgeCoEdgeTraits +{ + using ParentId = BRepGraph_FaceId; + + static ParentId ParentIdOf(const BRepGraphInc::CoEdgeDef& theCoEdge) { return theCoEdge.FaceId; } + + static uint32_t NbParents(const BRepGraph& theGraph) { return theGraph.Topo().Faces().Nb(); } +}; + struct EdgeOfVertexRefTraits { - using ParentId = BRepGraph_EdgeId; - using ChildId = BRepGraph_VertexId; - using RefId = BRepGraph_VertexRefId; + using ParentId = BRepGraph_EdgeId; + using ChildId = BRepGraph_VertexId; + using RefId = BRepGraph_VertexRefId; + using ContainerType = NCollection_LinearVector; static RefId FindRef(const BRepGraph& theGraph, const BRepGraph_EdgeId theParent, @@ -449,7 +629,7 @@ struct EdgeOfVertexRefTraits { for (BRepGraph_RefsVertexOfEdge aIt(theGraph, theParent); aIt.More(); aIt.Next()) { - if (theGraph.Refs().ChildNode(aIt.CurrentId()) == BRepGraph_NodeId(theChild)) + if (theGraph.Refs().Gen().ChildNode(aIt.CurrentId()) == BRepGraph_NodeId(theChild)) { return aIt.CurrentId(); } @@ -458,128 +638,198 @@ struct EdgeOfVertexRefTraits } }; -struct CompSolidOfSolidRefTraits +struct FaceFromWireRefTraits { - using ParentId = BRepGraph_CompSolidId; - using ChildId = BRepGraph_SolidId; - using RefId = BRepGraph_SolidRefId; + using IdType = BRepGraph_FaceId; + using RefIdType = BRepGraph_WireRefId; + using ContainerType = NCollection_LinearVector; - static RefId FindRef(const BRepGraph& theGraph, - const BRepGraph_CompSolidId theParent, - const BRepGraph_SolidId theChild) + static IdType Id(const BRepGraph& theGraph, const RefIdType theRefId) { - for (BRepGraph_RefsSolidOfCompSolid aIt(theGraph, theParent); aIt.More(); aIt.Next()) - { - if (theGraph.Refs().ChildNode(aIt.CurrentId()) == BRepGraph_NodeId(theChild)) - { - return aIt.CurrentId(); - } - } - return RefId(); + return theGraph.Refs().Wires().Entry(theRefId).ParentFaceId; } }; -struct CompoundOfChildRefTraits +struct ShellFromFaceRefTraits { - using ParentId = BRepGraph_CompoundId; - using ChildId = BRepGraph_NodeId; - using RefId = BRepGraph_ChildRefId; + using IdType = BRepGraph_ShellId; + using RefIdType = BRepGraph_FaceRefId; + using ContainerType = NCollection_LinearVector; - static RefId FindRef(const BRepGraph& theGraph, - const BRepGraph_CompoundId theParent, - const BRepGraph_NodeId theChild) + static IdType Id(const BRepGraph& theGraph, const RefIdType theRefId) { - for (BRepGraph_RefsChildOfCompound aIt(theGraph, theParent); aIt.More(); aIt.Next()) - { - if (theGraph.Refs().ChildNode(aIt.CurrentId()) == theChild) - { - return aIt.CurrentId(); - } - } - return RefId(); + return theGraph.Refs().Faces().Entry(theRefId).ParentShellId; } }; -struct ProductOfOccurrenceRefTraits +struct SolidFromShellRefTraits { - using ParentId = BRepGraph_ProductId; - using ChildId = BRepGraph_OccurrenceId; - using RefId = BRepGraph_OccurrenceRefId; + using IdType = BRepGraph_SolidId; + using RefIdType = BRepGraph_ShellRefId; + using ContainerType = NCollection_LinearVector; - static RefId FindRef(const BRepGraph& theGraph, - const BRepGraph_ProductId theParent, - const BRepGraph_OccurrenceId theChild) + static IdType Id(const BRepGraph& theGraph, const RefIdType theRefId) { - for (BRepGraph_RefsOccurrenceOfProduct aIt(theGraph, theParent); aIt.More(); aIt.Next()) - { - if (theGraph.Refs().ChildNode(aIt.CurrentId()) == BRepGraph_NodeId(theChild)) - { - return aIt.CurrentId(); - } - } - return RefId(); + return theGraph.Refs().Shells().Entry(theRefId).ParentSolidId; + } +}; + +struct CompSolidFromSolidRefTraits +{ + using IdType = BRepGraph_CompSolidId; + using RefIdType = BRepGraph_SolidRefId; + using ContainerType = NCollection_LinearVector; + + static IdType Id(const BRepGraph& theGraph, const RefIdType theRefId) + { + return theGraph.Refs().Solids().Entry(theRefId).ParentCompSolidId; + } +}; + +struct CompoundFromChildRefTraits +{ + using IdType = BRepGraph_CompoundId; + using RefIdType = BRepGraph_ChildRefId; + using ContainerType = NCollection_LinearVector; + + static IdType Id(const BRepGraph& theGraph, const RefIdType theRefId) + { + return theGraph.Refs().Children().Entry(theRefId).ParentCompoundId; + } +}; + +struct OccurrenceFromOccurrenceRefTraits +{ + using IdType = BRepGraph_OccurrenceId; + using RefIdType = BRepGraph_OccurrenceRefId; + using ContainerType = NCollection_LinearVector; + + static IdType Id(const BRepGraph& theGraph, const RefIdType theRefId) + { + return theGraph.Refs().Occurrences().Entry(theRefId).ChildOccurrenceId; + } +}; + +struct ProductFromOccurrenceRefTraits +{ + using IdType = BRepGraph_ProductId; + using RefIdType = BRepGraph_OccurrenceRefId; + using ContainerType = NCollection_LinearVector; + + static IdType Id(const BRepGraph& theGraph, const RefIdType theRefId) + { + return theGraph.Refs().Occurrences().Entry(theRefId).ParentProductId; } }; } // namespace BRepGraph_ReverseIterator // Vertex -> parent Edges -using BRepGraph_EdgesOfVertex = BRepGraph_ReverseIterator::ParentsOf; +using BRepGraph_EdgesOfVertex = + BRepGraph_ReverseIterator::ParentsOf>; +// Vertex -> parent Compounds +using BRepGraph_CompoundsOfVertex = + BRepGraph_ReverseIterator::IdsOfRefs; + // Edge -> parent Wires -using BRepGraph_WiresOfEdge = BRepGraph_ReverseIterator::ParentsOf; +class BRepGraph_WiresOfEdge : public BRepGraph_ReverseIterator::EdgeParentsOf< + BRepGraph_ReverseIterator::WireFromEdgeCoEdgeTraits> +{ +public: + using BRepGraph_ReverseIterator::EdgeParentsOf< + BRepGraph_ReverseIterator::WireFromEdgeCoEdgeTraits>::EdgeParentsOf; +}; + // Edge -> parent CoEdges -using BRepGraph_CoEdgesOfEdge = BRepGraph_ReverseIterator::ParentsOf; -// Edge -> parent Faces (derived from CoEdge.FaceDefId) -using BRepGraph_FacesOfEdge = BRepGraph_ReverseIterator::ParentsOf; +using BRepGraph_CoEdgesOfEdge = + BRepGraph_ReverseIterator::ParentsOf>; + +// Edge -> parent Faces (derived from CoEdge.FaceId) +class BRepGraph_FacesOfEdge : public BRepGraph_ReverseIterator::EdgeParentsOf< + BRepGraph_ReverseIterator::FaceFromEdgeCoEdgeTraits> +{ +public: + using BRepGraph_ReverseIterator::EdgeParentsOf< + BRepGraph_ReverseIterator::FaceFromEdgeCoEdgeTraits>::EdgeParentsOf; +}; + +// Edge -> parent Compounds +using BRepGraph_CompoundsOfEdge = + BRepGraph_ReverseIterator::IdsOfRefs; +// CoEdge -> parent Compounds +using BRepGraph_CompoundsOfCoEdge = + BRepGraph_ReverseIterator::IdsOfRefs; // Wire -> parent Faces -using BRepGraph_FacesOfWire = BRepGraph_ReverseIterator::ParentsOf; -// CoEdge -> parent Wires -using BRepGraph_WiresOfCoEdge = BRepGraph_ReverseIterator::ParentsOf; +using BRepGraph_FacesOfWire = + BRepGraph_ReverseIterator::IdsOfRefs; +// Wire -> parent Compounds +using BRepGraph_CompoundsOfWire = + BRepGraph_ReverseIterator::IdsOfRefs; // Face -> parent Shells -using BRepGraph_ShellsOfFace = BRepGraph_ReverseIterator::ParentsOf; +using BRepGraph_ShellsOfFace = + BRepGraph_ReverseIterator::IdsOfRefs; // Face -> parent Compounds -using BRepGraph_CompoundsOfFace = BRepGraph_ReverseIterator::ParentsOf; +using BRepGraph_CompoundsOfFace = + BRepGraph_ReverseIterator::IdsOfRefs; // Shell -> parent Solids -using BRepGraph_SolidsOfShell = BRepGraph_ReverseIterator::ParentsOf; +using BRepGraph_SolidsOfShell = + BRepGraph_ReverseIterator::IdsOfRefs; // Shell -> parent Compounds -using BRepGraph_CompoundsOfShell = BRepGraph_ReverseIterator::ParentsOf; +using BRepGraph_CompoundsOfShell = + BRepGraph_ReverseIterator::IdsOfRefs; // Solid -> parent CompSolids -using BRepGraph_CompSolidsOfSolid = BRepGraph_ReverseIterator::ParentsOf; +using BRepGraph_CompSolidsOfSolid = + BRepGraph_ReverseIterator::IdsOfRefs; // Solid -> parent Compounds -using BRepGraph_CompoundsOfSolid = BRepGraph_ReverseIterator::ParentsOf; +using BRepGraph_CompoundsOfSolid = + BRepGraph_ReverseIterator::IdsOfRefs; // CompSolid -> parent Compounds -using BRepGraph_CompoundsOfCompSolid = BRepGraph_ReverseIterator::ParentsOf; +using BRepGraph_CompoundsOfCompSolid = + BRepGraph_ReverseIterator::IdsOfRefs; // Compound -> parent Compounds -using BRepGraph_CompoundsOfCompound = BRepGraph_ReverseIterator::ParentsOf; +using BRepGraph_CompoundsOfCompound = + BRepGraph_ReverseIterator::IdsOfRefs; +// Any child -> parent Compounds +using BRepGraph_CompoundsOfChild = + BRepGraph_ReverseIterator::IdsOfRefs; // Product -> Occurrences -using BRepGraph_OccurrencesOfProduct = BRepGraph_ReverseIterator::ParentsOf; +using BRepGraph_OccurrencesOfProduct = BRepGraph_ReverseIterator::IdsOfRefs< + BRepGraph_ReverseIterator::OccurrenceFromOccurrenceRefTraits>; +// Any occurrence child -> Occurrences +using BRepGraph_OccurrencesOfChild = BRepGraph_ReverseIterator::IdsOfRefs< + BRepGraph_ReverseIterator::OccurrenceFromOccurrenceRefTraits>; +// Occurrence -> parent Products +using BRepGraph_ProductsOfOccurrence = + BRepGraph_ReverseIterator::IdsOfRefs; // Ref-based reverse iterators: yield (ParentId, RefId) pairs. // These find the specific reference entry in each parent that links to the child. // Wire -> parent Faces (with WireRefId) using BRepGraph_RefsFacesOfWire = - BRepGraph_ReverseIterator::RefsParentsOf; + BRepGraph_ReverseIterator::IdsOfRefs; // Face -> parent Shells (with FaceRefId) using BRepGraph_RefsShellsOfFace = - BRepGraph_ReverseIterator::RefsParentsOf; + BRepGraph_ReverseIterator::IdsOfRefs; // Shell -> parent Solids (with ShellRefId) using BRepGraph_RefsSolidsOfShell = - BRepGraph_ReverseIterator::RefsParentsOf; -// CoEdge -> parent Wires (with CoEdgeRefId) + BRepGraph_ReverseIterator::IdsOfRefs; +// CoEdge -> parent Wires (with direct CoEdgeId usage in each wire) using BRepGraph_RefsWiresOfCoEdge = - BRepGraph_ReverseIterator::RefsParentsOf; + BRepGraph_ReverseIterator::LookupParentRefsOf; // Vertex -> parent Edges (with VertexRefId) using BRepGraph_RefsEdgesOfVertex = - BRepGraph_ReverseIterator::RefsParentsOf; + BRepGraph_ReverseIterator::LookupParentRefsOf; // Solid -> parent CompSolids (with SolidRefId) using BRepGraph_RefsCompSolidsOfSolid = - BRepGraph_ReverseIterator::RefsParentsOf; + BRepGraph_ReverseIterator::IdsOfRefs; // Any child -> parent Compounds (with ChildRefId) using BRepGraph_RefsCompoundsOfChild = - BRepGraph_ReverseIterator::RefsParentsOf; + BRepGraph_ReverseIterator::IdsOfRefs; // Occurrence -> parent Products (with OccurrenceRefId) using BRepGraph_RefsProductsOfOccurrence = - BRepGraph_ReverseIterator::RefsParentsOf; + BRepGraph_ReverseIterator::IdsOfRefs; #endif // _BRepGraph_ReverseIterator_HeaderFile diff --git a/opencascade/BRepGraph_ShapesView.hxx b/opencascade/BRepGraph_ShapesView.hxx index d3af85d96..24b379c98 100644 --- a/opencascade/BRepGraph_ShapesView.hxx +++ b/opencascade/BRepGraph_ShapesView.hxx @@ -15,22 +15,151 @@ #define _BRepGraph_ShapesView_HeaderFile #include +#include +#include +#include +#include +#include +#include +#include -//! @brief Read-only view for TopoDS_Shape reconstruction from graph data. +class BRepTools_History; +class TCollection_AsciiString; + +//! @brief View for TopoDS_Shape ingestion, reconstruction and lookup. //! //! Reconstructs TopoDS shapes from graph nodes on demand, with caching //! for repeated access. Topology nodes are delegated to the incidence-table //! reconstruction backend, while Product / Occurrence nodes are assembled at //! the facade level using product-local roots and occurrence placement chains. -//! Provides lookup from original construction-time shapes back to their graph -//! NodeIds via TShape pointer comparison. Shape() is the stable cached public +//! Provides lookup from construction-time shapes back to their graph NodeIds +//! using OCCT shape identity (TShape + Location, orientation ignored). +//! Shape() is the stable cached public //! route for repeated access; Reconstruct() forces a fresh rebuild with the //! same node-kind semantics and bypasses the persistent reconstructed-shape cache. -//! BRepGraph_Builder::Add() and Compact() clear the persistent reconstructed-shape cache. +//! Add() and Compact() clear the persistent reconstructed-shape cache. //! Obtained via BRepGraph::Shapes(). class BRepGraph::ShapesView { public: + //! Shape-ingestion options. + struct Options + { + BRepGraphInc_Populate::Options Populate; + bool CreateAutoProduct = true; //!< wrap topology root in a Product (unparented Add only) + bool Flatten = false; //!< drop hierarchy containers, append faces as roots + bool Parallel = false; //!< run face-level construction in parallel + //! Capture every input subshape's NodeId in Result::AddedNodes. Off by + //! default so the hot path pays nothing. Used by algorithm wrappers + //! (Booleans, fillets, ...) that need to translate TopoDS_Shape objects + //! returned by an OCCT algorithm into graph NodeIds for history harvest. + bool TrackAddedNodes = false; + }; + + //! Status of a single Add() call. + enum class AddStatus + { + Success, //!< All faces built successfully. + SuccessWithWarnings, //!< Build completed with diagnostics, e.g. unbounded natural faces. + Failed //!< Build failed (e.g., null shape). + }; + + //! Outcome of a single Add() call. + struct Result + { + BRepGraph_NodeId TopologyRoot; + BRepGraph_ProductId Product; + BRepGraph_OccurrenceId Occurrence; + BRepGraph_RefId InsertedRef; + AddStatus Status = AddStatus::Failed; + + //! True if the build succeeded (with or without warnings). + [[nodiscard]] bool IsOk() const { return Status != AddStatus::Failed; } + + //! Populated only when Options::TrackAddedNodes is true. Maps every + //! subshape of the input @c theShape (including the root) to the + //! BRepGraph_NodeId it resolves to after the Add. Multiple input + //! shapes that share identity collapse to one entry, as in OCCT's + //! map types. + NCollection_DataMap AddedNodes; + }; + + //! Ingest a TopoDS_Shape as a new root subgraph, wrapping the topology root in a Product. + //! @param[in] theShape shape to ingest + //! @return Result with TopologyRoot, Product and Occurrence set on success. + [[nodiscard]] Standard_EXPORT Result Add(const TopoDS_Shape& theShape); + + //! Ingest a TopoDS_Shape as a new root subgraph with explicit options. + //! @param[in] theShape shape to ingest + //! @param[in] theOptions shape-ingestion options + //! @return Result with TopologyRoot set on success; Product/Occurrence set + //! when theOptions.CreateAutoProduct is true. + [[nodiscard]] Standard_EXPORT Result Add(const TopoDS_Shape& theShape, const Options& theOptions); + + //! Ingest a TopoDS_Shape under an existing parent. + //! + //! Parent kind dispatch: + //! - Product: creates a child part-product, links via Occurrence with shape.Location(). + //! - Compound: appends topology root as a child reference. + //! - Shell: appends a Face as a FaceRef; other shapes via AddChild. + //! - Solid: appends a Shell as a ShellRef; other shapes via AddChild. + //! - CompSolid: appends a Solid as a SolidRef. + //! Other parent kinds (Wire, Edge, Vertex, Occurrence) are not supported and yield + //! an invalid Result (Result::Ok == false) without modification to the graph. + //! @param[in] theShape shape to ingest + //! @param[in] theParent parent node receiving the topology + //! @return Result with TopologyRoot set, plus (Product, Occurrence, InsertedRef) for Product + //! parents or InsertedRef for topology container parents. + [[nodiscard]] Standard_EXPORT Result Add(const TopoDS_Shape& theShape, + const BRepGraph_NodeId theParent); + + //! Ingest a shape under an existing parent with explicit options. + //! Options::CreateAutoProduct is ignored. + [[nodiscard]] Standard_EXPORT Result Add(const TopoDS_Shape& theShape, + const BRepGraph_NodeId theParent, + const Options& theOptions); + + //! Collect a TopoDS_Shape -> NodeId map for graph roots and all subshapes + //! resolvable through FindNode(). This is intended for algorithms that + //! reconstruct selected graph roots to TopoDS, run OCCT, and then need to + //! translate BRepTools_History back to graph NodeIds. + Standard_EXPORT void CollectHistoryInputs( + const NCollection_Array1& theRoots, + NCollection_DataMap& theOutInputs) + const; + + //! Add an OCCT algorithm result and absorb BRepTools_History into the + //! registered BRepGraph_LayerHistory layer using explicit input shape mapping. + [[nodiscard]] Standard_EXPORT Result AddWithHistory( + const TopoDS_Shape& theResultShape, + const NCollection_DataMap& theInputs, + const occ::handle& theHistory, + const TCollection_AsciiString& theOpLabel); + + //! Add an OCCT algorithm result and absorb BRepTools_History with explicit options. + [[nodiscard]] Standard_EXPORT Result AddWithHistory( + const TopoDS_Shape& theResultShape, + const NCollection_DataMap& theInputs, + const occ::handle& theHistory, + const TCollection_AsciiString& theOpLabel, + const Options& theOptions); + + //! Convenience overload that collects the history input map from selected roots. + [[nodiscard]] Standard_EXPORT Result + AddWithHistory(const TopoDS_Shape& theResultShape, + const NCollection_Array1& theInputRoots, + const occ::handle& theHistory, + const TCollection_AsciiString& theOpLabel); + + //! Convenience overload that collects the history input map from selected roots + //! and uses explicit options. + [[nodiscard]] Standard_EXPORT Result + AddWithHistory(const TopoDS_Shape& theResultShape, + const NCollection_Array1& theInputRoots, + const occ::handle& theHistory, + const TCollection_AsciiString& theOpLabel, + const Options& theOptions); + //! Return or reconstruct a TopoDS_Shape for a node. //! Prefer this route for repeated public queries. //! Returns a cached shape when available and valid; otherwise reconstructs. @@ -48,19 +177,10 @@ public: //! @return true if an original shape exists [[nodiscard]] Standard_EXPORT bool HasOriginal(const BRepGraph_NodeId theNode) const; - //! Return a pointer to the original TopoDS_Shape stored during graph construction. - //! This is the non-throw lookup counterpart of OriginalOf(). - //! @param[in] theNode node identifier - //! @return pointer to original shape for an active node, or nullptr when absent/invalid/removed - [[nodiscard]] Standard_EXPORT const TopoDS_Shape* FindOriginal( - const BRepGraph_NodeId theNode) const; - //! Return the original TopoDS_Shape stored during graph construction. //! @param[in] theNode node identifier - //! @return reference to the exact TopoDS_Shape stored during graph construction - //! @exception Standard_ProgramError if no original shape exists - [[nodiscard]] Standard_EXPORT const TopoDS_Shape& OriginalOf( - const BRepGraph_NodeId theNode) const; + //! @return original shape for an active node, or null shape when absent/invalid/removed + [[nodiscard]] Standard_EXPORT TopoDS_Shape Original(const BRepGraph_NodeId theNode) const; //! Reconstruct a TopoDS_Shape from a graph node without using the persistent cache. //! Use this when the caller explicitly needs a fresh rebuild instead of the @@ -73,36 +193,102 @@ public: //! @return reconstructed shape, or null shape for invalid/removed nodes [[nodiscard]] Standard_EXPORT TopoDS_Shape Reconstruct(const BRepGraph_NodeId theRoot) const; + //! Remove the cached reconstructed shape for one node. + //! Does not change graph generation counters and does not rebuild the shape. + //! Invalid or removed nodes are ignored. + Standard_EXPORT void ClearCached(const BRepGraph_NodeId theNode); + + //! Remove the cached reconstructed shape for the node referenced by one reference. + //! Does not change graph generation counters and does not rebuild the shape. + //! Invalid or removed references are ignored. + Standard_EXPORT void ClearCached(const BRepGraph_RefId theRef); + //! Look up the definition NodeId for a shape from graph construction input. - //! Uses TShape pointer comparison (same semantics as IsSame()). + //! Uses OCCT IsSame() semantics (TShape + Location, orientation ignored). //! Synthetic Product / Occurrence reconstructions are not given dedicated //! TShape bindings, so lookup is only guaranteed for construction-time topology. - //! Programmatically created Builder().Add*() nodes can still be located by + //! Programmatically created Editor().Add*() nodes can still be located by //! UID or by direct iteration over Topo() definitions. //! @param[in] theShape shape to look up //! @return active node identifier, or invalid NodeId if the shape is absent or removed [[nodiscard]] Standard_EXPORT BRepGraph_NodeId FindNode(const TopoDS_Shape& theShape) const; //! Check if a shape is known to the graph (was part of construction input). - //! Uses TShape pointer comparison (same semantics as IsSame()). + //! Uses OCCT IsSame() semantics (TShape + Location, orientation ignored). //! Synthetic Product / Occurrence reconstructions are not given dedicated //! TShape bindings, so this is only guaranteed for construction-time topology. - //! Programmatically created Builder().Add*() nodes can still be located by + //! Programmatically created Editor().Add*() nodes can still be located by //! UID or by direct iteration over Topo() definitions. //! @param[in] theShape shape to check //! @return true if the shape has a corresponding active definition node [[nodiscard]] Standard_EXPORT bool HasNode(const TopoDS_Shape& theShape) const; + //! Remove the active graph node corresponding to a construction-time shape. + //! This is the convenience equivalent of FindNode(theShape) followed by + //! Editor().Gen().RemoveNode(node). + //! @param[in] theShape shape to remove + //! @return true when an active node was found and removed + Standard_EXPORT bool RemoveShape(const TopoDS_Shape& theShape); + private: friend class BRepGraph; friend struct BRepGraph_Data; - explicit ShapesView(const BRepGraph* theGraph) + explicit ShapesView(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + [[nodiscard]] static AddStatus appendImpl( + BRepGraph& theGraph, + const TopoDS_Shape& theShape, + const Options& theOptions, + NCollection_LinearVector* theOutFlatRoots = nullptr); + + //! Walk @p theShape and populate @p theMap with (subshape -> NodeId) + //! entries for every subshape resolvable through @c theGraph.Shapes(). + //! Used by the Add() overloads when Options::TrackAddedNodes is true. + //! Shape identity follows TopTools_ShapeMapHasher (TShape pointer + + //! Location), matching OCCT's standard shape-keyed maps. + static void collectAddedNodes( + const BRepGraph& theGraph, + const TopoDS_Shape& theShape, + NCollection_DataMap& theMap); + + //! Bind source shape keys to nodes populated from a location-stripped input shape. + //! This keeps ShapesView::FindNode() usable with the original TopoDS subshapes + //! when root placement is stored on a Product occurrence or Compound child ref. + static void bindSourceShapeAliases(BRepGraph& theGraph, + const TopoDS_Shape& theSourceShape, + const TopoDS_Shape& thePopulatedShape); + + static BRepGraph_NodeId detectTopologyRoot(const BRepGraph& theGraph, + const TopAbs_ShapeEnum theShapeType, + const uint32_t theOldCountOfShapeKind); + + static uint32_t snapshotCountForKind(const BRepGraph& theGraph, + const TopAbs_ShapeEnum theShapeType); + + static void populateUIDsIncremental(BRepGraph& theGraph, + const uint32_t theOldVtx, + const uint32_t theOldEdge, + const uint32_t theOldCoEdge, + const uint32_t theOldWire, + const uint32_t theOldFace, + const uint32_t theOldShell, + const uint32_t theOldSolid, + const uint32_t theOldComp, + const uint32_t theOldCS, + const uint32_t theOldProduct, + const uint32_t theOldOccurrence, + const uint32_t theOldShellRef, + const uint32_t theOldFaceRef, + const uint32_t theOldWireRef, + const uint32_t theOldVertexRef, + const uint32_t theOldSolidRef, + const uint32_t theOldChildRef); + + BRepGraph* myGraph; }; #endif // _BRepGraph_ShapesView_HeaderFile diff --git a/opencascade/BRepGraph_SupplementEditor.hxx b/opencascade/BRepGraph_SupplementEditor.hxx new file mode 100644 index 000000000..8381effdc --- /dev/null +++ b/opencascade/BRepGraph_SupplementEditor.hxx @@ -0,0 +1,127 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_SupplementEditor_HeaderFile +#define _BRepGraph_SupplementEditor_HeaderFile + +#include +#include + +//! @brief Lightweight mutation facade for runtime supplement attachments. +class BRepGraph_SupplementEditor +{ +public: + //! @brief Create an editor facade bound to one graph instance. + //! @param[in] theGraph graph receiving supplement attachments + explicit BRepGraph_SupplementEditor(BRepGraph& theGraph) + : myGraph(theGraph) + { + } + + //! @brief Attach one supplemental shape to an arbitrary supported core owner. + //! @param[in] theOwner active owner node + //! @param[in] theKind semantic attachment kind + //! @param[in] theShape supplemental shape to attach + //! @return non-zero attachment uid on success, `0` on rejection + [[nodiscard]] Standard_EXPORT uint64_t + Attach(BRepGraph_NodeId theOwner, + BRepGraph_LayerTopoSupplement::AttachmentKind theKind, + const TopoDS_Shape& theShape); + + //! @brief Attach a supplemental shape to a vertex owner. + //! @param[in] theVertex active vertex owner + //! @param[in] theShape supplemental shape to attach + //! @param[in] theKind semantic attachment kind + //! @return non-zero attachment uid on success, `0` on rejection + [[nodiscard]] Standard_EXPORT uint64_t + AttachToVertex(BRepGraph_VertexId theVertex, + const TopoDS_Shape& theShape, + BRepGraph_LayerTopoSupplement::AttachmentKind theKind = + BRepGraph_LayerTopoSupplement::AttachmentKind::VertexSupplementShape); + + //! @brief Attach a supplemental shape to an edge owner. + //! @param[in] theEdge active edge owner + //! @param[in] theShape supplemental shape to attach + //! @param[in] theKind semantic attachment kind + //! @return non-zero attachment uid on success, `0` on rejection + [[nodiscard]] Standard_EXPORT uint64_t + AttachToEdge(BRepGraph_EdgeId theEdge, + const TopoDS_Shape& theShape, + BRepGraph_LayerTopoSupplement::AttachmentKind theKind = + BRepGraph_LayerTopoSupplement::AttachmentKind::EdgeInternalVertex); + + //! @brief Attach a supplemental shape to a face owner. + //! @param[in] theFace active face owner + //! @param[in] theShape supplemental shape to attach + //! @param[in] theKind semantic attachment kind + //! @return non-zero attachment uid on success, `0` on rejection + [[nodiscard]] Standard_EXPORT uint64_t + AttachToFace(BRepGraph_FaceId theFace, + const TopoDS_Shape& theShape, + BRepGraph_LayerTopoSupplement::AttachmentKind theKind = + BRepGraph_LayerTopoSupplement::AttachmentKind::FaceDirectVertex); + + //! @brief Attach a supplemental shape to a solid owner. + //! @param[in] theSolid active solid owner + //! @param[in] theShape supplemental shape to attach + //! @param[in] theKind semantic attachment kind + //! @return non-zero attachment uid on success, `0` on rejection + [[nodiscard]] Standard_EXPORT uint64_t + AttachToSolid(BRepGraph_SolidId theSolid, + const TopoDS_Shape& theShape, + BRepGraph_LayerTopoSupplement::AttachmentKind theKind = + BRepGraph_LayerTopoSupplement::AttachmentKind::SolidAuxShape); + + //! @brief Attach a supplemental shape to a compsolid owner. + //! @param[in] theCompSolid active compsolid owner + //! @param[in] theShape supplemental shape to attach + //! @param[in] theKind semantic attachment kind + //! @return non-zero attachment uid on success, `0` on rejection + [[nodiscard]] Standard_EXPORT uint64_t + AttachToCompSolid(BRepGraph_CompSolidId theCompSolid, + const TopoDS_Shape& theShape, + BRepGraph_LayerTopoSupplement::AttachmentKind theKind = + BRepGraph_LayerTopoSupplement::AttachmentKind::CompSolidAuxShape); + + //! @brief Attach a supplemental shape to a shell owner. + //! @param[in] theShell active shell owner + //! @param[in] theShape supplemental shape to attach + //! @param[in] theKind semantic attachment kind + //! @return non-zero attachment uid on success, `0` on rejection + [[nodiscard]] Standard_EXPORT uint64_t + AttachToShell(BRepGraph_ShellId theShell, + const TopoDS_Shape& theShape, + BRepGraph_LayerTopoSupplement::AttachmentKind theKind = + BRepGraph_LayerTopoSupplement::AttachmentKind::ShellAuxShape); + + //! @brief Attach a supplemental shape to a compound owner. + //! @param[in] theCompound active compound owner + //! @param[in] theShape supplemental shape to attach + //! @param[in] theKind semantic attachment kind + //! @return non-zero attachment uid on success, `0` on rejection + [[nodiscard]] Standard_EXPORT uint64_t + AttachToCompound(BRepGraph_CompoundId theCompound, + const TopoDS_Shape& theShape, + BRepGraph_LayerTopoSupplement::AttachmentKind theKind = + BRepGraph_LayerTopoSupplement::AttachmentKind::CompoundAuxShape); + + //! @brief Remove one attachment by uid. + //! @param[in] theUid layer-local attachment uid + //! @return `true` when the attachment existed and was removed + Standard_EXPORT bool RemoveAttachment(uint64_t theUid); + +private: + BRepGraph& myGraph; +}; + +#endif // _BRepGraph_SupplementEditor_HeaderFile diff --git a/opencascade/BRepGraph_SupplementIterator.hxx b/opencascade/BRepGraph_SupplementIterator.hxx new file mode 100644 index 000000000..96d5b9785 --- /dev/null +++ b/opencascade/BRepGraph_SupplementIterator.hxx @@ -0,0 +1,79 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_SupplementIterator_HeaderFile +#define _BRepGraph_SupplementIterator_HeaderFile + +#include +#include +#include +#include + +//! @brief Iterator over supplemental TopoDS attachments owned by one core node. +//! +//! The iterator resolves `BRepGraph_LayerTopoSupplement` through the graph layer +//! registry and yields only explicit supplement attachments. Core traversal +//! remains core-only and does not surface these entries. +class BRepGraph_SupplementIterator +{ +public: + //! @brief Construct an iterator over supplement attachments of one owner. + //! @param[in] theGraph graph providing the supplement layer + //! @param[in] theOwner core owner node whose attachments should be iterated + explicit BRepGraph_SupplementIterator(const BRepGraph& theGraph, const BRepGraph_NodeId theOwner) + : myLayer(theGraph.LayerRegistry().FindLayer()), + myUids(myLayer.IsNull() ? nullptr : &myLayer->AttachedTo(theOwner)) + { + skipInvalid(); + } + + //! @brief Return true when the iterator currently points to an attachment. + [[nodiscard]] bool More() const + { + return myUids != nullptr && myEntry != nullptr && myIndex < myUids->Size(); + } + + //! @brief Advance to the next attachment. + void Next() + { + ++myIndex; + skipInvalid(); + } + + //! @brief Return the current layer-local attachment uid. + [[nodiscard]] uint64_t Uid() const { return More() ? myUids->Value(myIndex) : uint64_t(0); } + + //! @brief Return the current attachment entry. + [[nodiscard]] const BRepGraph_LayerTopoSupplement::Entry& Value() const { return *myEntry; } + + //! @brief STL range-for support. + NCollection_ForwardRangeIterator begin() + { + return NCollection_ForwardRangeIterator(this); + } + + //! @brief Sentinel marking end of iteration. + NCollection_ForwardRangeSentinel end() const { return NCollection_ForwardRangeSentinel{}; } + +private: + //! @brief Skip missing entries in owner-local uid storage. + Standard_EXPORT void skipInvalid(); + +private: + occ::handle myLayer; + const NCollection_LinearVector* myUids = nullptr; + const BRepGraph_LayerTopoSupplement::Entry* myEntry = nullptr; + size_t myIndex = 0; +}; + +#endif // _BRepGraph_SupplementIterator_HeaderFile diff --git a/opencascade/BRepGraph_Tool.hxx b/opencascade/BRepGraph_Tool.hxx index b9ff61f81..08899b6b3 100644 --- a/opencascade/BRepGraph_Tool.hxx +++ b/opencascade/BRepGraph_Tool.hxx @@ -15,17 +15,12 @@ #define _BRepGraph_Tool_HeaderFile #include -#include -#include -#include #include #include #include #include #include -#include -#include -#include +#include #include #include #include @@ -48,24 +43,31 @@ class Adaptor3d_CurveOnSurface; //! the queried property. //! //! Methods are grouped by topology kind via nested classes: -//! BRepGraph_Tool::Vertex, Edge, CoEdge, Face, Wire. +//! BRepGraph_Tool::Vertex, Edge, CoEdge, Face, Wire, Shell. class BRepGraph_Tool { public: using VertexUsage = BRepGraphInc::VertexInstance; using CoEdgeUsage = BRepGraphInc::CoEdgeInstance; - using VertexRef = BRepGraphInc::VertexRef; - using WireRef = BRepGraphInc::WireRef; - using CoEdgeDef = BRepGraphInc::CoEdgeDef; + using FaceUsage = BRepGraphInc::FaceInstance; + using WireUsage = BRepGraphInc::WireInstance; + using ShellUsage = BRepGraphInc::ShellInstance; //! @brief Vertex geometry accessors. //! - //! Provides 3D point retrieval (with or without Location applied), - //! tolerance access, and parameter lookup for vertex-on-curve and - //! vertex-on-surface representations. + //! Provides 3D point retrieval (with or without Location applied) and + //! tolerance access. class Vertex { public: + //! Resolves a vertex reference id to a lightweight usage value. + //! @param[in] theGraph source graph + //! @param[in] theVertexRef typed vertex reference identifier + //! @return vertex usage, or invalid usage if the reference is invalid or removed + [[nodiscard]] Standard_EXPORT static VertexUsage Usage( + const BRepGraph& theGraph, + const BRepGraph_VertexRefId theVertexRef); + //! Returns the vertex 3D point with VertexUsage Location applied. //! @param[in] theGraph source graph //! @param[in] theRef vertex incidence reference carrying Location @@ -80,6 +82,13 @@ public: [[nodiscard]] Standard_EXPORT static gp_Pnt Pnt(const BRepGraph& theGraph, const BRepGraph_VertexId theVertex); + //! Returns the vertex 3D point with vertex reference location applied. + //! @param[in] theGraph source graph + //! @param[in] theVertexRef typed vertex reference identifier + //! @return transformed 3D point + [[nodiscard]] Standard_EXPORT static gp_Pnt Pnt(const BRepGraph& theGraph, + const BRepGraph_VertexRefId theVertexRef); + //! Returns the vertex tolerance. //! @param[in] theGraph source graph //! @param[in] theVertex typed vertex definition identifier @@ -87,35 +96,12 @@ public: [[nodiscard]] Standard_EXPORT static double Tolerance(const BRepGraph& theGraph, const BRepGraph_VertexId theVertex); - //! Returns the vertex parameter on an edge's 3D curve. - //! @param[in] theGraph source graph - //! @param[in] theVertex typed vertex definition identifier - //! @param[in] theEdge typed edge definition identifier - //! @return curve parameter - //! @throws Standard_NoSuchObject if vertex has no PointOnCurve for this edge - [[nodiscard]] Standard_EXPORT static double Parameter(const BRepGraph& theGraph, - const BRepGraph_VertexId theVertex, - const BRepGraph_EdgeId theEdge); - - //! Returns the vertex (U,V) parameters on a face surface. - //! @param[in] theGraph source graph - //! @param[in] theVertex typed vertex definition identifier - //! @param[in] theFace typed face definition identifier - //! @return 2D point with (U,V) parameters - //! @throws Standard_NoSuchObject if vertex has no PointOnSurface for this face - [[nodiscard]] Standard_EXPORT static gp_Pnt2d Parameters(const BRepGraph& theGraph, - const BRepGraph_VertexId theVertex, - const BRepGraph_FaceId theFace); - - //! Returns the vertex parameter on a coedge's PCurve. - //! @param[in] theGraph source graph - //! @param[in] theVertex typed vertex definition identifier - //! @param[in] theCoEdge typed coedge definition identifier - //! @return PCurve parameter - //! @throws Standard_NoSuchObject if vertex has no PointOnPCurve for this coedge - [[nodiscard]] Standard_EXPORT static double PCurveParameter(const BRepGraph& theGraph, - const BRepGraph_VertexId theVertex, - const BRepGraph_CoEdgeId theCoEdge); + //! Returns the vertex tolerance by vertex reference identifier. + //! @param[in] theGraph source graph + //! @param[in] theVertexRef typed vertex reference identifier + //! @return tolerance value + [[nodiscard]] Standard_EXPORT static double Tolerance(const BRepGraph& theGraph, + const BRepGraph_VertexRefId theVertexRef); //! Returns the number of edges that reference this vertex. //! @param[in] theGraph source graph @@ -125,12 +111,11 @@ public: const BRepGraph_VertexId theVertex); }; - //! @brief Edge geometry, curve, polygon, and continuity accessors. + //! @brief Edge geometry, curve, and continuity accessors. //! //! Provides tolerance, degeneracy, and parameter flags; raw and - //! location-adjusted 3D curve access; polygon discretization; - //! continuity queries between adjacent faces; and PCurve lookup - //! for edge-face contexts including seam edge support. + //! location-adjusted 3D curve access; and PCurve lookup for edge-face + //! contexts including seam edge support. class Edge { public: @@ -141,26 +126,19 @@ public: [[nodiscard]] Standard_EXPORT static double Tolerance(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge); - //! Returns true if the edge is degenerate (collapses to a point on surface). + //! Returns true if the edge is degenerate, derived from current geometry. //! @param[in] theGraph source graph //! @param[in] theEdge typed edge definition identifier //! @return true if degenerate [[nodiscard]] Standard_EXPORT static bool Degenerated(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge); - //! Returns the SameParameter flag. - //! @param[in] theGraph source graph - //! @param[in] theEdge typed edge definition identifier - //! @return true if all PCurves are reparametrized to the same range as the 3D curve - [[nodiscard]] Standard_EXPORT static bool SameParameter(const BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge); - - //! Returns the SameRange flag. + //! Returns true if the edge forms a topological loop, derived from vertex topology. //! @param[in] theGraph source graph //! @param[in] theEdge typed edge definition identifier - //! @return true if PCurve parameter range equals the 3D curve range - [[nodiscard]] Standard_EXPORT static bool SameRange(const BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge); + //! @return true if closed + [[nodiscard]] Standard_EXPORT static bool IsClosed(const BRepGraph& theGraph, + const BRepGraph_EdgeId theEdge); //! Returns the 3D curve parameter range as (first, last). //! @param[in] theGraph source graph @@ -170,37 +148,19 @@ public: const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge); - //! Returns the start vertex reference entry (carries Location and Orientation). - //! @param[in] theGraph source graph - //! @param[in] theEdge typed edge definition identifier - //! @return const reference to the start VertexRef - [[nodiscard]] Standard_EXPORT static const VertexRef& StartVertexRef( - const BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge); - - //! Returns the end vertex reference entry (carries Location and Orientation). + //! Returns the start vertex reference id directly. //! @param[in] theGraph source graph //! @param[in] theEdge typed edge definition identifier - //! @return const reference to the end VertexRef - [[nodiscard]] Standard_EXPORT static const VertexRef& EndVertexRef( + //! @return start vertex reference id + [[nodiscard]] Standard_EXPORT static BRepGraph_VertexRefId StartVertexId( const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge); - //! Returns the start vertex definition id directly (shortcut for - //! `StartVertexRef(...).VertexDefId`). Invalid if the edge has no start vertex. + //! Returns the end vertex reference id directly. //! @param[in] theGraph source graph //! @param[in] theEdge typed edge definition identifier - //! @return start vertex id - [[nodiscard]] Standard_EXPORT static BRepGraph_VertexId StartVertexId( - const BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge); - - //! Returns the end vertex definition id directly (shortcut for - //! `EndVertexRef(...).VertexDefId`). Invalid if the edge has no end vertex. - //! @param[in] theGraph source graph - //! @param[in] theEdge typed edge definition identifier - //! @return end vertex id - [[nodiscard]] Standard_EXPORT static BRepGraph_VertexId EndVertexId( + //! @return end vertex reference id + [[nodiscard]] Standard_EXPORT static BRepGraph_VertexRefId EndVertexId( const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge); @@ -243,50 +203,63 @@ public: const BRepGraph& theGraph, const CoEdgeUsage& theRef); - //! Returns true if the edge has a 3D polygon discretization. + //! Find an active edge by its boundary vertices. //! @param[in] theGraph source graph - //! @param[in] theEdge typed edge definition identifier - //! @return true if edge has a polygon - [[nodiscard]] Standard_EXPORT static bool HasPolygon3D(const BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge); + //! @param[in] theStartVertex start vertex to match + //! @param[in] theEndVertex end vertex to match + //! @param[in] theToIgnoreOrientation when true, also matches the reverse vertex order + //! @return edge id, or invalid if no active edge matches + [[nodiscard]] Standard_EXPORT static BRepGraph_EdgeId FindByVertices( + const BRepGraph& theGraph, + const BRepGraph_VertexId theStartVertex, + const BRepGraph_VertexId theEndVertex, + const bool theToIgnoreOrientation = false); - //! Returns the 3D polygon handle (definition frame). + //! Find an active coedge carrying PCurve data for the given edge-face use. //! @param[in] theGraph source graph - //! @param[in] theEdge typed edge definition identifier - //! @return polygon handle, or null handle if no polygon - [[nodiscard]] Standard_EXPORT static const occ::handle& Polygon3D( + //! @param[in] theEdge edge definition to match + //! @param[in] theFace face definition to match + //! @return matching coedge id, or invalid if the edge/face pair has no active PCurve coedge + [[nodiscard]] Standard_EXPORT static BRepGraph_CoEdgeId FindPCurveCoEdgeId( const BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge); - - //! Returns true if the edge has continuity info between two faces. - //! @param[in] theGraph source graph - //! @param[in] theEdge typed edge definition identifier - //! @param[in] theFace1 typed first face definition identifier - //! @param[in] theFace2 typed second face definition identifier - //! @return true if continuity is recorded - [[nodiscard]] Standard_EXPORT static bool HasContinuity(const BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace1, - const BRepGraph_FaceId theFace2); + const BRepGraph_EdgeId theEdge, + const BRepGraph_FaceId theFace); - //! Returns the geometric continuity between two adjacent faces. - //! @param[in] theGraph source graph - //! @param[in] theEdge typed edge definition identifier - //! @param[in] theFace1 typed first face definition identifier - //! @param[in] theFace2 typed second face definition identifier - //! @return continuity order (GeomAbs_C0 if not found) - [[nodiscard]] Standard_EXPORT static GeomAbs_Shape Continuity(const BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace1, - const BRepGraph_FaceId theFace2); + //! Find an active PCurve coedge for the given edge-face use and preferred orientation. + //! @param[in] theGraph source graph + //! @param[in] theEdge edge definition to match + //! @param[in] theFace face definition to match + //! @param[in] theOrientation preferred coedge orientation + //! @return exact orientation match when present; otherwise the first active PCurve + //! coedge on the edge-face pair; invalid if there is no active PCurve coedge + [[nodiscard]] Standard_EXPORT static BRepGraph_CoEdgeId FindPCurveCoEdgeId( + const BRepGraph& theGraph, + const BRepGraph_EdgeId theEdge, + const BRepGraph_FaceId theFace, + const TopAbs_Orientation theOrientation); - //! Returns the maximum continuity across all face pairs for this edge. + //! Find an active coedge for the given edge-face use. //! @param[in] theGraph source graph - //! @param[in] theEdge typed edge definition identifier - //! @return maximum continuity order - [[nodiscard]] Standard_EXPORT static GeomAbs_Shape MaxContinuity( + //! @param[in] theEdge edge definition to match + //! @param[in] theFace face definition to match + //! @return matching coedge id, or invalid if the edge/face pair has no active coedge + [[nodiscard]] Standard_EXPORT static BRepGraph_CoEdgeId FindCoEdgeId( const BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge); + const BRepGraph_EdgeId theEdge, + const BRepGraph_FaceId theFace); + + //! Find an active coedge for the given edge-face use and preferred orientation. + //! @param[in] theGraph source graph + //! @param[in] theEdge edge definition to match + //! @param[in] theFace face definition to match + //! @param[in] theOrientation preferred coedge orientation + //! @return exact orientation match when present; otherwise the first active coedge on the + //! edge-face pair; invalid if there is no active coedge for the edge-face pair + [[nodiscard]] Standard_EXPORT static BRepGraph_CoEdgeId FindCoEdgeId( + const BRepGraph& theGraph, + const BRepGraph_EdgeId theEdge, + const BRepGraph_FaceId theFace, + const TopAbs_Orientation theOrientation); //! Returns the number of faces that reference this edge via coedges. //! @param[in] theGraph source graph @@ -309,36 +282,14 @@ public: [[nodiscard]] Standard_EXPORT static bool IsBoundary(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge); - //! Returns true if the edge has two PCurves on a face (seam/closed surface). + //! Returns true if the edge is a seam on the given face. //! @param[in] theGraph source graph //! @param[in] theEdge typed edge definition identifier //! @param[in] theFace typed face definition identifier //! @return true if the edge is a seam on this face - [[nodiscard]] Standard_EXPORT static bool IsClosedOnFace(const BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace); - - //! Finds the CoEdge entity for an edge on a face. - //! @param[in] theGraph source graph - //! @param[in] theEdge typed edge definition identifier - //! @param[in] theFace typed face definition identifier - //! @return pointer to CoEdgeDef, or nullptr if not found - [[nodiscard]] Standard_EXPORT static const CoEdgeDef* FindPCurve( - const BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace); - - //! Finds the CoEdge entity with specific orientation (for seam edges). - //! @param[in] theGraph source graph - //! @param[in] theEdge typed edge definition identifier - //! @param[in] theFace typed face definition identifier - //! @param[in] theOri edge orientation on the face - //! @return pointer to CoEdgeDef, or nullptr if not found - [[nodiscard]] Standard_EXPORT static const CoEdgeDef* FindPCurve( - const BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace, - const TopAbs_Orientation theOri); + [[nodiscard]] Standard_EXPORT static bool IsSeamOnFace(const BRepGraph& theGraph, + const BRepGraph_EdgeId theEdge, + const BRepGraph_FaceId theFace); //! Returns a CurveOnSurface adaptor built from a CoEdgeUsage and face. //! @param[in] theGraph source graph @@ -351,11 +302,10 @@ public: const BRepGraph_FaceId theFace); }; - //! @brief CoEdge (half-edge) parametric curve and polygon accessors. + //! @brief CoEdge (half-edge) parametric curve accessors. //! //! Provides PCurve retrieval, adaptor construction, UV endpoint - //! access, parameter range queries, and polygon-on-surface access - //! for coedge definitions. + //! access, and parameter range queries for coedge definitions. class CoEdge { public: @@ -407,6 +357,20 @@ public: [[nodiscard]] Standard_EXPORT static bool HasPCurve(const BRepGraph& theGraph, const BRepGraph_CoEdgeId theCoEdge); + //! Returns true if the coedge's PCurve parameter matches the 3D curve. + //! @param[in] theGraph source graph + //! @param[in] theCoEdge typed coedge definition identifier + //! @return true if same parameter + [[nodiscard]] Standard_EXPORT static bool SameParameter(const BRepGraph& theGraph, + const BRepGraph_CoEdgeId theCoEdge); + + //! Returns true if the coedge's PCurve range equals the 3D curve range. + //! @param[in] theGraph source graph + //! @param[in] theCoEdge typed coedge definition identifier + //! @return true if same range + [[nodiscard]] Standard_EXPORT static bool SameRange(const BRepGraph& theGraph, + const BRepGraph_CoEdgeId theCoEdge); + //! Returns the raw PCurve handle by coedge identifier (no Location - UV space). //! @param[in] theGraph source graph //! @param[in] theCoEdge typed coedge definition identifier @@ -415,14 +379,6 @@ public: const BRepGraph& theGraph, const BRepGraph_CoEdgeId theCoEdge); - //! Returns the raw PCurve handle from a CoEdgeDef (no Location - UV space). - //! @param[in] theGraph source graph - //! @param[in] theCoEdge coedge entity reference - //! @return curve handle, or null handle if no PCurve - [[nodiscard]] Standard_EXPORT static const occ::handle& PCurve( - const BRepGraph& theGraph, - const CoEdgeDef& theCoEdge); - //! Returns a PCurve adaptor by coedge identifier. //! If the coedge has a stored PCurve (Curve2DRepIdx >= 0), returns it directly. //! Otherwise, for planar face surfaces, computes the PCurve on-the-fly by projecting @@ -458,32 +414,22 @@ public: [[nodiscard]] Standard_EXPORT static std::pair Range( const BRepGraph& theGraph, const BRepGraph_CoEdgeId theCoEdge); - - //! Returns true if the coedge has a polygon-on-surface representation. - //! @param[in] theGraph source graph - //! @param[in] theCoEdge typed coedge definition identifier - //! @return true if polygon exists - [[nodiscard]] Standard_EXPORT static bool HasPolygonOnSurface( - const BRepGraph& theGraph, - const BRepGraph_CoEdgeId theCoEdge); - - //! Returns the polygon-on-surface (2D) for the coedge. - //! @param[in] theGraph source graph - //! @param[in] theCoEdge typed coedge definition identifier - //! @return polygon handle, or null handle if no polygon - [[nodiscard]] Standard_EXPORT static const occ::handle& PolygonOnSurface( - const BRepGraph& theGraph, - const BRepGraph_CoEdgeId theCoEdge); }; - //! @brief Face surface, triangulation, and property accessors. + //! @brief Face surface and property accessors. //! //! Provides tolerance, natural restriction flag, surface handle - //! and adaptor access (with optional UV bounds), active triangulation - //! retrieval, and outer wire lookup. + //! and adaptor access (with optional UV bounds), and outer wire lookup. class Face { public: + //! Resolves a face reference id to a lightweight usage value. + //! @param[in] theGraph source graph + //! @param[in] theFaceRef typed face reference identifier + //! @return face usage, or invalid usage if the reference is invalid or removed + [[nodiscard]] Standard_EXPORT static FaceUsage Usage(const BRepGraph& theGraph, + const BRepGraph_FaceRefId theFaceRef); + //! Returns the face tolerance. //! @param[in] theGraph source graph //! @param[in] theFace typed face definition identifier @@ -491,12 +437,9 @@ public: [[nodiscard]] Standard_EXPORT static double Tolerance(const BRepGraph& theGraph, const BRepGraph_FaceId theFace); - //! Returns the NaturalRestriction flag. - //! @param[in] theGraph source graph - //! @param[in] theFace typed face definition identifier - //! @return true if face has natural restriction - [[nodiscard]] Standard_EXPORT static bool NaturalRestriction(const BRepGraph& theGraph, - const BRepGraph_FaceId theFace); + //! Returns the face tolerance by face reference identifier. + [[nodiscard]] Standard_EXPORT static double Tolerance(const BRepGraph& theGraph, + const BRepGraph_FaceRefId theFaceRef); //! Returns true if the face has a surface representation. //! @param[in] theGraph source graph @@ -505,28 +448,21 @@ public: [[nodiscard]] Standard_EXPORT static bool HasSurface(const BRepGraph& theGraph, const BRepGraph_FaceId theFace); - //! Returns true if the face has an active triangulation. - //! @param[in] theGraph source graph - //! @param[in] theFace typed face definition identifier - //! @return true if triangulation exists - [[nodiscard]] Standard_EXPORT static bool HasTriangulation(const BRepGraph& theGraph, - const BRepGraph_FaceId theFace); + //! Returns true if the face reference resolves to a face with a surface. + [[nodiscard]] Standard_EXPORT static bool HasSurface(const BRepGraph& theGraph, + const BRepGraph_FaceRefId theFaceRef); - //! Returns the outer wire reference, or nullptr if none. + //! Returns the outer wire definition id directly. //! @param[in] theGraph source graph //! @param[in] theFace typed face definition identifier - //! @return pointer to the outer WireRef, or nullptr - [[nodiscard]] Standard_EXPORT static const WireRef* OuterWire(const BRepGraph& theGraph, - const BRepGraph_FaceId theFace); + //! @return outer wire id, or invalid if the face has no wire + [[nodiscard]] Standard_EXPORT static BRepGraph_WireId OuterWire(const BRepGraph& theGraph, + const BRepGraph_FaceId theFace); - //! Returns the outer wire definition id directly (shortcut for - //! `OuterWire(...)->WireDefId`). Invalid if the face has no outer wire. - //! @param[in] theGraph source graph - //! @param[in] theFace typed face definition identifier - //! @return outer wire id - [[nodiscard]] Standard_EXPORT static BRepGraph_WireId OuterWireId( - const BRepGraph& theGraph, - const BRepGraph_FaceId theFace); + //! Returns the outer wire definition id by face reference identifier. + [[nodiscard]] Standard_EXPORT static BRepGraph_WireId OuterWire( + const BRepGraph& theGraph, + const BRepGraph_FaceRefId theFaceRef); //! Returns the raw surface handle (definition frame, no copy). //! @param[in] theGraph source graph @@ -536,6 +472,11 @@ public: const BRepGraph& theGraph, const BRepGraph_FaceId theFace); + //! Returns the raw surface handle by face reference identifier. + [[nodiscard]] Standard_EXPORT static const occ::handle& Surface( + const BRepGraph& theGraph, + const BRepGraph_FaceRefId theFaceRef); + //! Returns a surface adaptor in definition frame. //! @param[in] theGraph source graph //! @param[in] theFace typed face definition identifier @@ -544,6 +485,16 @@ public: const BRepGraph& theGraph, const BRepGraph_FaceId theFace); + //! Returns a surface adaptor with FaceUsage Location applied. + [[nodiscard]] Standard_EXPORT static GeomAdaptor_TransformedSurface SurfaceAdaptor( + const BRepGraph& theGraph, + const FaceUsage& theRef); + + //! Returns a surface adaptor by face reference identifier with reference Location applied. + [[nodiscard]] Standard_EXPORT static GeomAdaptor_TransformedSurface SurfaceAdaptor( + const BRepGraph& theGraph, + const BRepGraph_FaceRefId theFaceRef); + //! Returns a surface adaptor with explicit UV bounds. //! @param[in] theGraph source graph //! @param[in] theFace typed face definition identifier @@ -560,13 +511,23 @@ public: const double theVFirst, const double theVLast); - //! Returns the active triangulation for the face (definition frame). - //! @param[in] theGraph source graph - //! @param[in] theFace typed face definition identifier - //! @return triangulation handle, or null handle if none - [[nodiscard]] Standard_EXPORT static const occ::handle& Triangulation( - const BRepGraph& theGraph, - const BRepGraph_FaceId theFace); + //! Returns a surface adaptor with explicit UV bounds and FaceUsage Location applied. + [[nodiscard]] Standard_EXPORT static GeomAdaptor_TransformedSurface SurfaceAdaptor( + const BRepGraph& theGraph, + const FaceUsage& theRef, + const double theUFirst, + const double theULast, + const double theVFirst, + const double theVLast); + + //! Returns a surface adaptor with explicit UV bounds by face reference identifier. + [[nodiscard]] Standard_EXPORT static GeomAdaptor_TransformedSurface SurfaceAdaptor( + const BRepGraph& theGraph, + const BRepGraph_FaceRefId theFaceRef, + const double theUFirst, + const double theULast, + const double theVFirst, + const double theVLast); //! Returns the number of wire references on the face (outer + holes). //! @param[in] theGraph source graph @@ -575,8 +536,11 @@ public: [[nodiscard]] Standard_EXPORT static uint32_t NbWires(const BRepGraph& theGraph, const BRepGraph_FaceId theFace); + //! Returns the number of wire references by face reference identifier. + [[nodiscard]] Standard_EXPORT static uint32_t NbWires(const BRepGraph& theGraph, + const BRepGraph_FaceRefId theFaceRef); + //! Returns the UV parameter bounds of the face surface. - //! For faces with NaturalRestriction the bounds come directly from the surface. //! Fills out-parameters with the surface bounds; all values are set to 0.0 if //! the face has no surface. //! @param[in] theGraph source graph @@ -591,24 +555,43 @@ public: double& theUMax, double& theVMin, double& theVMax); + + //! Returns the UV parameter bounds by face reference identifier. + Standard_EXPORT static void Bounds(const BRepGraph& theGraph, + const BRepGraph_FaceRefId theFaceRef, + double& theUMin, + double& theUMax, + double& theVMin, + double& theVMax); }; //! @brief Wire property accessors. //! //! Provides wire closure, size, and ownership queries. - //! For ordered edge traversal, use BRepGraphInc_WireExplorer or access - //! the WireDef::CoEdgeRefIds vector directly via TopoView. + //! For ordered coedge traversal, use BRepGraph_CoEdgesOfWire or + //! TopoView::Wires().Relations(theWire).CoEdgeIds. class Wire { public: - //! Returns true if the wire is topologically closed. + //! Resolves a wire reference id to a lightweight usage value. + //! @param[in] theGraph source graph + //! @param[in] theWireRef typed wire reference identifier + //! @return wire usage, or invalid usage if the reference is invalid or removed + [[nodiscard]] Standard_EXPORT static WireUsage Usage(const BRepGraph& theGraph, + const BRepGraph_WireRefId theWireRef); + + //! Returns true if the wire is topologically closed, derived from ordered coedge chain. //! @param[in] theGraph source graph //! @param[in] theWire typed wire definition identifier //! @return true if closed [[nodiscard]] Standard_EXPORT static bool IsClosed(const BRepGraph& theGraph, const BRepGraph_WireId theWire); - //! Number of CoEdge references in the wire (raw count: seam halves count twice, + //! Returns true if the referenced wire is topologically closed. + [[nodiscard]] Standard_EXPORT static bool IsClosed(const BRepGraph& theGraph, + const BRepGraph_WireRefId theWireRef); + + //! Number of CoEdge usages in the wire (raw count: seam halves count twice, //! matching TopoDS_Iterator(wire) semantics). //! @param[in] theGraph source graph //! @param[in] theWire typed wire definition identifier @@ -616,14 +599,23 @@ public: [[nodiscard]] Standard_EXPORT static uint32_t NbCoEdges(const BRepGraph& theGraph, const BRepGraph_WireId theWire); + //! Number of CoEdge usages in the referenced wire. + [[nodiscard]] Standard_EXPORT static uint32_t NbCoEdges(const BRepGraph& theGraph, + const BRepGraph_WireRefId theWireRef); + //! Number of distinct underlying edges in the wire (seam halves count once). //! @param[in] theGraph source graph //! @param[in] theWire typed wire definition identifier - //! @return number of distinct EdgeDefIds reachable from the wire's CoEdgeRefIds + //! @return number of distinct ChildEdgeIds reachable from the wire's CoEdgeIds [[nodiscard]] Standard_EXPORT static uint32_t NbDistinctEdges(const BRepGraph& theGraph, const BRepGraph_WireId theWire); - //! Returns the first owning face for this wire via the reverse-index table. + //! Number of distinct underlying edges in the referenced wire. + [[nodiscard]] Standard_EXPORT static uint32_t NbDistinctEdges( + const BRepGraph& theGraph, + const BRepGraph_WireRefId theWireRef); + + //! Returns the first owning face for this wire via relation tables. //! Returns an invalid id if the wire has no owning face (free wire). //! @param[in] theGraph source graph //! @param[in] theWire typed wire definition identifier @@ -631,7 +623,12 @@ public: [[nodiscard]] Standard_EXPORT static BRepGraph_FaceId FaceOf(const BRepGraph& theGraph, const BRepGraph_WireId theWire); - //! Returns true if this wire is the outer boundary (IsOuter flag) of its owning face. + //! Returns the first owning face for the referenced wire. + [[nodiscard]] Standard_EXPORT static BRepGraph_FaceId FaceOf( + const BRepGraph& theGraph, + const BRepGraph_WireRefId theWireRef); + + //! Returns true if this wire is the first active wire of its owning face. //! Scans WireRefs that reference this wire. //! Returns false for free wires (no owning face). //! @param[in] theGraph source graph @@ -639,6 +636,10 @@ public: //! @return true if outer wire [[nodiscard]] Standard_EXPORT static bool IsOuter(const BRepGraph& theGraph, const BRepGraph_WireId theWire); + + //! Returns true if the referenced wire is the outer wire of its owning face. + [[nodiscard]] Standard_EXPORT static bool IsOuter(const BRepGraph& theGraph, + const BRepGraph_WireRefId theWireRef); }; //! @brief Shell property accessors. @@ -647,83 +648,37 @@ public: class Shell { public: - //! Returns true if the shell is topologically closed (watertight boundary). + //! Resolves a shell reference id to a lightweight usage value. + //! @param[in] theGraph source graph + //! @param[in] theShellRef typed shell reference identifier + //! @return shell usage, or invalid usage if the reference is invalid or removed + [[nodiscard]] Standard_EXPORT static ShellUsage Usage(const BRepGraph& theGraph, + const BRepGraph_ShellRefId theShellRef); + + //! Returns true if the shell is topologically closed, derived from face-boundary edge + //! incidence. //! @param[in] theGraph source graph //! @param[in] theShell typed shell definition identifier //! @return true if closed [[nodiscard]] Standard_EXPORT static bool IsClosed(const BRepGraph& theGraph, const BRepGraph_ShellId theShell); + //! Returns true if the referenced shell is topologically closed. + [[nodiscard]] Standard_EXPORT static bool IsClosed(const BRepGraph& theGraph, + const BRepGraph_ShellRefId theShellRef); + //! Returns the number of face references in the shell. //! @param[in] theGraph source graph //! @param[in] theShell typed shell definition identifier //! @return number of face entries (including removed) [[nodiscard]] Standard_EXPORT static uint32_t NbFaces(const BRepGraph& theGraph, const BRepGraph_ShellId theShell); - }; - //! @brief Mesh cache writes and representation creation. - //! - //! Static methods for creating mesh representations in storage and - //! writing to the mesh cache. These do NOT trigger markModified() - //! or mutation tracking -- mesh data is derived, not model data. - class Mesh - { - public: - //! Create a new TriangulationRep in storage. - //! @return typed identifier, or invalid if the handle is null - [[nodiscard]] Standard_EXPORT static BRepGraph_TriangulationRepId CreateTriangulationRep( - BRepGraph& theGraph, - const occ::handle& theTriangulation); - - //! Create a new Polygon3DRep in storage. - //! @return typed identifier, or invalid if the handle is null - [[nodiscard]] Standard_EXPORT static BRepGraph_Polygon3DRepId CreatePolygon3DRep( - BRepGraph& theGraph, - const occ::handle& thePolygon); - - //! Create a new PolygonOnTriRep in storage. - //! @return typed identifier, or invalid if polygon is null or theTriRepId is invalid - [[nodiscard]] Standard_EXPORT static BRepGraph_PolygonOnTriRepId CreatePolygonOnTriRep( - BRepGraph& theGraph, - const occ::handle& thePolygon, - const BRepGraph_TriangulationRepId theTriRepId); - - //! Append a triangulation rep to the face's cached mesh (multi-LOD support). - Standard_EXPORT static void AppendCachedTriangulation( - BRepGraph& theGraph, - const BRepGraph_FaceId theFace, - const BRepGraph_TriangulationRepId theTriRepId); - - //! Set the active triangulation index in the face's cached mesh. - Standard_EXPORT static void SetCachedActiveIndex(BRepGraph& theGraph, - const BRepGraph_FaceId theFace, - const int theActiveIndex); - - //! Clear cached mesh for a face and its coedges. - Standard_EXPORT static void ClearFaceCache(BRepGraph& theGraph, const BRepGraph_FaceId theFace); - - //! Set the polygon-3D rep in the edge's cached mesh. - Standard_EXPORT static void SetCachedPolygon3D(BRepGraph& theGraph, - const BRepGraph_EdgeId theEdge, - const BRepGraph_Polygon3DRepId thePolyRepId); - - //! Clear cached mesh for an edge. - Standard_EXPORT static void ClearEdgeCache(BRepGraph& theGraph, const BRepGraph_EdgeId theEdge); - - //! Append a polygon-on-tri rep to the coedge's cached mesh (seam edge support). - Standard_EXPORT static void AppendCachedPolygonOnTri( - BRepGraph& theGraph, - const BRepGraph_CoEdgeId theCoEdge, - const BRepGraph_PolygonOnTriRepId thePolyRepId); - - //! Set the polygon-2D rep in the coedge's cached mesh. - Standard_EXPORT static void SetCachedPolygon2D(BRepGraph& theGraph, - const BRepGraph_CoEdgeId theCoEdge, - const BRepGraph_Polygon2DRepId thePolyRepId); + //! Returns the number of face references in the referenced shell. + [[nodiscard]] Standard_EXPORT static uint32_t NbFaces(const BRepGraph& theGraph, + const BRepGraph_ShellRefId theShellRef); }; -private: BRepGraph_Tool() = delete; }; diff --git a/opencascade/BRepGraph_TopoView.hxx b/opencascade/BRepGraph_TopoView.hxx index 7fd1815c0..9425e6d62 100644 --- a/opencascade/BRepGraph_TopoView.hxx +++ b/opencascade/BRepGraph_TopoView.hxx @@ -15,14 +15,22 @@ #define _BRepGraph_TopoView_HeaderFile #include -#include +#include #include +#include #include #include #include +#include #include class Adaptor3d_CurveOnSurface; +class Geom_Surface; +class Geom_Curve; +class Geom2d_Curve; +class Poly_Triangulation; +class BRepGraph_FacesOfEdge; +class BRepGraph_WiresOfEdge; //! @brief Unified read-only view over topology definitions, adjacency, and representations. //! @@ -44,9 +52,10 @@ class Adaptor3d_CurveOnSurface; //! reference IDs (BRepGraph_FaceRefId, BRepGraph_ShellRefId) and return //! reference-entry structs carrying per-use orientation and location. //! -//! Reverse-index accessors return const references to internal vectors. The -//! reference itself is always valid; the returned vector may be empty when the -//! queried entity has no parents of that kind. +//! Relations() is the single entry point for ordered topology relation containers. +//! Adjacency helpers return references only into existing relation storage. +//! Ref-owned parent links are exposed as reference-id containers; callers resolve +//! parent definitions through RefsView entries or typed iterators. class BRepGraph::TopoView { public: @@ -54,324 +63,436 @@ public: class FaceOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + //! Return the total number of face definitions (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + //! Return the number of active (non-soft-removed) face definitions. + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; + + //! Return the first valid face identifier for iteration. [[nodiscard]] BRepGraph_FaceId StartId() const { return BRepGraph_FaceId::Start(); } + //! Return the past-the-end face identifier (one past the last valid id). [[nodiscard]] BRepGraph_FaceId EndId() const { return BRepGraph_FaceId(Nb()); } + //! Return the definition struct for the given face. + //! @param[in] theFace typed face identifier [[nodiscard]] Standard_EXPORT const BRepGraphInc::FaceDef& Definition( const BRepGraph_FaceId theFace) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& Shells( + + //! Return the relation struct (adjacency lists) for the given face. + //! @param[in] theFace typed face identifier + [[nodiscard]] Standard_EXPORT const BRepGraphInc::FaceRelations& Relations( const BRepGraph_FaceId theFace) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& Compounds( + + //! Return the surface handle for the given face. + //! May be null if the face has no surface representation. + //! @param[in] theFace typed face identifier + [[nodiscard]] Standard_EXPORT occ::handle Surface( + const BRepGraph_FaceId theFace) const; + + //! Return the active triangulation for the given face. + //! Returns null if the face has no triangulation or it has been invalidated. + //! @param[in] theFace typed face identifier + [[nodiscard]] Standard_EXPORT occ::handle ActiveTriangulation( const BRepGraph_FaceId theFace) const; - [[nodiscard]] Standard_EXPORT BRepGraph_SurfaceRepId - SurfaceRepId(const BRepGraph_FaceId theFace) const; - [[nodiscard]] Standard_EXPORT BRepGraph_TriangulationRepId - ActiveTriangulationRepId(const BRepGraph_FaceId theFace) const; - [[nodiscard]] Standard_EXPORT NCollection_DynamicArray SameDomain( - const BRepGraph_FaceId theFace, - const occ::handle& theAllocator) const; - [[nodiscard]] Standard_EXPORT NCollection_DynamicArray SharedEdges( - const BRepGraph_FaceId theFaceA, - const BRepGraph_FaceId theFaceB, - const occ::handle& theAllocator) const; - [[nodiscard]] Standard_EXPORT NCollection_DynamicArray Adjacent( - const BRepGraph_FaceId theFace, - const occ::handle& theAllocator) const; - [[nodiscard]] Standard_EXPORT BRepGraph_WireId OuterWire(const BRepGraph_FaceId theFace) const; private: friend class TopoView; - explicit FaceOps(const BRepGraph* theGraph) + explicit FaceOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Edge-oriented topology queries. class EdgeOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + //! Return the total number of edge definitions (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + //! Return the number of active (non-soft-removed) edge definitions. + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; + + //! Return the first valid edge identifier for iteration. [[nodiscard]] BRepGraph_EdgeId StartId() const { return BRepGraph_EdgeId::Start(); } + //! Return the past-the-end edge identifier (one past the last valid id). [[nodiscard]] BRepGraph_EdgeId EndId() const { return BRepGraph_EdgeId(Nb()); } + //! Return the definition struct for the given edge. + //! @param[in] theEdge typed edge identifier [[nodiscard]] Standard_EXPORT const BRepGraphInc::EdgeDef& Definition( const BRepGraph_EdgeId theEdge) const; - [[nodiscard]] Standard_EXPORT uint32_t NbFaces(const BRepGraph_EdgeId theEdge) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& Wires( + + //! Return the relation struct (adjacency lists) for the given edge. + //! @param[in] theEdge typed edge identifier + [[nodiscard]] Standard_EXPORT const BRepGraphInc::EdgeRelations& Relations( const BRepGraph_EdgeId theEdge) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& CoEdges( + + //! Return the number of active faces adjacent to the given edge through active coedges. + //! @param[in] theEdge typed edge definition identifier + //! @return active adjacent face count + [[nodiscard]] Standard_EXPORT uint32_t NbFaces(const BRepGraph_EdgeId theEdge) const; + + //! Return an iterator over active wires that reference the given edge through active coedges. + //! @param[in] theEdge typed edge definition identifier + //! @return iterator positioned at the first active wire, or at end if none exists + [[nodiscard]] Standard_EXPORT BRepGraph_WiresOfEdge + WiresOf(const BRepGraph_EdgeId theEdge) const; + + //! Return an iterator over active wires from a stored edge-coedge relation index. + //! @param[in] theEdge typed edge definition identifier + //! @param[in] theStartIndex zero-based index in EdgeRelations::CoEdgeIds to resume from + //! @return iterator positioned at the first active wire at or after theStartIndex + [[nodiscard]] Standard_EXPORT BRepGraph_WiresOfEdge WiresOf(const BRepGraph_EdgeId theEdge, + const uint32_t theStartIndex) const; + + //! Return an iterator over active faces adjacent to the given edge through active coedges. + //! @param[in] theEdge typed edge definition identifier + //! @return iterator positioned at the first active face, or at end if none exists + [[nodiscard]] Standard_EXPORT BRepGraph_FacesOfEdge + FacesOf(const BRepGraph_EdgeId theEdge) const; + + //! Return an iterator over active faces from a stored edge-coedge relation index. + //! @param[in] theEdge typed edge definition identifier + //! @param[in] theStartIndex zero-based index in EdgeRelations::CoEdgeIds to resume from + //! @return iterator positioned at the first active face at or after theStartIndex + [[nodiscard]] Standard_EXPORT BRepGraph_FacesOfEdge FacesOf(const BRepGraph_EdgeId theEdge, + const uint32_t theStartIndex) const; + + //! Return the coedges that reference the given edge. + //! @param[in] theEdge typed edge identifier + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& CoEdges( const BRepGraph_EdgeId theEdge) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& Faces( + + //! Return the 3D curve handle for the given edge. + //! May be null if the edge has no 3D curve representation. + //! @param[in] theEdge typed edge identifier + [[nodiscard]] Standard_EXPORT occ::handle Curve3D( const BRepGraph_EdgeId theEdge) const; - [[nodiscard]] Standard_EXPORT BRepGraph_Curve3DRepId - Curve3DRepId(const BRepGraph_EdgeId theEdge) const; - [[nodiscard]] Standard_EXPORT NCollection_DynamicArray Adjacent( - const BRepGraph_EdgeId theEdge, - const occ::handle& theAllocator) const; - [[nodiscard]] Standard_EXPORT bool IsBoundary(const BRepGraph_EdgeId theEdge) const; - [[nodiscard]] Standard_EXPORT bool IsManifold(const BRepGraph_EdgeId theEdge) const; - [[nodiscard]] Standard_EXPORT const BRepGraphInc::CoEdgeDef* FindPCurve( - const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace) const; - [[nodiscard]] Standard_EXPORT const BRepGraphInc::CoEdgeDef* FindPCurve( - const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace, - const TopAbs_Orientation theOrientation) const; - - //! Find the CoEdgeId for a given (edge, face) pair. - //! @param[in] theEdge edge to look up - //! @param[in] theFace face the edge belongs to - //! @return CoEdgeId, or invalid if no coedge binds this edge to this face - [[nodiscard]] Standard_EXPORT BRepGraph_CoEdgeId - FindCoEdgeId(const BRepGraph_EdgeId theEdge, const BRepGraph_FaceId theFace) const; - - //! Find the CoEdgeId for a given (edge, face, orientation) triple. - //! Useful for seam edges where two coedges share the same face. - //! @param[in] theEdge edge to look up - //! @param[in] theFace face the edge belongs to - //! @param[in] theOrientation orientation to match (FORWARD or REVERSED) - //! @return CoEdgeId, or invalid if no coedge matches - [[nodiscard]] Standard_EXPORT BRepGraph_CoEdgeId - FindCoEdgeId(const BRepGraph_EdgeId theEdge, - const BRepGraph_FaceId theFace, - const TopAbs_Orientation theOrientation) const; private: friend class TopoView; - explicit EdgeOps(const BRepGraph* theGraph) + explicit EdgeOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Vertex-oriented topology queries. class VertexOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + //! Return the total number of vertex definitions (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + //! Return the number of active (non-soft-removed) vertex definitions. + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; + + //! Return the first valid vertex identifier for iteration. [[nodiscard]] BRepGraph_VertexId StartId() const { return BRepGraph_VertexId::Start(); } + //! Return the past-the-end vertex identifier (one past the last valid id). [[nodiscard]] BRepGraph_VertexId EndId() const { return BRepGraph_VertexId(Nb()); } + //! Return the definition struct for the given vertex. + //! @param[in] theVertex typed vertex identifier [[nodiscard]] Standard_EXPORT const BRepGraphInc::VertexDef& Definition( const BRepGraph_VertexId theVertex) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& Edges( + + //! Return the relation struct (adjacency lists) for the given vertex. + //! @param[in] theVertex typed vertex identifier + [[nodiscard]] Standard_EXPORT const BRepGraphInc::VertexRelations& Relations( + const BRepGraph_VertexId theVertex) const; + + //! Return the edges incident to the given vertex. + //! @param[in] theVertex typed vertex identifier + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& Edges( const BRepGraph_VertexId theVertex) const; private: friend class TopoView; - explicit VertexOps(const BRepGraph* theGraph) + explicit VertexOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Wire-oriented topology queries. class WireOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + //! Return the total number of wire definitions (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + //! Return the number of active (non-soft-removed) wire definitions. + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; + + //! Return the first valid wire identifier for iteration. [[nodiscard]] BRepGraph_WireId StartId() const { return BRepGraph_WireId::Start(); } + //! Return the past-the-end wire identifier (one past the last valid id). [[nodiscard]] BRepGraph_WireId EndId() const { return BRepGraph_WireId(Nb()); } + //! Return the definition struct for the given wire. + //! @param[in] theWire typed wire identifier [[nodiscard]] Standard_EXPORT const BRepGraphInc::WireDef& Definition( const BRepGraph_WireId theWire) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& Faces( + + //! Return the relation struct (adjacency lists) for the given wire. + //! @param[in] theWire typed wire identifier + [[nodiscard]] Standard_EXPORT const BRepGraphInc::WireRelations& Relations( const BRepGraph_WireId theWire) const; private: friend class TopoView; - explicit WireOps(const BRepGraph* theGraph) + explicit WireOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Shell-oriented topology queries. class ShellOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + //! Return the total number of shell definitions (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + //! Return the number of active (non-soft-removed) shell definitions. + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; + + //! Return the first valid shell identifier for iteration. [[nodiscard]] BRepGraph_ShellId StartId() const { return BRepGraph_ShellId::Start(); } + //! Return the past-the-end shell identifier (one past the last valid id). [[nodiscard]] BRepGraph_ShellId EndId() const { return BRepGraph_ShellId(Nb()); } + //! Return the definition struct for the given shell. + //! @param[in] theShell typed shell identifier [[nodiscard]] Standard_EXPORT const BRepGraphInc::ShellDef& Definition( const BRepGraph_ShellId theShell) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& Solids( - const BRepGraph_ShellId theShell) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& Compounds( + + //! Return the relation struct (adjacency lists) for the given shell. + //! @param[in] theShell typed shell identifier + [[nodiscard]] Standard_EXPORT const BRepGraphInc::ShellRelations& Relations( const BRepGraph_ShellId theShell) const; private: friend class TopoView; - explicit ShellOps(const BRepGraph* theGraph) + explicit ShellOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Solid-oriented topology queries. class SolidOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + //! Return the total number of solid definitions (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + + //! Return the number of active (non-soft-removed) solid definitions. + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; + //! Return the first valid solid identifier for iteration. [[nodiscard]] BRepGraph_SolidId StartId() const { return BRepGraph_SolidId::Start(); } + //! Return the past-the-end solid identifier (one past the last valid id). [[nodiscard]] BRepGraph_SolidId EndId() const { return BRepGraph_SolidId(Nb()); } + //! Return the definition struct for the given solid. + //! @param[in] theSolid typed solid identifier [[nodiscard]] Standard_EXPORT const BRepGraphInc::SolidDef& Definition( const BRepGraph_SolidId theSolid) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& CompSolids( - const BRepGraph_SolidId theSolid) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& Compounds( + + //! Return the relation struct (adjacency lists) for the given solid. + //! @param[in] theSolid typed solid identifier + [[nodiscard]] Standard_EXPORT const BRepGraphInc::SolidRelations& Relations( const BRepGraph_SolidId theSolid) const; private: friend class TopoView; - explicit SolidOps(const BRepGraph* theGraph) + explicit SolidOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Coedge-oriented topology and representation queries. class CoEdgeOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + //! Return the total number of coedge definitions (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + //! Return the number of active (non-soft-removed) coedge definitions. + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; + + //! Return the first valid coedge identifier for iteration. [[nodiscard]] BRepGraph_CoEdgeId StartId() const { return BRepGraph_CoEdgeId::Start(); } + //! Return the past-the-end coedge identifier (one past the last valid id). [[nodiscard]] BRepGraph_CoEdgeId EndId() const { return BRepGraph_CoEdgeId(Nb()); } + //! Return the definition struct for the given coedge. + //! @param[in] theCoEdge typed coedge identifier [[nodiscard]] Standard_EXPORT const BRepGraphInc::CoEdgeDef& Definition( const BRepGraph_CoEdgeId theCoEdge) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& Wires( - const BRepGraph_CoEdgeId theCoEdge) const; + + //! Return the parent edge of the given coedge. + //! @param[in] theCoEdge typed coedge identifier [[nodiscard]] Standard_EXPORT BRepGraph_EdgeId Edge(const BRepGraph_CoEdgeId theCoEdge) const; + + //! Return the face that owns the given coedge. + //! @param[in] theCoEdge typed coedge identifier [[nodiscard]] Standard_EXPORT BRepGraph_FaceId Face(const BRepGraph_CoEdgeId theCoEdge) const; - [[nodiscard]] Standard_EXPORT BRepGraph_Curve2DRepId - Curve2DRepId(const BRepGraph_CoEdgeId theCoEdge) const; - [[nodiscard]] Standard_EXPORT BRepGraph_CoEdgeId - SeamPair(const BRepGraph_CoEdgeId theCoEdge) const; + + //! Return the wire that owns the given coedge. + //! @param[in] theCoEdge typed coedge identifier + [[nodiscard]] Standard_EXPORT BRepGraph_WireId Wire(const BRepGraph_CoEdgeId theCoEdge) const; + + //! Return the 2D PCurve handle for the given coedge. + //! May be null if the coedge has no PCurve representation. + //! @param[in] theCoEdge typed coedge identifier + [[nodiscard]] Standard_EXPORT occ::handle Curve2D( + const BRepGraph_CoEdgeId theCoEdge) const; private: friend class TopoView; - explicit CoEdgeOps(const BRepGraph* theGraph) + explicit CoEdgeOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Compound-oriented topology queries. class CompoundOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + //! Return the total number of compound definitions (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + + //! Return the number of active (non-soft-removed) compound definitions. + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; + //! Return the first valid compound identifier for iteration. [[nodiscard]] BRepGraph_CompoundId StartId() const { return BRepGraph_CompoundId::Start(); } + //! Return the past-the-end compound identifier (one past the last valid id). [[nodiscard]] BRepGraph_CompoundId EndId() const { return BRepGraph_CompoundId(Nb()); } + //! Return the definition struct for the given compound. + //! @param[in] theCompound typed compound identifier [[nodiscard]] Standard_EXPORT const BRepGraphInc::CompoundDef& Definition( const BRepGraph_CompoundId theCompound) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& - ParentCompounds(const BRepGraph_CompoundId theCompound) const; + + //! Return the relation struct (child references) for the given compound. + //! @param[in] theCompound typed compound identifier + [[nodiscard]] Standard_EXPORT const BRepGraphInc::CompoundRelations& Relations( + const BRepGraph_CompoundId theCompound) const; private: friend class TopoView; - explicit CompoundOps(const BRepGraph* theGraph) + explicit CompoundOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Comp-solid oriented topology queries. class CompSolidOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + //! Return the total number of comp-solid definitions (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + //! Return the number of active (non-soft-removed) comp-solid definitions. + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; + + //! Return the first valid comp-solid identifier for iteration. [[nodiscard]] BRepGraph_CompSolidId StartId() const { return BRepGraph_CompSolidId::Start(); } + //! Return the past-the-end comp-solid identifier (one past the last valid id). [[nodiscard]] BRepGraph_CompSolidId EndId() const { return BRepGraph_CompSolidId(Nb()); } + //! Return the definition struct for the given comp-solid. + //! @param[in] theCompSolid typed comp-solid identifier [[nodiscard]] Standard_EXPORT const BRepGraphInc::CompSolidDef& Definition( const BRepGraph_CompSolidId theCompSolid) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& Compounds( + + //! Return the relation struct (child solids) for the given comp-solid. + //! @param[in] theCompSolid typed comp-solid identifier + [[nodiscard]] Standard_EXPORT const BRepGraphInc::CompSolidRelations& Relations( const BRepGraph_CompSolidId theCompSolid) const; private: friend class TopoView; - explicit CompSolidOps(const BRepGraph* theGraph) + explicit CompSolidOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Product-oriented raw assembly queries. class ProductOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + //! Return the total number of product definitions (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + //! Return the number of active (non-soft-removed) product definitions. + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; + + //! Return the first valid product identifier for iteration. [[nodiscard]] BRepGraph_ProductId StartId() const { return BRepGraph_ProductId::Start(); } + //! Return the past-the-end product identifier (one past the last valid id). [[nodiscard]] BRepGraph_ProductId EndId() const { return BRepGraph_ProductId(Nb()); } + //! Return the definition struct for the given product. + //! @param[in] theProduct typed product definition identifier [[nodiscard]] Standard_EXPORT const BRepGraphInc::ProductDef& Definition( const BRepGraph_ProductId theProduct) const; - [[nodiscard]] Standard_EXPORT const NCollection_DynamicArray& Instances( + + //! Return the relation struct (occurrences, shape root) for the given product. + //! @param[in] theProduct typed product definition identifier + [[nodiscard]] Standard_EXPORT const BRepGraphInc::ProductRelations& Relations( const BRepGraph_ProductId theProduct) const; + + //! Return the topology root NodeId for the given product. + //! For assemblies (no topology root) returns an invalid NodeId. + //! @param[in] theProduct typed product definition identifier [[nodiscard]] Standard_EXPORT BRepGraph_NodeId ShapeRoot(const BRepGraph_ProductId theProduct) const; @@ -391,7 +512,7 @@ public: //! Number of active child occurrences of a product. //! @param[in] theProduct typed product definition identifier - [[nodiscard]] Standard_EXPORT int NbComponents(const BRepGraph_ProductId theProduct) const; + [[nodiscard]] Standard_EXPORT uint32_t NbComponents(const BRepGraph_ProductId theProduct) const; //! Return the i-th active child occurrence identifier of a product. //! @param[in] theProduct typed product definition identifier @@ -402,29 +523,47 @@ public: private: friend class TopoView; - explicit ProductOps(const BRepGraph* theGraph) + explicit ProductOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Occurrence-oriented raw assembly queries. class OccurrenceOps { public: - [[nodiscard]] Standard_EXPORT int Nb() const; - [[nodiscard]] Standard_EXPORT int NbActive() const; + //! Return the total number of occurrence definitions (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb() const; + + //! Return the number of active (non-soft-removed) occurrence definitions. + [[nodiscard]] Standard_EXPORT uint32_t NbActive() const; + //! Return the first valid occurrence identifier for iteration. [[nodiscard]] BRepGraph_OccurrenceId StartId() const { return BRepGraph_OccurrenceId::Start(); } + //! Return the past-the-end occurrence identifier (one past the last valid id). [[nodiscard]] BRepGraph_OccurrenceId EndId() const { return BRepGraph_OccurrenceId(Nb()); } + //! Return the definition struct for the given occurrence. + //! @param[in] theOccurrence typed occurrence identifier [[nodiscard]] Standard_EXPORT const BRepGraphInc::OccurrenceDef& Definition( const BRepGraph_OccurrenceId theOccurrence) const; + + //! Return the relation struct (parent, placement) for the given occurrence. + //! @param[in] theOccurrence typed occurrence identifier + [[nodiscard]] Standard_EXPORT const BRepGraphInc::OccurrenceRelations& Relations( + const BRepGraph_OccurrenceId theOccurrence) const; + + //! Return the product that this occurrence instantiates. + //! @param[in] theOccurrence typed occurrence identifier [[nodiscard]] Standard_EXPORT BRepGraph_ProductId Product(const BRepGraph_OccurrenceId theOccurrence) const; + + //! Return the parent product that owns this occurrence. + //! @param[in] theOccurrence typed occurrence identifier [[nodiscard]] Standard_EXPORT BRepGraph_ProductId ParentProduct(const BRepGraph_OccurrenceId theOccurrence) const; //! Return the local placement of an occurrence (OccurrenceRef::LocalLocation). @@ -438,62 +577,100 @@ public: private: friend class TopoView; - explicit OccurrenceOps(const BRepGraph* theGraph) + explicit OccurrenceOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Generic topology and assembly count / meta queries. class GenOps { public: + //! Return the base definition pointer for any topology node (polymorphic). + //! Returns null if the node id is invalid, out of range, or soft-removed. + //! @param[in] theId node identifier (any kind) [[nodiscard]] Standard_EXPORT const BRepGraphInc::BaseDef* TopoEntity( const BRepGraph_NodeId theId) const; - [[nodiscard]] Standard_EXPORT int NbNodes() const; + + //! Return the compound (child) reference identifiers that point to the given node. + //! @param[in] theChild node identifier + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& + CompoundRefIds(const BRepGraph_NodeId theChild) const; + + //! Return the occurrence reference identifiers that point to the given node. + //! @param[in] theChild node identifier + [[nodiscard]] Standard_EXPORT const NCollection_LinearVector& + OccurrenceRefIds(const BRepGraph_NodeId theChild) const; + + //! True if the node has at least one compound parent. + //! @param[in] theNode node identifier + [[nodiscard]] Standard_EXPORT bool HasCompoundParents(const BRepGraph_NodeId theNode) const; + + //! True if the node has at least one occurrence parent. + //! @param[in] theNode node identifier + [[nodiscard]] Standard_EXPORT bool HasOccurrenceParents(const BRepGraph_NodeId theNode) const; + + //! Return the total number of nodes across all topology kinds (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t NbNodes() const; + + //! Return the number of node definitions of the specified kind (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t Nb(const BRepGraph_NodeId::Kind theKind) const; + + //! Return true if the node id kind and index are within storage bounds. + [[nodiscard]] Standard_EXPORT bool IsValid(const BRepGraph_NodeId theNode) const; + + //! Return true if the node id is valid and not soft-removed. + [[nodiscard]] Standard_EXPORT bool IsActive(const BRepGraph_NodeId theNode) const; + + //! Return true if the given node is invalid or has been soft-removed. + //! @param[in] theNode node identifier [[nodiscard]] Standard_EXPORT bool IsRemoved(const BRepGraph_NodeId theNode) const; private: friend class TopoView; - explicit GenOps(const BRepGraph* theGraph) + explicit GenOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! @brief Analytic geometry representation queries. class GeometryOps { public: - [[nodiscard]] Standard_EXPORT int NbSurfaces() const; - [[nodiscard]] Standard_EXPORT int NbCurves3D() const; - [[nodiscard]] Standard_EXPORT int NbCurves2D() const; + //! Return the total number of face surface representations (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t NbFaceSurfaces() const; + + //! Return the total number of edge 3D curve representations (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t NbEdgeCurves3D() const; + + //! Return the total number of coedge 2D PCurve representations (including soft-removed). + [[nodiscard]] Standard_EXPORT uint32_t NbCoEdgeCurves2D() const; + + //! Return the number of active (non-soft-removed) face surface representations. + [[nodiscard]] Standard_EXPORT uint32_t NbActiveFaceSurfaces() const; - [[nodiscard]] Standard_EXPORT int NbActiveSurfaces() const; - [[nodiscard]] Standard_EXPORT int NbActiveCurves3D() const; - [[nodiscard]] Standard_EXPORT int NbActiveCurves2D() const; + //! Return the number of active (non-soft-removed) edge 3D curve representations. + [[nodiscard]] Standard_EXPORT uint32_t NbActiveEdgeCurves3D() const; - [[nodiscard]] Standard_EXPORT const BRepGraphInc::SurfaceRep& SurfaceRep( - const BRepGraph_SurfaceRepId theRep) const; - [[nodiscard]] Standard_EXPORT const BRepGraphInc::Curve3DRep& Curve3DRep( - const BRepGraph_Curve3DRepId theRep) const; - [[nodiscard]] Standard_EXPORT const BRepGraphInc::Curve2DRep& Curve2DRep( - const BRepGraph_Curve2DRepId theRep) const; + //! Return the number of active (non-soft-removed) coedge 2D PCurve representations. + [[nodiscard]] Standard_EXPORT uint32_t NbActiveCoEdgeCurves2D() const; private: friend class TopoView; - explicit GeometryOps(const BRepGraph* theGraph) + explicit GeometryOps(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; //! Grouped face-oriented queries. @@ -537,10 +714,10 @@ public: //! Representations use dense 0-based indexing. Iterate through grouped accessors: //! @code - //! for (int i = 0; i < aGraph.Topo().Geometry().NbSurfaces(); ++i) + //! for (BRepGraph_FaceId aFId = aGraph.Topo().Faces().StartId(); + //! aFId < aGraph.Topo().Faces().EndId(); aFId = aFId.Next()) //! { - //! const BRepGraphInc::SurfaceRep& aRep = - //! aGraph.Topo().Geometry().SurfaceRep(BRepGraph_SurfaceRepId(i)); + //! occ::handle aSurf = aGraph.Topo().Faces().Surface(aFId); //! } //! @endcode @@ -549,7 +726,7 @@ private: friend struct BRepGraph_Data; friend class BRepGraph_Tool; - explicit TopoView(const BRepGraph* theGraph) + explicit TopoView(BRepGraph* theGraph) : myGraph(theGraph), myFaces(theGraph), myEdges(theGraph), @@ -567,20 +744,20 @@ private: { } - const BRepGraph* myGraph; - FaceOps myFaces; - EdgeOps myEdges; - VertexOps myVertices; - WireOps myWires; - ShellOps myShells; - SolidOps mySolids; - CoEdgeOps myCoEdges; - CompoundOps myCompounds; - CompSolidOps myCompSolids; - ProductOps myProducts; - OccurrenceOps myOccurrences; - GenOps myGen; - GeometryOps myGeometry; + BRepGraph* myGraph; + FaceOps myFaces; + EdgeOps myEdges; + VertexOps myVertices; + WireOps myWires; + ShellOps myShells; + SolidOps mySolids; + CoEdgeOps myCoEdges; + CompoundOps myCompounds; + CompSolidOps myCompSolids; + ProductOps myProducts; + OccurrenceOps myOccurrences; + GenOps myGen; + GeometryOps myGeometry; }; #endif // _BRepGraph_TopoView_HeaderFile diff --git a/opencascade/BRepGraph_Transform.hxx b/opencascade/BRepGraph_Transform.hxx index 5ded63041..d00b0173c 100644 --- a/opencascade/BRepGraph_Transform.hxx +++ b/opencascade/BRepGraph_Transform.hxx @@ -15,42 +15,44 @@ #define _BRepGraph_Transform_HeaderFile #include +#include #include -#include - +#include #include #include //! @brief Graph-to-graph transformation. //! -//! Produces a new BRepGraph by copying and then applying a geometric -//! transformation to vertex points and geometry node locations. +//! Applies a geometric transformation to vertex points and geometry node +//! locations by copying into a target graph, then transforming in-place. //! //! Two geometry modes (matching BRepBuilderAPI_Transform semantics): -//! - theCopyGeom = true (geometry-level): deep-copy geometry, transform handles -//! in-place via Geom_Surface::Transform() etc., reset locations to identity. -//! - theCopyGeom = false (root-level): light-copy with shared geometry, apply +//! - GeomPolicy::Copy (geometry-level): deep-copy geometry, create new +//! transformed handles via Geom_Geometry::Transformed(), reset locations +//! to identity. +//! - GeomPolicy::Share (root-level): light-copy with shared geometry, apply //! transform via location modification only. //! -//! Mesh handling (theCopyMesh parameter): -//! - theCopyMesh = false (default): triangulations and polygons are discarded -//! after a geometry-level transform and must be recomputed. -//! - theCopyMesh = true: all mesh data (Poly_Triangulation on FaceDefs and the +//! Mesh handling (MeshPolicy parameter): +//! - MeshPolicy::Drop (default for Transform): triangulations and polygons are +//! discarded after a geometry-level transform and must be recomputed. +//! - MeshPolicy::Copy: all mesh data (Poly_Triangulation on FaceDefs and the //! MeshLayer cache, Poly_Polygon3D on edges, Poly_PolygonOnTriangulation on //! coedges) is copied and transformed in sync with the geometry. //! In location-only mode the mesh data is copied as-is (nodes stay in the //! graph coordinate system, which is unaffected by a pure location compose). //! -//! @note Returns BRepGraph directly (not a Result struct) because this is an -//! immutable operation producing a new graph. Check IsDone() for success. +//! @note Check the return value for success: Perform returns bool, +//! TransformNode returns the mapped root NodeId (invalid on failure). //! //! ## Typical usage //! @code //! BRepGraph aGraph; -//! BRepGraph_Builder::Add(aGraph, myShape); +//! aGraph.Shapes().Add(myShape); //! gp_Trsf aTrsf; //! aTrsf.SetTranslation(gp_Vec(10.0, 0.0, 0.0)); -//! BRepGraph aTransformed = BRepGraph_Transform::Perform(aGraph, aTrsf); +//! BRepGraph aTransformed; +//! BRepGraph_Transform::Perform(aGraph, aTransformed, aTrsf); //! TopoDS_Shape aShape = aTransformed.Shapes().Shape(); //! @endcode class BRepGraph_Transform @@ -58,56 +60,83 @@ class BRepGraph_Transform public: DEFINE_STANDARD_ALLOC - //! Transform the entire graph. - //! @param[in] theGraph a pre-built BRepGraph (must have IsDone() == true) - //! @param[in] theTrsf the transformation to apply - //! @param[in] theCopyGeom if true, geometry is deep-copied before transforming; - //! if false, light-copy then transform locations/points only - //! @param[in] theCopyMesh if true, mesh data (triangulations, polygons) is copied and - //! transformed; if false, meshes are discarded after transform - //! @return a new BRepGraph with the transformation applied - [[nodiscard]] Standard_EXPORT static BRepGraph Perform(const BRepGraph& theGraph, - const gp_Trsf& theTrsf, - const bool theCopyGeom = true, - const bool theCopyMesh = false); + //! Transform the entire graph into a target graph. + //! + //! Self-transform (theSourceGraph == theTargetGraph): + //! Applies transform in-place on theTargetGraph. + //! + //! External transform to empty target (theTargetGraph.IsEmpty()): + //! Copies source into target, then transforms. + //! + //! External transform to non-empty target: + //! Appends source entities into target with explicit mapping, then transforms. + //! + //! @param[in] theSourceGraph a pre-built BRepGraph (must not be empty) + //! @param[in,out] theTargetGraph destination graph (may already contain data) + //! @param[in] theTrsf the transformation to apply + //! @param[in] theGeomPolicy geometry handle policy (default: Copy) + //! @param[in] theMeshPolicy mesh data policy (default: Drop) + //! @return true on success, false on failure (empty source, or Drop + + //! geometry-modification-required) + Standard_EXPORT static bool Perform( + const BRepGraph& theSourceGraph, + BRepGraph& theTargetGraph, + const gp_Trsf& theTrsf, + const BRepGraph_Copy::GeomPolicy theGeomPolicy = BRepGraph_Copy::GeomPolicy::Copy, + const BRepGraph_Copy::MeshPolicy theMeshPolicy = BRepGraph_Copy::MeshPolicy::Drop); - //! Transform a single node sub-graph of any kind (Face, Shell, Solid, Wire, Edge, Vertex). - //! Produces a new BRepGraph containing only the specified node and its referenced sub-graph. - //! The transform is applied to all copied geometry (same rules as Perform()). - //! @param[in] theGraph a pre-built BRepGraph - //! @param[in] theNodeId node identifier (any kind: Face, Shell, Solid, Wire, Edge, Vertex, - //! Compound, CompSolid, Product, Occurrence) - //! @param[in] theTrsf the transformation to apply - //! @param[in] theCopyGeom if true, geometry is deep-copied before transforming - //! @param[in] theCopyMesh if true, mesh data is copied and transformed - //! @return a new BRepGraph containing only the specified sub-graph, transformed - [[nodiscard]] Standard_EXPORT static BRepGraph TransformNode(const BRepGraph& theGraph, - const BRepGraph_NodeId theNodeId, - const gp_Trsf& theTrsf, - const bool theCopyGeom = true, - const bool theCopyMesh = false); + //! Transform a single node sub-graph of any kind. + //! Topology nodes are copied and transformed by baking the transform into their definitions. + //! + //! Self-transform (theSourceGraph == theTargetGraph): + //! Duplicates the sub-graph with new entity IDs, then transforms the copy. + //! + //! External transform: + //! Copies the sub-graph into theTargetGraph, then transforms. + //! + //! @param[in] theSourceGraph a pre-built BRepGraph + //! @param[in,out] theTargetGraph destination graph (may already contain data) + //! @param[in] theNodeId node identifier (any kind) + //! @param[in] theTrsf the transformation to apply + //! @param[in] theGeomPolicy geometry handle policy (default: Copy; Drop is invalid for topology) + //! @param[in] theMeshPolicy mesh data policy (default: Drop) + //! @return the mapped root NodeId in theTargetGraph, or invalid NodeId on failure + [[nodiscard]] Standard_EXPORT static BRepGraph_NodeId TransformNode( + const BRepGraph& theSourceGraph, + BRepGraph& theTargetGraph, + const BRepGraph_NodeId theNodeId, + const gp_Trsf& theTrsf, + const BRepGraph_Copy::GeomPolicy theGeomPolicy = BRepGraph_Copy::GeomPolicy::Copy, + const BRepGraph_Copy::MeshPolicy theMeshPolicy = BRepGraph_Copy::MeshPolicy::Drop); - //! Apply an in-place location-only transform to a single reference. - //! Composes theTrsf into the reference's LocalLocation field without copying - //! any geometry. This is O(1) and equivalent to TopoDS_Shape::Moved(trsf). + //! Apply an in-place location-only transform to a child reference. + //! Composes theTrsf into ChildRef placement without copying any geometry. //! Cached mesh data on entities downstream of the moved ref is stored in the //! entity's local frame and is unaffected; callers that bake a world transform //! into a cache key own the invalidation responsibility. //! @note Only pure rotation/translation transforms (scale == 1) are supported. - //! The method is a no-op and returns false if |scaleFactor| != 1. + //! The method returns false if |scaleFactor| != 1. //! @param[in] theGraph the graph containing the reference - //! @param[in] theRefId reference to move (any ref kind) + //! @param[in] theRefId child reference to move //! @param[in] theTrsf the transformation to compose into the location - //! @return true on success; false if theTrsf has a non-unit scale factor - Standard_EXPORT static bool MoveRef(BRepGraph& theGraph, - const BRepGraph_RefId& theRefId, - const gp_Trsf& theTrsf); + //! @return true on success; false if the ref is invalid/removed or theTrsf has non-unit scale + Standard_EXPORT static bool MoveRef(BRepGraph& theGraph, + const BRepGraph_ChildRefId theRefId, + const gp_Trsf& theTrsf); + + //! Apply an in-place location-only transform to an occurrence reference. + //! Composes theTrsf into OccurrenceRef placement without copying any geometry. + //! @note Only pure rotation/translation transforms (scale == 1) are supported. + //! @return true on success; false if the ref is invalid/removed or theTrsf has non-unit scale + Standard_EXPORT static bool MoveRef(BRepGraph& theGraph, + const BRepGraph_OccurrenceRefId theRefId, + const gp_Trsf& theTrsf); + + BRepGraph_Transform() = delete; private: //! Apply location-only transform by storing per-node locations. static void applyLocationTransform(BRepGraph& theGraph, const gp_Trsf& theTrsf); - - BRepGraph_Transform() = delete; }; #endif // _BRepGraph_Transform_HeaderFile diff --git a/opencascade/BRepGraph_TransientCache.hxx b/opencascade/BRepGraph_TransientCache.hxx deleted file mode 100644 index 122644a5c..000000000 --- a/opencascade/BRepGraph_TransientCache.hxx +++ /dev/null @@ -1,362 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraph_TransientCache_HeaderFile -#define _BRepGraph_TransientCache_HeaderFile - -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -//! @brief Descriptor of one transient cache family. -//! -//! A cache kind defines stable public identity for one class of transient, -//! recomputable per-node data such as bounding boxes or UV bounds. -//! Instances are process-global descriptors registered in -//! BRepGraph_CacheKindRegistry and referenced from graphs by dense runtime slots. -class BRepGraph_CacheKind : public Standard_Transient -{ -public: - //! Create a cache kind descriptor. - //! @param[in] theID stable public GUID identity - //! @param[in] theName display-only name - //! @param[in] theNodeKindsMask optional node-kind applicability mask; - //! 0 means "unspecified / unrestricted" - Standard_EXPORT BRepGraph_CacheKind( - const Standard_GUID& theID, - const TCollection_AsciiString& theName = TCollection_AsciiString(), - const int theNodeKindsMask = 0); - - //! Stable public identity. - [[nodiscard]] const Standard_GUID& ID() const { return myID; } - - //! Display-only metadata. - [[nodiscard]] const TCollection_AsciiString& Name() const { return myName; } - - //! Optional node-kind applicability mask. - [[nodiscard]] int NodeKindsMask() const { return myNodeKindsMask; } - - //! True if this cache kind is applicable to the given node kind. - //! Cache kinds with NodeKindsMask() == 0 are treated as unrestricted. - [[nodiscard]] bool SupportsNodeKind(const BRepGraph_NodeId::Kind theKind) const - { - return myNodeKindsMask == 0 || (myNodeKindsMask & KindBit(theKind)) != 0; - } - - //! Convenience: bitmask bit for a given node kind. - static int KindBit(const BRepGraph_NodeId::Kind theKind) - { - return 1 << static_cast(theKind); - } - - DEFINE_STANDARD_RTTIEXT(BRepGraph_CacheKind, Standard_Transient) - -private: - Standard_GUID myID; - TCollection_AsciiString myName; - int myNodeKindsMask = 0; -}; - -//! @brief Process-global registry of cache kind descriptors. -//! -//! Maps stable GUID identity to dense runtime slot index. Slot indices are an -//! internal storage detail used by BRepGraph_TransientCache for O(1) indexing. -//! The registry is shared across all BRepGraph instances in the current process, -//! so cache-kind GUIDs should be globally unique. -class BRepGraph_CacheKindRegistry -{ -public: - //! Register a cache kind descriptor. - //! Idempotent: the same GUID always yields the same slot. - //! Slot assignment is process-global and graph-instance independent. - //! @return dense runtime slot, or -1 for null input - [[nodiscard]] Standard_EXPORT static int Register( - const occ::handle& theKind); - - //! Find slot by GUID. Returns -1 if not found. - [[nodiscard]] Standard_EXPORT static int FindSlot(const Standard_GUID& theGUID); - - //! Find slot by GUID. - //! @param[out] theSlot dense runtime slot if found - //! @return true if the GUID is registered - Standard_EXPORT static bool FindSlot(const Standard_GUID& theGUID, int& theSlot); - - //! Find descriptor by GUID. - [[nodiscard]] Standard_EXPORT static occ::handle FindKind( - const Standard_GUID& theGUID); - - //! Find descriptor by slot. - [[nodiscard]] Standard_EXPORT static occ::handle FindKind(const int theSlot); - - //! Check whether a GUID is registered. - [[nodiscard]] Standard_EXPORT static bool Contains(const Standard_GUID& theGUID); - - //! Check whether a slot is registered. - [[nodiscard]] Standard_EXPORT static bool Contains(const int theSlot); - - //! Number of registered cache kinds. - [[nodiscard]] Standard_EXPORT static int NbRegistered(); - -private: - BRepGraph_CacheKindRegistry() = delete; -}; - -//! @brief Abstract base for transient per-node cache values. -//! -//! Inherits from Standard_Transient and is stored via -//! occ::handle. This uses OCCT's embedded refcount and is -//! consistent with the Handle pattern used throughout the codebase. -class BRepGraph_CacheValue : public Standard_Transient -{ -public: - //! Mark the cached value as needing recomputation. Lock-free. - void Invalidate() { myDirty.store(true, std::memory_order_release); } - - //! True if the cached value needs recomputation. - bool IsDirty() const { return myDirty.load(std::memory_order_acquire); } - - DEFINE_STANDARD_RTTI_INLINE(BRepGraph_CacheValue, Standard_Transient) - -protected: - BRepGraph_CacheValue() - : myDirty(true) - { - } - - //! Subclass calls after successful computation to clear the dirty flag. - void MarkClean() const { myDirty.store(false, std::memory_order_release); } - - //! Mutex for thread-safe Get() in subclasses. - mutable std::shared_mutex myMutex; - -private: - mutable std::atomic myDirty; -}; - -//! @brief Concrete typed wrapper for a lazily-computed per-node value. -//! -//! @tparam T cached value type (for example double). -template -class BRepGraph_TypedCacheValue : public BRepGraph_CacheValue -{ -public: - BRepGraph_TypedCacheValue() = default; - - //! Construct with an initial value (marked clean). - explicit BRepGraph_TypedCacheValue(const T& theInitial) - : myValue(theInitial) - { - MarkClean(); - } - - //! Get the cached value, computing via theComputer if dirty. - //! Thread-safe: uses the base class shared_mutex. - T Get(const std::function& theComputer) const - { - if (!IsDirty()) - { - std::shared_lock aLock(myMutex); - if (!IsDirty()) - { - return myValue; - } - } - - std::unique_lock aLock(myMutex); - if (IsDirty()) - { - myValue = theComputer(); - MarkClean(); - } - return myValue; - } - - //! Direct write - stores the value and marks clean. - void Set(const T& theValue) - { - std::unique_lock aLock(myMutex); - myValue = theValue; - MarkClean(); - } - - //! Direct read. Caller must guarantee freshness. - const T& UncheckedValue() const { return myValue; } - -private: - mutable T myValue{}; -}; - -//! @brief Centralized transient cache for algorithm-computed per-node values. -//! -//! Stores short-lived cached data (BndBox, UVBounds, etc.) in dense per-cache-kind -//! vectors indexed by entity index. O(1) access by direct indexing - no hashing. -//! -//! ## SubtreeGen-based freshness -//! Each stored slot records SubtreeGen at write time. On read, if stored -//! SubtreeGen differs from entity's current SubtreeGen the cached value is -//! considered stale - the caller decides how to handle it. -//! -//! ## Lifecycle -//! NOT a Layer. Cleared on BRepGraph_Builder::Add() and Compact(). No OnNodeRemoved handling - -//! stale data is auto-detected by SubtreeGen mismatch. -//! -//! ## Thread safety -//! After Reserve(), Get() and Set() for in-range indices bypass the mutex -//! entirely - safe because parallel algorithms access different entity slots. -//! Out-of-range access (entities added after construction) falls back to mutex. -class BRepGraph_TransientCache -{ -public: - //! Number of Kind enum slots to cover (0..11, with gap at 9). - static constexpr int THE_KIND_COUNT = BRepGraph_NodeId::THE_KIND_COUNT; - - //! Default number of cache-kind slots reserved after BRepGraph_Builder::Add(). - static constexpr int THE_DEFAULT_RESERVED_KIND_COUNT = 16; - - //! Per-slot storage: cached value handle + SubtreeGen stamp. - struct CacheSlot - { - occ::handle Value; - uint32_t StoredSubtreeGen = 0; - }; - - //! Store a cached value for a node and cache kind. - //! @pre Reserve() must have been called for lock-free parallel access - //! on in-range entity indices; out-of-range access falls back to mutex. - Standard_EXPORT void Set(const BRepGraph_NodeId theNode, - const occ::handle& theKind, - const occ::handle& theValue, - const uint32_t theCurrentSubtreeGen); - - //! Store a cached value using a pre-resolved kind slot index. - //! Bypasses BRepGraph_CacheKindRegistry lookup - use in hot parallel paths. - //! @param[in] theKindSlot slot from BRepGraph_CacheKindRegistry::Register() - Standard_EXPORT void Set(const BRepGraph_NodeId theNode, - const int theKindSlot, - const occ::handle& theValue, - const uint32_t theCurrentSubtreeGen); - - //! Retrieve a cached value for a node and cache kind. - //! @pre Reserve() must have been called for lock-free parallel access - //! on in-range entity indices; out-of-range access falls back to mutex. - [[nodiscard]] Standard_EXPORT occ::handle Get( - const BRepGraph_NodeId theNode, - const occ::handle& theKind, - const uint32_t theCurrentSubtreeGen) const; - - //! Retrieve a cached value using a pre-resolved kind slot index. - //! Bypasses BRepGraph_CacheKindRegistry lookup - use in hot parallel paths. - //! @param[in] theKindSlot slot from BRepGraph_CacheKindRegistry::Register() - [[nodiscard]] Standard_EXPORT occ::handle Get( - const BRepGraph_NodeId theNode, - const int theKindSlot, - const uint32_t theCurrentSubtreeGen) const; - - //! Remove a cached value for a node and cache kind. - [[nodiscard]] Standard_EXPORT bool Remove(const BRepGraph_NodeId theNode, - const occ::handle& theKind); - - //! Remove a cached value using a pre-resolved cache-kind slot. - [[nodiscard]] Standard_EXPORT bool Remove(const BRepGraph_NodeId theNode, const int theKindSlot); - - //! Collect fresh cache-kind slot indices for a node (zero heap allocation). - //! Used internally by CacheView::CacheKindIterator. - //! @param[in] theNode node to query - //! @param[in] theCurrentSubtreeGen freshness stamp to match - //! @param[out] theSlots output array (caller-allocated, must hold - //! THE_DEFAULT_RESERVED_KIND_COUNT) - //! @return number of populated slots written to theSlots - Standard_EXPORT int CollectCacheKindSlots(const BRepGraph_NodeId theNode, - const uint32_t theCurrentSubtreeGen, - int theSlots[]) const; - - //! Pre-allocate storage for lock-free parallel access. - Standard_EXPORT void Reserve(const int theKindCount, const int theCounts[THE_KIND_COUNT]); - - //! True if Reserve() has been called and storage is pre-allocated. - [[nodiscard]] bool IsReserved() const noexcept - { - return myIsReserved.load(std::memory_order_acquire); - } - - //! Clear all cached data. Called on BRepGraph_Builder::Add() and Compact(). - Standard_EXPORT void Clear() noexcept; - - //! Move constructor: transfers data, creates fresh mutex. - BRepGraph_TransientCache(BRepGraph_TransientCache&& theOther) noexcept - : myKinds(std::move(theOther.myKinds)), - myIsReserved(theOther.myIsReserved.load(std::memory_order_relaxed)) - { - theOther.myIsReserved.store(false, std::memory_order_relaxed); - } - - //! Move assignment: transfers data, mutex stays local. - BRepGraph_TransientCache& operator=(BRepGraph_TransientCache&& theOther) noexcept - { - if (this != &theOther) - { - myKinds = std::move(theOther.myKinds); - myIsReserved.store(theOther.myIsReserved.load(std::memory_order_relaxed), - std::memory_order_relaxed); - theOther.myIsReserved.store(false, std::memory_order_relaxed); - } - return *this; - } - - BRepGraph_TransientCache() = default; - BRepGraph_TransientCache(const BRepGraph_TransientCache&) = delete; - BRepGraph_TransientCache& operator=(const BRepGraph_TransientCache&) = delete; - -private: - //! Per-node-kind dense vector of cache slots. - struct NodeKindStore - { - NCollection_DynamicArray mySlots; - }; - - //! Per-cache-kind storage: one node-kind store per entity kind. - struct CacheKindSlot - { - NodeKindStore myNodeKinds[THE_KIND_COUNT]; - }; - - //! Ensure myKinds has capacity for the given cache-kind slot. - void ensureKind(const int theKindSlot); - - //! Access slot (mutable) - grows vector if needed. - CacheSlot& changeSlot(const BRepGraph_NodeId theNode, const int theKindSlot); - - //! Access slot (const) - returns nullptr if out of range. - const CacheSlot* seekSlot(const BRepGraph_NodeId theNode, const int theKindSlot) const; - - //! Outer vector indexed by cache-kind slot. - NCollection_DynamicArray myKinds; - - //! True after Reserve() - enables lock-free access for in-range slots. - std::atomic myIsReserved{false}; - - //! Protects structural modifications (vector growth) during concurrent access. - mutable std::shared_mutex myMutex; -}; - -#endif // _BRepGraph_TransientCache_HeaderFile diff --git a/opencascade/BRepGraph_UID.hxx b/opencascade/BRepGraph_UID.hxx index 0958b4cf3..431759a3c 100644 --- a/opencascade/BRepGraph_UID.hxx +++ b/opencascade/BRepGraph_UID.hxx @@ -15,104 +15,93 @@ #define _BRepGraph_UID_HeaderFile #include +#include +#include #include #include #include +#include -//! Unique node identifier within a BRepGraph. +//! Unique definition-node identifier within a BRepGraph. //! -//! Identity = (Kind, Counter). Two nodes of different kinds may share a +//! Identity = (Kind, Counter). Two nodes of different kinds may share a //! counter value but their UIDs are distinct. Within one kind, counter //! values never repeat (monotonic, never resets). //! -//! Generation is NOT part of identity; it indicates which BRepGraph::Clear() cycle -//! produced this UID (for stale-reference detection). -//! //! Trivially copyable, cheap to pass by value. -//! -//! ## Serialization Contract -//! -//! Entity UIDs (BRepGraph_UID) and reference UIDs (BRepGraph_RefUID) share -//! a single monotonic counter (BRepGraph_Data::myNextUIDCounter). -//! To persist a BRepGraph across sessions: -//! 1. Write: for each entity, serialize (Kind, Counter, OwnGen). -//! 2. Read: reconstruct entities, populate UID vectors with deserialized -//! (Kind, Counter) values, set myNextUIDCounter to -//! max(all_entity_counters, all_ref_counters) + 1. -//! 3. myGeneration resets to 0 on load (session-scoped). -//! 4. VersionStamps from a previous session will correctly detect staleness -//! via Generation mismatch. struct BRepGraph_UID { + BRepGraph_NodeId::Kind Kind = BRepGraph_NodeId::Kind::Solid; + uint32_t Counter = 0; + //! Default: invalid UID (counter = 0 is the invalid sentinel). - BRepGraph_UID() - : myCounter(0), - myKind(BRepGraph_NodeId::Kind::Solid), - myGeneration(0) - { - } + BRepGraph_UID() = default; - //! Construct a valid UID. Called internally by BRepGraph::allocateUID(). + //! Construct a valid UID. Called internally by BRepGraphInc_Storage::AllocateNodeUID(). //! @pre theCounter > 0 (counter = 0 is reserved as the invalid sentinel) - BRepGraph_UID(const BRepGraph_NodeId::Kind theKind, - const size_t theCounter, - const uint32_t theGeneration) - : myCounter(theCounter), - myKind(theKind), - myGeneration(theGeneration) + BRepGraph_UID(const BRepGraph_NodeId::Kind theKind, const uint32_t theCounter) + : Kind(theKind), + Counter(theCounter) { - Standard_ASSERT_VOID(theCounter > 0, "BRepGraph_UID: counter must be > 0 for valid UIDs"); } //! Factory: returns an explicitly invalid UID. static BRepGraph_UID Invalid() { return BRepGraph_UID(); } - [[nodiscard]] bool IsValid() const { return myCounter > 0; } - - [[nodiscard]] BRepGraph_NodeId::Kind Kind() const { return myKind; } - - [[nodiscard]] size_t Counter() const { return myCounter; } - - [[nodiscard]] uint32_t Generation() const { return myGeneration; } + //! True if this UID has a valid kind and a non-zero counter. + [[nodiscard]] bool IsValid() const { return Counter > 0 && BRepGraph_NodeId::IsValidKind(Kind); } - [[nodiscard]] bool IsTopology() const { return BRepGraph_NodeId::IsTopologyKind(myKind); } + [[nodiscard]] bool IsTopology() const + { + return IsValid() && BRepGraph_NodeId::IsTopologyKind(Kind); + } - [[nodiscard]] bool IsAssembly() const { return BRepGraph_NodeId::IsAssemblyKind(myKind); } + [[nodiscard]] bool IsAssembly() const + { + return IsValid() && BRepGraph_NodeId::IsAssemblyKind(Kind); + } - //! Equality: Identity = (Kind, Counter). Generation excluded. - //! Two invalid UIDs are equal. - bool operator==(const BRepGraph_UID& theOther) const + //! Equality: Identity = (Kind, Counter). Two invalid UIDs are equal. + friend bool operator==(const BRepGraph_UID& theLeft, const BRepGraph_UID& theRight) noexcept { - if (myCounter == 0 || theOther.myCounter == 0) - return (myCounter == 0) == (theOther.myCounter == 0); - return myKind == theOther.myKind && myCounter == theOther.myCounter; + if (theLeft.Counter == 0 || theRight.Counter == 0) + { + return (theLeft.Counter == 0) == (theRight.Counter == 0); + } + return theLeft.Kind == theRight.Kind && theLeft.Counter == theRight.Counter; } - bool operator!=(const BRepGraph_UID& theOther) const { return !(*this == theOther); } + friend bool operator!=(const BRepGraph_UID& theLeft, const BRepGraph_UID& theRight) noexcept + { + return !(theLeft == theRight); + } - bool operator<(const BRepGraph_UID& theOther) const + friend bool operator<(const BRepGraph_UID& theLeft, const BRepGraph_UID& theRight) noexcept { - if (myKind != theOther.myKind) - return static_cast(myKind) < static_cast(theOther.myKind); - return myCounter < theOther.myCounter; + if (theLeft.Kind != theRight.Kind) + { + return static_cast(theLeft.Kind) < static_cast(theRight.Kind); + } + return theLeft.Counter < theRight.Counter; } - //! Hash value: f(Kind, Counter). - [[nodiscard]] size_t HashValue() const + //! Hash value compatible with operator==. + [[nodiscard]] size_t HashValue() const noexcept { + if (Counter == 0) + { + return opencascade::hash(0); + } size_t aCombination[2]; - aCombination[0] = opencascade::hash(static_cast(myKind)); - aCombination[1] = opencascade::hash(myCounter); + aCombination[0] = opencascade::hash(static_cast(Kind)); + aCombination[1] = opencascade::hash(Counter); return opencascade::hashBytes(aCombination, sizeof(aCombination)); } - -private: - size_t myCounter; //!< 0 = invalid sentinel; valid counters start at 1. - BRepGraph_NodeId::Kind myKind; //!< Node kind. - uint32_t myGeneration; //!< BRepGraph::Clear() cycle that produced this UID. }; +static_assert(sizeof(BRepGraph_UID) <= 8, "BRepGraph_UID must stay compact"); + //! std::hash specialization for NCollection_DefaultHasher support. template <> struct std::hash diff --git a/opencascade/BRepGraph_UIDsView.hxx b/opencascade/BRepGraph_UIDsView.hxx index 161a18367..0c98960e5 100644 --- a/opencascade/BRepGraph_UIDsView.hxx +++ b/opencascade/BRepGraph_UIDsView.hxx @@ -19,13 +19,17 @@ class Standard_GUID; -//! @brief Read-only view for persistent unique identifiers. +//! @brief Read-only view for persistent node and reference identifiers. //! //! UIDs are (Kind, Counter) pairs that persist across graph mutations //! (Compact, node removal). Counters are monotonic and independent of vector //! indices. Clear() starts a new graph generation and refreshes the graph //! GUID, enabling stale-reference detection when a graph is rebuilt. -//! Provides bidirectional NodeId/UID resolution. Obtained via BRepGraph::UIDs(). +//! Provides bidirectional NodeId/UID and RefId/RefUID resolution. +//! +//! Version stamps are exposed here for graph-owned cache and layer freshness +//! checks. They reuse node/reference UID identity and do not introduce a +//! persistent representation identity. class BRepGraph::UIDsView { public: @@ -40,6 +44,11 @@ public: //! removed [[nodiscard]] Standard_EXPORT BRepGraph_RefUID Of(const BRepGraph_RefId theRefId) const; + //! Return the persistent UID assigned to a generic graph item. + //! @param[in] theItem definition-node or reference-entry item id + //! @return durable item UID, or invalid UID if the item is out of bounds or removed + [[nodiscard]] Standard_EXPORT BRepGraph_ItemUID Of(const BRepGraph_ItemId theItem) const; + //! Resolve a UID back to a NodeId using the internal reverse index. //! @param[in] theUID unique identifier to resolve //! @return corresponding active NodeId, or invalid NodeId if not found/removed @@ -50,6 +59,11 @@ public: //! @return corresponding active RefId, or invalid RefId if not found/removed [[nodiscard]] Standard_EXPORT BRepGraph_RefId RefIdFrom(const BRepGraph_RefUID& theUID) const; + //! Resolve a generic item UID back to a transient item id. + //! @param[in] theUID durable node/reference item identity + //! @return active item id, or invalid item id if the UID cannot be resolved + [[nodiscard]] Standard_EXPORT BRepGraph_ItemId ItemIdFrom(const BRepGraph_ItemUID& theUID) const; + //! Check if a UID is valid and exists in this graph generation. //! @param[in] theUID unique identifier to check //! @return true if the UID resolves to an active node in this graph generation @@ -60,6 +74,9 @@ public: //! @return true if the RefUID resolves to an active reference in this graph generation [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_RefUID& theUID) const; + //! Check if a generic item UID exists in this graph generation. + [[nodiscard]] Standard_EXPORT bool Has(const BRepGraph_ItemUID& theUID) const; + //! Return the current generation counter (incremented on each BRepGraph::Clear()). //! @return graph generation number [[nodiscard]] Standard_EXPORT uint32_t Generation() const; @@ -83,8 +100,20 @@ public: [[nodiscard]] Standard_EXPORT BRepGraph_VersionStamp StampOf(const BRepGraph_RefId theRefId) const; + //! Produce a version stamp for an owner-scoped use record. + //! Use records have no durable UID or mutation generation; the stamp uses the owning + //! definition-node UID, OwnGen, and graph Generation. + //! @param[in] theRepId use-record identifier + //! @return version stamp, or invalid stamp if theRepId is invalid, removed, or out of bounds + [[nodiscard]] Standard_EXPORT BRepGraph_VersionStamp + StampOf(const BRepGraph_RepId theRepId) const; + + //! Produce a version stamp for the given definition-node or reference-entry item. + [[nodiscard]] Standard_EXPORT BRepGraph_VersionStamp + StampOf(const BRepGraph_ItemId theItem) const; + //! Check if a previously-taken stamp is stale. - //! A stamp is stale when the stamped node or reference has been mutated, + //! A stamp is stale when the stamped item has been mutated, //! removed, or the graph was rebuilt since the stamp was taken. //! @param[in] theStamp version stamp to check //! @return true if the stamp no longer matches the current graph state @@ -94,12 +123,12 @@ private: friend class BRepGraph; friend struct BRepGraph_Data; - explicit UIDsView(const BRepGraph* theGraph) + explicit UIDsView(BRepGraph* theGraph) : myGraph(theGraph) { } - const BRepGraph* myGraph; + BRepGraph* myGraph; }; #endif // _BRepGraph_UIDsView_HeaderFile diff --git a/opencascade/BRepGraph_UsagePath.hxx b/opencascade/BRepGraph_UsagePath.hxx new file mode 100644 index 000000000..e2728a910 --- /dev/null +++ b/opencascade/BRepGraph_UsagePath.hxx @@ -0,0 +1,122 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _BRepGraph_UsagePath_HeaderFile +#define _BRepGraph_UsagePath_HeaderFile + +#include +#include +#include + +#include +#include + +//! Explicit identity of a concrete usage from traversal root to selected node. +//! +//! A usage path is an ordered sequence of steps that records the exact +//! traversal from a root node down to a specific graph entity. Each step +//! captures the node reached, the reference through which it was reached, +//! and the sibling order (step index) at that level. +//! +//! Paths are used to disambiguate multiple occurrences of the same +//! definition reachable through different references or sibling positions. +class BRepGraph_UsagePath +{ +public: + //! One concrete traversal step in a usage path. + //! + //! Ref is valid for reference-owned links and invalid for structural links + //! such as CoEdge -> Edge or Occurrence -> Product/topology-root. Step keeps + //! sibling order explicit, so coincident or structurally-linked usages remain + //! distinguishable without relying on location or hashes. + struct Step + { + BRepGraph_NodeId Node; + BRepGraph_RefId Ref; + int StepIndex = -1; + + bool operator==(const Step& theOther) const + { + return Node == theOther.Node && Ref == theOther.Ref && StepIndex == theOther.StepIndex; + } + }; + +public: + //! Creates an empty usage path. + BRepGraph_UsagePath() = default; + + //! Creates a usage path with pre-allocated capacity. + //! @param[in] theCapacity number of steps to pre-allocate + explicit BRepGraph_UsagePath(const size_t theCapacity) + : mySteps(theCapacity) + { + } + + //! Returns the number of steps in the path. + size_t Size() const { return mySteps.Size(); } + + //! Returns true if the path has no steps. + bool IsEmpty() const { return mySteps.IsEmpty(); } + + //! Returns the step at the given index. + //! @param[in] theIdx zero-based index + const Step& Value(const size_t theIdx) const { return mySteps.Value(theIdx); } + + //! Returns the first step in the path. + const Step& First() const { return mySteps.First(); } + + //! Returns the last step in the path. + const Step& Last() const { return mySteps.Last(); } + + //! Appends a step to the end of the path. + //! @param[in] theStep step to append + void Append(Step theStep) { mySteps.Append(std::move(theStep)); } + + //! Inserts a step before the given index. + //! @param[in] theIdx zero-based index to insert before + //! @param[in] theStep step to insert + void InsertBefore(const size_t theIdx, Step theStep) + { + mySteps.InsertBefore(theIdx, std::move(theStep)); + } + + //! Removes all steps from the path. + void Clear() { mySteps.Clear(); } + + //! Returns true if this path is equal to the other path. + //! @param[in] theOther path to compare with + bool IsEqual(const BRepGraph_UsagePath& theOther) const; + + //! Returns true if this path is equal to the other path. + //! @param[in] theOther path to compare with + bool operator==(const BRepGraph_UsagePath& theOther) const { return IsEqual(theOther); } + + //! Returns a hash code for this path. + //! Uses first step, last step, and size for O(1) computation. + size_t HashCode() const; + +private: + NCollection_LinearVector mySteps; +}; + +//! std::hash specialization for BRepGraph_UsagePath. +template <> +struct std::hash +{ + size_t operator()(const BRepGraph_UsagePath& thePath) const noexcept + { + return thePath.HashCode(); + } +}; + +#endif // _BRepGraph_UsagePath_HeaderFile diff --git a/opencascade/BRepGraph_Validate.hxx b/opencascade/BRepGraph_Validate.hxx index d588b668f..97bad30f3 100644 --- a/opencascade/BRepGraph_Validate.hxx +++ b/opencascade/BRepGraph_Validate.hxx @@ -15,16 +15,15 @@ #define _BRepGraph_Validate_HeaderFile #include - #include -#include +#include #include #include //! @brief Structural invariant checker for BRepGraph. //! //! Read-only algorithm that verifies the graph's internal consistency: -//! cross-reference bounds, reverse index symmetry, incidence ref consistency, +//! cross-reference bounds, relation symmetry, incidence ref consistency, //! geometry reference validity, removed-node isolation, and wire connectivity. //! //! Distinct from BRepGraphCheck (geometric shape validity). This class @@ -35,12 +34,13 @@ //! | Check | Lightweight | Audit | //! |--------------------------------|:-----------:|:-----:| //! | Active entity count boundary | YES | YES | +//! | Document root product sanity | YES | YES | //! | Cross-reference bounds | - | YES | //! | Reverse-index consistency | - | YES | //! | Face-count cache consistency | - | YES | //! | Incidence ref consistency | - | YES | //! | Geometry representation refs | - | YES | -//! | Removed-node isolation | - | YES | +//! | Removed-node isolation | YES | YES | //! | Wire edge connectivity | - | YES | //! | Entity ID positional integrity | - | YES | //! | UID round-trip integrity | - | YES | @@ -50,10 +50,10 @@ //! //! | Mode | What it checks | Cost | Recommended use | //! |------|----------------|------|-----------------| -//! | `Lightweight` | Active entity count boundary only | Low | Hot-path release builds when the -//! graph structure is already trusted | | `Audit` | Full structural audit from cross-reference -//! bounds through assembly DAG cycle detection | Higher | Default validation mode for production -//! pipelines, test gates, and API-boundary verification | +//! | `Lightweight` | Active entity count boundary plus removed-node isolation | Low | Hot-path +//! release builds when the graph structure is already trusted | | `Audit` | Full structural audit +//! from cross-reference bounds through assembly DAG cycle detection | Higher | Default validation +//! mode for production pipelines, test gates, and API-boundary verification | //! //! For production pipelines, prefer `Mode::Audit`; `Mode::Lightweight` is intended //! for hot-path release builds where the graph structure is already trusted. @@ -89,30 +89,13 @@ public: //! Aggregated validation result. struct Result { - NCollection_DynamicArray Issues; + NCollection_LinearVector Issues; //! True if no Error-level issues were found. - [[nodiscard]] bool IsValid() const - { - for (const Issue& anIssue : Issues) - { - if (anIssue.Sev == Severity::Error) - return false; - } - return true; - } + [[nodiscard]] Standard_EXPORT bool IsValid() const; //! Count issues of a given severity. - [[nodiscard]] int NbIssues(const Severity theSev) const - { - int aCount = 0; - for (const Issue& anIssue : Issues) - { - if (anIssue.Sev == theSev) - ++aCount; - } - return aCount; - } + [[nodiscard]] Standard_EXPORT int NbIssues(const Severity theSev) const; }; //! Validation options. @@ -158,8 +141,12 @@ public: [[nodiscard]] Standard_EXPORT static Result Perform(const BRepGraph& theGraph, const Options& theOptions); -private: BRepGraph_Validate() = delete; + +private: + static void CheckOwnedUseReferences( + const BRepGraph& theGraph, + NCollection_LinearVector& theIssues); }; #endif // _BRepGraph_Validate_HeaderFile diff --git a/opencascade/BRepGraph_VersionStamp.hxx b/opencascade/BRepGraph_VersionStamp.hxx index 963e450f5..fcc3d3b56 100644 --- a/opencascade/BRepGraph_VersionStamp.hxx +++ b/opencascade/BRepGraph_VersionStamp.hxx @@ -14,17 +14,18 @@ #ifndef _BRepGraph_VersionStamp_HeaderFile #define _BRepGraph_VersionStamp_HeaderFile +#include #include #include #include #include -//! @brief Snapshot of an entity/ref identity and version at a point in time. +//! @brief Snapshot of a graph item identity and its freshness generation. //! -//! Combines a persistent UID (entity or reference entry) with -//! OwnGen (own-data version counter) and graph Generation (BRepGraph::Clear() cycle). -//! Computed on demand via BRepGraph::UIDs().StampOf(). +//! Combines a persistent node or reference UID with OwnGen (own-data mutation counter) +//! and graph Generation (BRepGraph::Clear() cycle). It is intended for custom cache and +//! layer freshness checks, not as a separate topology identity model. //! //! Usage pattern: //! @code @@ -39,17 +40,16 @@ struct BRepGraph_VersionStamp //! Identity domain encoded in this stamp. enum class Domain : uint8_t { - None = 0, - Entity = 1, - Ref = 2 + None = 0, + Node = 1, + Reference = 2 }; - BRepGraph_UID myUID; //!< Entity identity for entity-domain stamps. - BRepGraph_RefUID myRefUID; //!< Reference identity for ref-domain stamps. - uint32_t - myMutationGen; //!< OwnGen counter at snapshot time (maps to BaseDef::OwnGen / BaseRef::OwnGen). - uint32_t myGeneration; //!< Graph BRepGraph::Clear() generation at snapshot time. - Domain myDomain; //!< Active identity domain. + BRepGraph_UID myNodeUID; //!< Definition-node identity for node-domain stamps. + BRepGraph_RefUID myRefUID; //!< Reference-entry identity for reference-domain stamps. + uint32_t myMutationGen; //!< OwnGen counter at snapshot time. + uint32_t myGeneration; //!< Graph BRepGraph::Clear() generation at snapshot time. + Domain myDomain; //!< Active identity domain. //! Default constructor. Creates an invalid stamp (invalid UID, zero counters). BRepGraph_VersionStamp() @@ -59,17 +59,17 @@ struct BRepGraph_VersionStamp { } - //! Construct an entity-domain stamp from components. - //! @param[in] theUID persistent entity identity + //! Construct a node-domain stamp from components. + //! @param[in] theUID persistent definition-node identity //! @param[in] theMutationGen OwnGen counter (own-data mutation counter) //! @param[in] theGeneration graph BRepGraph::Clear() generation BRepGraph_VersionStamp(const BRepGraph_UID& theUID, const uint32_t theMutationGen, const uint32_t theGeneration) - : myUID(theUID), + : myNodeUID(theUID), myMutationGen(theMutationGen), myGeneration(theGeneration), - myDomain(Domain::Entity) + myDomain(Domain::Node) { } @@ -83,69 +83,69 @@ struct BRepGraph_VersionStamp : myRefUID(theRefUID), myMutationGen(theMutationGen), myGeneration(theGeneration), - myDomain(Domain::Ref) + myDomain(Domain::Reference) { } //! Check if the stamp has a valid identity in its domain. [[nodiscard]] bool IsValid() const { - if (myDomain == Domain::Entity) - return myUID.IsValid(); - if (myDomain == Domain::Ref) + if (myDomain == Domain::Node) + { + return myNodeUID.IsValid(); + } + if (myDomain == Domain::Reference) + { return myRefUID.IsValid(); - return myUID.IsValid() || myRefUID.IsValid(); + } + return myNodeUID.IsValid() || myRefUID.IsValid(); } - //! True when this is an entity-domain stamp. - [[nodiscard]] bool IsEntityStamp() const + //! True when this is a definition-node-domain stamp. + [[nodiscard]] bool IsNodeStamp() const { - if (myDomain == Domain::Entity) - return myUID.IsValid(); - return myDomain == Domain::None && myUID.IsValid() && !myRefUID.IsValid(); + if (myDomain == Domain::Node) + { + return myNodeUID.IsValid(); + } + return myDomain == Domain::None && myNodeUID.IsValid() && !myRefUID.IsValid(); } //! True when this is a reference-domain stamp. [[nodiscard]] bool IsRefStamp() const { - if (myDomain == Domain::Ref) + if (myDomain == Domain::Reference) + { return myRefUID.IsValid(); - return myDomain == Domain::None && myRefUID.IsValid() && !myUID.IsValid(); + } + return myDomain == Domain::None && myRefUID.IsValid() && !myNodeUID.IsValid(); } - //! Full equality: same domain, UID, OwnGen, and Generation. - //! Two invalid stamps are equal. - bool operator==(const BRepGraph_VersionStamp& theOther) const + //! Return the active generic item identity. + [[nodiscard]] BRepGraph_ItemUID ItemUID() const { - if (!IsValid() && !theOther.IsValid()) - return true; - if (myDomain != theOther.myDomain) - return false; - if (myMutationGen != theOther.myMutationGen || myGeneration != theOther.myGeneration) - return false; - if (myDomain == Domain::Entity) - return myUID == theOther.myUID; - if (myDomain == Domain::Ref) - return myRefUID == theOther.myRefUID; - return myUID == theOther.myUID && myRefUID == theOther.myRefUID; + if (myDomain == Domain::Node) + { + return BRepGraph_ItemUID::Node(myNodeUID.Kind, myNodeUID.Counter); + } + if (myDomain == Domain::Reference) + { + return BRepGraph_ItemUID::Reference(myRefUID.Kind, myRefUID.Counter); + } + return BRepGraph_ItemUID(); } + //! Full equality: same domain, UID, OwnGen, and Generation. + //! Two invalid stamps are equal. + Standard_EXPORT bool operator==(const BRepGraph_VersionStamp& theOther) const; + bool operator!=(const BRepGraph_VersionStamp& theOther) const { return !(*this == theOther); } - //! Check if two stamps refer to the same entity/reference regardless of version. + //! Check if two stamps refer to the same graph item regardless of version. //! Compares active UID only, ignoring OwnGen and Generation. //! @param[in] theOther stamp to compare with //! @return true if both stamps have the same domain and UID - [[nodiscard]] bool IsSameNode(const BRepGraph_VersionStamp& theOther) const - { - if (myDomain != theOther.myDomain) - return false; - if (myDomain == Domain::Entity) - return myUID == theOther.myUID; - if (myDomain == Domain::Ref) - return myRefUID == theOther.myRefUID; - return myUID == theOther.myUID && myRefUID == theOther.myRefUID; - } + [[nodiscard]] Standard_EXPORT bool IsSameItem(const BRepGraph_VersionStamp& theOther) const; //! Derive a deterministic Standard_GUID from this stamp. //! The graph GUID is incorporated into the hash, making per-node GUIDs @@ -157,20 +157,7 @@ struct BRepGraph_VersionStamp //! Compute hash value consistent with operator==. //! @return hash combining active UID, domain, OwnGen, and Generation - [[nodiscard]] size_t HashValue() const - { - size_t aCombination[4]; - aCombination[0] = opencascade::hash(static_cast(myDomain)); - if (myDomain == Domain::Entity) - aCombination[1] = myUID.HashValue(); - else if (myDomain == Domain::Ref) - aCombination[1] = myRefUID.HashValue(); - else - aCombination[1] = opencascade::hash(0); - aCombination[2] = opencascade::hash(myMutationGen); - aCombination[3] = opencascade::hash(myGeneration); - return opencascade::hashBytes(aCombination, sizeof(aCombination)); - } + [[nodiscard]] Standard_EXPORT size_t HashValue() const; }; //! std::hash specialization for NCollection_DefaultHasher support. diff --git a/opencascade/BRepGraph_WireExplorer.hxx b/opencascade/BRepGraph_WireExplorer.hxx deleted file mode 100644 index c2fb49c8a..000000000 --- a/opencascade/BRepGraph_WireExplorer.hxx +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright (c) 2026 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepGraph_WireExplorer_HeaderFile -#define _BRepGraph_WireExplorer_HeaderFile - -#include -#include -#include -#include -#include -#include - -class BRepGraph; - -//! @brief Iterator for traversing wire edges in connection order using graph data. -//! @see BRepGraph class comment "Iterator guide" for choosing between iterator types. -//! -//! Reorders wire coedges by vertex adjacency: the end vertex of each edge -//! matches the start vertex of the next. This is the graph equivalent of -//! BRepTools_WireExplorer, operating on pre-built BRepGraph data. -//! -//! The coedges are reordered on construction (O(N^2) worst case for N coedges). -//! For most wires this is fast since N is small (4-8 edges typically). -//! -//! Internal storage uses NCollection_LocalArray with stack allocation for -//! wires with up to 16 edges (the common case), falling back to heap for larger wires. -//! -//! Usage: -//! @code -//! BRepGraph_WireExplorer anExp(aGraph, aWireId); -//! for (; anExp.More(); anExp.Next()) -//! { -//! const BRepGraph_CoEdgeId aCoEdgeId = anExp.CurrentCoEdgeId(); -//! const BRepGraphInc::CoEdgeDef& aDef = aGraph.Topo().CoEdges().Definition(aCoEdgeId); -//! // ... use aDef ... -//! } -//! @endcode -class BRepGraph_WireExplorer -{ -public: - //! Initialize the explorer from a pre-built BRepGraph and wire identifier. - //! Collects coedge IDs from graph iterators and reorders them by vertex connectivity. - //! @param[in] theGraph pre-built BRepGraph (IsDone() == true) - //! @param[in] theWire wire definition identifier - BRepGraph_WireExplorer(const BRepGraph& theGraph, const BRepGraph_WireId theWire) - : myCurrent(0), - myLength(0) - { - buildOrder(theGraph, theWire); - } - - //! Returns true if there are more edges to iterate. - bool More() const { return myCurrent < myLength; } - - //! Advance to the next edge. - void Next() { ++myCurrent; } - - //! Reset the iterator to the beginning (for re-iteration). - void Reset() { myCurrent = 0; } - - //! Current coedge definition identifier in connection order. - BRepGraph_CoEdgeId CurrentCoEdgeId() const { return myOrder[myCurrent]; } - - //! Number of coedges in the ordered sequence. - int NbEdges() const { return myLength; } - - //! Current coedge identifier (alias for CurrentCoEdgeId(), enables range-for). - BRepGraph_CoEdgeId Current() const { return CurrentCoEdgeId(); } - - //! Returns an STL-compatible iterator for range-based for loops. - //! Yields BRepGraph_CoEdgeId values. - NCollection_ForwardRangeIterator begin() - { - return NCollection_ForwardRangeIterator(this); - } - - //! Returns a sentinel marking the end of iteration. - NCollection_ForwardRangeSentinel end() const { return NCollection_ForwardRangeSentinel{}; } - -private: - //! Resolve the oriented start vertex of an edge. - static BRepGraph_NodeId orientedStartVertex(const BRepGraph& theGraph, - const BRepGraphInc::EdgeDef& theEdge, - const TopAbs_Orientation theOrientation) - { - const BRepGraph_VertexRefId aRefId = - (theOrientation == TopAbs_FORWARD) ? theEdge.StartVertexRefId : theEdge.EndVertexRefId; - if (!aRefId.IsValid()) - return BRepGraph_NodeId(); - return theGraph.Refs().Vertices().Entry(aRefId).VertexDefId; - } - - //! Resolve the oriented end vertex of an edge. - static BRepGraph_NodeId orientedEndVertex(const BRepGraph& theGraph, - const BRepGraphInc::EdgeDef& theEdge, - const TopAbs_Orientation theOrientation) - { - const BRepGraph_VertexRefId aRefId = - (theOrientation == TopAbs_FORWARD) ? theEdge.EndVertexRefId : theEdge.StartVertexRefId; - if (!aRefId.IsValid()) - return BRepGraph_NodeId(); - return theGraph.Refs().Vertices().Entry(aRefId).VertexDefId; - } - - //! Recursive backtracking chain: try to extend myOrder from theDepth onward, - //! picking each unused candidate whose oriented start matches the previous - //! oriented end. Returns true iff a full chain covering [0, theNbEdges) is built. - bool chainRecursive(const BRepGraph& theGraph, - const NCollection_LocalArray& theInput, - NCollection_LocalArray& theUsed, - const int theDepth, - const int theNbEdges) - { - if (theDepth == theNbEdges) - return true; - - const BRepGraphInc::CoEdgeDef& aPrevCoEdge = - theGraph.Topo().CoEdges().Definition(myOrder[theDepth - 1]); - const BRepGraphInc::EdgeDef& aPrevEdge = - theGraph.Topo().Edges().Definition(aPrevCoEdge.EdgeDefId); - const BRepGraph_NodeId aPrevEnd = - orientedEndVertex(theGraph, aPrevEdge, aPrevCoEdge.Orientation); - - for (int i = 0; i < theNbEdges; ++i) - { - if (theUsed[i]) - continue; - const BRepGraphInc::CoEdgeDef& aCandCoEdge = - theGraph.Topo().CoEdges().Definition(theInput[i]); - const BRepGraphInc::EdgeDef& aCandEdge = - theGraph.Topo().Edges().Definition(aCandCoEdge.EdgeDefId); - const BRepGraph_NodeId aCandStart = - orientedStartVertex(theGraph, aCandEdge, aCandCoEdge.Orientation); - - if (!aPrevEnd.IsValid() || !aCandStart.IsValid() || aPrevEnd != aCandStart) - continue; - - myOrder[theDepth] = theInput[i]; - theUsed[i] = true; - if (chainRecursive(theGraph, theInput, theUsed, theDepth + 1, theNbEdges)) - return true; - theUsed[i] = false; - } - return false; - } - - //! Build connection-ordered coedge sequence from graph data. - //! Uses greedy depth-first backtracking so that wires with ambiguous - //! continuations (e.g. cylinder lateral face with a seam pair) still produce - //! a fully connected chain whenever one exists. For pathologically disconnected - //! wires, remaining coedges are appended in input order. - void buildOrder(const BRepGraph& theGraph, const BRepGraph_WireId theWire) - { - int aNbEdges = 0; - for (BRepGraph_RefsCoEdgeOfWire aCountIt(theGraph, theWire); aCountIt.More(); aCountIt.Next()) - ++aNbEdges; - - if (aNbEdges == 0) - return; - - NCollection_LocalArray anInput(aNbEdges); - { - int anIdx = 0; - for (BRepGraph_RefsCoEdgeOfWire aCEIt(theGraph, theWire); aCEIt.More(); aCEIt.Next()) - { - const BRepGraphInc::CoEdgeRef& aCRef = theGraph.Refs().CoEdges().Entry(aCEIt.CurrentId()); - anInput[anIdx++] = aCRef.CoEdgeDefId; - } - } - - myOrder.Allocate(aNbEdges); - myLength = aNbEdges; - - NCollection_LocalArray aUsed(aNbEdges); - for (int i = 0; i < aNbEdges; ++i) - aUsed[i] = false; - - myOrder[0] = anInput[0]; - aUsed[0] = true; - - if (!chainRecursive(theGraph, anInput, aUsed, 1, aNbEdges)) - { - // Pathologically disconnected wire: append any unused coedges in input order. - for (int aPlaced = 1; aPlaced < aNbEdges; ++aPlaced) - { - for (int i = 0; i < aNbEdges; ++i) - { - if (!aUsed[i]) - { - myOrder[aPlaced] = anInput[i]; - aUsed[i] = true; - break; - } - } - } - } - } - - NCollection_LocalArray myOrder; //!< Ordered coedge IDs (stack for <=16). - int myCurrent; //!< Current iteration index. - int myLength; //!< Number of coedges. -}; - -#endif // _BRepGraph_WireExplorer_HeaderFile diff --git a/opencascade/Convert_GridPolynomialToPoles.hxx b/opencascade/Convert_GridPolynomialToPoles.hxx index 4e2fc6b1d..cc4662bc6 100644 --- a/opencascade/Convert_GridPolynomialToPoles.hxx +++ b/opencascade/Convert_GridPolynomialToPoles.hxx @@ -22,10 +22,10 @@ #include #include -#include -#include #include +#include #include +#include //! Convert a grid of Polynomial Surfaces //! that are have continuity CM to an @@ -45,12 +45,23 @@ public: //! The have to be formatted than an "C array" //! [MaxUDegree+1] [MaxVDegree+1] [3] Standard_EXPORT Convert_GridPolynomialToPoles( - const int MaxUDegree, - const int MaxVDegree, - const occ::handle>& NumCoeff, - const occ::handle>& Coefficients, - const occ::handle>& PolynomialUIntervals, - const occ::handle>& PolynomialVIntervals); + const int theMaxUDegree, + const int theMaxVDegree, + const NCollection_Array1& theNumCoeff, + const NCollection_Array1& theCoefficients, + const NCollection_Array1& thePolynomialUIntervals, + const NCollection_Array1& thePolynomialVIntervals); + + //! Handle-based overload (delegates to the array-based constructor). + //! Provided for backward compatibility; new code should prefer the + //! @c NCollection_Array1 form which avoids unnecessary heap allocation. + Standard_EXPORT Convert_GridPolynomialToPoles( + const int theMaxUDegree, + const int theMaxVDegree, + const occ::handle>& theNumCoeff, + const occ::handle>& theCoefficients, + const occ::handle>& thePolynomialUIntervals, + const occ::handle>& thePolynomialVIntervals); //! To one grid of polynomial Surface. //! Warning! @@ -67,18 +78,33 @@ public: //! [1, NbVSurfaces*NbUSurfaces, 1,2] array. //! if is not a Standard_EXPORT Convert_GridPolynomialToPoles( - const int NbUSurfaces, - const int NBVSurfaces, - const int UContinuity, - const int VContinuity, - const int MaxUDegree, - const int MaxVDegree, - const occ::handle>& NumCoeffPerSurface, - const occ::handle>& Coefficients, - const occ::handle>& PolynomialUIntervals, - const occ::handle>& PolynomialVIntervals, - const occ::handle>& TrueUIntervals, - const occ::handle>& TrueVIntervals); + const int theNbUSurfaces, + const int theNbVSurfaces, + const int theUContinuity, + const int theVContinuity, + const int theMaxUDegree, + const int theMaxVDegree, + const NCollection_Array2& theNumCoeffPerSurface, + const NCollection_Array1& theCoefficients, + const NCollection_Array1& thePolynomialUIntervals, + const NCollection_Array1& thePolynomialVIntervals, + const NCollection_Array1& theTrueUIntervals, + const NCollection_Array1& theTrueVIntervals); + + //! Handle-based overload (delegates to the array-based constructor). + Standard_EXPORT Convert_GridPolynomialToPoles( + const int theNbUSurfaces, + const int theNbVSurfaces, + const int theUContinuity, + const int theVContinuity, + const int theMaxUDegree, + const int theMaxVDegree, + const occ::handle>& theNumCoeffPerSurface, + const occ::handle>& theCoefficients, + const occ::handle>& thePolynomialUIntervals, + const occ::handle>& thePolynomialVIntervals, + const occ::handle>& theTrueUIntervals, + const occ::handle>& theTrueVIntervals); //! Returns the number of poles in the U parametric direction. [[nodiscard]] Standard_EXPORT int NbUPoles() const; @@ -117,16 +143,16 @@ public: [[nodiscard]] Standard_EXPORT bool IsDone() const; private: - Standard_EXPORT void Perform(const int UContinuity, - const int VContinuity, - const int MaxUDegree, - const int MaxVDegree, - const occ::handle>& NumCoeffPerSurface, - const occ::handle>& Coefficients, - const occ::handle>& PolynomialUIntervals, - const occ::handle>& PolynomialVIntervals, - const occ::handle>& TrueUIntervals, - const occ::handle>& TrueVIntervals); + Standard_EXPORT void Perform(const int theUContinuity, + const int theVContinuity, + const int theMaxUDegree, + const int theMaxVDegree, + const NCollection_Array2& theNumCoeffPerSurface, + const NCollection_Array1& theCoefficients, + const NCollection_Array1& thePolynomialUIntervals, + const NCollection_Array1& thePolynomialVIntervals, + const NCollection_Array1& theTrueUIntervals, + const NCollection_Array1& theTrueVIntervals); Standard_EXPORT void BuildArray(const int Degree, const NCollection_Array1& Knots, diff --git a/opencascade/GeomFill_Gordon.hxx b/opencascade/GeomFill_Gordon.hxx index 0051af1a6..b181223db 100644 --- a/opencascade/GeomFill_Gordon.hxx +++ b/opencascade/GeomFill_Gordon.hxx @@ -27,17 +27,15 @@ //! High-level Gordon surface construction from arbitrary curve networks. //! //! A Gordon surface (transfinite interpolation) constructs a smooth B-spline -//! surface from a network of intersecting profile (V) and guide (U) curves -//! using the Boolean sum formula: -//! S = S_profiles + S_guides - S_tensor +//! surface from a network of intersecting profile (V) and guide (U) curves. //! //! This generalizes the existing GeomFill_Coons (4-boundary patch) to N x M //! curve networks. //! //! This class accepts arbitrary Geom_Curve inputs, handles conversion to BSpline, -//! intersection detection, network sorting, curve reparametrization for -//! compatibility, then delegates to GeomFill_GordonBuilder for the core -//! mathematical construction. +//! expands periodic B-splines into explicit non-periodic form, finds intersections, +//! sorts the network, reparametrizes curves for compatibility, then evaluates a +//! transfinite interpolation surface over the compatible network. //! //! Usage: //! @code @@ -51,12 +49,77 @@ //! @endcode //! //! Limitations: -//! - Non-rational curves only +//! - Every profile must intersect every guide. Multiple contacts are accepted +//! only when they contain a single monotone branch over the ordered network. +//! - Rational networks are combined by exact common-denominator multiplication. +//! Construction can fail if the resulting product degree exceeds OCCT's +//! B-spline degree limit. +//! - ApproximationMode::AllowApproximateFallback may build a sampled surface +//! when exact construction fails, or rebuild rational curves approximately +//! when exact reparametrization is required. Such a surface is marked by +//! IsApproximate() and does not guarantee exact interpolation of the input curves. class GeomFill_Gordon { public: DEFINE_STANDARD_ALLOC + //! Result state of the last Perform() call. + enum class ResultStatus + { + NotStarted, //!< Perform() has not been called since initialization. + Done, //!< Surface has been constructed. + InvalidInput, //!< Input network has too few profile or guide curves. + ConversionFailed, //!< Curves could not be converted/reparametrized to B-splines. + IntersectionFailed, //!< Full profile/guide intersection table could not be built. + OrderingFailed, //!< Network curves could not be ordered consistently. + ReparametrizationFailed, //!< Intersections could not be equalized in parameter space. + CompatibilityFailed, //!< Prepared network failed geometric compatibility checks. + CurveCompatibilityFailed, //!< Prepared curve families are not B-spline compatible. + RationalReparametrizationFailed, //!< Rational curves require unsupported exact + //!< reparametrization. + SkinningFailed, //!< Intermediate profile/guide skinning has failed. + ReferenceSurfaceFailed, //!< Intersection-grid reference surface could not be built. + KnotAlignmentFailed, //!< Intermediate surfaces could not be aligned. + RationalDegreeOverflow, //!< Exact rational product degree exceeds OCCT's B-spline limit. + RationalConstructionFailed, //!< Exact rational numerator/denominator construction has failed. + PeriodicityFailed, //!< Closed seam could not be converted to periodic form. + ApproximationFailed, //!< Optional approximate fallback has failed. + ConstructionFailed //!< Final B-spline surface construction has failed. + }; + + //! Controls behavior when exact pole-based construction fails. + enum class ApproximationMode + { + ExactOnly, //!< Report exact construction failure (default). + AllowApproximateFallback //!< Try a sampled B-spline fallback without exact interpolation. + }; + + //! Construction stage reached by the last Perform() call. + enum class BuildStage + { + NotStarted, //!< Perform() has not started. + InputConversion, //!< Input curves are being converted to working B-splines. + ContactDiscovery, //!< Profile/guide contacts are being collected. + NetworkOrdering, //!< Contacts and curves are being ordered into a monotone network. + Reparametrization, //!< Curves are being rebuilt to shared network parameters. + ExactConstruction, //!< Exact B-spline network surface is being constructed. + Validation, //!< Result is being checked against prepared curves. + Approximation //!< Optional sampled fallback is being built. + }; + + //! Diagnostics for the last Perform() call. + struct BuildReport + { + ResultStatus Status = ResultStatus::NotStarted; + BuildStage FailedStage = BuildStage::NotStarted; + bool IsApproximate = false; + double MaxContactGap = 0.0; + double MaxReparametrizationDeviation = 0.0; + double MaxProfileDeviation = 0.0; + double MaxGuideDeviation = 0.0; + double MaxApproximationDeviation = 0.0; + }; + //! Creates an empty Gordon surface algorithm. Standard_EXPORT GeomFill_Gordon(); @@ -75,64 +138,46 @@ public: //! By default, single-thread mode is used. void SetParallelMode(bool theToUseParallel) { myToUseParallel = theToUseParallel; } + //! Sets optional fallback behavior for failures in exact B-spline construction. + //! Approximate fallback results should be checked by IsApproximate(). + void SetApproximationMode(ApproximationMode theMode) { myApproximationMode = theMode; } + + //! Returns current fallback behavior. + [[nodiscard]] ApproximationMode GetApproximationMode() const { return myApproximationMode; } + //! Returns true if internal parallel processing is enabled. [[nodiscard]] bool IsParallelMode() const { return myToUseParallel; } //! Returns true if the surface was successfully constructed. - [[nodiscard]] bool IsDone() const { return myIsDone; } + [[nodiscard]] bool IsDone() const { return myReport.Status == ResultStatus::Done; } + + //! Returns true if the resulting surface was produced by approximate fallback. + //! Approximate results do not have the exact Gordon interpolation guarantee. + [[nodiscard]] bool IsApproximate() const { return myReport.IsApproximate; } + + //! Returns the result state of the last Perform() call. + [[nodiscard]] ResultStatus Status() const { return myReport.Status; } + + //! Returns diagnostics for the last Perform() call. + [[nodiscard]] const BuildReport& Report() const { return myReport; } //! Returns the resulting Gordon B-spline surface. [[nodiscard]] Standard_EXPORT const occ::handle& Surface() const; private: - //! Converts all input curves to BSpline and reparametrizes to [0,1]. - bool convertToBSpline(); - - //! Computes all profile x guide intersections using GeomAPI_ExtremaCurveCurve. - //! Fills myProfileParams and myGuideParams. - //! @return true if all N x M intersections were found - bool computeIntersections(); - - //! Sorts the network so profiles are ordered left-to-right - //! and guides bottom-to-top, based on intersection parameters. - bool sortNetwork(); - - //! Snaps intersection parameters that are near curve start/end boundaries - //! to the exact boundary values, eliminating numerical inaccuracies. - //! Based on occ_gordon's EliminateInaccuraciesNetworkIntersections. - void eliminateInaccuracies(); - - //! Validates that profiles and guides actually intersect at their claimed - //! parameters within tolerance after reparametrization. - //! Based on occ_gordon's CheckCurveNetworkCompatibility. - //! @return true if all intersection points are within tolerance - bool checkNetworkCompatibility() const; - - //! Averages intersection parameters and reparametrizes curves - //! so intersections occur at averaged target parameters. - //! Uses approximation-based approach with kink detection and - //! intelligent sample distribution for robustness. - bool reparametrize(); - - //! Computes the geometric scale factor from all curve endpoints. - //! Used for scale-relative tolerance computations. - void computeScale(); - - //! Detects whether the curve network is closed in U or V direction. - //! Sets myIsUClosed and myIsVClosed flags. - void detectClosedness(); - + NCollection_Array1> myInputProfiles; + NCollection_Array1> myInputGuides; NCollection_Array1> myProfiles; NCollection_Array1> myGuides; NCollection_Array2 myProfileParams; NCollection_Array2 myGuideParams; occ::handle mySurface; double myTolerance = 0.0; - double myScale = 1.0; bool myIsUClosed = false; bool myIsVClosed = false; bool myToUseParallel = false; - bool myIsDone = false; + ApproximationMode myApproximationMode = ApproximationMode::ExactOnly; + BuildReport myReport; }; #endif // _GeomFill_Gordon_HeaderFile diff --git a/opencascade/GeomFill_GordonBuilder.hxx b/opencascade/GeomFill_GordonBuilder.hxx deleted file mode 100644 index e404727a1..000000000 --- a/opencascade/GeomFill_GordonBuilder.hxx +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2025 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _GeomFill_GordonBuilder_HeaderFile -#define _GeomFill_GordonBuilder_HeaderFile - -#include -#include -#include - -#include -#include -#include -#include -#include - -//! Core mathematical kernel for Gordon surface construction via the Boolean sum method. -//! -//! Accepts pre-compatible BSpline curves (same degree and knot vector within each -//! direction) and intersection parameters. Builds three intermediate surfaces -//! (skin profiles, skin guides, tensor product) then computes the Boolean sum: -//! S_gordon = S_profiles + S_guides - S_tensor -//! -//! This class can be used independently when curves are already compatible, -//! or via GeomFill_Gordon which handles curve preparation. -//! -//! Supports closed (periodic) curve networks when the first and last curves -//! in a direction are geometrically identical. The closedness flags enable -//! C2-continuous periodic interpolation during skinning. -//! -//! Limitations: -//! - Non-rational curves only -class GeomFill_GordonBuilder -{ -public: - DEFINE_STANDARD_ALLOC - - //! Creates an empty Gordon builder. - Standard_EXPORT GeomFill_GordonBuilder(); - - //! Initializes the builder with compatible BSpline curves and intersection parameters. - //! @param[in] theProfiles array of profile curves (V-direction sections), must share - //! the same degree and knot vector - //! @param[in] theGuides array of guide curves (U-direction sections), must share - //! the same degree and knot vector - //! @param[in] theProfileParams parameter values at which profiles are positioned - //! (in V-direction), size must equal theProfiles.Length() - //! @param[in] theGuideParams parameter values at which guides are positioned - //! (in U-direction), size must equal theGuides.Length() - //! @param[in] theTolerance geometric tolerance for validation - //! @param[in] theIsUClosed if true, the U-direction (guides) forms a closed loop - //! @param[in] theIsVClosed if true, the V-direction (profiles) forms a closed loop - Standard_EXPORT void Init(const NCollection_Array1>& theProfiles, - const NCollection_Array1>& theGuides, - const NCollection_Array1& theProfileParams, - const NCollection_Array1& theGuideParams, - double theTolerance, - bool theIsUClosed = false, - bool theIsVClosed = false); - - //! Performs the Gordon surface construction. - Standard_EXPORT void Perform(); - - //! Enables/disables parallel processing in internal stages. - //! By default, single-thread mode is used. - void SetParallelMode(bool theToUseParallel) { myToUseParallel = theToUseParallel; } - - //! Returns true if internal parallel processing is enabled. - [[nodiscard]] bool IsParallelMode() const { return myToUseParallel; } - - //! Returns true if the surface was successfully constructed. - [[nodiscard]] bool IsDone() const { return myIsDone; } - - //! Returns the resulting Gordon surface. - //! @return handle to the constructed B-spline surface - [[nodiscard]] Standard_EXPORT const occ::handle& Surface() const; - - //! Returns the intermediate surface skinned through profiles. - [[nodiscard]] Standard_EXPORT const occ::handle& ProfileSurface() const; - - //! Returns the intermediate surface skinned through guides. - [[nodiscard]] Standard_EXPORT const occ::handle& GuideSurface() const; - - //! Returns the intermediate tensor product surface. - [[nodiscard]] Standard_EXPORT const occ::handle& TensorSurface() const; - -private: - //! Builds a skinned surface by interpolating pole columns of compatible curves. - //! @param[in] theSections array of compatible BSpline curves - //! @param[in] theSectionParams parameter values for each section - //! @param[in] theIsClosed if true, use periodic interpolation in V-direction - //! @return the skinned B-spline surface, or null handle on failure - occ::handle buildSkinSurface( - const NCollection_Array1>& theSections, - const NCollection_Array1& theSectionParams, - bool theIsClosed = false) const; - - //! Builds a tensor product surface interpolating a grid of intersection points. - //! @param[in] thePoints 2D array of intersection points (NGuides x NProfiles) - //! @param[in] theUParams parameter values in U-direction (guide params) - //! @param[in] theVParams parameter values in V-direction (profile params) - //! @param[in] theIsUClosed if true, use periodic interpolation in U-direction - //! @param[in] theIsVClosed if true, use periodic interpolation in V-direction - //! @return the tensor product B-spline surface, or null handle on failure - occ::handle buildTensorSurface(const NCollection_Array2& thePoints, - const NCollection_Array1& theUParams, - const NCollection_Array1& theVParams, - bool theIsUClosed = false, - bool theIsVClosed = false) const; - - //! Unifies knot vectors of two surfaces so they share the same degrees and knots - //! in both U and V directions. - //! @param[in,out] theSurf1 first surface to unify - //! @param[in,out] theSurf2 second surface to unify - static void unifySurfaces(occ::handle& theSurf1, - occ::handle& theSurf2); - - //! Computes the Boolean sum: S_gordon = S_profiles + S_guides - S_tensor. - //! All three surfaces must have identical degree and knot vectors. - //! @param[in] theProfileSurf surface skinned through profiles - //! @param[in] theGuideSurf surface skinned through guides - //! @param[in] theTensorSurf tensor product surface - //! @return the Gordon surface - occ::handle computeBooleanSum( - const occ::handle& theProfileSurf, - const occ::handle& theGuideSurf, - const occ::handle& theTensorSurf) const; - - NCollection_Array1> myProfiles; - NCollection_Array1> myGuides; - NCollection_Array1 myProfileParams; - NCollection_Array1 myGuideParams; - occ::handle mySurface; - occ::handle myProfileSurface; - occ::handle myGuideSurface; - occ::handle myTensorSurface; - double myTolerance = 0.0; - bool myIsUClosed = false; - bool myIsVClosed = false; - bool myToUseParallel = false; - bool myIsDone = false; -}; - -#endif // _GeomFill_GordonBuilder_HeaderFile diff --git a/opencascade/GeomFill_NetworkSurface.hxx b/opencascade/GeomFill_NetworkSurface.hxx new file mode 100644 index 000000000..3c89e6db4 --- /dev/null +++ b/opencascade/GeomFill_NetworkSurface.hxx @@ -0,0 +1,122 @@ +// Copyright (c) 2025 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _GeomFill_NetworkSurface_HeaderFile +#define _GeomFill_NetworkSurface_HeaderFile + +#include +#include +#include + +#include +#include +#include +#include +#include + +//! Low-level Gordon surface construction from a compatible B-spline curve network. +//! +//! This class builds the final surface for an already prepared Gordon network: +//! input curves must be explicit non-periodic B-spline curves, consistently +//! ordered, and consistently reparametrized. Curve families are made compatible +//! by the builder before skinning when they are polynomial. +//! +//! Profile skin, guide skin, and an intersection-grid reference surface are +//! built in B-spline form and aligned to a common knot basis. The final surface +//! is obtained by moving the profile-skin poles by the guide-skin deviation +//! measured from this reference surface. No point-grid surface approximation is +//! performed here. +//! +//! This class does not find curve intersections, sort the network, convert +//! arbitrary curves, or reparametrize the input. These operations are handled +//! by GeomFill_Gordon before calling this builder. +//! +//! Limitations: +//! - Periodic input curves are not accepted; callers should expand a required +//! period before initialization. +//! - Rational construction uses exact common-denominator multiplication and +//! can fail if the resulting product degree exceeds OCCT's B-spline degree +//! limit. +//! - At least two profiles and two guides are required +class GeomFill_NetworkSurface +{ +public: + DEFINE_STANDARD_ALLOC + + //! Result state of the last Perform() call. + enum class ResultStatus + { + NotStarted, //!< Perform() has not been called since initialization. + Done, //!< Surface has been constructed. + InvalidInput, //!< Prepared network does not satisfy builder requirements. + CurveCompatibilityFailed, //!< Curve families could not be converted to a compatible basis. + SkinningFailed, //!< Profile or guide skin interpolation has failed. + ReferenceSurfaceFailed, //!< Intersection-grid reference surface could not be built. + KnotAlignmentFailed, //!< Intermediate surfaces could not be aligned to one knot basis. + RationalDegreeOverflow, //!< Exact rational product degree exceeds OCCT's B-spline limit. + RationalConstructionFailed, //!< Exact rational numerator/denominator construction has failed. + ConstructionFailed, //!< Internal B-spline construction has failed. + PeriodicityFailed //!< Closed seam could not be converted to periodic form. + }; + + //! Creates an empty network surface algorithm. + Standard_EXPORT GeomFill_NetworkSurface(); + + //! Initializes the algorithm with a compatible profile/guide B-spline network. + //! @param[in] theProfiles profile curves evaluated in U direction + //! @param[in] theGuides guide curves evaluated in V direction + //! @param[in] theProfileParameters V parameters locating profiles on guide skin + //! @param[in] theGuideParameters U parameters locating guides on profile skin + //! @param[in] theIntersectionPoints validated profile/guide contact grid + //! @param[in] theIntersectionWeights rational weights for the contact grid + //! @param[in] theTolerance geometric tolerance for closed-seam checks + //! @param[in] theIsUClosed indicates that first/last guide curves close the U seam + //! @param[in] theIsVClosed indicates that first/last profile curves close the V seam + Standard_EXPORT void Init(const NCollection_Array1>& theProfiles, + const NCollection_Array1>& theGuides, + const NCollection_Array1& theProfileParameters, + const NCollection_Array1& theGuideParameters, + const NCollection_Array2& theIntersectionPoints, + const NCollection_Array2& theIntersectionWeights, + double theTolerance, + bool theIsUClosed, + bool theIsVClosed); + + //! Performs the pole-based network surface construction. + Standard_EXPORT void Perform(); + + //! Returns true if the surface was successfully constructed. + [[nodiscard]] bool IsDone() const { return myStatus == ResultStatus::Done; } + + //! Returns the result state of the last Perform() call. + [[nodiscard]] ResultStatus Status() const { return myStatus; } + + //! Returns the constructed B-spline surface. + //! @throws StdFail_NotDone if Perform() has not completed successfully. + [[nodiscard]] Standard_EXPORT const occ::handle& Surface() const; + +private: + NCollection_Array1> myProfiles; + NCollection_Array1> myGuides; + NCollection_Array1 myProfileParameters; + NCollection_Array1 myGuideParameters; + NCollection_Array2 myIntersectionPoints; + NCollection_Array2 myIntersectionWeights; + occ::handle mySurface; + double myTolerance = 0.0; + bool myIsUClosed = false; + bool myIsVClosed = false; + ResultStatus myStatus = ResultStatus::NotStarted; +}; + +#endif // _GeomFill_NetworkSurface_HeaderFile diff --git a/opencascade/GeomHash_Polygon2DHasher.hxx b/opencascade/GeomHash_Polygon2DHasher.hxx new file mode 100644 index 000000000..b01b54f2d --- /dev/null +++ b/opencascade/GeomHash_Polygon2DHasher.hxx @@ -0,0 +1,39 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _GeomHash_Polygon2DHasher_HeaderFile +#define _GeomHash_Polygon2DHasher_HeaderFile + +#include +#include + +#include + +class Poly_Polygon2D; + +struct GeomHash_Polygon2DHasher +{ + double CompTolerance; + double HashTolerance; + + Standard_EXPORT GeomHash_Polygon2DHasher( + const double theCompTolerance = Precision::Computational(), + const double theHashTolerance = Precision::Computational()); + + Standard_EXPORT std::size_t operator()(const occ::handle& thePoly) const noexcept; + + Standard_EXPORT bool operator()(const occ::handle& thePoly1, + const occ::handle& thePoly2) const noexcept; +}; + +#endif // _GeomHash_Polygon2DHasher_HeaderFile diff --git a/opencascade/GeomHash_Polygon3DHasher.hxx b/opencascade/GeomHash_Polygon3DHasher.hxx new file mode 100644 index 000000000..de6983b47 --- /dev/null +++ b/opencascade/GeomHash_Polygon3DHasher.hxx @@ -0,0 +1,39 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _GeomHash_Polygon3DHasher_HeaderFile +#define _GeomHash_Polygon3DHasher_HeaderFile + +#include +#include + +#include + +class Poly_Polygon3D; + +struct GeomHash_Polygon3DHasher +{ + double CompTolerance; + double HashTolerance; + + Standard_EXPORT GeomHash_Polygon3DHasher( + const double theCompTolerance = Precision::Computational(), + const double theHashTolerance = Precision::Computational()); + + Standard_EXPORT std::size_t operator()(const occ::handle& thePoly) const noexcept; + + Standard_EXPORT bool operator()(const occ::handle& thePoly1, + const occ::handle& thePoly2) const noexcept; +}; + +#endif // _GeomHash_Polygon3DHasher_HeaderFile diff --git a/opencascade/GeomHash_PolygonOnTriHasher.hxx b/opencascade/GeomHash_PolygonOnTriHasher.hxx new file mode 100644 index 000000000..c6cec57fb --- /dev/null +++ b/opencascade/GeomHash_PolygonOnTriHasher.hxx @@ -0,0 +1,46 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _GeomHash_PolygonOnTriHasher_HeaderFile +#define _GeomHash_PolygonOnTriHasher_HeaderFile + +#include +#include + +#include +#include + +class Poly_PolygonOnTriangulation; + +struct PolygonOnTriHashKey +{ + occ::handle Poly; + uint32_t TriRepId; +}; + +struct GeomHash_PolygonOnTriHasher +{ + double CompTolerance; + double HashTolerance; + + Standard_EXPORT GeomHash_PolygonOnTriHasher( + const double theCompTolerance = Precision::Computational(), + const double theHashTolerance = Precision::Computational()); + + Standard_EXPORT std::size_t operator()(const PolygonOnTriHashKey& theKey) const noexcept; + + Standard_EXPORT bool operator()(const PolygonOnTriHashKey& theKey1, + const PolygonOnTriHashKey& theKey2) const noexcept; +}; + +#endif // _GeomHash_PolygonOnTriHasher_HeaderFile diff --git a/opencascade/GeomHash_TriangulationHasher.hxx b/opencascade/GeomHash_TriangulationHasher.hxx new file mode 100644 index 000000000..fc9fb528d --- /dev/null +++ b/opencascade/GeomHash_TriangulationHasher.hxx @@ -0,0 +1,40 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _GeomHash_TriangulationHasher_HeaderFile +#define _GeomHash_TriangulationHasher_HeaderFile + +#include +#include + +#include + +class Poly_Triangulation; + +struct GeomHash_TriangulationHasher +{ + double CompTolerance; + double HashTolerance; + + Standard_EXPORT GeomHash_TriangulationHasher( + const double theCompTolerance = Precision::Computational(), + const double theHashTolerance = Precision::Computational()); + + Standard_EXPORT std::size_t operator()( + const occ::handle& theTri) const noexcept; + + Standard_EXPORT bool operator()(const occ::handle& theTri1, + const occ::handle& theTri2) const noexcept; +}; + +#endif // _GeomHash_TriangulationHasher_HeaderFile diff --git a/opencascade/Graphic3d_Aspects.hxx b/opencascade/Graphic3d_Aspects.hxx index d0c07c797..962635de2 100644 --- a/opencascade/Graphic3d_Aspects.hxx +++ b/opencascade/Graphic3d_Aspects.hxx @@ -151,6 +151,14 @@ public: //! Forbids material distinction between front and back faces. void SetDistinguishOff() { myToDistinguishMaterials = false; } + //! Return true if per-vertex color should be applied to back-facing fragments. + //! True by default for backward compatibility. + bool ToUseVertexColorForBackFaces() const { return myToUseVertexColorForBackFaces; } + + //! Set whether per-vertex color should be applied to back-facing fragments. + //! When disabled, back faces use back material/interior color without vertex color modulation. + void SetUseVertexColorForBackFaces(bool theToUse) { myToUseVertexColorForBackFaces = theToUse; } + //! Return shader program. const occ::handle& ShaderProgram() const { return myProgram; } @@ -537,6 +545,7 @@ public: && myTextFontAspect == theOther.myTextFontAspect && myTextAngle == theOther.myTextAngle && myToSkipFirstEdge == theOther.myToSkipFirstEdge && myToDistinguishMaterials == theOther.myToDistinguishMaterials + && myToUseVertexColorForBackFaces == theOther.myToUseVertexColorForBackFaces && myToDrawEdges == theOther.myToDrawEdges && myToDrawSilhouette == theOther.myToDrawSilhouette && myToMapTexture == theOther.myToMapTexture @@ -610,6 +619,7 @@ protected: bool myToSkipFirstEdge; bool myToDistinguishMaterials; + bool myToUseVertexColorForBackFaces; bool myToDrawEdges; bool myToDrawSilhouette; bool myToMapTexture; diff --git a/opencascade/Graphic3d_CView.hxx b/opencascade/Graphic3d_CView.hxx index 285d4360f..14304cbd4 100644 --- a/opencascade/Graphic3d_CView.hxx +++ b/opencascade/Graphic3d_CView.hxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -174,6 +175,13 @@ public: //! @return computed bounding box Standard_EXPORT virtual Bnd_Box MinMaxValues(const bool theToIncludeAuxiliary = false) const; + //! Return primary and graphical bounding boxes used by camera Z fitting. + virtual void ZFitAllBounds(Bnd_Box& thePrimaryBox, Bnd_Box& theGraphicBox) const + { + thePrimaryBox = MinMaxValues(false); + theGraphicBox = MinMaxValues(true); + } + //! Returns the coordinates of the boundary box of all structures in the set . //! If is TRUE, then the boundary box //! also includes minimum and maximum limits of graphical elements @@ -454,6 +462,43 @@ public: //! The default implementation is a no-op; drivers with shader support override it. virtual void GridErase() {} + //! Return snapped point for the shader-rendered grid under the window pixel. + //! The default implementation is a no-op; drivers with shader grid support override it. + virtual bool ShaderGridEcho(const int theX, const int theY, Graphic3d_Vertex& thePoint) const + { + (void)theX; + (void)theY; + (void)thePoint; + return false; + } + + //! Return snapped point and display point for the shader-rendered grid under the window pixel. + //! The snapped point is the geometric grid point in world coordinates. + //! The display point is a clip-safe proxy projected to the same window position for echo marker + //! presentation; it should not be used as the geometric snap result. + virtual bool ShaderGridEcho(const int theX, + const int theY, + Graphic3d_Vertex& thePoint, + Graphic3d_Vertex& theDisplayPoint) const + { + if (!ShaderGridEcho(theX, theY, thePoint)) + { + return false; + } + theDisplayPoint = thePoint; + return true; + } + + //! Return snapped point for the shader-rendered grid from an arbitrary world point. + //! The default implementation is a no-op; drivers with shader grid support override it. + virtual bool ShaderGridSnapPoint(const Graphic3d_Vertex& thePoint, + Graphic3d_Vertex& theGridPoint) const + { + (void)thePoint; + (void)theGridPoint; + return false; + } + //! Returns environment texture set for the view. const occ::handle& TextureEnv() const { return myTextureEnvData; } diff --git a/opencascade/Graphic3d_ShaderFlags.hxx b/opencascade/Graphic3d_ShaderFlags.hxx index 49b910f7d..884d24090 100644 --- a/opencascade/Graphic3d_ShaderFlags.hxx +++ b/opencascade/Graphic3d_ShaderFlags.hxx @@ -43,8 +43,10 @@ enum Graphic3d_ShaderFlags Graphic3d_ShaderFlags_WriteOit = 0x0800, //!< write coverage buffer for Blended Order-Independent Transparency Graphic3d_ShaderFlags_OitDepthPeeling = 0x1000, //!< handle Depth Peeling OIT + Graphic3d_ShaderFlags_VertColorFrontOnly = + 0x2000, //!< apply per-vertex color only to front-facing fragments // - Graphic3d_ShaderFlags_NB = 0x2000, //!< overall number of combinations + Graphic3d_ShaderFlags_NB = 0x4000, //!< overall number of combinations Graphic3d_ShaderFlags_IsPoint = Graphic3d_ShaderFlags_PointSimple | Graphic3d_ShaderFlags_PointSprite | Graphic3d_ShaderFlags_PointSpriteA, diff --git a/opencascade/NCollection_Allocator.hxx b/opencascade/NCollection_Allocator.hxx index 950289cc3..1c02161bf 100644 --- a/opencascade/NCollection_Allocator.hxx +++ b/opencascade/NCollection_Allocator.hxx @@ -75,7 +75,12 @@ public: } //! Returns an object address. - pointer address(reference theItem) const noexcept { return &theItem; } + template + typename std::enable_if::value, pointer>::type address( + reference theItem) const noexcept + { + return &theItem; + } //! Returns an object address. const_pointer address(const_reference theItem) const noexcept { return &theItem; } @@ -89,7 +94,8 @@ public: //! Frees previously allocated memory. void deallocate(pointer thePnt, const size_type) const { - Standard::Free(static_cast(thePnt)); + typedef typename std::remove_const::type non_const_value_type; + Standard::Free(static_cast(const_cast(thePnt))); } //! Reallocates memory for theSize objects. diff --git a/opencascade/NCollection_Array1.hxx b/opencascade/NCollection_Array1.hxx index 2784b3c00..36107c7bc 100644 --- a/opencascade/NCollection_Array1.hxx +++ b/opencascade/NCollection_Array1.hxx @@ -149,6 +149,26 @@ public: construct(0, mySize); } + //! Zero-based constructor from first element reference. + //! When theUseBuffer is true, wraps contiguous storage starting at theBegin. + //! Otherwise allocates own storage of theSize elements. + explicit NCollection_Array1(const_reference theBegin, + const size_t theSize, + const bool theUseBuffer) + : myLowerBound(0), + mySize(theSize), + myPointer(theUseBuffer ? const_cast(&theBegin) : nullptr), + myIsOwner(!theUseBuffer) + { + if (!myIsOwner) + { + return; + } + myPointer = myAllocator.allocate(mySize); + myIsOwner = true; + construct(0, mySize); + } + //! Zero-based constructor: allocates theSize elements with lower bound 0. //! Use At()/ChangeAt() or STL iterators for optimal access (no offset subtraction). explicit NCollection_Array1(const size_t theSize) @@ -437,15 +457,21 @@ protected: if (myIsOwner) { if (theToCopyData) + { destroy(myPointer, theNewSize, mySize); + } else + { destroy(myPointer, 0, mySize); + } } myLowerBound = theNewLower; if (theNewSize == 0) { if (myIsOwner) + { myAllocator.deallocate(aPrevPtr, mySize); + } myPointer = nullptr; mySize = 0; myIsOwner = false; @@ -468,7 +494,9 @@ protected: else { if (myIsOwner) + { myAllocator.deallocate(aPrevPtr, mySize); + } myPointer = myAllocator.allocate(theNewSize); construct(0, theNewSize); } diff --git a/opencascade/NCollection_DynamicArray.hxx b/opencascade/NCollection_DynamicArray.hxx index 651885a5f..04cfd17f3 100644 --- a/opencascade/NCollection_DynamicArray.hxx +++ b/opencascade/NCollection_DynamicArray.hxx @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -75,14 +74,245 @@ public: using const_reference = const TheItemType&; public: - using iterator = NCollection_IndexedIterator; - using const_iterator = NCollection_IndexedIterator; + template + class DynamicIterator + { + public: + using iterator_category = std::random_access_iterator_tag; + using value_type = TheItemType; + using difference_type = ptrdiff_t; + using pointer = typename std::conditional::type; + using reference = typename std::conditional::type; + + public: + DynamicIterator() noexcept + : myOwner(nullptr), + myIndex(0), + myUsedSize(0), + myInternalSize(1), + myBlockShift(0), + myBlockMask(0), + myBlockIndex(0), + myCurrPtr(nullptr), + myBlockEnd(nullptr) + { + } + + DynamicIterator(const NCollection_DynamicArray& theArray) noexcept + : DynamicIterator(0, theArray) + { + } + + DynamicIterator(const size_t theIndex, const NCollection_DynamicArray& theArray) noexcept + : myOwner(&theArray), + myIndex(theIndex), + myUsedSize(theArray.myUsedSize), + myInternalSize(theArray.myInternalSize), + myBlockShift(theArray.myBlockShift), + myBlockMask(theArray.myBlockMask), + myBlockIndex(0), + myCurrPtr(nullptr), + myBlockEnd(nullptr) + { + setIndex(theIndex); + } + + DynamicIterator(const DynamicIterator& theOther) noexcept + : myOwner(theOther.myOwner), + myIndex(theOther.myIndex), + myUsedSize(theOther.myUsedSize), + myInternalSize(theOther.myInternalSize), + myBlockShift(theOther.myBlockShift), + myBlockMask(theOther.myBlockMask), + myBlockIndex(theOther.myBlockIndex), + myCurrPtr(theOther.myCurrPtr), + myBlockEnd(theOther.myBlockEnd) + { + } + + DynamicIterator& operator=(const DynamicIterator& theOther) noexcept + { + myOwner = theOther.myOwner; + myIndex = theOther.myIndex; + myUsedSize = theOther.myUsedSize; + myInternalSize = theOther.myInternalSize; + myBlockShift = theOther.myBlockShift; + myBlockMask = theOther.myBlockMask; + myBlockIndex = theOther.myBlockIndex; + myCurrPtr = theOther.myCurrPtr; + myBlockEnd = theOther.myBlockEnd; + return *this; + } + + public: + bool operator==(const DynamicIterator& theOther) const noexcept + { + return myOwner == theOther.myOwner && myIndex == theOther.myIndex; + } + + template + bool operator==(const DynamicIterator& theOther) const noexcept + { + return myOwner == theOther.myOwner && myIndex == theOther.myIndex; + } + + template + bool operator!=(const DynamicIterator& theOther) const noexcept + { + return myOwner != theOther.myOwner || myIndex != theOther.myIndex; + } + + bool operator!=(const DynamicIterator& theOther) const noexcept { return !(*this == theOther); } + + reference operator*() const noexcept { return *myCurrPtr; } + + pointer operator->() const noexcept { return myCurrPtr; } + + DynamicIterator& operator++() noexcept + { + ++myIndex; + ++myCurrPtr; + if (myIndex >= myUsedSize) + { + myCurrPtr = nullptr; + myBlockEnd = nullptr; + } + else if (myCurrPtr == myBlockEnd) + { + ++myBlockIndex; + myCurrPtr = blockStart(myBlockIndex); + myBlockEnd = myCurrPtr + myInternalSize; + } + return *this; + } + + DynamicIterator operator++(int) noexcept + { + DynamicIterator theOld(*this); + ++(*this); + return theOld; + } + + DynamicIterator& operator--() noexcept + { + if (myIndex == myUsedSize) + { + setIndex(myUsedSize - 1); + return *this; + } + + --myIndex; + if (myCurrPtr > blockStart(myBlockIndex)) + { + --myCurrPtr; + } + else + { + --myBlockIndex; + myCurrPtr = blockStart(myBlockIndex) + (myInternalSize - 1); + myBlockEnd = blockStart(myBlockIndex) + myInternalSize; + } + return *this; + } + + DynamicIterator operator--(int) noexcept + { + DynamicIterator theOld(*this); + --(*this); + return theOld; + } + + DynamicIterator& operator+=(const difference_type theOffset) noexcept + { + setIndex(static_cast(static_cast(myIndex) + theOffset)); + return *this; + } + + DynamicIterator operator+(const difference_type theOffset) const noexcept + { + DynamicIterator aTemp(*this); + aTemp += theOffset; + return aTemp; + } + + DynamicIterator& operator-=(const difference_type theOffset) noexcept + { + return *this += -theOffset; + } + + DynamicIterator operator-(const difference_type theOffset) const noexcept + { + DynamicIterator aTemp(*this); + aTemp += -theOffset; + return aTemp; + } + + difference_type operator-(const DynamicIterator& theOther) const noexcept + { + return static_cast(myIndex) - static_cast(theOther.myIndex); + } + + reference operator[](const difference_type theOffset) const noexcept + { + return *(*this + theOffset); + } + + bool operator<(const DynamicIterator& theOther) const noexcept + { + return (*this - theOther) < 0; + } + + bool operator>(const DynamicIterator& theOther) const noexcept { return theOther < *this; } + + bool operator<=(const DynamicIterator& theOther) const noexcept { return !(theOther < *this); } + + bool operator>=(const DynamicIterator& theOther) const noexcept { return !(*this < theOther); } + + friend DynamicIterator operator+(const difference_type theOffset, + const DynamicIterator& theIter) noexcept + { + return theIter + theOffset; + } + + friend class DynamicIterator; + + private: + void setIndex(const size_t theIndex) noexcept + { + myIndex = theIndex; + if (myIndex >= myUsedSize || myOwner == nullptr) + { + myCurrPtr = nullptr; + myBlockEnd = nullptr; + myBlockIndex = 0; + return; + } + + myBlockIndex = myIndex >> myBlockShift; + const size_t aLocalIndex = myIndex & myBlockMask; + myCurrPtr = blockStart(myBlockIndex) + aLocalIndex; + myBlockEnd = blockStart(myBlockIndex) + myInternalSize; + } + + TheItemType* blockStart(const size_t theBlockIndex) const noexcept + { + return myOwner->getArray()[theBlockIndex]; + } + + private: + const NCollection_DynamicArray* myOwner; + size_t myIndex; + size_t myUsedSize; + size_t myInternalSize; + size_t myBlockShift; + size_t myBlockMask; + size_t myBlockIndex; + TheItemType* myCurrPtr; + TheItemType* myBlockEnd; + }; + + using iterator = DynamicIterator; + using const_iterator = DynamicIterator; using Iterator = NCollection_Iterator>; public: @@ -278,7 +508,9 @@ public: //! @name public methods "NCollection_DynamicArray::InsertAfter: index out of range"); Appended(); for (size_t i = myUsedSize - 1; i > theIndex + 1; --i) + { at(i) = std::move(at(i - 1)); + } at(theIndex + 1) = theValue; return at(theIndex + 1); } @@ -290,7 +522,9 @@ public: //! @name public methods "NCollection_DynamicArray::InsertAfter: index out of range"); Appended(); for (size_t i = myUsedSize - 1; i > theIndex + 1; --i) + { at(i) = std::move(at(i - 1)); + } at(theIndex + 1) = std::forward(theValue); return at(theIndex + 1); } @@ -319,7 +553,9 @@ public: //! @name public methods "NCollection_DynamicArray::InsertBefore: index out of range"); Appended(); for (size_t i = myUsedSize - 1; i > theIndex; --i) + { at(i) = std::move(at(i - 1)); + } at(theIndex) = theValue; return at(theIndex); } @@ -331,7 +567,9 @@ public: //! @name public methods "NCollection_DynamicArray::InsertBefore: index out of range"); Appended(); for (size_t i = myUsedSize - 1; i > theIndex; --i) + { at(i) = std::move(at(i - 1)); + } at(theIndex) = std::forward(theValue); return at(theIndex); } @@ -562,10 +800,14 @@ public: //! @name public methods } } if (theReleaseMemory) + { myAlloc.deallocate(aCurStart, myInternalSize); + } } if (theReleaseMemory) + { myContainer.Clear(theReleaseMemory); + } myUsedSize = 0; } diff --git a/opencascade/NCollection_FlatDataMap.hxx b/opencascade/NCollection_FlatDataMap.hxx index 652849fb1..1ed4d6963 100644 --- a/opencascade/NCollection_FlatDataMap.hxx +++ b/opencascade/NCollection_FlatDataMap.hxx @@ -710,6 +710,9 @@ public: } } + //! Reserve capacity for at least theN elements + void Reserve(const size_t theN) { reserve(theN); } + public: // **************** Iterator access **************** diff --git a/opencascade/NCollection_FlatMap.hxx b/opencascade/NCollection_FlatMap.hxx index 917a3a92e..cda81b0b2 100644 --- a/opencascade/NCollection_FlatMap.hxx +++ b/opencascade/NCollection_FlatMap.hxx @@ -538,6 +538,9 @@ public: } } + //! Reserve capacity for at least theN elements + void Reserve(const size_t theN) { reserve(theN); } + public: // **************** Iterator access **************** diff --git a/opencascade/NCollection_LinearVector.hxx b/opencascade/NCollection_LinearVector.hxx index 4d8cd8f19..2685fc825 100644 --- a/opencascade/NCollection_LinearVector.hxx +++ b/opencascade/NCollection_LinearVector.hxx @@ -15,6 +15,7 @@ #define NCollection_LinearVector_HeaderFile #include +#include #include #include @@ -487,6 +488,14 @@ public: } } + //! Returns a span as Array1 with shared memory. + //! Modifying the vector or the array may invalidate the shared buffer. + //! @return array view of the vector data + NCollection_Array1 ToArray1() const + { + return NCollection_Array1(myData, mySize); + } + //! @return iterator to the first element. iterator begin() noexcept { return myData; } @@ -510,7 +519,7 @@ private: void grow(const size_t theMinCapacity) { Standard_OutOfMemory_Raise_if(theMinCapacity > MaxSize(), "NCollection_LinearVector::grow"); - size_t aNewCap = myCapacity > 0 ? myCapacity * 2 : 8; + size_t aNewCap = myCapacity > 0 ? myCapacity * 2 : 2; if (myCapacity > MaxSize() / 2) { aNewCap = MaxSize(); diff --git a/opencascade/NCollection_LocalArray.hxx b/opencascade/NCollection_LocalArray.hxx index 3bb41a35a..656bc5d97 100644 --- a/opencascade/NCollection_LocalArray.hxx +++ b/opencascade/NCollection_LocalArray.hxx @@ -16,6 +16,7 @@ #define _NCollection_LocalArray_HeaderFile #include +#include #include #include @@ -57,7 +58,9 @@ public: if constexpr (!IS_TRIVIAL) { for (size_t i = 0; i < mySize; ++i) + { myPtr[i].~theItem(); + } } Deallocate(); } @@ -75,7 +78,9 @@ public: if constexpr (!IS_TRIVIAL) { for (size_t i = theNewSize; i < mySize; ++i) + { myPtr[i].~theItem(); + } } mySize = theNewSize; return; @@ -104,11 +109,17 @@ public: const size_t aCopy = theToCopy ? std::min(anOldSize, theNewSize) : 0; myPtr = inlinePtr(); for (size_t i = 0; i < aCopy; ++i) + { new (myPtr + i) theItem(std::move(anOldPtr[i])); + } for (size_t i = aCopy; i < theNewSize; ++i) + { new (myPtr + i) theItem(); + } for (size_t i = 0; i < anOldSize; ++i) + { anOldPtr[i].~theItem(); + } Standard::Free(anOldPtr); } myPtr = inlinePtr(); @@ -119,7 +130,9 @@ public: if constexpr (!IS_TRIVIAL) { for (size_t i = mySize; i < theNewSize; ++i) + { new (myPtr + i) theItem(); + } } } mySize = theNewSize; @@ -158,13 +171,21 @@ public: theItem* aNewPtr = static_cast(Standard::Allocate(aNewBytes)); const size_t aCopy = theToCopy ? std::min(mySize, theNewSize) : 0; for (size_t i = 0; i < aCopy; ++i) + { new (aNewPtr + i) theItem(std::move(myPtr[i])); + } for (size_t i = aCopy; i < theNewSize; ++i) + { new (aNewPtr + i) theItem(); + } for (size_t i = 0; i < mySize; ++i) + { myPtr[i].~theItem(); + } if (!aWasInline) + { Standard::Free(myPtr); + } myPtr = aNewPtr; } mySize = theNewSize; @@ -189,9 +210,13 @@ public: else { for (size_t i = 0; i < aNb; ++i) + { new (inlinePtr() + i) theItem(std::move(theOther.inlinePtr()[i])); + } for (size_t i = 0; i < aNb; ++i) + { theOther.inlinePtr()[i].~theItem(); + } } } else @@ -205,7 +230,9 @@ public: NCollection_LocalArray& operator=(NCollection_LocalArray&& theOther) noexcept { if (this == &theOther) + { return *this; + } if constexpr (IS_TRIVIAL) { @@ -236,26 +263,36 @@ public: { // Destroy our current elements. for (size_t i = 0; i < mySize; ++i) + { myPtr[i].~theItem(); + } if (theOther.isInline()) { if (!isInline()) + { Standard::Free(myPtr); + } myPtr = inlinePtr(); mySize = theOther.mySize; // When the source is inline, mySize is bounded by MAX_ARRAY_SIZE. const size_t aNb = std::min(mySize, static_cast(MAX_ARRAY_SIZE)); for (size_t i = 0; i < aNb; ++i) + { new (inlinePtr() + i) theItem(std::move(theOther.inlinePtr()[i])); + } for (size_t i = 0; i < aNb; ++i) + { theOther.inlinePtr()[i].~theItem(); + } } else { // Take ownership of theOther's heap allocation directly. if (!isInline()) + { Standard::Free(myPtr); + } myPtr = theOther.myPtr; mySize = theOther.mySize; theOther.myPtr = theOther.inlinePtr(); @@ -265,6 +302,14 @@ public: return *this; } + //! Returns a span as Array1 with shared memory. + //! Modifying the local array or the array view may invalidate the shared buffer. + //! @return array view of the local array data + NCollection_Array1 ToArray1() const + { + return NCollection_Array1(myPtr, mySize); + } + NCollection_LocalArray(const NCollection_LocalArray&) = delete; NCollection_LocalArray& operator=(const NCollection_LocalArray&) = delete; @@ -272,7 +317,9 @@ protected: void Deallocate() { if (!isInline()) + { Standard::Free(myPtr); + } } //! Pointer to inline buffer storage. diff --git a/opencascade/NCollection_OccAllocator.hxx b/opencascade/NCollection_OccAllocator.hxx index 93e8f91a6..0d87dcb1e 100644 --- a/opencascade/NCollection_OccAllocator.hxx +++ b/opencascade/NCollection_OccAllocator.hxx @@ -136,7 +136,9 @@ public: //! Frees previously allocated memory. void deallocate(pointer thePnt, size_type) { - myAllocator.IsNull() ? Standard::Free(thePnt) : myAllocator->Free(thePnt); + typedef typename std::remove_const::type non_const_value_type; + non_const_value_type* aPnt = const_cast(thePnt); + myAllocator.IsNull() ? Standard::Free(aPnt) : myAllocator->Free(aPnt); } //! Constructs an object. @@ -148,7 +150,12 @@ public: } //! Returns an object address. - pointer address(reference theItem) const noexcept { return &theItem; } + template + typename std::enable_if::value, pointer>::type address( + reference theItem) const noexcept + { + return &theItem; + } //! Returns an object address. const_pointer address(const_reference theItem) const noexcept { return &theItem; } diff --git a/opencascade/OpenGl_Context.hxx b/opencascade/OpenGl_Context.hxx index 5d2e33ce2..3c5ef7182 100644 --- a/opencascade/OpenGl_Context.hxx +++ b/opencascade/OpenGl_Context.hxx @@ -887,6 +887,10 @@ public: //! @name methods to alter or retrieve current state //! Setup current color. Standard_EXPORT void SetColor4fv(const NCollection_Vec4& theColor); + //! Setup current front and back colors. + Standard_EXPORT void SetColor4fv(const NCollection_Vec4& theFrontColor, + const NCollection_Vec4& theBackColor); + //! Setup type of line. Standard_EXPORT void SetTypeOfLine(const Aspect_TypeOfLine theType, const float theFactor = 1.0f); diff --git a/opencascade/OpenGl_PrimitiveArray.hxx b/opencascade/OpenGl_PrimitiveArray.hxx index ccfa15517..7414e1bdf 100644 --- a/opencascade/OpenGl_PrimitiveArray.hxx +++ b/opencascade/OpenGl_PrimitiveArray.hxx @@ -128,7 +128,9 @@ private: //! Main procedure to draw array void drawArray(const occ::handle& theWorkspace, const NCollection_Vec4* theFaceColors, - const bool theHasVertColor) const; + const NCollection_Vec4& theBackColor, + const bool theHasVertColor, + const bool theToUseVertexColorForBackFaces) const; //! Auxiliary procedures void drawEdges(const occ::handle& theWorkspace) const; diff --git a/opencascade/OpenGl_ShaderGrid.hxx b/opencascade/OpenGl_ShaderGrid.hxx new file mode 100644 index 000000000..1422ae25e --- /dev/null +++ b/opencascade/OpenGl_ShaderGrid.hxx @@ -0,0 +1,160 @@ +// Copyright (c) 2026 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _OpenGl_ShaderGrid_HeaderFile +#define _OpenGl_ShaderGrid_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//! State and geometry model of the OpenGl shader-rendered grid. +class OpenGl_ShaderGrid +{ +public: + //! Return TRUE if the grid is currently shown. + bool IsShown() const { return myIsShown; } + + //! Return TRUE if the grid is rendered as a background. + bool IsBackground() const { return myParams.IsBackground(); } + + //! Return current parameters. + const Aspect_GridParams& Params() const { return myParams; } + + //! Store grid state. Returns FALSE when parameters cannot produce a shader grid. + bool Display(const Aspect_GridParams& theParams, + const gp_Ax3& thePlane, + const occ::handle& theCamera, + const occ::handle& theContext); + + //! Clear grid state. + void Erase(); + + //! Add helper bounds required by camera Z fitting. + void AddZFitBounds(Bnd_Box& theGraphicBox, const occ::handle& theCamera) const; + + //! Return snapped point for the grid under the window pixel. + bool Echo(const occ::handle& theCamera, + const int theWidth, + const int theHeight, + const int theX, + const int theY, + Graphic3d_Vertex& thePoint, + Graphic3d_Vertex& theDisplayPoint) const; + + //! Return snapped point for an arbitrary world point. + bool SnapPoint(const occ::handle& theCamera, + const Graphic3d_Vertex& thePoint, + Graphic3d_Vertex& theGridPoint) const; + + //! Upload shader uniforms for current grid state. + void SetUniforms(const occ::handle& theContext, + const occ::handle& theProgram, + const occ::handle& theCamera, + const NCollection_Mat4& theWorldView) const; + + //! Return worldview matrix to use for drawing. + NCollection_Mat4 DrawWorldView(const NCollection_Mat4& theCurrentWorldView) const; + +private: + //! Compute grid plane frame. + void frame(gp_Pnt& theOrigin, gp_XYZ& theX, gp_XYZ& theY, gp_XYZ& theN) const; + + //! Compute effective scales for the current camera. + void effectiveScale(const occ::handle& theCamera, + double& theScaleX, + double& theScaleY) const; + + //! Return TRUE if local coordinates are inside configured grid domain. + bool isPointInBounds(const double theLocalX, const double theLocalY) const; + + //! Add local point to box. + static void addLocalPoint(Bnd_Box& theBox, + const gp_Pnt& theOrigin, + const gp_XYZ& theX, + const gp_XYZ& theY, + const double theLocalX, + const double theLocalY); + + //! Add configured finite bounds to the box. + void addFiniteBounds(Bnd_Box& theBox) const; + + //! Add view footprint bounds to the box. + void addViewFootprintBounds(Bnd_Box& theBox, + const occ::handle& theCamera) const; + + //! Intersect camera ray at NDC point with the grid plane. + bool planeLocalHit(const occ::handle& theCamera, + const double theNdcX, + const double theNdcY, + double& theLocalX, + double& theLocalY, + gp_XYZ* theHit = nullptr, + const bool theToRejectBehind = true) const; + + //! Return stable visible reference point in local coordinates. + bool referenceLocal(const occ::handle& theCamera, + double& theLocalX, + double& theLocalY) const; + + //! Return local shift snapped to a grid phase. + static double snappedLocalShift(const double theLocal, const double theScale); + + //! Return TRUE if previous and new grid definitions share the same background anchor frame. + bool hasSameAnchorFrame(const Aspect_GridParams& theParams, const gp_Ax3& thePlane) const; + + //! Accept echo candidate if it is visible and closer to the requested pixel. + bool acceptEchoCandidate(const occ::handle& theCamera, + const int theWidth, + const int theHeight, + const int theX, + const int theY, + const gp_Pnt& theGridOrigin, + const gp_XYZ& theGridX, + const gp_XYZ& theGridY, + const double theLocalX, + const double theLocalY, + gp_XYZ& theBestSnapped, + double& theBestDist2, + bool& theHasBestPoint) const; + + //! Convert point to current draw view coordinates. + static NCollection_Vec3 viewPoint(const NCollection_Mat4& theWorldView, + const gp_Pnt& thePoint); + + //! Convert direction to current draw view coordinates. + static NCollection_Vec3 viewDirection(const NCollection_Mat4& theWorldView, + const gp_XYZ& theDirection); + + //! Return display-safe echo marker point. + static bool echoDisplayPoint(const occ::handle& theCamera, + const gp_XYZ& theSnapped, + gp_Pnt& theDisplayPoint); + + //! Return TRUE if angle belongs to arc. + static bool angleInArc(const double theStart, const double theEnd, const double theAngle); + +private: + Aspect_GridParams myParams; + gp_Ax3 myPlane; + NCollection_Mat4 myRefViewMatrix; + bool myIsShown = false; +}; + +#endif // _OpenGl_ShaderGrid_HeaderFile diff --git a/opencascade/OpenGl_ShaderManager.hxx b/opencascade/OpenGl_ShaderManager.hxx index c7c7cb1f6..5ced685d2 100644 --- a/opencascade/OpenGl_ShaderManager.hxx +++ b/opencascade/OpenGl_ShaderManager.hxx @@ -107,6 +107,7 @@ public: theAlphaMode, Aspect_IS_SOLID, theHasVertColor, + true, // use vertex color for back faces by default for compatibility theEnableEnvMap, false, theCustomProgram); @@ -118,6 +119,7 @@ public: Graphic3d_AlphaMode theAlphaMode, Aspect_InteriorStyle theInteriorStyle, bool theHasVertColor, + bool theToUseVertexColorForBackFaces, bool theEnableEnvMap, bool theEnableMeshEdges, const occ::handle& theCustomProgram) @@ -136,6 +138,7 @@ public: theAlphaMode, theInteriorStyle, theHasVertColor, + theToUseVertexColorForBackFaces, theEnableEnvMap, theEnableMeshEdges); occ::handle& aProgram = getStdProgram(aShadeModelOnFace, aBits); @@ -155,8 +158,13 @@ public: return bindProgramWithState(theCustomProgram, theShadingModel); } - int aBits = - getProgramBits(theTextures, theAlphaMode, Aspect_IS_SOLID, theHasVertColor, false, false); + int aBits = getProgramBits(theTextures, + theAlphaMode, + Aspect_IS_SOLID, + theHasVertColor, + true, // lines have no front/back face semantics + false, + false); if (theLineType != Aspect_TOL_SOLID) { aBits |= Graphic3d_ShaderFlags_StippleLine; @@ -188,6 +196,7 @@ public: Graphic3d_AlphaMode_Opaque, Aspect_IS_SOLID, false, + true, // outline has no vertex-color back-face policy false, false); if (myOutlinePrograms.IsNull()) @@ -600,6 +609,7 @@ protected: Graphic3d_AlphaMode theAlphaMode, Aspect_InteriorStyle theInteriorStyle, bool theHasVertColor, + bool theToUseVertexColorForBackFaces, bool theEnableEnvMap, bool theEnableMeshEdges) const { @@ -635,6 +645,10 @@ protected: if (theHasVertColor && theInteriorStyle != Aspect_IS_HIDDENLINE) { aBits |= Graphic3d_ShaderFlags_VertColor; + if (!theToUseVertexColorForBackFaces) + { + aBits |= Graphic3d_ShaderFlags_VertColorFrontOnly; + } } if (myOitState.ActiveMode() == Graphic3d_RTM_BLEND_OIT) diff --git a/opencascade/OpenGl_ShaderProgram.hxx b/opencascade/OpenGl_ShaderProgram.hxx index a61e6f20e..551be32de 100644 --- a/opencascade/OpenGl_ShaderProgram.hxx +++ b/opencascade/OpenGl_ShaderProgram.hxx @@ -65,6 +65,7 @@ enum OpenGl_StateVariable OpenGl_OCCT_COMMON_MATERIAL, OpenGl_OCCT_ALPHA_CUTOFF, OpenGl_OCCT_COLOR, + OpenGl_OCCT_BACK_COLOR, // Weighted, Blended Order-Independent Transparency rendering state OpenGl_OCCT_OIT_OUTPUT, diff --git a/opencascade/OpenGl_View.hxx b/opencascade/OpenGl_View.hxx index e806a2f49..8e7cab512 100644 --- a/opencascade/OpenGl_View.hxx +++ b/opencascade/OpenGl_View.hxx @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -162,6 +163,9 @@ public: //! @return computed bounding box Standard_EXPORT Bnd_Box MinMaxValues(const bool theToIncludeAuxiliary) const override; + //! Return primary and graphical bounding boxes used by camera Z fitting. + Standard_EXPORT void ZFitAllBounds(Bnd_Box& thePrimaryBox, Bnd_Box& theGraphicBox) const override; + //! Returns pointer to an assigned framebuffer object. Standard_EXPORT occ::handle FBO() const override; @@ -229,6 +233,21 @@ public: //! Erase the shader-rendered grid. Standard_EXPORT void GridErase() override; + //! Return snapped point for the shader-rendered grid under the window pixel. + Standard_EXPORT bool ShaderGridEcho(const int theX, + const int theY, + Graphic3d_Vertex& thePoint) const override; + + //! Return snapped point and clip-safe display point for the shader-rendered grid echo marker. + Standard_EXPORT bool ShaderGridEcho(const int theX, + const int theY, + Graphic3d_Vertex& thePoint, + Graphic3d_Vertex& theDisplayPoint) const override; + + //! Return snapped point for the shader-rendered grid from an arbitrary world point. + Standard_EXPORT bool ShaderGridSnapPoint(const Graphic3d_Vertex& thePoint, + Graphic3d_Vertex& theGridPoint) const override; + //! Returns number of mipmap levels used in specular IBL map. //! 0 if PBR environment is not created. Standard_EXPORT unsigned int SpecIBLMapLevels() const; @@ -539,11 +558,8 @@ protected: //! @name Background parameters OpenGl_Aspects* myTextureParams; //!< Stores texture and its parameters for textured background OpenGl_Aspects* myCubeMapParams; //!< Stores cubemap and its parameters for cubemap background OpenGl_Aspects* myColoredQuadParams; //!< Stores parameters for gradient (corner mode) background - Aspect_GridParams myGridParams; //!< parameters of shader grid - gp_Ax3 myGridPlane; //!< grid plane in world coordinates - NCollection_Mat4 myGridRefViewMatrix; //!< worldview captured at GridDisplay() for pan/rotate compensation + OpenGl_ShaderGrid myShaderGrid; //!< shader grid state and geometry model unsigned int myGridVao; //!< dedicated VAO for textureless grid draw - bool myToShowGrid; //!< flag indicating the grid is active OpenGl_BackgroundArray* myBackgrounds[Graphic3d_TypeOfBackground_NB]; //!< Array of primitive arrays of different background types // clang-format on occ::handle myTextureEnv; diff --git a/opencascade/OpenGl_Workspace.hxx b/opencascade/OpenGl_Workspace.hxx index 5568517e6..5ff48e53a 100644 --- a/opencascade/OpenGl_Workspace.hxx +++ b/opencascade/OpenGl_Workspace.hxx @@ -124,6 +124,14 @@ public: : myAspectsSet->Aspect()->InteriorColorRGBA(); } + //! Return back interior color taking into account highlight and distinguish flags. + const NCollection_Vec4& BackInteriorColor() const + { + return !myHighlightStyle.IsNull() ? myHighlightStyle->ColorRGBA() + : myAspectsSet->Aspect()->Distinguish() ? myAspectsSet->Aspect()->BackInteriorColorRGBA() + : myAspectsSet->Aspect()->InteriorColorRGBA(); + } + //! Return text color taking into account highlight flag. const NCollection_Vec4& TextColor() const { diff --git a/opencascade/Poly_ArrayOfNodes.hxx b/opencascade/Poly_ArrayOfNodes.hxx index 129c4fd73..05eea9860 100644 --- a/opencascade/Poly_ArrayOfNodes.hxx +++ b/opencascade/Poly_ArrayOfNodes.hxx @@ -101,9 +101,11 @@ public: public: //! A generalized accessor to point. inline gp_Pnt Value(int theIndex) const; + inline gp_Pnt Value(const size_t theIndex) const; //! A generalized setter for point. inline void SetValue(int theIndex, const gp_Pnt& theValue); + inline void SetValue(const size_t theIndex, const gp_Pnt& theValue); //! operator[] - alias to Value gp_Pnt operator[](int theIndex) const { return Value(theIndex); } @@ -127,6 +129,15 @@ inline gp_Pnt Poly_ArrayOfNodes::Value(int theIndex) const //================================================================================================= +inline gp_Pnt Poly_ArrayOfNodes::Value(const size_t theIndex) const +{ + Standard_OutOfRange_Raise_if(theIndex >= static_cast(mySize), + "Poly_ArrayOfNodes::Value(), out of range index"); + return Value(static_cast(theIndex)); +} + +//================================================================================================= + inline void Poly_ArrayOfNodes::SetValue(int theIndex, const gp_Pnt& theValue) { if (myStride == (int)sizeof(gp_Pnt)) @@ -141,4 +152,13 @@ inline void Poly_ArrayOfNodes::SetValue(int theIndex, const gp_Pnt& theValue) } } +//================================================================================================= + +inline void Poly_ArrayOfNodes::SetValue(const size_t theIndex, const gp_Pnt& theValue) +{ + Standard_OutOfRange_Raise_if(theIndex >= static_cast(mySize), + "Poly_ArrayOfNodes::SetValue(), out of range index"); + SetValue(static_cast(theIndex), theValue); +} + #endif // _Poly_ArrayOfNodes_HeaderFile diff --git a/opencascade/Poly_ArrayOfUVNodes.hxx b/opencascade/Poly_ArrayOfUVNodes.hxx index 6f5954cb3..893cdc455 100644 --- a/opencascade/Poly_ArrayOfUVNodes.hxx +++ b/opencascade/Poly_ArrayOfUVNodes.hxx @@ -101,9 +101,11 @@ public: public: //! A generalized accessor to point. inline gp_Pnt2d Value(int theIndex) const; + inline gp_Pnt2d Value(const size_t theIndex) const; //! A generalized setter for point. inline void SetValue(int theIndex, const gp_Pnt2d& theValue); + inline void SetValue(const size_t theIndex, const gp_Pnt2d& theValue); //! operator[] - alias to Value gp_Pnt2d operator[](int theIndex) const { return Value(theIndex); } @@ -127,6 +129,15 @@ inline gp_Pnt2d Poly_ArrayOfUVNodes::Value(int theIndex) const //================================================================================================= +inline gp_Pnt2d Poly_ArrayOfUVNodes::Value(const size_t theIndex) const +{ + Standard_OutOfRange_Raise_if(theIndex >= static_cast(mySize), + "Poly_ArrayOfUVNodes::Value(), out of range index"); + return Value(static_cast(theIndex)); +} + +//================================================================================================= + inline void Poly_ArrayOfUVNodes::SetValue(int theIndex, const gp_Pnt2d& theValue) { if (myStride == (int)sizeof(gp_Pnt2d)) @@ -141,4 +152,13 @@ inline void Poly_ArrayOfUVNodes::SetValue(int theIndex, const gp_Pnt2d& theValue } } +//================================================================================================= + +inline void Poly_ArrayOfUVNodes::SetValue(const size_t theIndex, const gp_Pnt2d& theValue) +{ + Standard_OutOfRange_Raise_if(theIndex >= static_cast(mySize), + "Poly_ArrayOfUVNodes::SetValue(), out of range index"); + SetValue(static_cast(theIndex), theValue); +} + #endif // _Poly_ArrayOfUVNodes_HeaderFile diff --git a/opencascade/Poly_Polygon2D.hxx b/opencascade/Poly_Polygon2D.hxx index 2ebeb36a6..39e8f6cf7 100644 --- a/opencascade/Poly_Polygon2D.hxx +++ b/opencascade/Poly_Polygon2D.hxx @@ -36,6 +36,9 @@ public: //! Constructs a 2D polygon defined by the table of points, . Standard_EXPORT Poly_Polygon2D(const NCollection_Array1& Nodes); + //! Creates a copy of current polygon. + Standard_EXPORT virtual occ::handle Copy() const; + //! Returns the deflection of this polygon. //! Deflection is used in cases where the polygon is an //! approximate representation of a curve. Deflection diff --git a/opencascade/Poly_PolygonOnTriangulation.hxx b/opencascade/Poly_PolygonOnTriangulation.hxx index 762ee697e..28a1fc77f 100644 --- a/opencascade/Poly_PolygonOnTriangulation.hxx +++ b/opencascade/Poly_PolygonOnTriangulation.hxx @@ -80,6 +80,9 @@ public: //! Returns node at the given index. int Node(int theIndex) const { return myNodes.Value(theIndex); } + //! Returns mutable node-index array. + NCollection_Array1& ChangeNodeArray() { return myNodes; } + //! Sets node at the given index. void SetNode(int theIndex, int theNode) { myNodes.SetValue(theIndex, theNode); } @@ -102,6 +105,14 @@ public: myParameters->SetValue(theIndex, theValue); } + //! Returns mutable parameter array. + NCollection_Array1& ChangeParameterArray() + { + Standard_NullObject_Raise_if(myParameters.IsNull(), + "Poly_PolygonOnTriangulation::Parameter : parameters is NULL"); + return myParameters->ChangeArray1(); + } + //! Sets the table of the parameters associated with each node in this polygon. //! Raises exception if array size doesn't much number of polygon nodes. Standard_EXPORT void SetParameters(const occ::handle>& theParameters); diff --git a/opencascade/Poly_TriangulationParameters.hxx b/opencascade/Poly_TriangulationParameters.hxx index e3e28a742..7a4d99bdf 100644 --- a/opencascade/Poly_TriangulationParameters.hxx +++ b/opencascade/Poly_TriangulationParameters.hxx @@ -40,6 +40,9 @@ public: //! Destructor. ~Poly_TriangulationParameters() override = default; + //! Creates a copy of current triangulation parameters. + Standard_EXPORT occ::handle Copy() const; + //! Returns true if linear deflection is defined. bool HasDeflection() const { return !(myDeflection < 0.); } diff --git a/opencascade/Prs3d_ShadingAspect.hxx b/opencascade/Prs3d_ShadingAspect.hxx index d600ee8c0..d80b2b1e9 100644 --- a/opencascade/Prs3d_ShadingAspect.hxx +++ b/opencascade/Prs3d_ShadingAspect.hxx @@ -66,6 +66,15 @@ public: Standard_EXPORT double Transparency( const Aspect_TypeOfFacingModel aModel = Aspect_TOFM_FRONT_SIDE) const; + //! Return true if per-vertex color should be applied to back-facing fragments. + bool ToUseVertexColorForBackFaces() const { return myAspect->ToUseVertexColorForBackFaces(); } + + //! Set whether per-vertex color should be applied to back-facing fragments. + void SetUseVertexColorForBackFaces(bool theToUse) + { + myAspect->SetUseVertexColorForBackFaces(theToUse); + } + //! Returns the polygons aspect properties. const occ::handle& Aspect() const { return myAspect; } diff --git a/opencascade/ShapeAnalysis_FreeBounds.hxx b/opencascade/ShapeAnalysis_FreeBounds.hxx index cddc8582e..7c47cc09d 100644 --- a/opencascade/ShapeAnalysis_FreeBounds.hxx +++ b/opencascade/ShapeAnalysis_FreeBounds.hxx @@ -110,6 +110,7 @@ public: //! at its tail. //! //! Orientation of the edge can change when connecting. + //! Edges having INTERNAL or EXTERNAL orientation are ignored. //! If is True connection is performed only when //! adjacent edges share the same vertex. //! If is False connection is performed only when diff --git a/opencascade/Standard_Version.hxx b/opencascade/Standard_Version.hxx index 7fbb962e9..e06323def 100644 --- a/opencascade/Standard_Version.hxx +++ b/opencascade/Standard_Version.hxx @@ -1,4 +1,4 @@ -// Created on: 2026-05-08 +// Created on: 2026-08-26 // Copyright (c) 2002-2025 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. @@ -38,7 +38,7 @@ major, minor, and patch number // Primary definitions #define OCC_VERSION_MAJOR 8 #define OCC_VERSION_MINOR 0 -#define OCC_VERSION_MAINTENANCE 0 +#define OCC_VERSION_MAINTENANCE 1 //! This macro must be commented in official release, and set to non-empty //! string in other situations, to identify specifics of the version, e.g.: @@ -50,7 +50,7 @@ major, minor, and patch number // Derived (manually): version as real and string (major.minor) #define OCC_VERSION 8.0 #define OCC_VERSION_STRING "8.0" -#define OCC_VERSION_COMPLETE "8.0.0" +#define OCC_VERSION_COMPLETE "8.0.1" //! Derived: extended version as string ("major.minor.maintenance.dev") #ifdef OCC_VERSION_DEVELOPMENT diff --git a/opencascade/V3d_View.hxx b/opencascade/V3d_View.hxx index b73d265ce..18f8d5bf7 100644 --- a/opencascade/V3d_View.hxx +++ b/opencascade/V3d_View.hxx @@ -36,6 +36,7 @@ class Aspect_Window; class Graphic3d_Group; class Graphic3d_Structure; class Graphic3d_TextureEnv; +class Graphic3d_Vertex; //! Defines the application object VIEW for the //! VIEWER application. @@ -671,6 +672,21 @@ public: double& Yg, double& Zg) const; + //! Converts the projected point into the nearest visible grid point. + //! @return TRUE when an active grid accepts the point; FALSE otherwise. + //! Unlike the double-output overload, this method has no unproject fallback + //! and is intended for grid echo / snap-hit callers. + Standard_EXPORT bool ConvertToGrid(const int Xp, + const int Yp, + Graphic3d_Vertex& theGridPoint) const; + + //! Converts the projected point into the nearest visible grid point and echo display point. + //! The echo display point is suitable only for displaying the grid echo marker. + Standard_EXPORT bool ConvertToGridEcho(const int Xp, + const int Yp, + Graphic3d_Vertex& theGridPoint, + Graphic3d_Vertex& theEchoPoint) const; + //! Converts the point into the nearest grid point //! and display the grid marker. Standard_EXPORT void ConvertToGrid(const double X, @@ -907,11 +923,9 @@ public: const double theResolution = 0.0, const bool theToEnlargeIfLine = true) const; -public: //! @name CPU grid plumbing (deprecated, fed by V3d_Viewer::ActivateGrid) - //! Snap + CPU rendering. The CPU grid lives on the viewer's structure manager - //! and is visible in every active view; SetGrid on a view that has the shader - //! grid enabled erases the shader grid on this view, the CPU grid is left - //! intact (or re-displayed by V3d_Viewer::ActivateGrid). +public: //! @name Viewer grid plumbing + //! Viewer-managed grid plane and snap object. It is separate from the per-view + //! shader grid controlled by GridDisplay(). //! Defines or updates the grid plane and snap object on this view. //! @param[in] aPlane grid plane (origin + axes) @@ -922,11 +936,15 @@ public: //! @name CPU grid plumbing (deprecated, fed by V3d_Viewer::ActivateGrid //! @param[in] aFlag true to enable snap, false to disable Standard_EXPORT void SetGridActivity(const bool aFlag); -public: //! @name GPU shader grid (recommended) - //! Per-view immediate-mode shader; supports unbounded extents, AA, background, arc range. - //! GridDisplay erases the viewer-wide CPU grid rendering on entry (snap geometry - //! on Aspect_*Grid is preserved). GridErase only tears down the shader grid on - //! this view; restoring the CPU rendering needs V3d_Viewer::ActivateGrid. + //! Return TRUE if either viewer-managed grid or per-view shader grid is active. + bool IsGridActive() const { return MyViewer->IsGridActive() || myShaderGridActive; } + + //! Return TRUE if the per-view shader grid is active. + bool IsShaderGridActive() const { return myShaderGridActive; } + +public: //! @name Shader grid + //! Per-view immediate-mode shader grid; supports unbounded extents, AA, background, + //! circular grids, arc range and view-adaptive spacing. //! Display a shader-rendered grid on the viewer's privileged plane. //! @param[in] theParams appearance: color, scale, bounds, arc, draw-mode, background /