Skip to content

Commit 0af2cca

Browse files
authored
Modeling Data - BRepGraph iterators, ref caching, mutation APIs, and layer events (#1190)
- Add RelatedIterator, CacheKindIterator, LayerIterator, RefTransientCache - Add Builder::AppendFull, BuilderView::RemoveRef with orphan pruning - Add SetCoEdgePCurve, ClearFaceMesh, ClearEdgePolygon3D, ValidateMutationBoundary - Rename CoEdgeDef::Sense to Orientation, FreeChildRefIds to AuxChildRefIds - Propagate ref-modification events through LayerRegistry (deferred/immediate) - Extend DefsIterator/RefsIterator with filtered-kind iteration - Add CreateAutoProduct option to BRepGraphInc_Populate::Options - Update BRepGraph and BRepGraphInc READMEs
1 parent a56f239 commit 0af2cca

62 files changed

Lines changed: 4328 additions & 573 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/ModelingData/TKBRep/BRepGraph/BRepGraph.cxx

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ void BRepGraph::invalidateSubgraphImpl(const BRepGraph_NodeId theNode)
439439
{
440440
aPushChild(aChildIt.CurrentId(), aNextDepth);
441441
}
442-
for (const BRepGraph_ChildRefId& aChildRefId : aSolidEnt.FreeChildRefIds)
442+
for (const BRepGraph_ChildRefId& aChildRefId : aSolidEnt.AuxChildRefIds)
443443
aPushChild(aStorage.ChildRef(aChildRefId).ChildDefId, aNextDepth);
444444
break;
445445
}
@@ -452,7 +452,7 @@ void BRepGraph::invalidateSubgraphImpl(const BRepGraph_NodeId theNode)
452452
{
453453
aPushChild(aChildIt.CurrentId(), aNextDepth);
454454
}
455-
for (const BRepGraph_ChildRefId& aChildRefId : aShellEnt.FreeChildRefIds)
455+
for (const BRepGraph_ChildRefId& aChildRefId : aShellEnt.AuxChildRefIds)
456456
aPushChild(aStorage.ChildRef(aChildRefId).ChildDefId, aNextDepth);
457457
break;
458458
}
@@ -560,12 +560,25 @@ void BRepGraph::markRefModified(const BRepGraph_RefId theRefId) noexcept
560560

561561
//=================================================================================================
562562

563-
void BRepGraph::markRefModified(const BRepGraph_RefId /*theRefId*/,
563+
void BRepGraph::markRefModified(const BRepGraph_RefId theRefId,
564564
BRepGraphInc::BaseRef& theRef) noexcept
565565
{
566566
++theRef.OwnGen;
567567
myData->myPropagationWave.fetch_add(1, std::memory_order_relaxed);
568568

569+
// Only dispatch modification events for active (non-removed) refs.
570+
if (!theRef.IsRemoved)
571+
{
572+
if (myData->myDeferredMode.load(std::memory_order_relaxed))
573+
{
574+
myData->myDeferredRefModified.Append(theRefId);
575+
}
576+
else if (myLayerRegistry.HasRefModificationSubscribers())
577+
{
578+
myLayerRegistry.DispatchRefModified(theRefId);
579+
}
580+
}
581+
569582
if (!theRef.ParentId.IsValid())
570583
return;
571584

@@ -861,3 +874,63 @@ const BRepGraph_TransientCache& BRepGraph::transientCache() const
861874
{
862875
return myTransientCache;
863876
}
877+
878+
//=================================================================================================
879+
880+
BRepGraph_RefTransientCache& BRepGraph::refTransientCache()
881+
{
882+
return myRefTransientCache;
883+
}
884+
885+
//=================================================================================================
886+
887+
const BRepGraph_RefTransientCache& BRepGraph::refTransientCache() const
888+
{
889+
return myRefTransientCache;
890+
}
891+
892+
//=================================================================================================
893+
894+
const BRepGraphInc::BaseRef* BRepGraph::refEntity(const BRepGraph_RefId theId) const
895+
{
896+
if (!theId.IsValid())
897+
return nullptr;
898+
const BRepGraphInc_Storage& aStorage = myData->myIncStorage;
899+
switch (theId.RefKind)
900+
{
901+
case BRepGraph_RefId::Kind::Shell: {
902+
const BRepGraph_ShellRefId anId(theId.Index);
903+
return anId.IsValid(aStorage.NbShellRefs()) ? &aStorage.ShellRef(anId) : nullptr;
904+
}
905+
case BRepGraph_RefId::Kind::Face: {
906+
const BRepGraph_FaceRefId anId(theId.Index);
907+
return anId.IsValid(aStorage.NbFaceRefs()) ? &aStorage.FaceRef(anId) : nullptr;
908+
}
909+
case BRepGraph_RefId::Kind::Wire: {
910+
const BRepGraph_WireRefId anId(theId.Index);
911+
return anId.IsValid(aStorage.NbWireRefs()) ? &aStorage.WireRef(anId) : nullptr;
912+
}
913+
case BRepGraph_RefId::Kind::CoEdge: {
914+
const BRepGraph_CoEdgeRefId anId(theId.Index);
915+
return anId.IsValid(aStorage.NbCoEdgeRefs()) ? &aStorage.CoEdgeRef(anId) : nullptr;
916+
}
917+
case BRepGraph_RefId::Kind::Vertex: {
918+
const BRepGraph_VertexRefId anId(theId.Index);
919+
return anId.IsValid(aStorage.NbVertexRefs()) ? &aStorage.VertexRef(anId) : nullptr;
920+
}
921+
case BRepGraph_RefId::Kind::Solid: {
922+
const BRepGraph_SolidRefId anId(theId.Index);
923+
return anId.IsValid(aStorage.NbSolidRefs()) ? &aStorage.SolidRef(anId) : nullptr;
924+
}
925+
case BRepGraph_RefId::Kind::Child: {
926+
const BRepGraph_ChildRefId anId(theId.Index);
927+
return anId.IsValid(aStorage.NbChildRefs()) ? &aStorage.ChildRef(anId) : nullptr;
928+
}
929+
case BRepGraph_RefId::Kind::Occurrence: {
930+
const BRepGraph_OccurrenceRefId anId(theId.Index);
931+
return anId.IsValid(aStorage.NbOccurrenceRefs()) ? &aStorage.OccurrenceRef(anId) : nullptr;
932+
}
933+
default:
934+
return nullptr;
935+
}
936+
}

src/ModelingData/TKBRep/BRepGraph/BRepGraph.hxx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <BRepGraph_HistoryRecord.hxx>
2626
#include <BRepGraph_LayerRegistry.hxx>
2727
#include <BRepGraphInc_Populate.hxx>
28+
#include <BRepGraph_RefTransientCache.hxx>
2829
#include <BRepGraph_TransientCache.hxx>
2930

3031
#include <Standard_DefineAlloc.hxx>
@@ -61,7 +62,7 @@ class BRepGraph_History;
6162
//! - **RepId** (Kind + Index): separate geometry/mesh addressing (Surface,
6263
//! Curve3D, Curve2D, Triangulation, Polygon) decoupled from topology nodes.
6364
//! - **CoEdge**: half-edge entity owning PCurve data for each edge-face binding;
64-
//! seam edges use paired CoEdges with opposite Sense (Parasolid convention).
65+
//! seam edges use paired CoEdges with opposite Orientation (Parasolid convention).
6566
//! - **Lifecycle**: Build() populates from TopoDS_Shape; Builder().Mut*() guards
6667
//! provide RAII-scoped mutation with automatic cache invalidation and upward
6768
//! propagation.
@@ -219,6 +220,14 @@ private:
219220
[[nodiscard]] Standard_EXPORT BRepGraph_TransientCache& transientCache();
220221
[[nodiscard]] Standard_EXPORT const BRepGraph_TransientCache& transientCache() const;
221222

223+
//! Access the raw reference transient cache.
224+
[[nodiscard]] Standard_EXPORT BRepGraph_RefTransientCache& refTransientCache();
225+
[[nodiscard]] Standard_EXPORT const BRepGraph_RefTransientCache& refTransientCache() const;
226+
227+
//! Generic reference lookup by RefId (const).
228+
//! Returns nullptr if the RefId is invalid or out of range.
229+
Standard_EXPORT const BRepGraphInc::BaseRef* refEntity(const BRepGraph_RefId theId) const;
230+
222231
//! @}
223232

224233
Standard_EXPORT void invalidateSubgraphImpl(const BRepGraph_NodeId theNode);
@@ -260,8 +269,9 @@ private:
260269
std::unique_ptr<BRepGraph_Data> myData;
261270

262271
//! Registered layers are stored on BRepGraph, not BRepGraph_Data, to survive Compact swap.
263-
BRepGraph_LayerRegistry myLayerRegistry;
264-
BRepGraph_TransientCache myTransientCache; //!< Transient algorithm caches (BndBox, UVBounds)
272+
BRepGraph_LayerRegistry myLayerRegistry;
273+
BRepGraph_TransientCache myTransientCache; //!< Transient algorithm caches (BndBox, UVBounds)
274+
BRepGraph_RefTransientCache myRefTransientCache; //!< Transient per-reference caches
265275
};
266276

267277
// Included after BRepGraph is complete so the template body sees markModified().

src/ModelingData/TKBRep/BRepGraph/BRepGraph_Builder.cxx

Lines changed: 106 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// commercial license or contractual agreement.
1313

1414
#include <BRepGraph_Builder.hxx>
15+
#include <BRepGraph_BuilderView.hxx>
1516
#include <BRepGraph.hxx>
1617
#include <BRepGraph_Data.hxx>
1718
#include <BRepGraph_Layer.hxx>
@@ -50,6 +51,16 @@ static Standard_GUID generateRandomGUID()
5051
return Standard_GUID(aUUID);
5152
}
5253

54+
//=================================================================================================
55+
56+
static void assertMutationBoundary(BRepGraph& theGraph, const char* theContext)
57+
{
58+
(void)theContext;
59+
const bool isValid = theGraph.Builder().ValidateMutationBoundary();
60+
Standard_ASSERT_VOID(isValid, theContext);
61+
(void)isValid;
62+
}
63+
5364
} // namespace
5465

5566
//=================================================================================================
@@ -184,8 +195,7 @@ void BRepGraph_Builder::Perform(BRepGraph& theGraph,
184195

185196
populateUIDs(theGraph);
186197

187-
// Auto-create a single root Product pointing to the top-level topology node.
188-
// aTopologyRoot defaults to invalid (Index = -1); set only if topology exists.
198+
// Determine the top-level topology root node.
189199
{
190200
BRepGraphInc_Storage& aStorage = theGraph.myData->myIncStorage;
191201
BRepGraph_NodeId aTopologyRoot; // default: invalid (Index = -1)
@@ -230,13 +240,18 @@ void BRepGraph_Builder::Perform(BRepGraph& theGraph,
230240
if (aTopologyRoot.IsValid())
231241
theGraph.myData->myRootNodeIds.Append(aTopologyRoot);
232242

233-
BRepGraphInc::ProductDef& aProduct = aStorage.AppendProduct();
234-
const int aProductIdx = aStorage.NbProducts() - 1;
235-
aProduct.Id = BRepGraph_ProductId(aProductIdx);
236-
aProduct.ShapeRootId = aTopologyRoot; // invalid if no topology matched
237-
aProduct.RootOrientation = theShape.Orientation();
238-
aProduct.RootLocation = theShape.Location();
239-
theGraph.allocateUID(aProduct.Id);
243+
// Auto-create a single root Product pointing to the top-level topology node.
244+
// Skipped when CreateAutoProduct is false (e.g. XCAF builder manages Products itself).
245+
if (theOptions.CreateAutoProduct)
246+
{
247+
BRepGraphInc::ProductDef& aProduct = aStorage.AppendProduct();
248+
const int aProductIdx = aStorage.NbProducts() - 1;
249+
aProduct.Id = BRepGraph_ProductId(aProductIdx);
250+
aProduct.ShapeRootId = aTopologyRoot; // invalid if no topology matched
251+
aProduct.RootOrientation = theShape.Orientation();
252+
aProduct.RootLocation = theShape.Location();
253+
theGraph.allocateUID(aProduct.Id);
254+
}
240255
}
241256

242257
theGraph.myData->myIsDone = true;
@@ -266,13 +281,16 @@ void BRepGraph_Builder::Perform(BRepGraph& theGraph,
266281
}
267282
theGraph.myTransientCache.Reserve(aReservedKindCount, aCounts);
268283
}
284+
285+
assertMutationBoundary(theGraph, "Build: post-build mutation boundary inconsistency");
269286
}
270287

271288
//=================================================================================================
272289

273-
void BRepGraph_Builder::AppendFlattened(BRepGraph& theGraph,
274-
const TopoDS_Shape& theShape,
275-
const bool theParallel)
290+
void BRepGraph_Builder::AppendFlattened(BRepGraph& theGraph,
291+
const TopoDS_Shape& theShape,
292+
const bool theParallel,
293+
const BRepGraphInc_Populate::Options& theOptions)
276294
{
277295
if (theShape.IsNull())
278296
return;
@@ -308,7 +326,7 @@ void BRepGraph_Builder::AppendFlattened(BRepGraph& theGraph,
308326
theShape,
309327
theParallel,
310328
aAppendedRoots,
311-
BRepGraphInc_Populate::Options(),
329+
theOptions,
312330
aParamLayer.get(),
313331
aRegularityLayer.get(),
314332
aTmpAlloc);
@@ -344,6 +362,81 @@ void BRepGraph_Builder::AppendFlattened(BRepGraph& theGraph,
344362
}
345363

346364
theGraph.myData->myIsDone = true;
365+
366+
assertMutationBoundary(theGraph, "AppendFlattened: post-append mutation boundary inconsistency");
367+
}
368+
369+
//=================================================================================================
370+
371+
void BRepGraph_Builder::AppendFull(BRepGraph& theGraph,
372+
const TopoDS_Shape& theShape,
373+
const bool theParallel,
374+
const BRepGraphInc_Populate::Options& theOptions)
375+
{
376+
if (theShape.IsNull())
377+
return;
378+
379+
BRepGraphInc_Storage& aStorage = theGraph.myData->myIncStorage;
380+
const int anOldVtx = aStorage.NbVertices();
381+
const int anOldEdge = aStorage.NbEdges();
382+
const int anOldCoEdge = aStorage.NbCoEdges();
383+
const int anOldWire = aStorage.NbWires();
384+
const int anOldFace = aStorage.NbFaces();
385+
const int anOldShell = aStorage.NbShells();
386+
const int anOldSolid = aStorage.NbSolids();
387+
const int anOldComp = aStorage.NbCompounds();
388+
const int anOldCS = aStorage.NbCompSolids();
389+
const int anOldProduct = aStorage.NbProducts();
390+
const int anOldOccurrence = aStorage.NbOccurrences();
391+
const int anOldShellRef = aStorage.NbShellRefs();
392+
const int anOldFaceRef = aStorage.NbFaceRefs();
393+
const int anOldWireRef = aStorage.NbWireRefs();
394+
const int anOldCoEdgeRef = aStorage.NbCoEdgeRefs();
395+
const int anOldVertexRef = aStorage.NbVertexRefs();
396+
const int anOldSolidRef = aStorage.NbSolidRefs();
397+
const int anOldChildRef = aStorage.NbChildRefs();
398+
399+
occ::handle<NCollection_IncAllocator> aTmpAlloc = new NCollection_IncAllocator;
400+
const occ::handle<BRepGraph_ParamLayer> aParamLayer =
401+
theGraph.LayerRegistry().FindLayer<BRepGraph_ParamLayer>();
402+
const occ::handle<BRepGraph_RegularityLayer> aRegularityLayer =
403+
theGraph.LayerRegistry().FindLayer<BRepGraph_RegularityLayer>();
404+
BRepGraphInc_Populate::Append(aStorage,
405+
theShape,
406+
theParallel,
407+
theOptions,
408+
aParamLayer.get(),
409+
aRegularityLayer.get(),
410+
aTmpAlloc);
411+
412+
if (!aStorage.GetIsDone())
413+
return;
414+
415+
theGraph.myData->myCurrentShapes.Clear();
416+
417+
populateUIDsIncremental(theGraph,
418+
anOldVtx,
419+
anOldEdge,
420+
anOldCoEdge,
421+
anOldWire,
422+
anOldFace,
423+
anOldShell,
424+
anOldSolid,
425+
anOldComp,
426+
anOldCS,
427+
anOldProduct,
428+
anOldOccurrence,
429+
anOldShellRef,
430+
anOldFaceRef,
431+
anOldWireRef,
432+
anOldCoEdgeRef,
433+
anOldVertexRef,
434+
anOldSolidRef,
435+
anOldChildRef);
436+
437+
theGraph.myData->myIsDone = true;
438+
439+
assertMutationBoundary(theGraph, "AppendFull: post-append mutation boundary inconsistency");
347440
}
348441

349442
//=================================================================================================

src/ModelingData/TKBRep/BRepGraph/BRepGraph_Builder.hxx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,26 @@ public:
5151
//! @param[in,out] theGraph graph to extend
5252
//! @param[in] theShape shape to add
5353
//! @param[in] theParallel if true, per-face geometry extraction is parallel
54-
static Standard_EXPORT void AppendFlattened(BRepGraph& theGraph,
55-
const TopoDS_Shape& theShape,
56-
const bool theParallel);
54+
//! @param[in] theOptions populate options (e.g. CreateAutoProduct)
55+
static Standard_EXPORT void AppendFlattened(
56+
BRepGraph& theGraph,
57+
const TopoDS_Shape& theShape,
58+
const bool theParallel,
59+
const BRepGraphInc_Populate::Options& theOptions = BRepGraphInc_Populate::Options());
60+
61+
//! Append a shape to the existing graph without clearing.
62+
//! Preserves the full shape hierarchy: Solid/Shell/Compound/CompSolid nodes
63+
//! are created alongside Face/Edge/Vertex nodes. Shapes already present in
64+
//! the graph (same TShape pointer) are deduplicated and not re-added.
65+
//! @param[in,out] theGraph graph to extend
66+
//! @param[in] theShape shape to add
67+
//! @param[in] theParallel if true, per-face geometry extraction is parallel
68+
//! @param[in] theOptions populate options (e.g. CreateAutoProduct)
69+
static Standard_EXPORT void AppendFull(
70+
BRepGraph& theGraph,
71+
const TopoDS_Shape& theShape,
72+
const bool theParallel,
73+
const BRepGraphInc_Populate::Options& theOptions = BRepGraphInc_Populate::Options());
5774

5875
private:
5976
//! Allocate UIDs for all incidence entities after BRepGraphInc_Populate

0 commit comments

Comments
 (0)