mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-08-28 13:58:22 +08:00
Modeling, BRepGraph - Identity copy path, lock-free cache reads, per-CoEdge queries (#1306)
Identity copy path: - copyFullGraphIdentity with PrepareForLoad() + direct slot assignment - CopyDerivedRelationsFrom for O(K) relation vector copy - CopyRemovedFlagsFrom for bulk removed-flag copy - CopyShapeBindingsFrom for TShape/Original shape binding copy - PrepareForLoad skips Clear() when storage already empty (IsEmpty fast path) - appendRelationIdDirect for O(1) append in rebuild loop (duplicates structurally impossible) - ChangeCompoundRefsOfNodeInternal uses TryBound for single lookup - Counts() and ActiveCounts() accessors for Counts struct construction Lock-free cache reads: - EdgeEntry: packed atomic<uint8_t> (GeomStatus+IsClosed+IsComputed) - CoEdgeSameRangeEntry: packed atomic<uint8_t> (SameRange+SameParameter+Computed) - WireEntry: packed atomic<uint8_t> (IsClosed+IsComputed) - ShellEntry: atomic<ClosureStatus> with Invalid sentinel - All entries use memory_order_acquire/release pairs - ensureSize handles lazy array growth (no myPreSized) - Enums (GeomStatus, ClosureStatus) moved inside entry structs Per-CoEdge queries: - SameRange/SameParameter are per-CoEdge properties, bound to CoEdge OwnGen - Edge class no longer has SameParameter/SameRange/IsClosed coedge overloads - CoEdge class owns SameParameter/SameRange queries - Test files use local edgeSameParameter/edgeSameRange helpers Lock-free storage and registry: - BRepGraphInc_Storage: atomic dirty flags for UID reverse indexes - BRepGraph_LayerRegistry: atomic subscription masks for lock-free dispatch - Ensure/EnsureCache/EnsureLayer: double-checked locking with shared fast path Other optimizations: - Iterator Next() fast-path: check next element validity inline - NbFaces O(K) inline dedup with NCollection_LocalArray - GeomAdaptor_Curve/Surface/Geom2dAdaptor_Curve for cached geometry eval - Value() calls replaced with EvalD0() for clearer naming - TargetItem returns value instead of pointer (no null-pointer risk) - copyTopologyDefinitionsIdentity clears Curve3DRepId on GeomPolicy::Drop - ensureEdgeEntry concurrency: fast-path validation + selective field merge
This commit is contained in:
@@ -22,12 +22,15 @@
|
||||
#include <Geom2d_Curve.hxx>
|
||||
#include <Geom_Curve.hxx>
|
||||
#include <Geom_Surface.hxx>
|
||||
#include <GeomAdaptor_Curve.hxx>
|
||||
#include <GeomAdaptor_Surface.hxx>
|
||||
#include <Geom2dAdaptor_Curve.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <NCollection_FlatMap.hxx>
|
||||
#include <NCollection_Map.hxx>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(BRepGraph_CacheDerivedState, BRepGraph_Cache)
|
||||
@@ -41,6 +44,15 @@ const Standard_GUID& theGUID()
|
||||
return aGUID;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ensureSize(NCollection_DynamicArray<T>& theArray, uint32_t theIndex)
|
||||
{
|
||||
if (static_cast<size_t>(theIndex) >= theArray.Size())
|
||||
{
|
||||
theArray.SetValue(static_cast<size_t>(theIndex), T());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename IdT>
|
||||
IdT remappedNode(const BRepGraph_CopyRemap& theCopy, const IdT theId)
|
||||
{
|
||||
@@ -48,12 +60,12 @@ IdT remappedNode(const BRepGraph_CopyRemap& theCopy, const IdT theId)
|
||||
{
|
||||
return IdT();
|
||||
}
|
||||
const BRepGraph_ItemId* aTarget = theCopy.TargetItem(BRepGraph_ItemId(theId));
|
||||
if (aTarget == nullptr || !aTarget->IsNode())
|
||||
const BRepGraph_ItemId aTarget = theCopy.TargetItem(BRepGraph_ItemId(theId));
|
||||
if (!aTarget.IsNode())
|
||||
{
|
||||
return IdT();
|
||||
}
|
||||
return IdT::FromNodeId(aTarget->NodeId());
|
||||
return IdT::FromNodeId(aTarget.NodeId());
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
@@ -130,90 +142,80 @@ bool coEdgeOrientedVertices(const BRepGraph& theGraph,
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool isEdgeSameRange(const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge,
|
||||
const std::pair<double, double>& theEdgeRange)
|
||||
bool isCoEdgeSameRange(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge,
|
||||
const BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
const BRepGraphInc::EdgeRelations& anEdgeRel = theGraph.Topo().Edges().Relations(theEdge);
|
||||
for (const BRepGraph_CoEdgeId& aCoEdgeId : anEdgeRel.CoEdgeIds)
|
||||
if (!theCoEdge.IsValid(theGraph.Topo().CoEdges().Nb()) || theCoEdge.IsRemoved(theGraph))
|
||||
{
|
||||
if (!aCoEdgeId.IsValid(theGraph.Topo().CoEdges().Nb()) || aCoEdgeId.IsRemoved(theGraph))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const BRepGraphInc::CoEdgeDef& aCoEdge = theGraph.Topo().CoEdges().Definition(aCoEdgeId);
|
||||
if (!aCoEdge.FaceId.IsValid(theGraph.Topo().Faces().Nb()) || aCoEdge.FaceId.IsRemoved(theGraph))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (coEdgePCurve(theGraph, aCoEdgeId).IsNull())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::pair<double, double> aPCurveRange =
|
||||
BRepGraph_Tool::CoEdge::Range(theGraph, aCoEdgeId);
|
||||
if (std::abs(aPCurveRange.first - theEdgeRange.first) > Precision::PConfusion()
|
||||
|| std::abs(aPCurveRange.second - theEdgeRange.second) > Precision::PConfusion())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
const BRepGraphInc::CoEdgeDef& aCoEdge = theGraph.Topo().CoEdges().Definition(theCoEdge);
|
||||
if (!aCoEdge.FaceId.IsValid(theGraph.Topo().Faces().Nb()) || aCoEdge.FaceId.IsRemoved(theGraph))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (coEdgePCurve(theGraph, theCoEdge).IsNull())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::pair<double, double> anEdgeRange = BRepGraph_Tool::Edge::Range(theGraph, theEdge);
|
||||
const std::pair<double, double> aPCurveRange = BRepGraph_Tool::CoEdge::Range(theGraph, theCoEdge);
|
||||
return std::abs(aPCurveRange.first - anEdgeRange.first) <= Precision::PConfusion()
|
||||
&& std::abs(aPCurveRange.second - anEdgeRange.second) <= Precision::PConfusion();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool isEdgeSameParameter(const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge,
|
||||
const BRepGraphInc::EdgeDef& theEdgeDef,
|
||||
const occ::handle<Geom_Curve>& theCurve3D,
|
||||
const std::pair<double, double>& theEdgeRange)
|
||||
bool isCoEdgeSameParameter(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge,
|
||||
const BRepGraphInc::EdgeDef& theEdgeDef,
|
||||
const occ::handle<Geom_Curve>& theCurve3D,
|
||||
const std::pair<double, double>& theEdgeRange)
|
||||
{
|
||||
if (!theCoEdge.IsValid(theGraph.Topo().CoEdges().Nb()) || theCoEdge.IsRemoved(theGraph))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const BRepGraphInc::CoEdgeDef& aCoEdge = theGraph.Topo().CoEdges().Definition(theCoEdge);
|
||||
if (!aCoEdge.FaceId.IsValid(theGraph.Topo().Faces().Nb()) || aCoEdge.FaceId.IsRemoved(theGraph))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const occ::handle<Geom2d_Curve>& aPCurve = coEdgePCurve(theGraph, theCoEdge);
|
||||
if (aPCurve.IsNull())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const occ::handle<Geom_Surface> aSurface = faceSurface(theGraph, aCoEdge.FaceId);
|
||||
if (aSurface.IsNull())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const double aTol = theEdgeDef.Tolerance + Precision::Confusion();
|
||||
constexpr int THE_NB_SAMPLES = 5;
|
||||
|
||||
const BRepGraphInc::EdgeRelations& anEdgeRel = theGraph.Topo().Edges().Relations(theEdge);
|
||||
GeomAdaptor_Curve aCurveAdaptor(theCurve3D, theEdgeRange.first, theEdgeRange.second);
|
||||
Geom2dAdaptor_Curve aPCurveAdaptor(aPCurve);
|
||||
GeomAdaptor_Surface aSurfAdaptor(aSurface);
|
||||
|
||||
for (int anIdx = 0; anIdx <= THE_NB_SAMPLES; ++anIdx)
|
||||
{
|
||||
const double aParam =
|
||||
theEdgeRange.first + (theEdgeRange.second - theEdgeRange.first) * anIdx / THE_NB_SAMPLES;
|
||||
const gp_Pnt aPoint3D = theCurve3D->Value(aParam);
|
||||
|
||||
for (const BRepGraph_CoEdgeId& aCoEdgeId : anEdgeRel.CoEdgeIds)
|
||||
const gp_Pnt aPoint3D = aCurveAdaptor.EvalD0(aParam);
|
||||
const gp_Pnt2d aUV = aPCurveAdaptor.EvalD0(aParam);
|
||||
const gp_Pnt aSurfacePoint = aSurfAdaptor.EvalD0(aUV.X(), aUV.Y());
|
||||
if (aPoint3D.Distance(aSurfacePoint) > aTol)
|
||||
{
|
||||
if (!aCoEdgeId.IsValid(theGraph.Topo().CoEdges().Nb()) || aCoEdgeId.IsRemoved(theGraph))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const BRepGraphInc::CoEdgeDef& aCoEdge = theGraph.Topo().CoEdges().Definition(aCoEdgeId);
|
||||
if (!aCoEdge.FaceId.IsValid(theGraph.Topo().Faces().Nb())
|
||||
|| aCoEdge.FaceId.IsRemoved(theGraph))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const occ::handle<Geom2d_Curve>& aPCurve = coEdgePCurve(theGraph, aCoEdgeId);
|
||||
if (aPCurve.IsNull())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const occ::handle<Geom_Surface> aSurface = faceSurface(theGraph, aCoEdge.FaceId);
|
||||
if (aSurface.IsNull())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const gp_Pnt2d aUV = aPCurve->Value(aParam);
|
||||
const gp_Pnt aSurfacePoint = aSurface->Value(aUV.X(), aUV.Y());
|
||||
if (aPoint3D.Distance(aSurfacePoint) > aTol)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -247,10 +249,23 @@ const TCollection_AsciiString& BRepGraph_CacheDerivedState::Name() const
|
||||
|
||||
void BRepGraph_CacheDerivedState::Clear() noexcept
|
||||
{
|
||||
std::unique_lock aLock(myMutex);
|
||||
myEdgeEntries.Clear();
|
||||
myWireEntries.Clear();
|
||||
myShellEntries.Clear();
|
||||
std::lock_guard aLock(myMutex);
|
||||
for (EdgeEntry& aEntry : myEdgeEntries)
|
||||
{
|
||||
aEntry.Reset();
|
||||
}
|
||||
for (CoEdgeSameRangeEntry& aEntry : myCoEdgeSameRangeEntries)
|
||||
{
|
||||
aEntry.Reset();
|
||||
}
|
||||
for (WireEntry& aEntry : myWireEntries)
|
||||
{
|
||||
aEntry.Reset();
|
||||
}
|
||||
for (ShellEntry& aEntry : myShellEntries)
|
||||
{
|
||||
aEntry.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
@@ -260,132 +275,412 @@ void BRepGraph_CacheDerivedState::CopyFreshTo(const BRepGraph_CopyRemap& theCopy
|
||||
occ::handle<BRepGraph_CacheDerivedState> aTargetCache =
|
||||
theCopy.TargetGraph().CacheRegistry().Ensure<BRepGraph_CacheDerivedState>();
|
||||
|
||||
std::shared_lock aSourceLock(myMutex);
|
||||
std::unique_lock aTargetLock(aTargetCache->myMutex);
|
||||
std::lock_guard aSourceLock(myMutex);
|
||||
std::lock_guard aTargetLock(aTargetCache->myMutex);
|
||||
|
||||
for (NCollection_DataMap<BRepGraph_EdgeId, EdgeEntry>::Iterator anIt(myEdgeEntries); anIt.More();
|
||||
anIt.Next())
|
||||
for (const EdgeEntry& aSourceEntry : myEdgeEntries)
|
||||
{
|
||||
const BRepGraph_EdgeId aSourceEdge = anIt.Key();
|
||||
const EdgeEntry& aSourceEntry = anIt.Value();
|
||||
if (!aSourceEntry.IsFreshOwn(*this, BRepGraph_NodeId(aSourceEdge)))
|
||||
if (!aSourceEntry.IsFreshOwn(*this, aSourceEntry.Node()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const BRepGraph_EdgeId aSourceEdge = BRepGraph_EdgeId::FromNodeId(aSourceEntry.Node());
|
||||
const BRepGraph_EdgeId aTargetEdge = remappedNode(theCopy, aSourceEdge);
|
||||
if (!aTargetEdge.IsValidIn(theCopy.TargetGraph().Topo().Edges()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ensureSize(aTargetCache->myEdgeEntries, aTargetEdge.Index);
|
||||
EdgeEntry aTargetEntry = aSourceEntry;
|
||||
if (aTargetEntry.BindOwnGen(*aTargetCache, BRepGraph_NodeId(aTargetEdge)))
|
||||
{
|
||||
aTargetCache->myEdgeEntries.Bind(aTargetEdge, aTargetEntry);
|
||||
aTargetCache->myEdgeEntries.ChangeValue(static_cast<size_t>(aTargetEdge.Index)) =
|
||||
aTargetEntry;
|
||||
}
|
||||
}
|
||||
|
||||
for (NCollection_DataMap<BRepGraph_WireId, WireEntry>::Iterator anIt(myWireEntries); anIt.More();
|
||||
anIt.Next())
|
||||
for (const CoEdgeSameRangeEntry& aSourceEntry : myCoEdgeSameRangeEntries)
|
||||
{
|
||||
const BRepGraph_WireId aSourceWire = anIt.Key();
|
||||
const WireEntry& aSourceEntry = anIt.Value();
|
||||
if (!aSourceEntry.IsFreshOwn(*this, BRepGraph_NodeId(aSourceWire)))
|
||||
if (!aSourceEntry.IsFreshOwn(*this, aSourceEntry.Node()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const BRepGraph_CoEdgeId aSourceCoEdge = BRepGraph_CoEdgeId::FromNodeId(aSourceEntry.Node());
|
||||
const BRepGraph_CoEdgeId aTargetCoEdge = remappedNode(theCopy, aSourceCoEdge);
|
||||
if (!aTargetCoEdge.IsValidIn(theCopy.TargetGraph().Topo().CoEdges()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ensureSize(aTargetCache->myCoEdgeSameRangeEntries, aTargetCoEdge.Index);
|
||||
CoEdgeSameRangeEntry aTargetEntry = aSourceEntry;
|
||||
if (aTargetEntry.BindOwnGen(*aTargetCache, BRepGraph_NodeId(aTargetCoEdge)))
|
||||
{
|
||||
aTargetCache->myCoEdgeSameRangeEntries.ChangeValue(static_cast<size_t>(aTargetCoEdge.Index)) =
|
||||
aTargetEntry;
|
||||
}
|
||||
}
|
||||
|
||||
for (const WireEntry& aSourceEntry : myWireEntries)
|
||||
{
|
||||
if (!aSourceEntry.IsFreshOwn(*this, aSourceEntry.Node()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const BRepGraph_WireId aSourceWire = BRepGraph_WireId::FromNodeId(aSourceEntry.Node());
|
||||
const BRepGraph_WireId aTargetWire = remappedNode(theCopy, aSourceWire);
|
||||
if (!aTargetWire.IsValidIn(theCopy.TargetGraph().Topo().Wires()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ensureSize(aTargetCache->myWireEntries, aTargetWire.Index);
|
||||
WireEntry aTargetEntry = aSourceEntry;
|
||||
if (aTargetEntry.BindOwnGen(*aTargetCache, BRepGraph_NodeId(aTargetWire)))
|
||||
{
|
||||
aTargetCache->myWireEntries.Bind(aTargetWire, aTargetEntry);
|
||||
aTargetCache->myWireEntries.ChangeValue(static_cast<size_t>(aTargetWire.Index)) =
|
||||
aTargetEntry;
|
||||
}
|
||||
}
|
||||
|
||||
for (NCollection_DataMap<BRepGraph_ShellId, ShellEntry>::Iterator anIt(myShellEntries);
|
||||
anIt.More();
|
||||
anIt.Next())
|
||||
for (const ShellEntry& aSourceEntry : myShellEntries)
|
||||
{
|
||||
const BRepGraph_ShellId aSourceShell = anIt.Key();
|
||||
const ShellEntry& aSourceEntry = anIt.Value();
|
||||
if (!aSourceEntry.IsFreshOwn(*this, BRepGraph_NodeId(aSourceShell)))
|
||||
if (!aSourceEntry.IsFreshOwn(*this, aSourceEntry.Node()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const BRepGraph_ShellId aSourceShell = BRepGraph_ShellId::FromNodeId(aSourceEntry.Node());
|
||||
const BRepGraph_ShellId aTargetShell = remappedNode(theCopy, aSourceShell);
|
||||
if (!aTargetShell.IsValidIn(theCopy.TargetGraph().Topo().Shells()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ensureSize(aTargetCache->myShellEntries, aTargetShell.Index);
|
||||
ShellEntry aTargetEntry = aSourceEntry;
|
||||
if (aTargetEntry.BindOwnGen(*aTargetCache, BRepGraph_NodeId(aTargetShell)))
|
||||
{
|
||||
aTargetCache->myShellEntries.Bind(aTargetShell, aTargetEntry);
|
||||
aTargetCache->myShellEntries.ChangeValue(static_cast<size_t>(aTargetShell.Index)) =
|
||||
aTargetEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheDerivedState::ComputeEdgeStatus(const BRepGraph& theGraph,
|
||||
void BRepGraph_CacheDerivedState::computeStatusOnly(const BRepGraph& theGraph,
|
||||
BRepGraph_EdgeId theEdge,
|
||||
EdgeEntry& theEntry)
|
||||
{
|
||||
theEntry.Status = EdgeGeometryStatus::Invalid;
|
||||
theEntry.IsClosed = false;
|
||||
theEntry.SameRange = false;
|
||||
theEntry.SameParameter = false;
|
||||
const BRepGraphInc::EdgeDef& aDef = theGraph.Topo().Edges().Definition(theEdge);
|
||||
|
||||
const BRepGraph_VertexId aStartV = resolveChildVertex(theGraph, aDef.StartVertexRefId);
|
||||
const BRepGraph_VertexId aEndV = resolveChildVertex(theGraph, aDef.EndVertexRefId);
|
||||
const bool aClosed = aStartV.IsValid() && aStartV == aEndV;
|
||||
|
||||
const occ::handle<Geom_Curve>& aCurve3D = edgeCurve3D(theGraph, theEdge);
|
||||
EdgeEntry::GeomStatus aStatus;
|
||||
if (!aCurve3D.IsNull())
|
||||
{
|
||||
aStatus = EdgeEntry::GeomStatus::HasCurve3D;
|
||||
}
|
||||
else if (aClosed)
|
||||
{
|
||||
aStatus = EdgeEntry::GeomStatus::DegenerateOnSurface;
|
||||
}
|
||||
else if (aStartV.IsValid() && aEndV.IsValid())
|
||||
{
|
||||
const BRepGraphInc::VertexDef& aStartDef = theGraph.Topo().Vertices().Definition(aStartV);
|
||||
const BRepGraphInc::VertexDef& aEndDef = theGraph.Topo().Vertices().Definition(aEndV);
|
||||
aStatus = aStartDef.Point.Distance(aEndDef.Point) <= aDef.Tolerance
|
||||
? EdgeEntry::GeomStatus::DegenerateOnSurface
|
||||
: EdgeEntry::GeomStatus::MissingCurve3D;
|
||||
}
|
||||
else
|
||||
{
|
||||
aStatus = EdgeEntry::GeomStatus::MissingCurve3D;
|
||||
}
|
||||
|
||||
theEntry.Set(aStatus, aClosed);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraph_CacheDerivedState::computeSameRange(const BRepGraph& theGraph,
|
||||
BRepGraph_CoEdgeId theCoEdge,
|
||||
CoEdgeSameRangeEntry& theEntry)
|
||||
{
|
||||
if (!theCoEdge.IsValid(theGraph.Topo().CoEdges().Nb()) || theCoEdge.IsRemoved(theGraph))
|
||||
{
|
||||
theEntry.SetSameRange(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const BRepGraphInc::CoEdgeDef& aCoEdge = theGraph.Topo().CoEdges().Definition(theCoEdge);
|
||||
const BRepGraph_EdgeId anEdge = aCoEdge.ChildEdgeId;
|
||||
|
||||
if (!anEdge.IsValid(theGraph.Topo().Edges().Nb()) || anEdge.IsRemoved(theGraph))
|
||||
{
|
||||
theEntry.SetSameRange(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const occ::handle<Geom_Curve>& aCurve3D = edgeCurve3D(theGraph, anEdge);
|
||||
if (!aCurve3D.IsNull())
|
||||
{
|
||||
theEntry.SetSameRange(isCoEdgeSameRange(theGraph, theCoEdge, anEdge));
|
||||
}
|
||||
else
|
||||
{
|
||||
const BRepGraphInc::EdgeDef& aDef = theGraph.Topo().Edges().Definition(anEdge);
|
||||
const BRepGraph_VertexId aStartV = resolveChildVertex(theGraph, aDef.StartVertexRefId);
|
||||
const BRepGraph_VertexId aEndV = resolveChildVertex(theGraph, aDef.EndVertexRefId);
|
||||
theEntry.SetSameRange(aStartV.IsValid() && aStartV == aEndV);
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraph_CacheDerivedState::computeSameParameter(const BRepGraph& theGraph,
|
||||
BRepGraph_CoEdgeId theCoEdge,
|
||||
CoEdgeSameRangeEntry& theEntry)
|
||||
{
|
||||
if ((theEntry.Computed() & CoEdgeSameRangeEntry::ComputedSameRange) == 0)
|
||||
{
|
||||
computeSameRange(theGraph, theCoEdge, theEntry);
|
||||
}
|
||||
|
||||
if (!theCoEdge.IsValid(theGraph.Topo().CoEdges().Nb()) || theCoEdge.IsRemoved(theGraph))
|
||||
{
|
||||
theEntry.SetSameParameter(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const BRepGraphInc::CoEdgeDef& aCoEdge = theGraph.Topo().CoEdges().Definition(theCoEdge);
|
||||
const BRepGraph_EdgeId anEdge = aCoEdge.ChildEdgeId;
|
||||
|
||||
if (!anEdge.IsValid(theGraph.Topo().Edges().Nb()) || anEdge.IsRemoved(theGraph))
|
||||
{
|
||||
theEntry.SetSameParameter(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const BRepGraphInc::EdgeDef& aDef = theGraph.Topo().Edges().Definition(anEdge);
|
||||
const occ::handle<Geom_Curve>& aCurve3D = edgeCurve3D(theGraph, anEdge);
|
||||
|
||||
if (!aCurve3D.IsNull())
|
||||
{
|
||||
if (theEntry.SameRange())
|
||||
{
|
||||
const std::pair<double, double> aRange = BRepGraph_Tool::Edge::Range(theGraph, anEdge);
|
||||
theEntry.SetSameParameter(isCoEdgeSameParameter(theGraph, theCoEdge, aDef, aCurve3D, aRange));
|
||||
}
|
||||
else
|
||||
{
|
||||
theEntry.SetSameParameter(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const BRepGraph_VertexId aStartV = resolveChildVertex(theGraph, aDef.StartVertexRefId);
|
||||
const BRepGraph_VertexId aEndV = resolveChildVertex(theGraph, aDef.EndVertexRefId);
|
||||
theEntry.SetSameParameter(aStartV.IsValid() && aStartV == aEndV);
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheDerivedState::ensureEdgeEntry(BRepGraph_EdgeId theEdge, EdgeEntry& theEntry)
|
||||
{
|
||||
// Lock-free read path: check packed flags without mutex.
|
||||
if (static_cast<size_t>(theEdge.Index) < myEdgeEntries.Size())
|
||||
{
|
||||
const EdgeEntry& aCached = myEdgeEntries.Value(static_cast<size_t>(theEdge.Index));
|
||||
if (aCached.IsFreshOwn(*this, theEdge) && aCached.IsComputed())
|
||||
{
|
||||
theEntry = aCached;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const BRepGraph& aGraph = Graph();
|
||||
if (!theEdge.IsValid(aGraph.Topo().Edges().Nb()) || theEdge.IsRemoved(aGraph))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
EdgeEntry aEntry;
|
||||
computeStatusOnly(aGraph, theEdge, aEntry);
|
||||
|
||||
{
|
||||
std::unique_lock aLock(myMutex);
|
||||
ensureSize(myEdgeEntries, theEdge.Index);
|
||||
EdgeEntry& aStored = myEdgeEntries.ChangeValue(static_cast<size_t>(theEdge.Index));
|
||||
if (aStored.IsFreshOwn(*this, theEdge) && aStored.IsComputed())
|
||||
{
|
||||
theEntry = aStored;
|
||||
return true;
|
||||
}
|
||||
aStored = aEntry;
|
||||
if (!aStored.BindOwnGen(*this, theEdge))
|
||||
{
|
||||
aStored.Reset();
|
||||
return false;
|
||||
}
|
||||
theEntry = aStored;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheDerivedState::ensureCoEdgeSameRangeEntry(BRepGraph_CoEdgeId theCoEdge,
|
||||
uint8_t theRequiredFlags,
|
||||
CoEdgeSameRangeEntry& theEntry)
|
||||
{
|
||||
// Lock-free read path: check packed flags without mutex.
|
||||
if (static_cast<size_t>(theCoEdge.Index) < myCoEdgeSameRangeEntries.Size())
|
||||
{
|
||||
const CoEdgeSameRangeEntry& aCached =
|
||||
myCoEdgeSameRangeEntries.Value(static_cast<size_t>(theCoEdge.Index));
|
||||
if (aCached.IsFreshOwn(*this, theCoEdge))
|
||||
{
|
||||
const uint8_t aComputed = aCached.Computed();
|
||||
if ((aComputed & theRequiredFlags) == theRequiredFlags)
|
||||
{
|
||||
theEntry = aCached;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const BRepGraph& aGraph = Graph();
|
||||
if (!theCoEdge.IsValid(aGraph.Topo().CoEdges().Nb()) || theCoEdge.IsRemoved(aGraph))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CoEdgeSameRangeEntry aEntry;
|
||||
if (static_cast<size_t>(theCoEdge.Index) < myCoEdgeSameRangeEntries.Size())
|
||||
{
|
||||
const CoEdgeSameRangeEntry& aCached =
|
||||
myCoEdgeSameRangeEntries.Value(static_cast<size_t>(theCoEdge.Index));
|
||||
if (aCached.IsFreshOwn(*this, theCoEdge))
|
||||
{
|
||||
aEntry = aCached;
|
||||
}
|
||||
}
|
||||
|
||||
if ((aEntry.Computed() & CoEdgeSameRangeEntry::ComputedSameRange) == 0
|
||||
&& (theRequiredFlags & CoEdgeSameRangeEntry::ComputedSameRange))
|
||||
{
|
||||
computeSameRange(aGraph, theCoEdge, aEntry);
|
||||
}
|
||||
if ((aEntry.Computed() & CoEdgeSameRangeEntry::ComputedSameParam) == 0
|
||||
&& (theRequiredFlags & CoEdgeSameRangeEntry::ComputedSameParam))
|
||||
{
|
||||
computeSameParameter(aGraph, theCoEdge, aEntry);
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock aLock(myMutex);
|
||||
ensureSize(myCoEdgeSameRangeEntries, theCoEdge.Index);
|
||||
CoEdgeSameRangeEntry& aStored =
|
||||
myCoEdgeSameRangeEntries.ChangeValue(static_cast<size_t>(theCoEdge.Index));
|
||||
if (aStored.IsFreshOwn(*this, theCoEdge))
|
||||
{
|
||||
const uint8_t aMyPacked = aEntry.Packed.load(std::memory_order_relaxed);
|
||||
const uint8_t aMyComputed =
|
||||
aMyPacked
|
||||
& (CoEdgeSameRangeEntry::ComputedSameRange | CoEdgeSameRangeEntry::ComputedSameParam);
|
||||
const uint8_t aStoredPacked = aStored.Packed.load(std::memory_order_relaxed);
|
||||
const uint8_t aNewBits = aMyComputed & ~aStoredPacked;
|
||||
if (aNewBits != 0)
|
||||
{
|
||||
// Merge value bits (shifted by 2 from computed) and computed bits into a single store.
|
||||
const uint8_t aMerged = (aStoredPacked & ~((aNewBits << 2) | aNewBits))
|
||||
| (aMyPacked & (aNewBits << 2)) | aNewBits;
|
||||
aStored.Packed.store(aMerged, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aStored = aEntry;
|
||||
}
|
||||
if (!aStored.BindOwnGen(*this, theCoEdge))
|
||||
{
|
||||
aStored.Reset();
|
||||
return false;
|
||||
}
|
||||
theEntry = aStored;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheDerivedState::IsDegenerated(BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
EdgeEntry aEntry;
|
||||
if (!ensureEdgeEntry(theEdge, aEntry))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return aEntry.GetStatus() == EdgeEntry::GeomStatus::DegenerateOnSurface;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheDerivedState::SameParameter(BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
CoEdgeSameRangeEntry aEntry;
|
||||
if (!ensureCoEdgeSameRangeEntry(theCoEdge, CoEdgeSameRangeEntry::ComputedSameParam, aEntry))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return aEntry.SameParameter();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheDerivedState::SameRange(BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
CoEdgeSameRangeEntry aEntry;
|
||||
if (!ensureCoEdgeSameRangeEntry(theCoEdge, CoEdgeSameRangeEntry::ComputedSameRange, aEntry))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return aEntry.SameRange();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheDerivedState::IsClosed(BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
EdgeEntry aEntry;
|
||||
if (!ensureEdgeEntry(theEdge, aEntry))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return aEntry.IsClosed();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheDerivedState::ComputeEdgeProperties(const BRepGraph& theGraph,
|
||||
BRepGraph_EdgeId theEdge,
|
||||
bool& theIsDegenerated,
|
||||
bool& theIsClosed)
|
||||
{
|
||||
if (!theEdge.IsValid(theGraph.Topo().Edges().Nb()) || theEdge.IsRemoved(theGraph))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const BRepGraphInc::EdgeDef& aDef = theGraph.Topo().Edges().Definition(theEdge);
|
||||
EdgeEntry aStatusEntry;
|
||||
computeStatusOnly(theGraph, theEdge, aStatusEntry);
|
||||
|
||||
const BRepGraph_VertexId aStartV = resolveChildVertex(theGraph, aDef.StartVertexRefId);
|
||||
const BRepGraph_VertexId aEndV = resolveChildVertex(theGraph, aDef.EndVertexRefId);
|
||||
theEntry.IsClosed = aStartV.IsValid() && aStartV == aEndV;
|
||||
|
||||
const occ::handle<Geom_Curve>& aCurve3D = edgeCurve3D(theGraph, theEdge);
|
||||
const bool hasCurve3D = !aCurve3D.IsNull();
|
||||
theEntry.Status =
|
||||
hasCurve3D ? EdgeGeometryStatus::HasCurve3D : EdgeGeometryStatus::MissingCurve3D;
|
||||
|
||||
if (hasCurve3D)
|
||||
{
|
||||
const std::pair<double, double> anEdgeRange = BRepGraph_Tool::Edge::Range(theGraph, theEdge);
|
||||
theEntry.SameRange = isEdgeSameRange(theGraph, theEdge, anEdgeRange);
|
||||
theEntry.SameParameter =
|
||||
theEntry.SameRange && isEdgeSameParameter(theGraph, theEdge, aDef, aCurve3D, anEdgeRange);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (theEntry.IsClosed)
|
||||
{
|
||||
theEntry.Status = EdgeGeometryStatus::DegenerateOnSurface;
|
||||
theEntry.SameRange = true;
|
||||
theEntry.SameParameter = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aStartV.IsValid() && aEndV.IsValid())
|
||||
{
|
||||
const BRepGraphInc::VertexDef& aStartDef = theGraph.Topo().Vertices().Definition(aStartV);
|
||||
const BRepGraphInc::VertexDef& aEndDef = theGraph.Topo().Vertices().Definition(aEndV);
|
||||
|
||||
const double aDist = aStartDef.Point.Distance(aEndDef.Point);
|
||||
if (aDist <= aDef.Tolerance)
|
||||
{
|
||||
theEntry.Status = EdgeGeometryStatus::DegenerateOnSurface;
|
||||
theEntry.SameRange = true;
|
||||
theEntry.SameParameter = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
theIsDegenerated = aStatusEntry.GetStatus() == EdgeEntry::GeomStatus::DegenerateOnSurface;
|
||||
theIsClosed = aStatusEntry.IsClosed();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -433,22 +728,18 @@ bool BRepGraph_CacheDerivedState::ComputeWireIsClosed(const BRepGraph& theGraph,
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheDerivedState::ComputeShellStatus(const BRepGraph& theGraph,
|
||||
BRepGraph_ShellId theShell,
|
||||
ShellEntry& theEntry)
|
||||
BRepGraph_CacheDerivedState::ShellEntry::ClosureStatus BRepGraph_CacheDerivedState::
|
||||
computeShellClosure(const BRepGraph& theGraph, BRepGraph_ShellId theShell)
|
||||
{
|
||||
theEntry.Status = ShellClosureStatus::Invalid;
|
||||
|
||||
if (!theShell.IsValid(theGraph.Topo().Shells().Nb()) || theShell.IsRemoved(theGraph))
|
||||
{
|
||||
return false;
|
||||
return ShellEntry::ClosureStatus::Invalid;
|
||||
}
|
||||
|
||||
const BRepGraphInc::ShellRelations& aSR = theGraph.Topo().Shells().Relations(theShell);
|
||||
if (aSR.FaceRefIds.IsEmpty())
|
||||
{
|
||||
theEntry.Status = ShellClosureStatus::Empty;
|
||||
return true;
|
||||
return ShellEntry::ClosureStatus::Empty;
|
||||
}
|
||||
|
||||
NCollection_FlatMap<BRepGraph_FaceId> anActiveFaces;
|
||||
@@ -470,8 +761,7 @@ bool BRepGraph_CacheDerivedState::ComputeShellStatus(const BRepGraph& theGraph,
|
||||
|
||||
if (anActiveFaces.IsEmpty())
|
||||
{
|
||||
theEntry.Status = ShellClosureStatus::Empty;
|
||||
return true;
|
||||
return ShellEntry::ClosureStatus::Empty;
|
||||
}
|
||||
|
||||
NCollection_DataMap<BRepGraph_EdgeId, uint32_t> anEdgeUsage;
|
||||
@@ -515,9 +805,9 @@ bool BRepGraph_CacheDerivedState::ComputeShellStatus(const BRepGraph& theGraph,
|
||||
continue;
|
||||
}
|
||||
|
||||
EdgeEntry anEdgeEntry;
|
||||
if (!ComputeEdgeStatus(theGraph, anEdgeId, anEdgeEntry)
|
||||
|| anEdgeEntry.Status == EdgeGeometryStatus::DegenerateOnSurface)
|
||||
EdgeEntry aEdgeEntry;
|
||||
computeStatusOnly(theGraph, anEdgeId, aEdgeEntry);
|
||||
if (aEdgeEntry.GetStatus() == EdgeEntry::GeomStatus::DegenerateOnSurface)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -537,8 +827,7 @@ bool BRepGraph_CacheDerivedState::ComputeShellStatus(const BRepGraph& theGraph,
|
||||
|
||||
if (anEdgeUsage.IsEmpty())
|
||||
{
|
||||
theEntry.Status = ShellClosureStatus::Closed;
|
||||
return true;
|
||||
return ShellEntry::ClosureStatus::Closed;
|
||||
}
|
||||
|
||||
bool hasOpen = false;
|
||||
@@ -560,151 +849,98 @@ bool BRepGraph_CacheDerivedState::ComputeShellStatus(const BRepGraph& theGraph,
|
||||
|
||||
if (hasNonManifold)
|
||||
{
|
||||
theEntry.Status = ShellClosureStatus::NonManifold;
|
||||
return ShellEntry::ClosureStatus::NonManifold;
|
||||
}
|
||||
else if (hasOpen)
|
||||
if (hasOpen)
|
||||
{
|
||||
theEntry.Status = ShellClosureStatus::Open;
|
||||
return ShellEntry::ClosureStatus::Open;
|
||||
}
|
||||
else
|
||||
{
|
||||
theEntry.Status = ShellClosureStatus::Closed;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheDerivedState::GetEdgeStatus(BRepGraph_EdgeId theEdge, EdgeEntry& theEntry)
|
||||
{
|
||||
EdgeEntry aComputed;
|
||||
if (!ComputeEdgeStatus(Graph(), theEdge, aComputed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_lock aLock(myMutex);
|
||||
EdgeEntry* aStored = myEdgeEntries.ChangeSeek(theEdge);
|
||||
if (aStored != nullptr)
|
||||
{
|
||||
*aStored = aComputed;
|
||||
}
|
||||
else
|
||||
{
|
||||
myEdgeEntries.Bind(theEdge, aComputed);
|
||||
aStored = myEdgeEntries.ChangeSeek(theEdge);
|
||||
}
|
||||
if (!aStored->BindOwnGen(*this, theEdge))
|
||||
{
|
||||
myEdgeEntries.UnBind(theEdge);
|
||||
return false;
|
||||
}
|
||||
theEntry = *aStored;
|
||||
return true;
|
||||
return ShellEntry::ClosureStatus::Closed;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheDerivedState::GetWireIsClosed(BRepGraph_WireId theWire, bool& theClosed)
|
||||
{
|
||||
// Lock-free read path: check packed flags without mutex.
|
||||
if (static_cast<size_t>(theWire.Index) < myWireEntries.Size())
|
||||
{
|
||||
const WireEntry& aCached = myWireEntries.Value(static_cast<size_t>(theWire.Index));
|
||||
if (aCached.IsComputed() && aCached.IsFreshOwn(*this, theWire))
|
||||
{
|
||||
theClosed = aCached.IsClosed();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const bool aClosed = ComputeWireIsClosed(Graph(), theWire);
|
||||
|
||||
std::unique_lock aLock(myMutex);
|
||||
WireEntry* aStored = myWireEntries.ChangeSeek(theWire);
|
||||
if (aStored == nullptr)
|
||||
std::lock_guard aLock(myMutex);
|
||||
ensureSize(myWireEntries, theWire.Index);
|
||||
WireEntry& aStored = myWireEntries.ChangeValue(static_cast<size_t>(theWire.Index));
|
||||
if (!aStored.BindOwnGen(*this, theWire))
|
||||
{
|
||||
myWireEntries.Bind(theWire, WireEntry());
|
||||
aStored = myWireEntries.ChangeSeek(theWire);
|
||||
}
|
||||
aStored->IsClosed = aClosed;
|
||||
if (!aStored->BindOwnGen(*this, theWire))
|
||||
{
|
||||
myWireEntries.UnBind(theWire);
|
||||
aStored.Reset();
|
||||
return false;
|
||||
}
|
||||
aStored.SetClosed(aClosed);
|
||||
theClosed = aClosed;
|
||||
return true;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheDerivedState::GetShellStatus(BRepGraph_ShellId theShell, ShellEntry& theEntry)
|
||||
bool BRepGraph_CacheDerivedState::IsShellClosed(BRepGraph_ShellId theShell)
|
||||
{
|
||||
ShellEntry aComputed;
|
||||
if (!ComputeShellStatus(Graph(), theShell, aComputed))
|
||||
// Lock-free read path: check atomic Status without mutex.
|
||||
if (static_cast<size_t>(theShell.Index) < myShellEntries.Size())
|
||||
{
|
||||
return false;
|
||||
const ShellEntry& aCached = myShellEntries.Value(static_cast<size_t>(theShell.Index));
|
||||
const auto aStatus = aCached.Status.load(std::memory_order_acquire);
|
||||
if (aStatus != ShellEntry::ClosureStatus::Invalid && aCached.IsFreshOwn(*this, theShell))
|
||||
{
|
||||
return aStatus == ShellEntry::ClosureStatus::Closed;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_lock aLock(myMutex);
|
||||
ShellEntry* aStored = myShellEntries.ChangeSeek(theShell);
|
||||
if (aStored != nullptr)
|
||||
const ShellEntry::ClosureStatus aStatus = computeShellClosure(Graph(), theShell);
|
||||
|
||||
std::lock_guard aLock(myMutex);
|
||||
ensureSize(myShellEntries, theShell.Index);
|
||||
ShellEntry& aStored = myShellEntries.ChangeValue(static_cast<size_t>(theShell.Index));
|
||||
if (aStored.Status.load(std::memory_order_acquire) != ShellEntry::ClosureStatus::Invalid
|
||||
&& aStored.IsFreshOwn(*this, theShell))
|
||||
{
|
||||
*aStored = aComputed;
|
||||
return aStored.Status.load(std::memory_order_acquire) == ShellEntry::ClosureStatus::Closed;
|
||||
}
|
||||
else
|
||||
if (!aStored.BindOwnGen(*this, theShell))
|
||||
{
|
||||
myShellEntries.Bind(theShell, aComputed);
|
||||
aStored = myShellEntries.ChangeSeek(theShell);
|
||||
}
|
||||
if (!aStored->BindOwnGen(*this, theShell))
|
||||
{
|
||||
myShellEntries.UnBind(theShell);
|
||||
aStored.Reset();
|
||||
return false;
|
||||
}
|
||||
theEntry = *aStored;
|
||||
return true;
|
||||
aStored.Status.store(aStatus, std::memory_order_release);
|
||||
return aStatus == ShellEntry::ClosureStatus::Closed;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraph_CacheDerivedState::SetEdgeStatus(BRepGraph_EdgeId theEdge, const EdgeEntry& theEntry)
|
||||
bool BRepGraph_CacheDerivedState::ComputeShellIsClosed(const BRepGraph& theGraph,
|
||||
BRepGraph_ShellId theShell)
|
||||
{
|
||||
std::unique_lock aLock(myMutex);
|
||||
EdgeEntry* aStored = myEdgeEntries.ChangeSeek(theEdge);
|
||||
if (aStored != nullptr)
|
||||
{
|
||||
*aStored = theEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
myEdgeEntries.Bind(theEdge, theEntry);
|
||||
aStored = myEdgeEntries.ChangeSeek(theEdge);
|
||||
}
|
||||
[[maybe_unused]] const bool isBound = aStored->BindOwnGen(*this, theEdge);
|
||||
return computeShellClosure(theGraph, theShell) == ShellEntry::ClosureStatus::Closed;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraph_CacheDerivedState::SetWireIsClosed(BRepGraph_WireId theWire, bool theClosed)
|
||||
{
|
||||
std::unique_lock aLock(myMutex);
|
||||
WireEntry* aStored = myWireEntries.ChangeSeek(theWire);
|
||||
if (aStored == nullptr)
|
||||
std::lock_guard aLock(myMutex);
|
||||
ensureSize(myWireEntries, theWire.Index);
|
||||
WireEntry& aStored = myWireEntries.ChangeValue(static_cast<size_t>(theWire.Index));
|
||||
if (!aStored.BindOwnGen(*this, theWire))
|
||||
{
|
||||
myWireEntries.Bind(theWire, WireEntry());
|
||||
aStored = myWireEntries.ChangeSeek(theWire);
|
||||
aStored.Reset();
|
||||
return;
|
||||
}
|
||||
aStored->IsClosed = theClosed;
|
||||
[[maybe_unused]] const bool isBound = aStored->BindOwnGen(*this, theWire);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraph_CacheDerivedState::SetShellStatus(BRepGraph_ShellId theShell,
|
||||
const ShellEntry& theEntry)
|
||||
{
|
||||
std::unique_lock aLock(myMutex);
|
||||
ShellEntry* aStored = myShellEntries.ChangeSeek(theShell);
|
||||
if (aStored != nullptr)
|
||||
{
|
||||
*aStored = theEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
myShellEntries.Bind(theShell, theEntry);
|
||||
aStored = myShellEntries.ChangeSeek(theShell);
|
||||
}
|
||||
[[maybe_unused]] const bool isBound = aStored->BindOwnGen(*this, theShell);
|
||||
aStored.SetClosed(theClosed);
|
||||
}
|
||||
|
||||
@@ -16,73 +16,23 @@
|
||||
|
||||
#include <BRepGraph_Cache.hxx>
|
||||
#include <BRepGraph_NodeId.hxx>
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <NCollection_DynamicArray.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
#include <Standard_GUID.hxx>
|
||||
|
||||
#include <shared_mutex>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
class BRepGraphInc_Storage;
|
||||
|
||||
//! @brief Cache for derived edge, wire, and shell properties.
|
||||
//!
|
||||
//! Stores degeneracy, closure, SameRange, and SameParameter results derived from
|
||||
//! current BRepGraph topology and geometry. Cache getters compute on read,
|
||||
//! refresh the stored entries, and expose only fresh values to callers.
|
||||
//! 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:
|
||||
//! @brief Geometry status of an edge.
|
||||
//!
|
||||
enum class EdgeGeometryStatus
|
||||
{
|
||||
HasCurve3D, //!< Edge has a valid 3D curve
|
||||
DegenerateOnSurface, //!< Edge collapses to a point on a face surface
|
||||
MissingCurve3D, //!< Edge has no 3D curve and no valid degenerate evidence
|
||||
Invalid //!< Edge id is invalid or removed
|
||||
};
|
||||
|
||||
//! @brief Shell closure status.
|
||||
//!
|
||||
enum class ShellClosureStatus
|
||||
{
|
||||
Empty, //!< Shell has no active faces
|
||||
Open, //!< At least one non-degenerate boundary edge has exactly one use
|
||||
Closed, //!< All non-degenerate boundary edges have exactly two uses
|
||||
NonManifold, //!< At least one non-degenerate boundary edge has more than two uses
|
||||
Invalid //!< Shell id is invalid or removed
|
||||
};
|
||||
|
||||
//! @brief Cached derived-state entry for an edge.
|
||||
//!
|
||||
//! Inherits generation-based freshness tracking from NodeEntry and adds
|
||||
//! edge-specific derived properties.
|
||||
struct EdgeEntry : public NodeEntry
|
||||
{
|
||||
EdgeGeometryStatus Status = EdgeGeometryStatus::Invalid; //!< Edge geometry status
|
||||
bool IsClosed = false; //!< True if start vertex == end vertex
|
||||
bool SameRange = false; //!< True if all PCurve ranges equal 3D curve range
|
||||
bool SameParameter = false; //!< True if PCurves evaluate to the 3D curve on surfaces
|
||||
};
|
||||
|
||||
//! @brief Cached derived-state entry for a wire.
|
||||
//!
|
||||
//! Inherits generation-based freshness tracking from NodeEntry and adds
|
||||
//! wire-specific derived properties.
|
||||
struct WireEntry : public NodeEntry
|
||||
{
|
||||
bool IsClosed = false; //!< True if the wire forms a topological loop
|
||||
};
|
||||
|
||||
//! @brief Cached derived-state entry for a shell.
|
||||
//!
|
||||
//! Inherits generation-based freshness tracking from NodeEntry and adds
|
||||
//! shell-specific derived properties.
|
||||
struct ShellEntry : public NodeEntry
|
||||
{
|
||||
ShellClosureStatus Status = ShellClosureStatus::Invalid; //!< Shell closure status
|
||||
};
|
||||
|
||||
//! Returns the unique cache service GUID.
|
||||
[[nodiscard]] Standard_EXPORT static const Standard_GUID& GetID();
|
||||
|
||||
@@ -98,11 +48,27 @@ public:
|
||||
//! Copy fresh, remappable derived-state entries into the target graph.
|
||||
Standard_EXPORT void CopyFreshTo(const BRepGraph_CopyRemap& theCopy) const override;
|
||||
|
||||
//! @brief Return edge status, computing and storing a fresh entry.
|
||||
//! @param[in] theEdge edge definition identifier
|
||||
//! @param[out] theEntry filled with a fresh derived entry
|
||||
//! @return true if computation succeeded
|
||||
[[nodiscard]] Standard_EXPORT bool GetEdgeStatus(BRepGraph_EdgeId theEdge, EdgeEntry& theEntry);
|
||||
//! @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
|
||||
@@ -110,37 +76,34 @@ public:
|
||||
//! @return true if computation succeeded
|
||||
[[nodiscard]] Standard_EXPORT bool GetWireIsClosed(BRepGraph_WireId theWire, bool& theClosed);
|
||||
|
||||
//! @brief Return shell status, computing and storing a fresh entry.
|
||||
//! @param[in] theShell shell definition identifier
|
||||
//! @param[out] theEntry filled with a fresh derived entry
|
||||
//! @return true if computation succeeded
|
||||
[[nodiscard]] Standard_EXPORT bool GetShellStatus(BRepGraph_ShellId theShell,
|
||||
ShellEntry& theEntry);
|
||||
|
||||
//! @brief Store a pre-computed edge entry (warm-start from import or after computation).
|
||||
//! @param[in] theEdge edge definition identifier
|
||||
//! @param[in] theEntry pre-computed entry to store
|
||||
Standard_EXPORT void SetEdgeStatus(BRepGraph_EdgeId theEdge, const EdgeEntry& theEntry);
|
||||
|
||||
//! @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 Store a pre-computed shell entry (warm-start from import or after computation).
|
||||
//! @brief Test if a shell is closed.
|
||||
//! @param[in] theShell shell definition identifier
|
||||
//! @param[in] theEntry pre-computed entry to store
|
||||
Standard_EXPORT void SetShellStatus(BRepGraph_ShellId theShell, const ShellEntry& theEntry);
|
||||
//! @return true if the shell is closed
|
||||
[[nodiscard]] Standard_EXPORT bool IsShellClosed(BRepGraph_ShellId theShell);
|
||||
|
||||
//! Compute edge derived state directly from a BRepGraph without caching.
|
||||
//! Used by callers like Reconstruct that need one-shot computation.
|
||||
//! 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] theEntry filled with computed entry
|
||||
//! @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 ComputeEdgeStatus(const BRepGraph& theGraph,
|
||||
BRepGraph_EdgeId theEdge,
|
||||
EdgeEntry& theEntry);
|
||||
[[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
|
||||
@@ -149,23 +112,242 @@ public:
|
||||
[[nodiscard]] Standard_EXPORT static bool ComputeWireIsClosed(const BRepGraph& theGraph,
|
||||
BRepGraph_WireId theWire);
|
||||
|
||||
//! Compute shell closure status directly from a BRepGraph without caching.
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theShell shell definition identifier
|
||||
//! @param[out] theEntry filled with computed entry
|
||||
//! @return true if computation succeeded
|
||||
[[nodiscard]] Standard_EXPORT static bool ComputeShellStatus(const BRepGraph& theGraph,
|
||||
BRepGraph_ShellId theShell,
|
||||
ShellEntry& theEntry);
|
||||
|
||||
DEFINE_STANDARD_RTTIEXT(BRepGraph_CacheDerivedState, BRepGraph_Cache)
|
||||
|
||||
private:
|
||||
mutable std::shared_mutex myMutex;
|
||||
//! 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
|
||||
};
|
||||
|
||||
NCollection_DataMap<BRepGraph_EdgeId, EdgeEntry> myEdgeEntries;
|
||||
NCollection_DataMap<BRepGraph_WireId, WireEntry> myWireEntries;
|
||||
NCollection_DataMap<BRepGraph_ShellId, ShellEntry> myShellEntries;
|
||||
enum Flags : uint8_t
|
||||
{
|
||||
FlagNone = 0,
|
||||
StatusMask = 0x07,
|
||||
FlagClosed = 1 << 3,
|
||||
FlagComputed = 1 << 4,
|
||||
};
|
||||
|
||||
std::atomic<uint8_t> 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<GeomStatus>(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<uint8_t>(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<uint8_t> 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<uint8_t> 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<ClosureStatus> 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<EdgeEntry> myEdgeEntries;
|
||||
NCollection_DynamicArray<CoEdgeSameRangeEntry> myCoEdgeSameRangeEntries;
|
||||
NCollection_DynamicArray<WireEntry> myWireEntries;
|
||||
NCollection_DynamicArray<ShellEntry> myShellEntries;
|
||||
};
|
||||
|
||||
#endif // _BRepGraph_CacheDerivedState_HeaderFile
|
||||
|
||||
@@ -51,12 +51,12 @@ IdT remappedNode(const BRepGraph_CopyRemap& theCopy, const IdT theId)
|
||||
{
|
||||
return IdT();
|
||||
}
|
||||
const BRepGraph_ItemId* aTarget = theCopy.TargetItem(BRepGraph_ItemId(theId));
|
||||
if (aTarget == nullptr || !aTarget->IsNode())
|
||||
const BRepGraph_ItemId aTarget = theCopy.TargetItem(BRepGraph_ItemId(theId));
|
||||
if (!aTarget.IsNode())
|
||||
{
|
||||
return IdT();
|
||||
}
|
||||
return IdT::FromNodeId(aTarget->NodeId());
|
||||
return IdT::FromNodeId(aTarget.NodeId());
|
||||
}
|
||||
|
||||
void appendPolygonsOnTri(
|
||||
|
||||
@@ -126,6 +126,36 @@ occ::handle<BRepGraph_Cache> BRepGraph_CacheRegistry::FindCache(const Standard_G
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
occ::handle<BRepGraph_Cache> BRepGraph_CacheRegistry::ensureCache(
|
||||
const Standard_GUID& theGUID,
|
||||
const std::function<occ::handle<BRepGraph_Cache>()>& theFactory)
|
||||
{
|
||||
// Fast path: shared lock for read-only lookup.
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
occ::handle<BRepGraph_Cache> aCache = findCacheLocked(theGUID);
|
||||
if (!aCache.IsNull())
|
||||
{
|
||||
return aCache;
|
||||
}
|
||||
}
|
||||
|
||||
// Slow path: exclusive lock for creation.
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myMutex);
|
||||
// Re-check after acquiring exclusive lock (another thread may have created it).
|
||||
occ::handle<BRepGraph_Cache> aCache = findCacheLocked(theGUID);
|
||||
if (aCache.IsNull())
|
||||
{
|
||||
aCache = theFactory();
|
||||
registerCacheLocked(aCache);
|
||||
}
|
||||
return aCache;
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CacheRegistry::FindSlot(const Standard_GUID& theGUID, uint32_t& theSlot) const
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
@@ -228,6 +258,34 @@ void BRepGraph_CacheRegistry::CopyFreshCachesTo(
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraph_CacheRegistry::CopyFreshCachesTo(BRepGraph& theTargetGraph,
|
||||
BRepGraph_CopyRemap::MappingKind theMappingKind,
|
||||
BRepGraph_CopyRemap::Mode theMode) const
|
||||
{
|
||||
BRepGraph* aSourceGraph = nullptr;
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
aSourceGraph = myGraph;
|
||||
}
|
||||
if (aSourceGraph == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const BRepGraph_CopyRemap aCopy(*aSourceGraph, theTargetGraph, theMappingKind, theMode);
|
||||
for (uint32_t aSlot = 0;; ++aSlot)
|
||||
{
|
||||
occ::handle<BRepGraph_Cache> aCache = cacheAt(aSlot);
|
||||
if (aCache.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
aCache->CopyFreshTo(aCopy);
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
occ::handle<BRepGraph_Cache> BRepGraph_CacheRegistry::findCacheLocked(
|
||||
const Standard_GUID& theGUID) const
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
#include <Standard_GUID.hxx>
|
||||
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
|
||||
@@ -83,17 +84,12 @@ public:
|
||||
}
|
||||
|
||||
//! Return an existing cache service or create and register a default one.
|
||||
//! Template convenience wrapper: extracts GUID and calls ensureCache.
|
||||
template <typename T>
|
||||
[[nodiscard]] occ::handle<T> Ensure()
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myMutex);
|
||||
occ::handle<T> aCache = occ::down_cast<T>(findCacheLocked(T::GetID()));
|
||||
if (aCache.IsNull())
|
||||
{
|
||||
aCache = new T();
|
||||
registerCacheLocked(aCache);
|
||||
}
|
||||
return aCache;
|
||||
return occ::down_cast<T>(
|
||||
ensureCache(T::GetID(), []() -> occ::handle<BRepGraph_Cache> { return new T(); }));
|
||||
}
|
||||
|
||||
//! Return current graph-local slot for a GUID.
|
||||
@@ -133,6 +129,11 @@ public:
|
||||
const NCollection_FlatDataMap<BRepGraph_ItemId, BRepGraph_ItemId>& 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;
|
||||
|
||||
@@ -149,6 +150,13 @@ private:
|
||||
[[nodiscard]] Standard_EXPORT occ::handle<BRepGraph_Cache> 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<BRepGraph_Cache> ensureCache(
|
||||
const Standard_GUID& theGUID,
|
||||
const std::function<occ::handle<BRepGraph_Cache>()>& theFactory);
|
||||
|
||||
[[nodiscard]] Standard_EXPORT occ::handle<BRepGraph_Cache> cacheAt(uint32_t theSlot) const;
|
||||
|
||||
Standard_EXPORT uint32_t registerCacheLocked(const occ::handle<BRepGraph_Cache>& theCache);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <BRepGraph_RefsView.hxx>
|
||||
#include <BRepGraph_Tool.hxx>
|
||||
#include <BRepGraph_TopoView.hxx>
|
||||
#include <BRepGraphInc_Load.hxx>
|
||||
#include <Geom2d_Curve.hxx>
|
||||
#include <Geom_Curve.hxx>
|
||||
#include <Geom_Surface.hxx>
|
||||
@@ -299,146 +300,6 @@ size_t itemCapacityUpperBound(const BRepGraphInc_Storage& theStorage)
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
template <typename IdT>
|
||||
void bindIdentityRange(const uint32_t theSourceCount,
|
||||
const uint32_t theTargetCount,
|
||||
NCollection_FlatDataMap<BRepGraph_ItemId, BRepGraph_ItemId>& theItemRemap)
|
||||
{
|
||||
const uint32_t aCount = std::min(theSourceCount, theTargetCount);
|
||||
for (uint32_t anIndex = 0; anIndex < aCount; ++anIndex)
|
||||
{
|
||||
const IdT anId(anIndex);
|
||||
if (anId.IsValid())
|
||||
{
|
||||
bindItemRemap(theItemRemap, anId, anId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void bindIdentityItems(const BRepGraphInc_Storage& theSource,
|
||||
const BRepGraphInc_Storage& theTarget,
|
||||
NCollection_FlatDataMap<BRepGraph_ItemId, BRepGraph_ItemId>& theItemRemap)
|
||||
{
|
||||
theItemRemap.Reserve(itemCapacityUpperBound(theSource));
|
||||
bindIdentityRange<BRepGraph_VertexId>(theSource.NbVertices(),
|
||||
theTarget.NbVertices(),
|
||||
theItemRemap);
|
||||
bindIdentityRange<BRepGraph_EdgeId>(theSource.NbEdges(), theTarget.NbEdges(), theItemRemap);
|
||||
bindIdentityRange<BRepGraph_CoEdgeId>(theSource.NbCoEdges(), theTarget.NbCoEdges(), theItemRemap);
|
||||
bindIdentityRange<BRepGraph_WireId>(theSource.NbWires(), theTarget.NbWires(), theItemRemap);
|
||||
bindIdentityRange<BRepGraph_FaceId>(theSource.NbFaces(), theTarget.NbFaces(), theItemRemap);
|
||||
bindIdentityRange<BRepGraph_ShellId>(theSource.NbShells(), theTarget.NbShells(), theItemRemap);
|
||||
bindIdentityRange<BRepGraph_SolidId>(theSource.NbSolids(), theTarget.NbSolids(), theItemRemap);
|
||||
bindIdentityRange<BRepGraph_CompoundId>(theSource.NbCompounds(),
|
||||
theTarget.NbCompounds(),
|
||||
theItemRemap);
|
||||
bindIdentityRange<BRepGraph_CompSolidId>(theSource.NbCompSolids(),
|
||||
theTarget.NbCompSolids(),
|
||||
theItemRemap);
|
||||
bindIdentityRange<BRepGraph_ProductId>(theSource.NbProducts(),
|
||||
theTarget.NbProducts(),
|
||||
theItemRemap);
|
||||
bindIdentityRange<BRepGraph_OccurrenceId>(theSource.NbOccurrences(),
|
||||
theTarget.NbOccurrences(),
|
||||
theItemRemap);
|
||||
bindIdentityRange<BRepGraph_ShellRefId>(theSource.NbShellRefs(),
|
||||
theTarget.NbShellRefs(),
|
||||
theItemRemap);
|
||||
bindIdentityRange<BRepGraph_FaceRefId>(theSource.NbFaceRefs(),
|
||||
theTarget.NbFaceRefs(),
|
||||
theItemRemap);
|
||||
bindIdentityRange<BRepGraph_WireRefId>(theSource.NbWireRefs(),
|
||||
theTarget.NbWireRefs(),
|
||||
theItemRemap);
|
||||
bindIdentityRange<BRepGraph_VertexRefId>(theSource.NbVertexRefs(),
|
||||
theTarget.NbVertexRefs(),
|
||||
theItemRemap);
|
||||
bindIdentityRange<BRepGraph_SolidRefId>(theSource.NbSolidRefs(),
|
||||
theTarget.NbSolidRefs(),
|
||||
theItemRemap);
|
||||
bindIdentityRange<BRepGraph_ChildRefId>(theSource.NbChildRefs(),
|
||||
theTarget.NbChildRefs(),
|
||||
theItemRemap);
|
||||
bindIdentityRange<BRepGraph_OccurrenceRefId>(theSource.NbOccurrenceRefs(),
|
||||
theTarget.NbOccurrenceRefs(),
|
||||
theItemRemap);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void copyCurve2DReps(const BRepGraphInc_Storage& theSource,
|
||||
BRepGraphInc_Storage& theTarget,
|
||||
GeomPolicy theGeomPolicy)
|
||||
{
|
||||
for (BRepGraph_CoEdgeCurve2DRepId aRepId(0); aRepId.IsValid(theSource.NbCoEdgeCurves2D());
|
||||
++aRepId)
|
||||
{
|
||||
const BRepGraph_CoEdgeCurve2DRepId aNewRepId = theTarget.AppendCoEdgeCurve2DRep();
|
||||
Standard_ASSERT_RAISE(aNewRepId == aRepId, "BRepGraph_Copy: unexpected curve2d rep id");
|
||||
BRepGraphInc::CoEdgeCurve2DRep& aNewUse = theTarget.ChangeCoEdgeCurve2DRep(aNewRepId);
|
||||
aNewUse = theSource.CoEdgeCurve2DRep(aRepId);
|
||||
aNewUse.Curve = copyPCurve(aNewUse.Curve, theGeomPolicy);
|
||||
theTarget.SetRemoved(aNewRepId, theSource.IsRemoved(aRepId));
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void copyPersistentMeshReps(const BRepGraphInc_Storage& theSource,
|
||||
BRepGraphInc_Storage& theTarget,
|
||||
MeshPolicy theMeshPolicy)
|
||||
{
|
||||
for (BRepGraph_FaceTriangulationRepId aRepId(0); aRepId.IsValid(theSource.NbFaceTriangulations());
|
||||
++aRepId)
|
||||
{
|
||||
const BRepGraph_FaceTriangulationRepId aNewRepId = theTarget.AppendFaceTriangulationRep();
|
||||
Standard_ASSERT_RAISE(aNewRepId == aRepId, "BRepGraph_Copy: unexpected triangulation rep id");
|
||||
BRepGraphInc::FaceTriangulationRep& aNewRep = theTarget.ChangeFaceTriangulationRep(aNewRepId);
|
||||
aNewRep = theSource.FaceTriangulationRep(aRepId);
|
||||
aNewRep.Triangulation = copyMeshHandle(aNewRep.Triangulation, theMeshPolicy);
|
||||
theTarget.SetRemoved(aNewRepId, theSource.IsRemoved(aRepId));
|
||||
}
|
||||
|
||||
for (BRepGraph_EdgePolygon3DRepId aRepId(0); aRepId.IsValid(theSource.NbEdgePolygons3D());
|
||||
++aRepId)
|
||||
{
|
||||
const BRepGraph_EdgePolygon3DRepId aNewRepId = theTarget.AppendEdgePolygon3DRep();
|
||||
Standard_ASSERT_RAISE(aNewRepId == aRepId, "BRepGraph_Copy: unexpected polygon3d rep id");
|
||||
BRepGraphInc::EdgePolygon3DRep& aNewRep = theTarget.ChangeEdgePolygon3DRep(aNewRepId);
|
||||
aNewRep = theSource.EdgePolygon3DRep(aRepId);
|
||||
aNewRep.Polygon = copyMeshHandle(aNewRep.Polygon, theMeshPolicy);
|
||||
theTarget.SetRemoved(aNewRepId, theSource.IsRemoved(aRepId));
|
||||
}
|
||||
|
||||
for (BRepGraph_CoEdgePolygon2DRepId aRepId(0); aRepId.IsValid(theSource.NbCoEdgePolygons2D());
|
||||
++aRepId)
|
||||
{
|
||||
const BRepGraph_CoEdgePolygon2DRepId aNewRepId = theTarget.AppendCoEdgePolygon2DRep();
|
||||
Standard_ASSERT_RAISE(aNewRepId == aRepId, "BRepGraph_Copy: unexpected polygon2d rep id");
|
||||
BRepGraphInc::CoEdgePolygon2DRep& aNewRep = theTarget.ChangeCoEdgePolygon2DRep(aNewRepId);
|
||||
aNewRep = theSource.CoEdgePolygon2DRep(aRepId);
|
||||
aNewRep.Polygon = copyMeshHandle(aNewRep.Polygon, theMeshPolicy);
|
||||
theTarget.SetRemoved(aNewRepId, theSource.IsRemoved(aRepId));
|
||||
}
|
||||
|
||||
for (BRepGraph_CoEdgePolygonOnTriRepId aRepId(0);
|
||||
aRepId.IsValid(theSource.NbCoEdgePolygonsOnTri());
|
||||
++aRepId)
|
||||
{
|
||||
const BRepGraph_CoEdgePolygonOnTriRepId aNewRepId = theTarget.AppendCoEdgePolygonOnTriRep();
|
||||
Standard_ASSERT_RAISE(aNewRepId == aRepId,
|
||||
"BRepGraph_Copy: unexpected polygon-on-triangulation rep id");
|
||||
BRepGraphInc::CoEdgePolygonOnTriRep& aNewRep = theTarget.ChangeCoEdgePolygonOnTriRep(aNewRepId);
|
||||
aNewRep = theSource.CoEdgePolygonOnTriRep(aRepId);
|
||||
aNewRep.Polygon = copyMeshHandle(aNewRep.Polygon, theMeshPolicy);
|
||||
theTarget.SetRemoved(aNewRepId, theSource.IsRemoved(aRepId));
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void ensureTriangulationRep(GraphCopyContext& theCtx,
|
||||
const BRepGraph_FaceTriangulationRepId theSrcRepId,
|
||||
const BRepGraph_FaceId theDstFaceId)
|
||||
@@ -1065,6 +926,356 @@ BRepGraph_ProductId ensureProduct(GraphCopyContext& theCtx, BRepGraph_ProductId
|
||||
return aNewId;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
//! Build counts for identity copy, adjusting representation counts for drop policies.
|
||||
static BRepGraphInc_Load::Counts countsForIdentityCopy(const BRepGraphInc_Storage& theSrc,
|
||||
GeomPolicy theGeomPol,
|
||||
MeshPolicy theMeshPol)
|
||||
{
|
||||
BRepGraphInc_Load::Counts aCounts = theSrc.Counts();
|
||||
if (theGeomPol == GeomPolicy::Drop)
|
||||
{
|
||||
aCounts.NbFaceSurfaceReps = 0;
|
||||
aCounts.NbEdgeCurve3DReps = 0;
|
||||
aCounts.NbCoEdgeCurve2DReps = 0;
|
||||
}
|
||||
if (theMeshPol == MeshPolicy::Drop)
|
||||
{
|
||||
aCounts.NbFaceTriangulationReps = 0;
|
||||
aCounts.NbEdgePolygon3DReps = 0;
|
||||
aCounts.NbCoEdgePolygon2DReps = 0;
|
||||
aCounts.NbCoEdgePolygonOnTriReps = 0;
|
||||
}
|
||||
return aCounts;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
//! Copy all topology definitions slot-for-slot from source to destination.
|
||||
static void copyTopologyDefinitionsIdentity(const BRepGraphInc_Storage& theSrc,
|
||||
BRepGraphInc_Storage& theDst,
|
||||
GeomPolicy theGeomPol,
|
||||
MeshPolicy theMeshPol)
|
||||
{
|
||||
// Copy definition structs.
|
||||
for (BRepGraph_VertexId anId(0); anId.IsValid(theSrc.NbVertices()); ++anId)
|
||||
{
|
||||
theDst.ChangeVertex(anId) = theSrc.Vertex(anId);
|
||||
}
|
||||
for (BRepGraph_EdgeId anId(0); anId.IsValid(theSrc.NbEdges()); ++anId)
|
||||
{
|
||||
theDst.ChangeEdge(anId) = theSrc.Edge(anId);
|
||||
}
|
||||
for (BRepGraph_CoEdgeId anId(0); anId.IsValid(theSrc.NbCoEdges()); ++anId)
|
||||
{
|
||||
theDst.ChangeCoEdge(anId) = theSrc.CoEdge(anId);
|
||||
}
|
||||
for (BRepGraph_WireId anId(0); anId.IsValid(theSrc.NbWires()); ++anId)
|
||||
{
|
||||
theDst.ChangeWire(anId) = theSrc.Wire(anId);
|
||||
}
|
||||
for (BRepGraph_FaceId anId(0); anId.IsValid(theSrc.NbFaces()); ++anId)
|
||||
{
|
||||
BRepGraphInc::FaceDef& aDstFace = theDst.ChangeFace(anId);
|
||||
aDstFace = theSrc.Face(anId);
|
||||
// Clear surface rep id if geometry is dropped.
|
||||
if (theGeomPol == GeomPolicy::Drop)
|
||||
{
|
||||
aDstFace.SurfaceRepId = BRepGraph_FaceSurfaceRepId();
|
||||
}
|
||||
if (theMeshPol == MeshPolicy::Drop)
|
||||
{
|
||||
aDstFace.TriangulationRepId = BRepGraph_FaceTriangulationRepId();
|
||||
}
|
||||
}
|
||||
for (BRepGraph_ShellId anId(0); anId.IsValid(theSrc.NbShells()); ++anId)
|
||||
{
|
||||
theDst.ChangeShell(anId) = theSrc.Shell(anId);
|
||||
}
|
||||
for (BRepGraph_SolidId anId(0); anId.IsValid(theSrc.NbSolids()); ++anId)
|
||||
{
|
||||
theDst.ChangeSolid(anId) = theSrc.Solid(anId);
|
||||
}
|
||||
for (BRepGraph_CompoundId anId(0); anId.IsValid(theSrc.NbCompounds()); ++anId)
|
||||
{
|
||||
theDst.ChangeCompound(anId) = theSrc.Compound(anId);
|
||||
}
|
||||
for (BRepGraph_CompSolidId anId(0); anId.IsValid(theSrc.NbCompSolids()); ++anId)
|
||||
{
|
||||
theDst.ChangeCompSolid(anId) = theSrc.CompSolid(anId);
|
||||
}
|
||||
for (BRepGraph_ProductId anId(0); anId.IsValid(theSrc.NbProducts()); ++anId)
|
||||
{
|
||||
theDst.ChangeProduct(anId) = theSrc.Product(anId);
|
||||
}
|
||||
for (BRepGraph_OccurrenceId anId(0); anId.IsValid(theSrc.NbOccurrences()); ++anId)
|
||||
{
|
||||
theDst.ChangeOccurrence(anId) = theSrc.Occurrence(anId);
|
||||
}
|
||||
|
||||
// Copy coedge rep ids with policy filtering.
|
||||
if (theGeomPol == GeomPolicy::Drop || theMeshPol == MeshPolicy::Drop)
|
||||
{
|
||||
for (BRepGraph_CoEdgeId anId(0); anId.IsValid(theSrc.NbCoEdges()); ++anId)
|
||||
{
|
||||
BRepGraphInc::CoEdgeDef& aCoEdge = theDst.ChangeCoEdge(anId);
|
||||
if (theGeomPol == GeomPolicy::Drop)
|
||||
{
|
||||
aCoEdge.Curve2DRepId = BRepGraph_CoEdgeCurve2DRepId();
|
||||
}
|
||||
if (theMeshPol == MeshPolicy::Drop)
|
||||
{
|
||||
aCoEdge.Polygon2DRepId = BRepGraph_CoEdgePolygon2DRepId();
|
||||
aCoEdge.PolygonOnTriRepId = BRepGraph_CoEdgePolygonOnTriRepId();
|
||||
}
|
||||
}
|
||||
for (BRepGraph_EdgeId anId(0); anId.IsValid(theSrc.NbEdges()); ++anId)
|
||||
{
|
||||
if (theGeomPol == GeomPolicy::Drop)
|
||||
{
|
||||
theDst.ChangeEdge(anId).Curve3DRepId = BRepGraph_EdgeCurve3DRepId();
|
||||
}
|
||||
if (theMeshPol == MeshPolicy::Drop)
|
||||
{
|
||||
theDst.ChangeEdge(anId).Polygon3DRepId = BRepGraph_EdgePolygon3DRepId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
//! Copy all reference stores slot-for-slot from source to destination.
|
||||
static void copyReferencesIdentity(const BRepGraphInc_Storage& theSrc, BRepGraphInc_Storage& theDst)
|
||||
{
|
||||
for (BRepGraph_ShellRefId anId(0); anId.IsValid(theSrc.NbShellRefs()); ++anId)
|
||||
{
|
||||
theDst.ChangeShellRef(anId) = theSrc.ShellRef(anId);
|
||||
}
|
||||
for (BRepGraph_FaceRefId anId(0); anId.IsValid(theSrc.NbFaceRefs()); ++anId)
|
||||
{
|
||||
theDst.ChangeFaceRef(anId) = theSrc.FaceRef(anId);
|
||||
}
|
||||
for (BRepGraph_WireRefId anId(0); anId.IsValid(theSrc.NbWireRefs()); ++anId)
|
||||
{
|
||||
theDst.ChangeWireRef(anId) = theSrc.WireRef(anId);
|
||||
}
|
||||
for (BRepGraph_VertexRefId anId(0); anId.IsValid(theSrc.NbVertexRefs()); ++anId)
|
||||
{
|
||||
theDst.ChangeVertexRef(anId) = theSrc.VertexRef(anId);
|
||||
}
|
||||
for (BRepGraph_SolidRefId anId(0); anId.IsValid(theSrc.NbSolidRefs()); ++anId)
|
||||
{
|
||||
theDst.ChangeSolidRef(anId) = theSrc.SolidRef(anId);
|
||||
}
|
||||
for (BRepGraph_ChildRefId anId(0); anId.IsValid(theSrc.NbChildRefs()); ++anId)
|
||||
{
|
||||
theDst.ChangeChildRef(anId) = theSrc.ChildRef(anId);
|
||||
}
|
||||
for (BRepGraph_OccurrenceRefId anId(0); anId.IsValid(theSrc.NbOccurrenceRefs()); ++anId)
|
||||
{
|
||||
theDst.ChangeOccurrenceRef(anId) = theSrc.OccurrenceRef(anId);
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
//! Copy persistent representation stores with geometry/mesh policy.
|
||||
static void copyRepresentationsIdentity(const BRepGraphInc_Storage& theSrc,
|
||||
BRepGraphInc_Storage& theDst,
|
||||
GeomPolicy theGeomPol,
|
||||
MeshPolicy theMeshPol)
|
||||
{
|
||||
if (theGeomPol != GeomPolicy::Drop)
|
||||
{
|
||||
// Face surfaces.
|
||||
for (BRepGraph_FaceSurfaceRepId anId(0); anId.IsValid(theSrc.NbFaceSurfaces()); ++anId)
|
||||
{
|
||||
BRepGraphInc::FaceSurfaceRep& aDst = theDst.ChangeFaceSurfaceRep(anId);
|
||||
aDst = theSrc.FaceSurfaceRep(anId);
|
||||
if (theGeomPol == GeomPolicy::Copy && !aDst.Surface.IsNull())
|
||||
{
|
||||
aDst.Surface = occ::down_cast<Geom_Surface>(aDst.Surface->Copy());
|
||||
}
|
||||
}
|
||||
|
||||
// Edge 3D curves.
|
||||
for (BRepGraph_EdgeCurve3DRepId anId(0); anId.IsValid(theSrc.NbEdgeCurves3D()); ++anId)
|
||||
{
|
||||
BRepGraphInc::EdgeCurve3DRep& aDst = theDst.ChangeEdgeCurve3DRep(anId);
|
||||
aDst = theSrc.EdgeCurve3DRep(anId);
|
||||
if (theGeomPol == GeomPolicy::Copy && !aDst.Curve.IsNull())
|
||||
{
|
||||
aDst.Curve = occ::down_cast<Geom_Curve>(aDst.Curve->Copy());
|
||||
}
|
||||
}
|
||||
|
||||
// Coedge 2D curves.
|
||||
for (BRepGraph_CoEdgeCurve2DRepId anId(0); anId.IsValid(theSrc.NbCoEdgeCurves2D()); ++anId)
|
||||
{
|
||||
BRepGraphInc::CoEdgeCurve2DRep& aDst = theDst.ChangeCoEdgeCurve2DRep(anId);
|
||||
aDst = theSrc.CoEdgeCurve2DRep(anId);
|
||||
if (theGeomPol == GeomPolicy::Copy && !aDst.Curve.IsNull())
|
||||
{
|
||||
aDst.Curve = occ::down_cast<Geom2d_Curve>(aDst.Curve->Copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (theMeshPol != MeshPolicy::Drop)
|
||||
{
|
||||
// Face triangulations.
|
||||
for (BRepGraph_FaceTriangulationRepId anId(0); anId.IsValid(theSrc.NbFaceTriangulations());
|
||||
++anId)
|
||||
{
|
||||
BRepGraphInc::FaceTriangulationRep& aDst = theDst.ChangeFaceTriangulationRep(anId);
|
||||
aDst = theSrc.FaceTriangulationRep(anId);
|
||||
if (theMeshPol == MeshPolicy::Copy && !aDst.Triangulation.IsNull())
|
||||
{
|
||||
aDst.Triangulation = aDst.Triangulation->Copy();
|
||||
}
|
||||
}
|
||||
|
||||
// Edge 3D polygons.
|
||||
for (BRepGraph_EdgePolygon3DRepId anId(0); anId.IsValid(theSrc.NbEdgePolygons3D()); ++anId)
|
||||
{
|
||||
BRepGraphInc::EdgePolygon3DRep& aDst = theDst.ChangeEdgePolygon3DRep(anId);
|
||||
aDst = theSrc.EdgePolygon3DRep(anId);
|
||||
if (theMeshPol == MeshPolicy::Copy && !aDst.Polygon.IsNull())
|
||||
{
|
||||
aDst.Polygon = aDst.Polygon->Copy();
|
||||
}
|
||||
}
|
||||
|
||||
// Coedge 2D polygons.
|
||||
for (BRepGraph_CoEdgePolygon2DRepId anId(0); anId.IsValid(theSrc.NbCoEdgePolygons2D()); ++anId)
|
||||
{
|
||||
BRepGraphInc::CoEdgePolygon2DRep& aDst = theDst.ChangeCoEdgePolygon2DRep(anId);
|
||||
aDst = theSrc.CoEdgePolygon2DRep(anId);
|
||||
if (theMeshPol == MeshPolicy::Copy && !aDst.Polygon.IsNull())
|
||||
{
|
||||
aDst.Polygon = aDst.Polygon->Copy();
|
||||
}
|
||||
}
|
||||
|
||||
// Coedge polygon-on-triangulation.
|
||||
for (BRepGraph_CoEdgePolygonOnTriRepId anId(0); anId.IsValid(theSrc.NbCoEdgePolygonsOnTri());
|
||||
++anId)
|
||||
{
|
||||
BRepGraphInc::CoEdgePolygonOnTriRep& aDst = theDst.ChangeCoEdgePolygonOnTriRep(anId);
|
||||
aDst = theSrc.CoEdgePolygonOnTriRep(anId);
|
||||
if (theMeshPol == MeshPolicy::Copy && !aDst.Polygon.IsNull())
|
||||
{
|
||||
aDst.Polygon = aDst.Polygon->Copy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
//! Copy root product ids from source to destination.
|
||||
static void copyRootProductsIdentity(const BRepGraphInc_Storage& theSrc,
|
||||
BRepGraphInc_Storage& theDst)
|
||||
{
|
||||
theDst.ChangeRootProductIds().Clear();
|
||||
for (const BRepGraph_ProductId& aRootId : theSrc.RootProductIds())
|
||||
{
|
||||
theDst.ChangeRootProductIds().Append(aRootId);
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
//! Copy UID counters, generation, and graph GUID from source to destination.
|
||||
static void copyUIDAndGraphStateIdentity(const BRepGraphInc_Storage& theSrc,
|
||||
BRepGraphInc_Storage& theDst)
|
||||
{
|
||||
constexpr BRepGraph_NodeId::Kind aNodeKinds[] = {BRepGraph_NodeId::Kind::Vertex,
|
||||
BRepGraph_NodeId::Kind::Edge,
|
||||
BRepGraph_NodeId::Kind::CoEdge,
|
||||
BRepGraph_NodeId::Kind::Wire,
|
||||
BRepGraph_NodeId::Kind::Face,
|
||||
BRepGraph_NodeId::Kind::Shell,
|
||||
BRepGraph_NodeId::Kind::Solid,
|
||||
BRepGraph_NodeId::Kind::Compound,
|
||||
BRepGraph_NodeId::Kind::CompSolid,
|
||||
BRepGraph_NodeId::Kind::Product,
|
||||
BRepGraph_NodeId::Kind::Occurrence};
|
||||
for (const auto aKind : aNodeKinds)
|
||||
{
|
||||
theDst.SetNextNodeUIDCounter(aKind, theSrc.NextNodeUIDCounter(aKind));
|
||||
}
|
||||
|
||||
constexpr BRepGraph_RefId::Kind aRefKinds[] = {BRepGraph_RefId::Kind::Shell,
|
||||
BRepGraph_RefId::Kind::Face,
|
||||
BRepGraph_RefId::Kind::Wire,
|
||||
BRepGraph_RefId::Kind::Vertex,
|
||||
BRepGraph_RefId::Kind::Solid,
|
||||
BRepGraph_RefId::Kind::Child,
|
||||
BRepGraph_RefId::Kind::Occurrence};
|
||||
for (const auto aKind : aRefKinds)
|
||||
{
|
||||
theDst.SetNextRefUIDCounter(aKind, theSrc.NextRefUIDCounter(aKind));
|
||||
}
|
||||
|
||||
theDst.SetGeneration(theSrc.Generation());
|
||||
theDst.SetGraphGUID(theSrc.GraphGUID());
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
//! Copy removed flags and active counts from source to destination.
|
||||
static void copyFlagsAndActiveCountsIdentity(const BRepGraphInc_Storage& theSrc,
|
||||
BRepGraphInc_Storage& theDst)
|
||||
{
|
||||
// Bulk-copy all removed flags in a single pass per kind (vs per-slot loops).
|
||||
theDst.CopyRemovedFlagsFrom(theSrc);
|
||||
|
||||
// Recount active counts now that removed flags are correct.
|
||||
theDst.RecountActiveCounts();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
//! Fast identity copy: source and target ids match.
|
||||
//! Used for Perform(source, emptyTarget, ...) to avoid editor API overhead.
|
||||
static bool copyFullGraphIdentity(const BRepGraphInc_Storage& aSrc,
|
||||
BRepGraphInc_Storage& aDst,
|
||||
const BRepGraph& theSourceGraph,
|
||||
BRepGraph& theTargetGraph,
|
||||
GeomPolicy theGeomPolicy,
|
||||
MeshPolicy theMeshPolicy,
|
||||
BRepGraph_Copy::CachePolicy theCachePolicy)
|
||||
{
|
||||
const BRepGraphInc_Load::Counts aCounts =
|
||||
countsForIdentityCopy(aSrc, theGeomPolicy, theMeshPolicy);
|
||||
aDst.PrepareForLoad(aCounts);
|
||||
|
||||
copyTopologyDefinitionsIdentity(aSrc, aDst, theGeomPolicy, theMeshPolicy);
|
||||
copyReferencesIdentity(aSrc, aDst);
|
||||
copyRepresentationsIdentity(aSrc, aDst, theGeomPolicy, theMeshPolicy);
|
||||
copyRootProductsIdentity(aSrc, aDst);
|
||||
copyUIDAndGraphStateIdentity(aSrc, aDst);
|
||||
copyFlagsAndActiveCountsIdentity(aSrc, aDst);
|
||||
|
||||
aDst.CopyDerivedRelationsFrom(aSrc);
|
||||
aDst.MarkUIDReverseIndexesDirty();
|
||||
aDst.CopyShapeBindingsFrom(aSrc);
|
||||
|
||||
theSourceGraph.LayerRegistry().CopyLayersTo(theTargetGraph,
|
||||
BRepGraph_CopyRemap::MappingKind::Identity,
|
||||
BRepGraph_CopyRemap::Mode::Copy);
|
||||
if (theCachePolicy == BRepGraph_Copy::CachePolicy::CopyFresh)
|
||||
{
|
||||
theSourceGraph.CacheRegistry().CopyFreshCachesTo(theTargetGraph,
|
||||
BRepGraph_CopyRemap::MappingKind::Identity,
|
||||
BRepGraph_CopyRemap::Mode::Copy);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//=================================================================================================
|
||||
@@ -1180,382 +1391,14 @@ bool BRepGraph_Copy::Perform(const BRepGraph& theSourceGraph,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Empty target: identity-mapped fast path (old index == new index).
|
||||
|
||||
const bool doCopyMesh = theMeshPolicy != MeshPolicy::Drop;
|
||||
const BRepGraph::RefsView& aRefs = theSourceGraph.Refs();
|
||||
|
||||
// Bottom-up graph rebuild via EditorView.
|
||||
// Since this is a full copy into an empty target, old index == new index (identity mapping).
|
||||
copyCurve2DReps(theSourceGraph.incStorage(), theTargetGraph.incStorage(), theGeomPolicy);
|
||||
if (doCopyMesh)
|
||||
{
|
||||
copyPersistentMeshReps(theSourceGraph.incStorage(), theTargetGraph.incStorage(), theMeshPolicy);
|
||||
}
|
||||
|
||||
// Vertices.
|
||||
for (BRepGraph_FullVertexIterator aVertexIt(theSourceGraph); aVertexIt.More(); aVertexIt.Next())
|
||||
{
|
||||
const BRepGraph_VertexId aVertexId = aVertexIt.CurrentId();
|
||||
const BRepGraphInc::VertexDef& aVtx = theSourceGraph.Topo().Vertices().Definition(aVertexId);
|
||||
const BRepGraph_VertexId aNewVertexId =
|
||||
theTargetGraph.Editor().Vertices().Add(aVtx.Point, aVtx.Tolerance);
|
||||
Standard_ASSERT_RAISE(aNewVertexId == aVertexId, "BRepGraph_Copy: unexpected vertex id");
|
||||
theTargetGraph.incStorage().SetRemoved(aNewVertexId,
|
||||
theSourceGraph.incStorage().IsRemoved(aVertexId));
|
||||
}
|
||||
|
||||
// Edges.
|
||||
for (BRepGraph_FullEdgeIterator anEdgeIt(theSourceGraph); anEdgeIt.More(); anEdgeIt.Next())
|
||||
{
|
||||
const BRepGraph_EdgeId anEdgeId = anEdgeIt.CurrentId();
|
||||
const BRepGraphInc::EdgeDef& anEdge = theSourceGraph.Topo().Edges().Definition(anEdgeId);
|
||||
|
||||
const occ::handle<Geom_Curve>& anEdgeSrcCurve =
|
||||
BRepGraph_Tool::Edge::Curve(theSourceGraph, anEdgeId);
|
||||
occ::handle<Geom_Curve> aCurve = copyCurve(anEdgeSrcCurve, theGeomPolicy);
|
||||
|
||||
const BRepGraph_VertexRefId aStartRefId =
|
||||
BRepGraph_Tool::Edge::StartVertexId(theSourceGraph, anEdgeId);
|
||||
const BRepGraph_VertexRefId anEndRefId =
|
||||
BRepGraph_Tool::Edge::EndVertexId(theSourceGraph, anEdgeId);
|
||||
const BRepGraph_VertexId aStartVtxId =
|
||||
aStartRefId.IsValid() ? theSourceGraph.Refs().Vertices().Entry(aStartRefId).ChildVertexId
|
||||
: BRepGraph_VertexId();
|
||||
const BRepGraph_VertexId anEndVtxId =
|
||||
anEndRefId.IsValid() ? theSourceGraph.Refs().Vertices().Entry(anEndRefId).ChildVertexId
|
||||
: BRepGraph_VertexId();
|
||||
|
||||
const auto [aEdgePF, aEdgePL] = BRepGraph_Tool::Edge::Range(theSourceGraph, anEdgeId);
|
||||
|
||||
const BRepGraph_EdgeId aNewEdgeId = theTargetGraph.Editor().Edges().Add(aStartVtxId,
|
||||
anEndVtxId,
|
||||
aCurve,
|
||||
aEdgePF,
|
||||
aEdgePL,
|
||||
anEdge.Tolerance);
|
||||
Standard_ASSERT_RAISE(aNewEdgeId == anEdgeId, "BRepGraph_Copy: unexpected edge id");
|
||||
theTargetGraph.incStorage().SetRemoved(aNewEdgeId,
|
||||
theSourceGraph.incStorage().IsRemoved(anEdgeId));
|
||||
const BRepGraphInc::EdgeDef& aNewEdge = theTargetGraph.incStorage().Edge(aNewEdgeId);
|
||||
setRemovedLike(theSourceGraph.incStorage(),
|
||||
theTargetGraph.incStorage(),
|
||||
anEdge.StartVertexRefId,
|
||||
aNewEdge.StartVertexRefId);
|
||||
setRemovedLike(theSourceGraph.incStorage(),
|
||||
theTargetGraph.incStorage(),
|
||||
anEdge.EndVertexRefId,
|
||||
aNewEdge.EndVertexRefId);
|
||||
theTargetGraph.incStorage().ChangeEdge(anEdgeId).Polygon3DRepId = anEdge.Polygon3DRepId;
|
||||
}
|
||||
|
||||
// Wires.
|
||||
for (BRepGraph_FullWireIterator aWireIt(theSourceGraph); aWireIt.More(); aWireIt.Next())
|
||||
{
|
||||
const BRepGraph_WireId aWireId = aWireIt.CurrentId();
|
||||
NCollection_LinearVector<BRepGraph_CoEdgeId> aCoEdgeIds;
|
||||
for (BRepGraph_CoEdgesOfWire aCEIt(theSourceGraph, aWireId); aCEIt.More(); aCEIt.Next())
|
||||
{
|
||||
const BRepGraphInc::CoEdgeDef& aCoEdge =
|
||||
theSourceGraph.Topo().CoEdges().Definition(aCEIt.CurrentId());
|
||||
aCoEdgeIds.Append(
|
||||
theTargetGraph.Editor().CoEdges().Add(aCoEdge.ChildEdgeId, aCoEdge.Orientation));
|
||||
}
|
||||
const BRepGraph_WireId aNewWireId = theTargetGraph.Editor().Wires().Add(aCoEdgeIds.ToArray1());
|
||||
Standard_ASSERT_RAISE(aNewWireId == aWireId, "BRepGraph_Copy: unexpected wire id");
|
||||
theTargetGraph.incStorage().SetRemoved(aNewWireId,
|
||||
theSourceGraph.incStorage().IsRemoved(aWireId));
|
||||
}
|
||||
|
||||
// Faces.
|
||||
for (BRepGraph_FullFaceIterator aFaceIt(theSourceGraph); aFaceIt.More(); aFaceIt.Next())
|
||||
{
|
||||
const BRepGraph_FaceId aFaceId = aFaceIt.CurrentId();
|
||||
const BRepGraphInc::FaceDef& aFace = theSourceGraph.Topo().Faces().Definition(aFaceId);
|
||||
|
||||
const occ::handle<Geom_Surface>& aFaceSrcSurf =
|
||||
BRepGraph_Tool::Face::Surface(theSourceGraph, aFaceId);
|
||||
occ::handle<Geom_Surface> aSurf = copySurface(aFaceSrcSurf, theGeomPolicy);
|
||||
|
||||
BRepGraph_WireId aFirstWire;
|
||||
NCollection_LinearVector<BRepGraph_WireId> aNextWires;
|
||||
|
||||
for (BRepGraph_RefsWireOfFace aWRIt(theSourceGraph, aFaceId); aWRIt.More(); aWRIt.Next())
|
||||
{
|
||||
const BRepGraphInc::WireRef& aWR = aRefs.Wires().Entry(aWRIt.CurrentId());
|
||||
if (!aFirstWire.IsValid())
|
||||
{
|
||||
aFirstWire = aWR.ChildWireId;
|
||||
}
|
||||
else
|
||||
{
|
||||
aNextWires.Append(aWR.ChildWireId);
|
||||
}
|
||||
}
|
||||
|
||||
const BRepGraph_FaceId aNewFaceId = theTargetGraph.Editor().Faces().Add(aSurf,
|
||||
aFirstWire,
|
||||
aNextWires.ToArray1(),
|
||||
aFace.Tolerance);
|
||||
Standard_ASSERT_RAISE(aNewFaceId == aFaceId, "BRepGraph_Copy: unexpected face id");
|
||||
theTargetGraph.incStorage().SetRemoved(aNewFaceId,
|
||||
theSourceGraph.incStorage().IsRemoved(aFaceId));
|
||||
const BRepGraphInc::FaceRelations& aSrcRel = theSourceGraph.incStorage().FaceRelations(aFaceId);
|
||||
const BRepGraphInc::FaceRelations& aDstRel =
|
||||
theTargetGraph.incStorage().FaceRelations(aNewFaceId);
|
||||
const size_t aNbWireRefs = std::min(aSrcRel.WireRefIds.Size(), aDstRel.WireRefIds.Size());
|
||||
for (size_t anIdx = 0; anIdx < aNbWireRefs; ++anIdx)
|
||||
{
|
||||
theTargetGraph.incStorage().SetRemoved(
|
||||
aDstRel.WireRefIds.Value(anIdx),
|
||||
theSourceGraph.incStorage().IsRemoved(aSrcRel.WireRefIds.Value(anIdx)));
|
||||
}
|
||||
theTargetGraph.incStorage().ChangeFace(aFaceId).TriangulationRepId = aFace.TriangulationRepId;
|
||||
}
|
||||
|
||||
Standard_ASSERT_RAISE(theTargetGraph.incStorage().NbCoEdges()
|
||||
<= theSourceGraph.incStorage().NbCoEdges(),
|
||||
"BRepGraph_Copy: unexpected coedge count after wire copy");
|
||||
while (theTargetGraph.incStorage().NbCoEdges() < theSourceGraph.incStorage().NbCoEdges())
|
||||
{
|
||||
const BRepGraph_CoEdgeId aNewId = theTargetGraph.incStorage().AppendCoEdge();
|
||||
Standard_ASSERT_RAISE(aNewId.Index + 1u == theTargetGraph.incStorage().NbCoEdges(),
|
||||
"BRepGraph_Copy: unexpected coedge append id");
|
||||
}
|
||||
for (BRepGraph_CoEdgeId aCoEdgeId(0); aCoEdgeId.IsValid(theSourceGraph.incStorage().NbCoEdges());
|
||||
++aCoEdgeId)
|
||||
{
|
||||
theTargetGraph.incStorage().ChangeCoEdge(aCoEdgeId) =
|
||||
theSourceGraph.incStorage().CoEdge(aCoEdgeId);
|
||||
theTargetGraph.incStorage().SetRemoved(aCoEdgeId,
|
||||
theSourceGraph.incStorage().IsRemoved(aCoEdgeId));
|
||||
}
|
||||
|
||||
// Shells.
|
||||
for (BRepGraph_FullShellIterator aShellIt(theSourceGraph); aShellIt.More(); aShellIt.Next())
|
||||
{
|
||||
const BRepGraph_ShellId aShellId = aShellIt.CurrentId();
|
||||
BRepGraph_ShellId aNewShellId = theTargetGraph.Editor().Shells().Add();
|
||||
Standard_ASSERT_RAISE(aNewShellId == aShellId, "BRepGraph_Copy: unexpected shell id");
|
||||
theTargetGraph.incStorage().SetRemoved(aNewShellId,
|
||||
theSourceGraph.incStorage().IsRemoved(aShellId));
|
||||
|
||||
for (BRepGraph_RefsFaceOfShell aFRIt(theSourceGraph, aShellId); aFRIt.More(); aFRIt.Next())
|
||||
{
|
||||
const BRepGraphInc::FaceRef& aFR = aRefs.Faces().Entry(aFRIt.CurrentId());
|
||||
const BRepGraph_FaceRefId aNewRef =
|
||||
theTargetGraph.Editor().Shells().Append(aNewShellId, aFR.ChildFaceId, aFR.Orientation);
|
||||
theTargetGraph.incStorage().SetRemoved(
|
||||
aNewRef,
|
||||
theSourceGraph.incStorage().IsRemoved(aFRIt.CurrentId()));
|
||||
}
|
||||
}
|
||||
|
||||
// Solids.
|
||||
for (BRepGraph_FullSolidIterator aSolidIt(theSourceGraph); aSolidIt.More(); aSolidIt.Next())
|
||||
{
|
||||
const BRepGraph_SolidId aSolidId = aSolidIt.CurrentId();
|
||||
BRepGraph_SolidId aNewSolidId = theTargetGraph.Editor().Solids().Add();
|
||||
Standard_ASSERT_RAISE(aNewSolidId == aSolidId, "BRepGraph_Copy: unexpected solid id");
|
||||
theTargetGraph.incStorage().SetRemoved(aNewSolidId,
|
||||
theSourceGraph.incStorage().IsRemoved(aSolidId));
|
||||
|
||||
for (BRepGraph_RefsShellOfSolid aSRIt(theSourceGraph, aSolidId); aSRIt.More(); aSRIt.Next())
|
||||
{
|
||||
const BRepGraphInc::ShellRef& aSR = aRefs.Shells().Entry(aSRIt.CurrentId());
|
||||
const BRepGraph_ShellRefId aNewRef =
|
||||
theTargetGraph.Editor().Solids().Append(aNewSolidId, aSR.ChildShellId, aSR.Orientation);
|
||||
theTargetGraph.incStorage().SetRemoved(
|
||||
aNewRef,
|
||||
theSourceGraph.incStorage().IsRemoved(aSRIt.CurrentId()));
|
||||
}
|
||||
}
|
||||
|
||||
// Compounds.
|
||||
for (BRepGraph_FullCompoundIterator aCompoundIt(theSourceGraph); aCompoundIt.More();
|
||||
aCompoundIt.Next())
|
||||
{
|
||||
const BRepGraph_CompoundId aCompoundId = aCompoundIt.CurrentId();
|
||||
NCollection_LinearVector<BRepGraph_NodeId> aChildNodeIds;
|
||||
for (BRepGraph_RefsChildOfCompound aCRIt(theSourceGraph, aCompoundId); aCRIt.More();
|
||||
aCRIt.Next())
|
||||
{
|
||||
aChildNodeIds.Append(aRefs.Children().Entry(aCRIt.CurrentId()).ChildNodeId);
|
||||
}
|
||||
const BRepGraph_CompoundId aNewCompoundId =
|
||||
theTargetGraph.Editor().Compounds().Add(aChildNodeIds.ToArray1());
|
||||
Standard_ASSERT_RAISE(aNewCompoundId == aCompoundId, "BRepGraph_Copy: unexpected compound id");
|
||||
theTargetGraph.incStorage().SetRemoved(aNewCompoundId,
|
||||
theSourceGraph.incStorage().IsRemoved(aCompoundId));
|
||||
const BRepGraphInc::CompoundRelations& aSrcRel =
|
||||
theSourceGraph.incStorage().CompoundRelations(aCompoundId);
|
||||
const BRepGraphInc::CompoundRelations& aDstRel =
|
||||
theTargetGraph.incStorage().CompoundRelations(aNewCompoundId);
|
||||
const size_t aNbChildRefs = std::min(aSrcRel.ChildRefIds.Size(), aDstRel.ChildRefIds.Size());
|
||||
for (size_t anIdx = 0; anIdx < aNbChildRefs; ++anIdx)
|
||||
{
|
||||
theTargetGraph.incStorage().SetRemoved(
|
||||
aDstRel.ChildRefIds.Value(anIdx),
|
||||
theSourceGraph.incStorage().IsRemoved(aSrcRel.ChildRefIds.Value(anIdx)));
|
||||
}
|
||||
}
|
||||
|
||||
// CompSolids.
|
||||
for (BRepGraph_FullCompSolidIterator aCompSolidIt(theSourceGraph); aCompSolidIt.More();
|
||||
aCompSolidIt.Next())
|
||||
{
|
||||
const BRepGraph_CompSolidId aCompSolidId = aCompSolidIt.CurrentId();
|
||||
NCollection_LinearVector<BRepGraph_SolidId> aSolidNodeIds;
|
||||
for (BRepGraph_RefsSolidOfCompSolid aSRIt(theSourceGraph, aCompSolidId); aSRIt.More();
|
||||
aSRIt.Next())
|
||||
{
|
||||
aSolidNodeIds.Append(aRefs.Solids().Entry(aSRIt.CurrentId()).ChildSolidId);
|
||||
}
|
||||
const BRepGraph_CompSolidId aNewCompSolidId =
|
||||
theTargetGraph.Editor().CompSolids().Add(aSolidNodeIds.ToArray1());
|
||||
Standard_ASSERT_RAISE(aNewCompSolidId == aCompSolidId,
|
||||
"BRepGraph_Copy: unexpected compsolid id");
|
||||
theTargetGraph.incStorage().SetRemoved(aNewCompSolidId,
|
||||
theSourceGraph.incStorage().IsRemoved(aCompSolidId));
|
||||
const BRepGraphInc::CompSolidRelations& aSrcRel =
|
||||
theSourceGraph.incStorage().CompSolidRelations(aCompSolidId);
|
||||
const BRepGraphInc::CompSolidRelations& aDstRel =
|
||||
theTargetGraph.incStorage().CompSolidRelations(aNewCompSolidId);
|
||||
const size_t aNbSolidRefs = std::min(aSrcRel.SolidRefIds.Size(), aDstRel.SolidRefIds.Size());
|
||||
for (size_t anIdx = 0; anIdx < aNbSolidRefs; ++anIdx)
|
||||
{
|
||||
theTargetGraph.incStorage().SetRemoved(
|
||||
aDstRel.SolidRefIds.Value(anIdx),
|
||||
theSourceGraph.incStorage().IsRemoved(aSrcRel.SolidRefIds.Value(anIdx)));
|
||||
}
|
||||
}
|
||||
|
||||
// Products.
|
||||
for (BRepGraph_FullProductIterator aProductIt(theSourceGraph); aProductIt.More();
|
||||
aProductIt.Next())
|
||||
{
|
||||
const BRepGraph_ProductId aProductId = aProductIt.CurrentId();
|
||||
const BRepGraph_ProductId aNewId = theTargetGraph.incStorage().AppendProduct();
|
||||
Standard_ASSERT_RAISE(aNewId == aProductId, "BRepGraph_Copy: unexpected product id");
|
||||
theTargetGraph.incStorage().SetRemoved(aNewId,
|
||||
theSourceGraph.incStorage().IsRemoved(aProductId));
|
||||
}
|
||||
|
||||
// Occurrences.
|
||||
for (BRepGraph_FullOccurrenceIterator anOccurrenceIt(theSourceGraph); anOccurrenceIt.More();
|
||||
anOccurrenceIt.Next())
|
||||
{
|
||||
const BRepGraph_OccurrenceId anOccurrenceId = anOccurrenceIt.CurrentId();
|
||||
const BRepGraphInc::OccurrenceDef& aSrcOcc =
|
||||
theSourceGraph.incStorage().Occurrence(anOccurrenceId);
|
||||
const BRepGraph_OccurrenceId aNewId = theTargetGraph.incStorage().AppendOccurrence();
|
||||
Standard_ASSERT_RAISE(aNewId == anOccurrenceId, "BRepGraph_Copy: unexpected occurrence id");
|
||||
theTargetGraph.incStorage().ChangeOccurrence(aNewId).ChildNodeId = aSrcOcc.ChildNodeId;
|
||||
theTargetGraph.incStorage().SetRemoved(aNewId,
|
||||
theSourceGraph.incStorage().IsRemoved(anOccurrenceId));
|
||||
}
|
||||
|
||||
// OccurrenceRefs (carry LocalLocation).
|
||||
for (BRepGraph_FullOccurrenceRefIterator aRefIt(theSourceGraph); aRefIt.More(); aRefIt.Next())
|
||||
{
|
||||
const BRepGraph_OccurrenceRefId aRefId = aRefIt.CurrentId();
|
||||
const BRepGraphInc::OccurrenceRef& aSrcRef = theSourceGraph.incStorage().OccurrenceRef(aRefId);
|
||||
const BRepGraph_OccurrenceRefId aNewId = theTargetGraph.incStorage().AppendOccurrenceRef();
|
||||
BRepGraphInc::OccurrenceRef& aNewRef = theTargetGraph.incStorage().ChangeOccurrenceRef(aNewId);
|
||||
theTargetGraph.incStorage().SetRemoved(aNewId, theSourceGraph.incStorage().IsRemoved(aRefId));
|
||||
aNewRef.ParentProductId = aSrcRef.ParentProductId;
|
||||
aNewRef.ChildOccurrenceId = aSrcRef.ChildOccurrenceId;
|
||||
aNewRef.LocalLocation = aSrcRef.LocalLocation;
|
||||
}
|
||||
for (BRepGraph_FullProductIterator aProductIt(theSourceGraph); aProductIt.More();
|
||||
aProductIt.Next())
|
||||
{
|
||||
const BRepGraph_ProductId aProductId = aProductIt.CurrentId();
|
||||
theTargetGraph.incStorage().SetProductOccurrenceRefs(
|
||||
aProductId,
|
||||
theSourceGraph.incStorage().ProductRelations(aProductId).OccurrenceRefIds.ToArray1());
|
||||
}
|
||||
|
||||
// Copy per-kind next counters from source to target storage so that future
|
||||
// allocations continue from the correct values.
|
||||
constexpr BRepGraph_NodeId::Kind aNodeKinds[] = {BRepGraph_NodeId::Kind::Solid,
|
||||
BRepGraph_NodeId::Kind::Shell,
|
||||
BRepGraph_NodeId::Kind::Face,
|
||||
BRepGraph_NodeId::Kind::Wire,
|
||||
BRepGraph_NodeId::Kind::Edge,
|
||||
BRepGraph_NodeId::Kind::Vertex,
|
||||
BRepGraph_NodeId::Kind::Compound,
|
||||
BRepGraph_NodeId::Kind::CompSolid,
|
||||
BRepGraph_NodeId::Kind::CoEdge,
|
||||
BRepGraph_NodeId::Kind::Product,
|
||||
BRepGraph_NodeId::Kind::Occurrence};
|
||||
for (const auto aNodeKind : aNodeKinds)
|
||||
{
|
||||
theTargetGraph.incStorage().SetNextNodeUIDCounter(
|
||||
aNodeKind,
|
||||
theSourceGraph.incStorage().NextNodeUIDCounter(aNodeKind));
|
||||
}
|
||||
constexpr BRepGraph_RefId::Kind aRefKinds[] = {BRepGraph_RefId::Kind::Shell,
|
||||
BRepGraph_RefId::Kind::Face,
|
||||
BRepGraph_RefId::Kind::Wire,
|
||||
BRepGraph_RefId::Kind::Vertex,
|
||||
BRepGraph_RefId::Kind::Solid,
|
||||
BRepGraph_RefId::Kind::Child,
|
||||
BRepGraph_RefId::Kind::Occurrence};
|
||||
for (const auto aRefKind : aRefKinds)
|
||||
{
|
||||
theTargetGraph.incStorage().SetNextRefUIDCounter(
|
||||
aRefKind,
|
||||
theSourceGraph.incStorage().NextRefUIDCounter(aRefKind));
|
||||
}
|
||||
|
||||
theTargetGraph.incStorage().SetGeneration(theSourceGraph.incStorage().Generation());
|
||||
theTargetGraph.incStorage().SetGraphGUID(theSourceGraph.incStorage().GraphGUID());
|
||||
theTargetGraph.incStorage().RebuildDerivedRelationsPreservingActiveCounts();
|
||||
|
||||
// Build root product set: products not referenced as ChildNodeId by any occurrence.
|
||||
{
|
||||
NCollection_FlatMap<BRepGraph_ProductId> aReferencedProducts;
|
||||
for (BRepGraph_FullOccurrenceIterator anOccIt(theTargetGraph); anOccIt.More(); anOccIt.Next())
|
||||
{
|
||||
const BRepGraph_OccurrenceId anOccId = anOccIt.CurrentId();
|
||||
const BRepGraphInc::OccurrenceDef& anOcc = theTargetGraph.incStorage().Occurrence(anOccId);
|
||||
if (!theTargetGraph.incStorage().IsRemoved(anOccId)
|
||||
&& anOcc.ChildNodeId.NodeKind == BRepGraph_NodeId::Kind::Product)
|
||||
{
|
||||
const BRepGraph_ProductId aChildProductId =
|
||||
BRepGraph_ProductId::FromNodeId(anOcc.ChildNodeId);
|
||||
if (aChildProductId.IsValidIn(theTargetGraph.Topo().Products()))
|
||||
{
|
||||
aReferencedProducts.Add(aChildProductId);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (BRepGraph_FullProductIterator aProdIt(theTargetGraph); aProdIt.More(); aProdIt.Next())
|
||||
{
|
||||
const BRepGraph_ProductId aProdId = aProdIt.CurrentId();
|
||||
if (!theTargetGraph.incStorage().IsRemoved(aProdId) && !aReferencedProducts.Contains(aProdId))
|
||||
{
|
||||
theTargetGraph.incStorage().ChangeRootProductIds().Append(aProdId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
theTargetGraph.incStorage().MarkUIDReverseIndexesDirty();
|
||||
|
||||
NCollection_FlatDataMap<BRepGraph_ItemId, BRepGraph_ItemId> anItemRemap;
|
||||
bindIdentityItems(theSourceGraph.incStorage(), theTargetGraph.incStorage(), anItemRemap);
|
||||
theSourceGraph.LayerRegistry().CopyLayersTo(theTargetGraph,
|
||||
anItemRemap,
|
||||
BRepGraph_CopyRemap::Mode::Copy);
|
||||
if (theCachePolicy == CachePolicy::CopyFresh)
|
||||
{
|
||||
theSourceGraph.CacheRegistry().CopyFreshCachesTo(theTargetGraph,
|
||||
anItemRemap,
|
||||
BRepGraph_CopyRemap::Mode::Copy);
|
||||
}
|
||||
|
||||
return true;
|
||||
// Empty target: fast identity copy using PrepareForLoad() instead of editor APIs.
|
||||
return copyFullGraphIdentity(theSourceGraph.incStorage(),
|
||||
theTargetGraph.incStorage(),
|
||||
theSourceGraph,
|
||||
theTargetGraph,
|
||||
theGeomPolicy,
|
||||
theMeshPolicy,
|
||||
theCachePolicy);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
@@ -25,15 +25,42 @@ BRepGraph_CopyRemap::BRepGraph_CopyRemap(const BRepGraph& theSourceGraph,
|
||||
: mySourceGraph(&theSourceGraph),
|
||||
myTargetGraph(&theTargetGraph),
|
||||
myItemRemap(&theItemRemap),
|
||||
myMode(theMode)
|
||||
myMode(theMode),
|
||||
myMappingKind(MappingKind::Explicit)
|
||||
{
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
const BRepGraph_ItemId* BRepGraph_CopyRemap::TargetItem(const BRepGraph_ItemId theSourceItem) const
|
||||
BRepGraph_CopyRemap::BRepGraph_CopyRemap(const BRepGraph& theSourceGraph,
|
||||
BRepGraph& theTargetGraph,
|
||||
const BRepGraph_CopyRemap::MappingKind theMappingKind,
|
||||
const BRepGraph_CopyRemap::Mode theMode) noexcept
|
||||
: mySourceGraph(&theSourceGraph),
|
||||
myTargetGraph(&theTargetGraph),
|
||||
myItemRemap(nullptr),
|
||||
myMode(theMode),
|
||||
myMappingKind(theMappingKind)
|
||||
{
|
||||
return theSourceItem.IsValid() ? myItemRemap->Seek(theSourceItem) : nullptr;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
BRepGraph_ItemId BRepGraph_CopyRemap::TargetItem(const BRepGraph_ItemId theSourceItem) const
|
||||
{
|
||||
if (!theSourceItem.IsValid())
|
||||
{
|
||||
return BRepGraph_ItemId();
|
||||
}
|
||||
|
||||
if (myMappingKind == MappingKind::Identity)
|
||||
{
|
||||
// In identity mode, the source item id IS the target item id.
|
||||
return theSourceItem;
|
||||
}
|
||||
|
||||
const BRepGraph_ItemId* aFound = myItemRemap->Seek(theSourceItem);
|
||||
return aFound != nullptr ? *aFound : BRepGraph_ItemId();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
@@ -41,16 +68,14 @@ const BRepGraph_ItemId* BRepGraph_CopyRemap::TargetItem(const BRepGraph_ItemId t
|
||||
BRepGraph_ItemId BRepGraph_CopyRemap::TargetItemOrInvalid(
|
||||
const BRepGraph_ItemId theSourceItem) const
|
||||
{
|
||||
const BRepGraph_ItemId* aTarget = TargetItem(theSourceItem);
|
||||
return aTarget != nullptr ? *aTarget : BRepGraph_ItemId();
|
||||
return TargetItem(theSourceItem);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_CopyRemap::HasTargetItem(const BRepGraph_ItemId theSourceItem) const
|
||||
{
|
||||
const BRepGraph_ItemId* aTarget = TargetItem(theSourceItem);
|
||||
return aTarget != nullptr && aTarget->IsValid();
|
||||
return TargetItem(theSourceItem).IsValid();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
@@ -40,6 +40,13 @@ public:
|
||||
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_ItemId, BRepGraph_ItemId>;
|
||||
|
||||
BRepGraph_CopyRemap(const BRepGraph& theSourceGraph,
|
||||
@@ -47,6 +54,13 @@ public:
|
||||
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; }
|
||||
|
||||
@@ -65,9 +79,9 @@ public:
|
||||
//! 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 null if the source item was not copied.
|
||||
[[nodiscard]] Standard_EXPORT const BRepGraph_ItemId* TargetItem(
|
||||
const BRepGraph_ItemId theSourceItem) const;
|
||||
//! 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
|
||||
@@ -93,6 +107,7 @@ private:
|
||||
BRepGraph* myTargetGraph = nullptr;
|
||||
const ItemMap* myItemRemap = nullptr;
|
||||
Mode myMode = Mode::Copy;
|
||||
MappingKind myMappingKind = MappingKind::Explicit;
|
||||
};
|
||||
|
||||
#endif // _BRepGraph_CopyRemap_HeaderFile
|
||||
|
||||
@@ -368,24 +368,52 @@ 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<size_t>(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<ChildId, BRepGraph_NodeId>)
|
||||
{
|
||||
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
|
||||
{
|
||||
const RefId aRefId = myRefIds->Value(static_cast<size_t>(myIndex));
|
||||
const typename TraitsT::RefEntry& aRef = TraitsT::Ref(myGraph, aRefId);
|
||||
if constexpr (TraitsT::THE_IS_DIRECT)
|
||||
{
|
||||
return aRefId;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TraitsT::ChildIdOf(myGraph, aRef);
|
||||
}
|
||||
Standard_ASSERT_VOID(More(), "DefsOfParent::CurrentId() called on exhausted iterator");
|
||||
return myCurrentChild;
|
||||
}
|
||||
|
||||
[[nodiscard]] const ChildDef& Current() const { return TraitsT::Child(myGraph, CurrentId()); }
|
||||
[[nodiscard]] const ChildDef& Current() const
|
||||
{
|
||||
Standard_ASSERT_VOID(More(), "DefsOfParent::Current() called on exhausted iterator");
|
||||
return TraitsT::Child(myGraph, CurrentId());
|
||||
}
|
||||
|
||||
//! Returns the reference/coedge entry that carries the current child relation.
|
||||
[[nodiscard]] RefId CurrentRefId() const
|
||||
@@ -428,11 +456,13 @@ private:
|
||||
{
|
||||
if (myGraph.Topo().Gen().IsActive(aChildId))
|
||||
{
|
||||
myCurrentChild = aChildId;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (aChildId.IsValid(myNbChildren) && !aChildId.IsRemoved(myGraph))
|
||||
{
|
||||
myCurrentChild = aChildId;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -441,7 +471,8 @@ private:
|
||||
}
|
||||
|
||||
const BRepGraph& myGraph;
|
||||
const NCollection_LinearVector<RefId>* myRefIds = nullptr;
|
||||
const NCollection_LinearVector<RefId>* myRefIds = nullptr;
|
||||
ChildId myCurrentChild{};
|
||||
uint32_t myIndex = 0;
|
||||
uint32_t myLength = 0;
|
||||
uint32_t myNbRefs = 0;
|
||||
@@ -482,11 +513,13 @@ public:
|
||||
|
||||
[[nodiscard]] ChildId CurrentId() const
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
@@ -209,12 +209,12 @@ protected:
|
||||
{
|
||||
return BRepGraph_NodeId::Typed<TheKind>();
|
||||
}
|
||||
const BRepGraph_ItemId* aMapped = theCopy.TargetItem(BRepGraph_ItemId(theId));
|
||||
if (aMapped == nullptr || !aMapped->IsNode())
|
||||
const BRepGraph_ItemId aMapped = theCopy.TargetItem(BRepGraph_ItemId(theId));
|
||||
if (!aMapped.IsNode())
|
||||
{
|
||||
return BRepGraph_NodeId::Typed<TheKind>();
|
||||
}
|
||||
return BRepGraph_NodeId::Typed<TheKind>::FromNodeId(aMapped->NodeId());
|
||||
return BRepGraph_NodeId::Typed<TheKind>::FromNodeId(aMapped.NodeId());
|
||||
}
|
||||
|
||||
template <BRepGraph_RefId::Kind TheKind>
|
||||
@@ -226,12 +226,12 @@ protected:
|
||||
{
|
||||
return BRepGraph_RefId::Typed<TheKind>();
|
||||
}
|
||||
const BRepGraph_ItemId* aMapped = theCopy.TargetItem(BRepGraph_ItemId(theId));
|
||||
if (aMapped == nullptr || !aMapped->IsReference())
|
||||
const BRepGraph_ItemId aMapped = theCopy.TargetItem(BRepGraph_ItemId(theId));
|
||||
if (!aMapped.IsReference())
|
||||
{
|
||||
return BRepGraph_RefId::Typed<TheKind>();
|
||||
}
|
||||
return BRepGraph_RefId::Typed<TheKind>::FromRefId(aMapped->RefId());
|
||||
return BRepGraph_RefId::Typed<TheKind>::FromRefId(aMapped.RefId());
|
||||
}
|
||||
|
||||
//! Called after the layer is attached to a graph registry.
|
||||
|
||||
@@ -430,8 +430,8 @@ void BRepGraph_LayerDeferred::CopyTo(const BRepGraph_CopyRemap& theCopy) const
|
||||
for (NCollection_DataMap<BRepGraph_ItemId, Entry>::Iterator anIt(myEntries); anIt.More();
|
||||
anIt.Next())
|
||||
{
|
||||
const BRepGraph_ItemId* aTargetItem = theCopy.TargetItem(anIt.Key());
|
||||
if (aTargetItem == nullptr || !aTargetItem->IsValid())
|
||||
const BRepGraph_ItemId aTargetItem = theCopy.TargetItem(anIt.Key());
|
||||
if (!aTargetItem.IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -443,7 +443,7 @@ void BRepGraph_LayerDeferred::CopyTo(const BRepGraph_CopyRemap& theCopy) const
|
||||
{
|
||||
aRepresentations[aRepresentationIdx] = anEntry.Representations.Value(aRepresentationIdx);
|
||||
}
|
||||
aTarget->RegisterDeferredRepresentationsDirect(*aTargetItem,
|
||||
aTarget->RegisterDeferredRepresentationsDirect(aTargetItem,
|
||||
anEntry.Provider,
|
||||
anEntry.SourceKey,
|
||||
aRepresentations,
|
||||
|
||||
@@ -452,8 +452,8 @@ void BRepGraph_LayerHistory::CopyTo(const BRepGraph_CopyRemap& theCopy) const
|
||||
anIt.More();
|
||||
anIt.Next())
|
||||
{
|
||||
const BRepGraph_ItemId* aNewOriginalItem = theCopy.TargetItem(BRepGraph_ItemId(anIt.Key()));
|
||||
if (aNewOriginalItem == nullptr || !aNewOriginalItem->IsNode())
|
||||
const BRepGraph_ItemId aNewOriginalItem = theCopy.TargetItem(BRepGraph_ItemId(anIt.Key()));
|
||||
if (!aNewOriginalItem.IsNode())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -461,13 +461,13 @@ void BRepGraph_LayerHistory::CopyTo(const BRepGraph_CopyRemap& theCopy) const
|
||||
NCollection_LinearVector<BRepGraph_NodeId> aNewImages(THE_HISTORY_FILTERED_BLOCK_SIZE);
|
||||
for (const BRepGraph_NodeId& anOldImage : anIt.Value())
|
||||
{
|
||||
const BRepGraph_ItemId* aNewImageItem = theCopy.TargetItem(BRepGraph_ItemId(anOldImage));
|
||||
if (aNewImageItem != nullptr && aNewImageItem->IsNode())
|
||||
const BRepGraph_ItemId aNewImageItem = theCopy.TargetItem(BRepGraph_ItemId(anOldImage));
|
||||
if (aNewImageItem.IsNode())
|
||||
{
|
||||
appendUniqueNode(aNewImages, aNewImageItem->NodeId());
|
||||
appendUniqueNode(aNewImages, aNewImageItem.NodeId());
|
||||
}
|
||||
}
|
||||
aNewRecord.Mapping.Bind(aNewOriginalItem->NodeId(), std::move(aNewImages));
|
||||
aNewRecord.Mapping.Bind(aNewOriginalItem.NodeId(), std::move(aNewImages));
|
||||
}
|
||||
|
||||
if (!aNewRecord.Mapping.IsEmpty() || !aNewRecord.UidMapping.IsEmpty()
|
||||
@@ -497,8 +497,8 @@ void BRepGraph_LayerHistory::CopyTo(const BRepGraph_CopyRemap& theCopy) const
|
||||
const BRepGraph_ItemId theSourceOriginal,
|
||||
const BRepGraph_ItemUID& theDurableOriginalUID,
|
||||
const NCollection_LinearVector<BRepGraph_ItemId>& theSourceImages) {
|
||||
const BRepGraph_ItemId* aTargetOriginal = theCopy.TargetItem(theSourceOriginal);
|
||||
if (aTargetOriginal == nullptr || !aTargetOriginal->IsValid())
|
||||
const BRepGraph_ItemId aTargetOriginal = theCopy.TargetItem(theSourceOriginal);
|
||||
if (!aTargetOriginal.IsValid())
|
||||
{
|
||||
if (theKind == BRepGraph_LayerHistory::Kind::Deleted)
|
||||
{
|
||||
@@ -523,24 +523,24 @@ void BRepGraph_LayerHistory::CopyTo(const BRepGraph_CopyRemap& theCopy) const
|
||||
|
||||
NCollection_LinearVector<BRepGraph_ItemUID> aTargetImageUIDs(THE_HISTORY_FILTERED_BLOCK_SIZE);
|
||||
NCollection_LinearVector<BRepGraph_NodeId> aTargetImageNodes(THE_HISTORY_FILTERED_BLOCK_SIZE);
|
||||
bool areAllItemsNodes = aTargetOriginal->IsNode();
|
||||
bool areAllItemsNodes = aTargetOriginal.IsNode();
|
||||
for (const BRepGraph_ItemId& aSourceImage : theSourceImages)
|
||||
{
|
||||
const BRepGraph_ItemId* aTargetImage = theCopy.TargetItem(aSourceImage);
|
||||
if (aTargetImage == nullptr || !aTargetImage->IsValid())
|
||||
const BRepGraph_ItemId aTargetImage = theCopy.TargetItem(aSourceImage);
|
||||
if (!aTargetImage.IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const BRepGraph_ItemUID aTargetUID = theCopy.TargetUID(*aTargetImage);
|
||||
const BRepGraph_ItemUID aTargetUID = theCopy.TargetUID(aTargetImage);
|
||||
if (aTargetUID.IsValid())
|
||||
{
|
||||
appendUniqueItemUid(aTargetImageUIDs, aTargetUID);
|
||||
}
|
||||
|
||||
if (areAllItemsNodes && aTargetImage->IsNode())
|
||||
if (areAllItemsNodes && aTargetImage.IsNode())
|
||||
{
|
||||
appendUniqueNode(aTargetImageNodes, aTargetImage->NodeId());
|
||||
appendUniqueNode(aTargetImageNodes, aTargetImage.NodeId());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -550,10 +550,10 @@ void BRepGraph_LayerHistory::CopyTo(const BRepGraph_CopyRemap& theCopy) const
|
||||
|
||||
if (theKind == BRepGraph_LayerHistory::Kind::Deleted)
|
||||
{
|
||||
if (aTargetOriginal->IsNode())
|
||||
if (aTargetOriginal.IsNode())
|
||||
{
|
||||
NCollection_LinearVector<BRepGraph_NodeId> aDeleted(THE_HISTORY_REPLACEMENT_BLOCK_SIZE);
|
||||
aDeleted.Append(aTargetOriginal->NodeId());
|
||||
aDeleted.Append(aTargetOriginal.NodeId());
|
||||
aTarget->RecordDeleted(theOperationName, aDeleted.ToArray1());
|
||||
}
|
||||
if (theDurableOriginalUID.IsValid())
|
||||
@@ -573,13 +573,13 @@ void BRepGraph_LayerHistory::CopyTo(const BRepGraph_CopyRemap& theCopy) const
|
||||
if (areAllItemsNodes)
|
||||
{
|
||||
aTarget->Record(theOperationName,
|
||||
aTargetOriginal->NodeId(),
|
||||
aTargetOriginal.NodeId(),
|
||||
aTargetImageNodes.ToArray1(),
|
||||
theKind);
|
||||
return;
|
||||
}
|
||||
|
||||
const BRepGraph_ItemUID aTargetOriginalUID = theCopy.TargetUID(*aTargetOriginal);
|
||||
const BRepGraph_ItemUID aTargetOriginalUID = theCopy.TargetUID(aTargetOriginal);
|
||||
if (aTargetOriginalUID.IsValid())
|
||||
{
|
||||
aTarget->RecordItemUid(theOperationName,
|
||||
@@ -605,11 +605,11 @@ void BRepGraph_LayerHistory::CopyTo(const BRepGraph_CopyRemap& theCopy) const
|
||||
anIt.More();
|
||||
anIt.Next())
|
||||
{
|
||||
BRepGraph_NodeId aTargetNode;
|
||||
const BRepGraph_ItemId* aTargetOriginal = theCopy.TargetItem(BRepGraph_ItemId(anIt.Key()));
|
||||
if (aTargetOriginal != nullptr && aTargetOriginal->IsNode())
|
||||
BRepGraph_NodeId aTargetNode;
|
||||
const BRepGraph_ItemId aTargetOriginal = theCopy.TargetItem(BRepGraph_ItemId(anIt.Key()));
|
||||
if (aTargetOriginal.IsNode())
|
||||
{
|
||||
aTargetNode = aTargetOriginal->NodeId();
|
||||
aTargetNode = aTargetOriginal.NodeId();
|
||||
}
|
||||
else if (theCopy.TargetGraphConst().Topo().Gen().TopoEntity(anIt.Key()) != nullptr)
|
||||
{
|
||||
@@ -623,10 +623,10 @@ void BRepGraph_LayerHistory::CopyTo(const BRepGraph_CopyRemap& theCopy) const
|
||||
NCollection_LinearVector<BRepGraph_NodeId> aTargetImages(THE_HISTORY_FILTERED_BLOCK_SIZE);
|
||||
for (const BRepGraph_NodeId& aNode : anIt.Value())
|
||||
{
|
||||
const BRepGraph_ItemId* aTargetImage = theCopy.TargetItem(BRepGraph_ItemId(aNode));
|
||||
if (aTargetImage != nullptr && aTargetImage->IsNode())
|
||||
const BRepGraph_ItemId aTargetImage = theCopy.TargetItem(BRepGraph_ItemId(aNode));
|
||||
if (aTargetImage.IsNode())
|
||||
{
|
||||
appendUniqueNode(aTargetImages, aTargetImage->NodeId());
|
||||
appendUniqueNode(aTargetImages, aTargetImage.NodeId());
|
||||
}
|
||||
}
|
||||
aNewRecord.Mapping.Bind(aTargetNode, std::move(aTargetImages));
|
||||
@@ -702,11 +702,11 @@ void BRepGraph_LayerHistory::CopyTo(const BRepGraph_CopyRemap& theCopy) const
|
||||
if (aSourceImage.IsValid())
|
||||
{
|
||||
aSourceImages.Append(aSourceImage);
|
||||
const BRepGraph_ItemId* aTargetImage = theCopy.TargetItem(aSourceImage);
|
||||
if (aTargetImage != nullptr && aTargetImage->IsNode())
|
||||
const BRepGraph_ItemId aTargetImage = theCopy.TargetItem(aSourceImage);
|
||||
if (aTargetImage.IsNode())
|
||||
{
|
||||
const BRepGraph_UID aTargetUID =
|
||||
theCopy.TargetGraphConst().UIDs().Of(aTargetImage->NodeId());
|
||||
theCopy.TargetGraphConst().UIDs().Of(aTargetImage.NodeId());
|
||||
if (aTargetUID.IsValid())
|
||||
{
|
||||
appendUniqueUid(aTargetImageUIDs, aTargetUID);
|
||||
|
||||
@@ -456,23 +456,23 @@ void BRepGraph_LayerLock::CopyTo(const BRepGraph_CopyRemap& theCopy) const
|
||||
// Copy node root entries.
|
||||
for (OwnerMap::Iterator anIt(myNodeOwners); anIt.More(); anIt.Next())
|
||||
{
|
||||
const BRepGraph_ItemId* aTargetItem = theCopy.TargetItem(anIt.Key());
|
||||
if (aTargetItem == nullptr || !aTargetItem->IsValid())
|
||||
const BRepGraph_ItemId aTargetItem = theCopy.TargetItem(anIt.Key());
|
||||
if (!aTargetItem.IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
hasCopied = aTarget->SetOwner(*aTargetItem, anIt.Value(), false) || hasCopied;
|
||||
hasCopied = aTarget->SetOwner(aTargetItem, anIt.Value(), false) || hasCopied;
|
||||
}
|
||||
|
||||
// Copy ref root entries.
|
||||
for (OwnerMap::Iterator anIt(myRefOwners); anIt.More(); anIt.Next())
|
||||
{
|
||||
const BRepGraph_ItemId* aTargetItem = theCopy.TargetItem(anIt.Key());
|
||||
if (aTargetItem == nullptr || !aTargetItem->IsValid())
|
||||
const BRepGraph_ItemId aTargetItem = theCopy.TargetItem(anIt.Key());
|
||||
if (!aTargetItem.IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
hasCopied = aTarget->SetOwner(*aTargetItem, anIt.Value(), false) || hasCopied;
|
||||
hasCopied = aTarget->SetOwner(aTargetItem, anIt.Value(), false) || hasCopied;
|
||||
}
|
||||
|
||||
if (hasCopied)
|
||||
|
||||
@@ -30,14 +30,16 @@ BRepGraph_LayerRegistry::BRepGraph_LayerRegistry() = default;
|
||||
BRepGraph_LayerRegistry::BRepGraph_LayerRegistry(BRepGraph_LayerRegistry&& theOther) noexcept
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(theOther.myMutex);
|
||||
myLayers = std::move(theOther.myLayers);
|
||||
myGuidToSlot = std::move(theOther.myGuidToSlot);
|
||||
mySubscribedKindsMask = theOther.mySubscribedKindsMask;
|
||||
mySubscribedRefKindsMask = theOther.mySubscribedRefKindsMask;
|
||||
myGraph = theOther.myGraph;
|
||||
theOther.mySubscribedKindsMask = 0;
|
||||
theOther.mySubscribedRefKindsMask = 0;
|
||||
theOther.myGraph = nullptr;
|
||||
myLayers = std::move(theOther.myLayers);
|
||||
myGuidToSlot = std::move(theOther.myGuidToSlot);
|
||||
mySubscribedKindsMask.store(theOther.mySubscribedKindsMask.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
mySubscribedRefKindsMask.store(theOther.mySubscribedRefKindsMask.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
myGraph = theOther.myGraph;
|
||||
theOther.mySubscribedKindsMask.store(0, std::memory_order_relaxed);
|
||||
theOther.mySubscribedRefKindsMask.store(0, std::memory_order_relaxed);
|
||||
theOther.myGraph = nullptr;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
@@ -52,14 +54,17 @@ BRepGraph_LayerRegistry& BRepGraph_LayerRegistry::operator=(
|
||||
std::lock(aThisLock, anOtherLock);
|
||||
|
||||
detachAllLocked();
|
||||
myLayers = std::move(theOther.myLayers);
|
||||
myGuidToSlot = std::move(theOther.myGuidToSlot);
|
||||
mySubscribedKindsMask = theOther.mySubscribedKindsMask;
|
||||
mySubscribedRefKindsMask = theOther.mySubscribedRefKindsMask;
|
||||
myGraph = theOther.myGraph;
|
||||
theOther.mySubscribedKindsMask = 0;
|
||||
theOther.mySubscribedRefKindsMask = 0;
|
||||
theOther.myGraph = nullptr;
|
||||
myLayers = std::move(theOther.myLayers);
|
||||
myGuidToSlot = std::move(theOther.myGuidToSlot);
|
||||
mySubscribedKindsMask.store(theOther.mySubscribedKindsMask.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
mySubscribedRefKindsMask.store(
|
||||
theOther.mySubscribedRefKindsMask.load(std::memory_order_relaxed),
|
||||
std::memory_order_relaxed);
|
||||
myGraph = theOther.myGraph;
|
||||
theOther.mySubscribedKindsMask.store(0, std::memory_order_relaxed);
|
||||
theOther.mySubscribedRefKindsMask.store(0, std::memory_order_relaxed);
|
||||
theOther.myGraph = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -100,8 +105,12 @@ uint32_t BRepGraph_LayerRegistry::registerLayerLocked(const occ::handle<BRepGrap
|
||||
theLayer->attachGraph(myGraph);
|
||||
myLayers.Append(theLayer);
|
||||
myGuidToSlot.Bind(aGUID, aNewSlot);
|
||||
mySubscribedKindsMask |= theLayer->SubscribedKinds();
|
||||
mySubscribedRefKindsMask |= theLayer->SubscribedRefKinds();
|
||||
mySubscribedKindsMask.store(mySubscribedKindsMask.load(std::memory_order_relaxed)
|
||||
| theLayer->SubscribedKinds(),
|
||||
std::memory_order_relaxed);
|
||||
mySubscribedRefKindsMask.store(mySubscribedRefKindsMask.load(std::memory_order_relaxed)
|
||||
| theLayer->SubscribedRefKinds(),
|
||||
std::memory_order_relaxed);
|
||||
return aNewSlot;
|
||||
}
|
||||
|
||||
@@ -179,6 +188,35 @@ occ::handle<BRepGraph_Layer> BRepGraph_LayerRegistry::findLayerLocked(
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
occ::handle<BRepGraph_Layer> BRepGraph_LayerRegistry::ensureLayer(
|
||||
const Standard_GUID& theGUID,
|
||||
const std::function<occ::handle<BRepGraph_Layer>()>& theFactory)
|
||||
{
|
||||
// Fast path: shared lock for read-only lookup.
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
occ::handle<BRepGraph_Layer> aLayer = findLayerLocked(theGUID);
|
||||
if (!aLayer.IsNull())
|
||||
{
|
||||
return aLayer;
|
||||
}
|
||||
}
|
||||
|
||||
// Slow path: exclusive lock for creation.
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myMutex);
|
||||
occ::handle<BRepGraph_Layer> aLayer = findLayerLocked(theGUID);
|
||||
if (aLayer.IsNull())
|
||||
{
|
||||
aLayer = theFactory();
|
||||
registerLayerLocked(aLayer);
|
||||
}
|
||||
return aLayer;
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_LayerRegistry::FindSlot(const Standard_GUID& theGUID, uint32_t& theSlot) const
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
@@ -270,12 +308,10 @@ void BRepGraph_LayerRegistry::DispatchOnNodeReplaced(const BRepGraph_NodeId theO
|
||||
|
||||
void BRepGraph_LayerRegistry::DispatchNodeModified(const BRepGraph_NodeId theNode) noexcept
|
||||
{
|
||||
// Lock-free early exit: check subscription mask without mutex.
|
||||
if (mySubscribedKindsMask.load(std::memory_order_acquire) == 0)
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
if (mySubscribedKindsMask == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const int aKindBit = BRepGraph_Layer::KindBit(theNode.NodeKind);
|
||||
@@ -321,12 +357,10 @@ void BRepGraph_LayerRegistry::DispatchNodesModified(
|
||||
const NCollection_Array1<BRepGraph_NodeId>& theModifiedNodes,
|
||||
const int theModifiedKindsMask) noexcept
|
||||
{
|
||||
// Lock-free early exit: check subscription mask without mutex.
|
||||
if (mySubscribedKindsMask.load(std::memory_order_acquire) == 0 || theModifiedKindsMask == 0)
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
if (mySubscribedKindsMask == 0 || theModifiedKindsMask == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t aSlot = 0;; ++aSlot)
|
||||
@@ -369,8 +403,8 @@ void BRepGraph_LayerRegistry::CopyLayersTo(
|
||||
aSelf.detachAllLocked();
|
||||
aSelf.myLayers.Clear();
|
||||
aSelf.myGuidToSlot.Clear();
|
||||
aSelf.mySubscribedKindsMask = 0;
|
||||
aSelf.mySubscribedRefKindsMask = 0;
|
||||
aSelf.mySubscribedKindsMask.store(0, std::memory_order_relaxed);
|
||||
aSelf.mySubscribedRefKindsMask.store(0, std::memory_order_relaxed);
|
||||
aLock.unlock();
|
||||
|
||||
// Call CopyTo on each old (now detached) layer.
|
||||
@@ -404,6 +438,30 @@ void BRepGraph_LayerRegistry::CopyLayersTo(
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraph_LayerRegistry::CopyLayersTo(BRepGraph& theTargetGraph,
|
||||
BRepGraph_CopyRemap::MappingKind theMappingKind,
|
||||
BRepGraph_CopyRemap::Mode theMode) const
|
||||
{
|
||||
BRepGraph* aSourceGraph = nullptr;
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
aSourceGraph = myGraph;
|
||||
}
|
||||
|
||||
const BRepGraph_CopyRemap aCopy(*aSourceGraph, theTargetGraph, theMappingKind, theMode);
|
||||
for (uint32_t aSlot = 0;; ++aSlot)
|
||||
{
|
||||
occ::handle<BRepGraph_Layer> aLayer = layerAt(aSlot);
|
||||
if (aLayer.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
aLayer->CopyTo(aCopy);
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraph_LayerRegistry::ClearAll() noexcept
|
||||
{
|
||||
for (uint32_t aSlot = 0;; ++aSlot)
|
||||
@@ -451,12 +509,10 @@ void BRepGraph_LayerRegistry::DispatchOnRefRemoved(const BRepGraph_RefId theRef)
|
||||
|
||||
void BRepGraph_LayerRegistry::DispatchRefModified(const BRepGraph_RefId theRef) noexcept
|
||||
{
|
||||
// Lock-free early exit: check subscription mask without mutex.
|
||||
if (mySubscribedRefKindsMask.load(std::memory_order_acquire) == 0)
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
if (mySubscribedRefKindsMask == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const int aRefKindBit = BRepGraph_Layer::RefKindBit(theRef.RefKind);
|
||||
@@ -480,12 +536,10 @@ void BRepGraph_LayerRegistry::DispatchRefsModified(
|
||||
const NCollection_Array1<BRepGraph_RefId>& theModifiedRefs,
|
||||
const int theModifiedRefKindsMask) noexcept
|
||||
{
|
||||
// Lock-free early exit: check subscription mask without mutex.
|
||||
if (mySubscribedRefKindsMask.load(std::memory_order_acquire) == 0 || theModifiedRefKindsMask == 0)
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
if (mySubscribedRefKindsMask == 0 || theModifiedRefKindsMask == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t aSlot = 0;; ++aSlot)
|
||||
@@ -519,11 +573,13 @@ void BRepGraph_LayerRegistry::detachAllLocked() noexcept
|
||||
|
||||
void BRepGraph_LayerRegistry::recomputeSubscribedKindsMask()
|
||||
{
|
||||
mySubscribedKindsMask = 0;
|
||||
mySubscribedRefKindsMask = 0;
|
||||
uint32_t aKindsMask = 0;
|
||||
uint32_t aRefKindsMask = 0;
|
||||
for (const occ::handle<BRepGraph_Layer>& aLayer : myLayers)
|
||||
{
|
||||
mySubscribedKindsMask |= aLayer->SubscribedKinds();
|
||||
mySubscribedRefKindsMask |= aLayer->SubscribedRefKinds();
|
||||
aKindsMask |= aLayer->SubscribedKinds();
|
||||
aRefKindsMask |= aLayer->SubscribedRefKinds();
|
||||
}
|
||||
mySubscribedKindsMask.store(aKindsMask, std::memory_order_relaxed);
|
||||
mySubscribedRefKindsMask.store(aRefKindsMask, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
@@ -23,8 +23,10 @@
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
#include <Standard_GUID.hxx>
|
||||
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <atomic>
|
||||
|
||||
//! @brief Dense GUID-keyed runtime registry of graph layers.
|
||||
//!
|
||||
@@ -69,17 +71,12 @@ public:
|
||||
}
|
||||
|
||||
//! Return an existing layer or create and register a default one.
|
||||
//! Template convenience wrapper: extracts GUID and calls ensureLayer.
|
||||
template <typename T>
|
||||
[[nodiscard]] occ::handle<T> Ensure()
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myMutex);
|
||||
occ::handle<T> aLayer = occ::down_cast<T>(findLayerLocked(T::GetID()));
|
||||
if (aLayer.IsNull())
|
||||
{
|
||||
aLayer = new T();
|
||||
registerLayerLocked(aLayer);
|
||||
}
|
||||
return aLayer;
|
||||
return occ::down_cast<T>(
|
||||
ensureLayer(T::GetID(), []() -> occ::handle<BRepGraph_Layer> { return new T(); }));
|
||||
}
|
||||
|
||||
//! Return current slot for a GUID.
|
||||
@@ -99,15 +96,13 @@ public:
|
||||
//! True if any registered layer subscribes to node modification events.
|
||||
[[nodiscard]] bool HasModificationSubscribers() const
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
return mySubscribedKindsMask != 0;
|
||||
return mySubscribedKindsMask.load(std::memory_order_acquire) != 0;
|
||||
}
|
||||
|
||||
//! Bitwise OR of all registered layer node subscription masks.
|
||||
[[nodiscard]] int SubscribedKindsMask() const
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
return mySubscribedKindsMask;
|
||||
return static_cast<int>(mySubscribedKindsMask.load(std::memory_order_acquire));
|
||||
}
|
||||
|
||||
//! Dispatch OnNodeRemoved to all registered layers.
|
||||
@@ -141,18 +136,25 @@ public:
|
||||
const NCollection_FlatDataMap<BRepGraph_ItemId, BRepGraph_ItemId>& 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
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
return mySubscribedRefKindsMask != 0;
|
||||
return mySubscribedRefKindsMask.load(std::memory_order_acquire) != 0;
|
||||
}
|
||||
|
||||
//! Bitwise OR of all registered layer reference subscription masks.
|
||||
[[nodiscard]] int SubscribedRefKindsMask() const
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myMutex);
|
||||
return mySubscribedRefKindsMask;
|
||||
return static_cast<int>(mySubscribedRefKindsMask.load(std::memory_order_acquire));
|
||||
}
|
||||
|
||||
//! Dispatch OnRefRemoved to all registered layers (unconditional - not filtered).
|
||||
@@ -185,6 +187,13 @@ private:
|
||||
[[nodiscard]] Standard_EXPORT occ::handle<BRepGraph_Layer> 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<BRepGraph_Layer> ensureLayer(
|
||||
const Standard_GUID& theGUID,
|
||||
const std::function<occ::handle<BRepGraph_Layer>()>& theFactory);
|
||||
|
||||
[[nodiscard]] Standard_EXPORT occ::handle<BRepGraph_Layer> layerAt(uint32_t theSlot) const;
|
||||
|
||||
Standard_EXPORT uint32_t registerLayerLocked(const occ::handle<BRepGraph_Layer>& theLayer);
|
||||
@@ -195,9 +204,9 @@ private:
|
||||
private:
|
||||
NCollection_LinearVector<occ::handle<BRepGraph_Layer>> myLayers;
|
||||
NCollection_DataMap<Standard_GUID, uint32_t> myGuidToSlot;
|
||||
uint32_t mySubscribedKindsMask = 0;
|
||||
uint32_t mySubscribedRefKindsMask = 0;
|
||||
BRepGraph* myGraph = nullptr;
|
||||
std::atomic<uint32_t> mySubscribedKindsMask{0};
|
||||
std::atomic<uint32_t> mySubscribedRefKindsMask{0};
|
||||
BRepGraph* myGraph = nullptr;
|
||||
mutable std::shared_mutex myMutex;
|
||||
};
|
||||
|
||||
|
||||
@@ -327,13 +327,13 @@ void BRepGraph_LayerTopoSupplement::CopyTo(const BRepGraph_CopyRemap& theCopy) c
|
||||
}
|
||||
for (const Entry& anEntry : aSourceEntries)
|
||||
{
|
||||
const BRepGraph_ItemId* aTargetItem = theCopy.TargetItem(BRepGraph_ItemId(anEntry.BaseOwner));
|
||||
if (aTargetItem == nullptr || !aTargetItem->IsNode())
|
||||
const BRepGraph_ItemId aTargetItem = theCopy.TargetItem(BRepGraph_ItemId(anEntry.BaseOwner));
|
||||
if (!aTargetItem.IsNode())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const BRepGraph_NodeId aTargetOwner = aTargetItem->NodeId();
|
||||
const BRepGraph_NodeId aTargetOwner = aTargetItem.NodeId();
|
||||
if (!aTargetOwner.IsValid())
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -431,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<size_t>(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<ChildId, BRepGraph_NodeId>)
|
||||
{
|
||||
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<size_t>(myIndex)); }
|
||||
[[nodiscard]] RefId CurrentId() const
|
||||
{
|
||||
Standard_ASSERT_VOID(More(), "RefsOfParent::CurrentId() called on exhausted iterator");
|
||||
return myRefIds->Value(static_cast<size_t>(myIndex));
|
||||
}
|
||||
|
||||
[[nodiscard]] uint32_t Index() const { return myIndex; }
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace
|
||||
{
|
||||
struct BRepGraph_ReconstructionContext
|
||||
{
|
||||
const BRepGraph* Graph = nullptr;
|
||||
BRepGraph* Graph = nullptr;
|
||||
const BRepGraphInc_Storage* Storage = nullptr;
|
||||
BRepGraphInc_Reconstruct::Cache Cache;
|
||||
NCollection_FlatMap<BRepGraph_ProductId> ActiveProducts;
|
||||
@@ -677,7 +677,7 @@ static TopoDS_Shape reconstructShape(BRepGraph_ReconstructionContext& theContext
|
||||
}
|
||||
|
||||
static BRepGraph_ReconstructionContext makeReconstructionContext(
|
||||
const BRepGraph& theGraph,
|
||||
BRepGraph& theGraph,
|
||||
const BRepGraphInc_Storage& theStorage)
|
||||
{
|
||||
BRepGraph_ReconstructionContext aContext;
|
||||
|
||||
@@ -80,13 +80,6 @@ bool wireUVBounds(const BRepGraph& theGraph,
|
||||
return true;
|
||||
}
|
||||
|
||||
BRepGraph_EdgeId edgeOf(const BRepGraph& theGraph, const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
return theCoEdge.IsValid() && !theCoEdge.IsRemoved(theGraph)
|
||||
? theGraph.Topo().CoEdges().Definition(theCoEdge).ChildEdgeId
|
||||
: BRepGraph_EdgeId();
|
||||
}
|
||||
|
||||
BRepGraph_FaceId faceOf(const BRepGraph& theGraph, const BRepGraph_FaceRefId theFaceRef)
|
||||
{
|
||||
if (!theFaceRef.IsValid() || theGraph.Refs().Gen().IsRemoved(theFaceRef))
|
||||
@@ -274,76 +267,30 @@ double BRepGraph_Tool::Edge::Tolerance(const BRepGraph& theGraph, const BRepGrap
|
||||
|
||||
bool BRepGraph_Tool::Edge::Degenerated(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
BRepGraph_CacheDerivedState::EdgeEntry anEntry;
|
||||
return derivedStateCache(theGraph)->GetEdgeStatus(theEdge, anEntry)
|
||||
&& anEntry.Status == BRepGraph_CacheDerivedState::EdgeGeometryStatus::DegenerateOnSurface;
|
||||
return derivedStateCache(theGraph)->IsDegenerated(theEdge);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
double BRepGraph_Tool::Edge::Tolerance(const BRepGraph& theGraph,
|
||||
bool BRepGraph_Tool::CoEdge::SameParameter(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
return derivedStateCache(theGraph)->SameParameter(theCoEdge);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::CoEdge::SameRange(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdge = edgeOf(theGraph, theCoEdge);
|
||||
return anEdge.IsValid() ? Tolerance(theGraph, anEdge) : 0.0;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::Degenerated(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdge = edgeOf(theGraph, theCoEdge);
|
||||
return anEdge.IsValid() && Degenerated(theGraph, anEdge);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::SameParameter(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
BRepGraph_CacheDerivedState::EdgeEntry anEntry;
|
||||
return derivedStateCache(theGraph)->GetEdgeStatus(theEdge, anEntry) && anEntry.SameParameter;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::SameParameter(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdge = edgeOf(theGraph, theCoEdge);
|
||||
return anEdge.IsValid() && SameParameter(theGraph, anEdge);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::SameRange(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
BRepGraph_CacheDerivedState::EdgeEntry anEntry;
|
||||
return derivedStateCache(theGraph)->GetEdgeStatus(theEdge, anEntry) && anEntry.SameRange;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::SameRange(const BRepGraph& theGraph, const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdge = edgeOf(theGraph, theCoEdge);
|
||||
return anEdge.IsValid() && SameRange(theGraph, anEdge);
|
||||
return derivedStateCache(theGraph)->SameRange(theCoEdge);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::IsClosed(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
BRepGraph_CacheDerivedState::EdgeEntry anEntry;
|
||||
return derivedStateCache(theGraph)->GetEdgeStatus(theEdge, anEntry) && anEntry.IsClosed;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::IsClosed(const BRepGraph& theGraph, const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdge = edgeOf(theGraph, theCoEdge);
|
||||
return anEdge.IsValid() && IsClosed(theGraph, anEdge);
|
||||
return derivedStateCache(theGraph)->IsClosed(theEdge);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
@@ -366,15 +313,6 @@ std::pair<double, double> BRepGraph_Tool::Edge::Range(const BRepGraph& the
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
std::pair<double, double> BRepGraph_Tool::Edge::Range(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdge = edgeOf(theGraph, theCoEdge);
|
||||
return anEdge.IsValid() ? Range(theGraph, anEdge) : std::pair<double, double>{0.0, 0.0};
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::HasCurve(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
const occ::handle<Geom_Curve> aCurve = theGraph.Topo().Edges().Curve3D(theEdge);
|
||||
@@ -399,42 +337,6 @@ BRepGraph_VertexRefId BRepGraph_Tool::Edge::EndVertexId(const BRepGraph& t
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
BRepGraph_VertexRefId BRepGraph_Tool::Edge::StartVertexId(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
if (!theCoEdge.IsValid() || theCoEdge.IsRemoved(theGraph))
|
||||
{
|
||||
return BRepGraph_VertexRefId();
|
||||
}
|
||||
const BRepGraphInc::CoEdgeDef& aCoEdge = theGraph.Topo().CoEdges().Definition(theCoEdge);
|
||||
return aCoEdge.Orientation == TopAbs_REVERSED ? EndVertexId(theGraph, aCoEdge.ChildEdgeId)
|
||||
: StartVertexId(theGraph, aCoEdge.ChildEdgeId);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
BRepGraph_VertexRefId BRepGraph_Tool::Edge::EndVertexId(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
if (!theCoEdge.IsValid() || theCoEdge.IsRemoved(theGraph))
|
||||
{
|
||||
return BRepGraph_VertexRefId();
|
||||
}
|
||||
const BRepGraphInc::CoEdgeDef& aCoEdge = theGraph.Topo().CoEdges().Definition(theCoEdge);
|
||||
return aCoEdge.Orientation == TopAbs_REVERSED ? StartVertexId(theGraph, aCoEdge.ChildEdgeId)
|
||||
: EndVertexId(theGraph, aCoEdge.ChildEdgeId);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::HasCurve(const BRepGraph& theGraph, const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdge = edgeOf(theGraph, theCoEdge);
|
||||
return anEdge.IsValid() && HasCurve(theGraph, anEdge);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
GeomAdaptor_TransformedCurve BRepGraph_Tool::Edge::CurveAdaptor(
|
||||
const BRepGraph& theGraph,
|
||||
const BRepGraphInc::CoEdgeInstance& theRef)
|
||||
@@ -531,24 +433,6 @@ const occ::handle<Geom_Curve>& BRepGraph_Tool::Edge::Curve(const BRepGraph&
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
const occ::handle<Geom_Curve>& BRepGraph_Tool::Edge::Curve(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdge = edgeOf(theGraph, theCoEdge);
|
||||
return anEdge.IsValid() ? Curve(theGraph, anEdge) : THE_NULL_CURVE;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
GeomAdaptor_TransformedCurve BRepGraph_Tool::Edge::CurveAdaptor(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdge = edgeOf(theGraph, theCoEdge);
|
||||
return anEdge.IsValid() ? CurveAdaptor(theGraph, anEdge) : GeomAdaptor_TransformedCurve();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
occ::handle<Geom_Curve> BRepGraph_Tool::Edge::Curve(const BRepGraph& theGraph,
|
||||
const BRepGraphInc::CoEdgeInstance& theRef)
|
||||
{
|
||||
@@ -671,15 +555,6 @@ uint32_t BRepGraph_Tool::Edge::NbFaces(const BRepGraph& theGraph, const BRepGrap
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
uint32_t BRepGraph_Tool::Edge::NbFaces(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdge = edgeOf(theGraph, theCoEdge);
|
||||
return anEdge.IsValid() ? NbFaces(theGraph, anEdge) : 0;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::IsManifold(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
return NbFaces(theGraph, theEdge) == 2;
|
||||
@@ -687,14 +562,6 @@ bool BRepGraph_Tool::Edge::IsManifold(const BRepGraph& theGraph, const BRepGraph
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::IsManifold(const BRepGraph& theGraph, const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdge = edgeOf(theGraph, theCoEdge);
|
||||
return anEdge.IsValid() && IsManifold(theGraph, anEdge);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::IsBoundary(const BRepGraph& theGraph, const BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
return NbFaces(theGraph, theEdge) == 1;
|
||||
@@ -702,14 +569,6 @@ bool BRepGraph_Tool::Edge::IsBoundary(const BRepGraph& theGraph, const BRepGraph
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraph_Tool::Edge::IsBoundary(const BRepGraph& theGraph, const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdge = edgeOf(theGraph, theCoEdge);
|
||||
return anEdge.IsValid() && IsBoundary(theGraph, anEdge);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
TopAbs_Orientation BRepGraph_Tool::CoEdge::Orientation(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge)
|
||||
{
|
||||
@@ -905,7 +764,7 @@ std::pair<gp_Pnt2d, gp_Pnt2d> BRepGraph_Tool::CoEdge::UVPoints(const BRepGraph&
|
||||
{
|
||||
return {gp_Pnt2d(), gp_Pnt2d()};
|
||||
}
|
||||
return {aCurve->Value(aPCUse.ParamFirst), aCurve->Value(aPCUse.ParamLast)};
|
||||
return {aCurve->EvalD0(aPCUse.ParamFirst), aCurve->EvalD0(aPCUse.ParamLast)};
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
@@ -1448,9 +1307,7 @@ BRepGraph_Tool::ShellUsage BRepGraph_Tool::Shell::Usage(const BRepGraph&
|
||||
|
||||
bool BRepGraph_Tool::Shell::IsClosed(const BRepGraph& theGraph, const BRepGraph_ShellId theShell)
|
||||
{
|
||||
BRepGraph_CacheDerivedState::ShellEntry anEntry;
|
||||
return derivedStateCache(theGraph)->GetShellStatus(theShell, anEntry)
|
||||
&& anEntry.Status == BRepGraph_CacheDerivedState::ShellClosureStatus::Closed;
|
||||
return derivedStateCache(theGraph)->IsShellClosed(theShell);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
@@ -126,10 +126,6 @@ public:
|
||||
[[nodiscard]] Standard_EXPORT static double Tolerance(const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns the tolerance of the edge referenced by the coedge.
|
||||
[[nodiscard]] Standard_EXPORT static double Tolerance(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns true if the edge is degenerate, derived from current geometry.
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theEdge typed edge definition identifier
|
||||
@@ -137,34 +133,6 @@ public:
|
||||
[[nodiscard]] Standard_EXPORT static bool Degenerated(const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns true if the edge referenced by the coedge is degenerate.
|
||||
[[nodiscard]] Standard_EXPORT static bool Degenerated(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns true if all PCurves are reparametrized to the same range as the 3D curve.
|
||||
//! This is a derived geometry check, not a stored flag.
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theEdge typed edge definition identifier
|
||||
//! @return true if same parameter
|
||||
[[nodiscard]] Standard_EXPORT static bool SameParameter(const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns SameParameter for the edge referenced by the coedge.
|
||||
[[nodiscard]] Standard_EXPORT static bool SameParameter(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns true if PCurve parameter range equals the 3D curve range.
|
||||
//! This is a derived check, not a stored flag.
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theEdge typed edge definition identifier
|
||||
//! @return true if same range
|
||||
[[nodiscard]] Standard_EXPORT static bool SameRange(const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns SameRange for the edge referenced by the coedge.
|
||||
[[nodiscard]] Standard_EXPORT static bool SameRange(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! 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
|
||||
@@ -172,10 +140,6 @@ public:
|
||||
[[nodiscard]] Standard_EXPORT static bool IsClosed(const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns the closed flag for the edge referenced by the coedge.
|
||||
[[nodiscard]] Standard_EXPORT static bool IsClosed(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns the 3D curve parameter range as (first, last).
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theEdge typed edge definition identifier
|
||||
@@ -184,11 +148,6 @@ public:
|
||||
const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns the 3D curve parameter range for the edge referenced by the coedge.
|
||||
[[nodiscard]] Standard_EXPORT static std::pair<double, double> Range(
|
||||
const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns the start vertex reference id directly.
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theEdge typed edge definition identifier
|
||||
@@ -197,11 +156,6 @@ public:
|
||||
const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns the coedge start vertex reference id, respecting coedge orientation.
|
||||
[[nodiscard]] Standard_EXPORT static BRepGraph_VertexRefId StartVertexId(
|
||||
const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns the end vertex reference id directly.
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theEdge typed edge definition identifier
|
||||
@@ -210,11 +164,6 @@ public:
|
||||
const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns the coedge end vertex reference id, respecting coedge orientation.
|
||||
[[nodiscard]] Standard_EXPORT static BRepGraph_VertexRefId EndVertexId(
|
||||
const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns true if the edge has a 3D curve representation.
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theEdge typed edge definition identifier
|
||||
@@ -222,10 +171,6 @@ public:
|
||||
[[nodiscard]] Standard_EXPORT static bool HasCurve(const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns true if the edge referenced by the coedge has a 3D curve.
|
||||
[[nodiscard]] Standard_EXPORT static bool HasCurve(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns the raw 3D curve handle (definition frame, no copy).
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theEdge typed edge definition identifier
|
||||
@@ -234,11 +179,6 @@ public:
|
||||
const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns the raw 3D curve handle for the edge referenced by the coedge.
|
||||
[[nodiscard]] Standard_EXPORT static const occ::handle<Geom_Curve>& Curve(
|
||||
const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns the transformed 3D curve handle via CoEdgeUsage (applies Location, may copy).
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theRef coedge incidence reference carrying Location
|
||||
@@ -254,11 +194,6 @@ public:
|
||||
const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns the 3D curve adaptor for the edge referenced by the coedge.
|
||||
[[nodiscard]] Standard_EXPORT static GeomAdaptor_TransformedCurve CurveAdaptor(
|
||||
const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns the 3D curve adaptor via CoEdgeUsage (applies edge-in-wire Location in Trsf).
|
||||
//! Falls back to CurveOnSurface when no 3D curve exists.
|
||||
//! @param[in] theGraph source graph
|
||||
@@ -333,10 +268,6 @@ public:
|
||||
[[nodiscard]] Standard_EXPORT static uint32_t NbFaces(const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns the number of faces referencing the edge referenced by the coedge.
|
||||
[[nodiscard]] Standard_EXPORT static uint32_t NbFaces(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns true if the edge is shared by exactly two faces (manifold).
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theEdge typed edge definition identifier
|
||||
@@ -344,10 +275,6 @@ public:
|
||||
[[nodiscard]] Standard_EXPORT static bool IsManifold(const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns true if the edge referenced by the coedge is manifold.
|
||||
[[nodiscard]] Standard_EXPORT static bool IsManifold(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns true if the edge belongs to exactly one face (boundary / free edge).
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theEdge typed edge definition identifier
|
||||
@@ -355,10 +282,6 @@ public:
|
||||
[[nodiscard]] Standard_EXPORT static bool IsBoundary(const BRepGraph& theGraph,
|
||||
const BRepGraph_EdgeId theEdge);
|
||||
|
||||
//! Returns true if the edge referenced by the coedge is boundary.
|
||||
[[nodiscard]] Standard_EXPORT static bool IsBoundary(const BRepGraph& theGraph,
|
||||
const BRepGraph_CoEdgeId theCoEdge);
|
||||
|
||||
//! Returns true if the edge is a seam on the given face.
|
||||
//! @param[in] theGraph source graph
|
||||
//! @param[in] theEdge typed edge definition identifier
|
||||
@@ -434,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
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <BRepGraphInc_Storage.hxx>
|
||||
#include <Adaptor3d_CurveOnSurface.hxx>
|
||||
#include <Geom2d_Curve.hxx>
|
||||
#include <NCollection_LocalArray.hxx>
|
||||
#include <Geom2dAdaptor_Curve.hxx>
|
||||
#include <Geom_Curve.hxx>
|
||||
#include <Geom_Surface.hxx>
|
||||
@@ -148,12 +149,63 @@ const BRepGraphInc::EdgeRelations& BRepGraph::TopoView::EdgeOps::Relations(
|
||||
|
||||
uint32_t BRepGraph::TopoView::EdgeOps::NbFaces(const BRepGraph_EdgeId theEdge) const
|
||||
{
|
||||
uint32_t aCount = 0;
|
||||
for (BRepGraph_FacesOfEdge aFaceIt(*myGraph, theEdge); aFaceIt.More(); aFaceIt.Next())
|
||||
const BRepGraphInc_Storage& aStorage = myGraph->myData->myIncStorage;
|
||||
if (!theEdge.IsValid(aStorage.NbEdges()) || aStorage.IsRemoved(theEdge)
|
||||
|| aStorage.NbActiveFaces() == 0)
|
||||
{
|
||||
++aCount;
|
||||
return 0;
|
||||
}
|
||||
return aCount;
|
||||
|
||||
const NCollection_LinearVector<BRepGraph_CoEdgeId>& aCoEdges =
|
||||
aStorage.EdgeRelations(theEdge).CoEdgeIds;
|
||||
const size_t aNbCoEdges = aCoEdges.Size();
|
||||
if (aNbCoEdges == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Inline buffer covers edges with up to 32 coedges without heap allocation.
|
||||
// Seam edges (2 coedges, 1 face) and typical manifold edges (2 coedges, 2 faces)
|
||||
// are the overwhelmingly common cases.
|
||||
NCollection_LocalArray<BRepGraph_FaceId, 32> aSeenBuf(32);
|
||||
uint32_t aNbSeen = 0;
|
||||
|
||||
for (size_t aIdx = 0; aIdx < aNbCoEdges; ++aIdx)
|
||||
{
|
||||
const BRepGraph_CoEdgeId aCoEdgeId = aCoEdges.Value(aIdx);
|
||||
if (!aCoEdgeId.IsValid(aStorage.NbCoEdges()) || aStorage.IsRemoved(aCoEdgeId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const BRepGraph_FaceId aFace = aStorage.CoEdge(aCoEdgeId).FaceId;
|
||||
if (!aFace.IsValid(aStorage.NbFaces()) || aStorage.IsRemoved(aFace))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Linear scan over the small seen set (typically 1-2 entries).
|
||||
bool aFound = false;
|
||||
for (uint32_t aJ = 0; aJ < aNbSeen; ++aJ)
|
||||
{
|
||||
if (aSeenBuf[aJ] == aFace)
|
||||
{
|
||||
aFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aFound)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (aNbSeen >= aSeenBuf.Size())
|
||||
{
|
||||
aSeenBuf.Reallocate(static_cast<size_t>(aSeenBuf.Size() * 1.5));
|
||||
}
|
||||
aSeenBuf[aNbSeen++] = aFace;
|
||||
}
|
||||
|
||||
return aNbSeen;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
@@ -172,10 +172,10 @@ inline bool BuildSurfaceBoundary(SurfaceBoundary& theBoundary,
|
||||
const bool isUClosed = isFullPeriod(theSurface, true, theUMin, theUMax, aPeriodTol);
|
||||
const bool isVClosed = isFullPeriod(theSurface, false, theVMin, theVMax, aPeriodTol);
|
||||
|
||||
size_t aV00 = addSurfaceVertex(theBoundary, theSurface->Value(theUMin, theVMin), aTol);
|
||||
size_t aV10 = addSurfaceVertex(theBoundary, theSurface->Value(theUMax, theVMin), aTol);
|
||||
size_t aV11 = addSurfaceVertex(theBoundary, theSurface->Value(theUMax, theVMax), aTol);
|
||||
size_t aV01 = addSurfaceVertex(theBoundary, theSurface->Value(theUMin, theVMax), aTol);
|
||||
size_t aV00 = addSurfaceVertex(theBoundary, theSurface->EvalD0(theUMin, theVMin), aTol);
|
||||
size_t aV10 = addSurfaceVertex(theBoundary, theSurface->EvalD0(theUMax, theVMin), aTol);
|
||||
size_t aV11 = addSurfaceVertex(theBoundary, theSurface->EvalD0(theUMax, theVMax), aTol);
|
||||
size_t aV01 = addSurfaceVertex(theBoundary, theSurface->EvalD0(theUMin, theVMax), aTol);
|
||||
|
||||
if (isUClosed)
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <BRepGraph.hxx>
|
||||
#include <BRepGraphInc_Storage.hxx>
|
||||
#include <BRepGraph_CacheDerivedState.hxx>
|
||||
#include <BRepGraph_CacheRegistry.hxx>
|
||||
#include <BRepGraph_LayerRegistry.hxx>
|
||||
#include <BRepGraph_LayerTopoSupplement.hxx>
|
||||
#include <BRepGraph_TopoView.hxx>
|
||||
@@ -128,8 +129,7 @@ void BRepGraphInc_Reconstruct::Cache::Bind(const BRepGraph_NodeId theNode,
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
TopoDS_Shape BRepGraphInc_Reconstruct::Node(const BRepGraph& theGraph,
|
||||
const BRepGraph_NodeId theNode)
|
||||
TopoDS_Shape BRepGraphInc_Reconstruct::Node(BRepGraph& theGraph, const BRepGraph_NodeId theNode)
|
||||
{
|
||||
Cache aCache;
|
||||
return Node(theGraph, theNode, aCache);
|
||||
@@ -137,7 +137,7 @@ TopoDS_Shape BRepGraphInc_Reconstruct::Node(const BRepGraph& theGraph,
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
TopoDS_Shape BRepGraphInc_Reconstruct::Node(const BRepGraph& theGraph,
|
||||
TopoDS_Shape BRepGraphInc_Reconstruct::Node(BRepGraph& theGraph,
|
||||
const BRepGraph_NodeId theNode,
|
||||
Cache& theCache)
|
||||
{
|
||||
@@ -176,14 +176,15 @@ TopoDS_Shape BRepGraphInc_Reconstruct::Node(const BRepGraph& theGraph,
|
||||
const BRepGraphInc::EdgeDef& anEdge = aStorage.Edge(BRepGraph_EdgeId(theNode));
|
||||
TopoDS_Edge aNewEdge;
|
||||
|
||||
BRepGraph_CacheDerivedState::EdgeEntry anEdgeEntry;
|
||||
[[maybe_unused]] const bool isEdgeStateComputed =
|
||||
BRepGraph_CacheDerivedState::ComputeEdgeStatus(theGraph,
|
||||
BRepGraph_EdgeId(theNode),
|
||||
anEdgeEntry);
|
||||
bool anIsDegenerated = false;
|
||||
bool anIsClosed = false;
|
||||
[[maybe_unused]] const bool isEdgeStateComputed =
|
||||
BRepGraph_CacheDerivedState::ComputeEdgeProperties(theGraph,
|
||||
BRepGraph_EdgeId(theNode),
|
||||
anIsDegenerated,
|
||||
anIsClosed);
|
||||
|
||||
if (anEdgeEntry.Status
|
||||
== BRepGraph_CacheDerivedState::EdgeGeometryStatus::DegenerateOnSurface)
|
||||
if (anIsDegenerated)
|
||||
{
|
||||
aBB.MakeEdge(aNewEdge);
|
||||
aBB.Degenerated(aNewEdge, true);
|
||||
@@ -219,8 +220,30 @@ TopoDS_Shape BRepGraphInc_Reconstruct::Node(const BRepGraph& theGraph,
|
||||
aParamLast = aUse.ParamLast;
|
||||
}
|
||||
aBB.Range(aNewEdge, aParamFirst, aParamLast);
|
||||
aBB.SameParameter(aNewEdge, anEdgeEntry.SameParameter);
|
||||
aBB.SameRange(aNewEdge, anEdgeEntry.SameRange);
|
||||
|
||||
// SameRange/SameParameter are per-CoEdge properties.
|
||||
// Set edge-level flags: true only if ALL coedges agree.
|
||||
auto aCache = theGraph.CacheRegistry().Ensure<BRepGraph_CacheDerivedState>();
|
||||
bool aSameRange = true;
|
||||
bool aSameParameter = true;
|
||||
const BRepGraphInc::EdgeRelations& anEdgeRel =
|
||||
aStorage.EdgeRelations(BRepGraph_EdgeId(theNode));
|
||||
for (const BRepGraph_CoEdgeId& aCoEdgeId : anEdgeRel.CoEdgeIds)
|
||||
{
|
||||
if (aCoEdgeId.IsValid(aStorage.NbCoEdges()) && !aStorage.IsRemoved(aCoEdgeId))
|
||||
{
|
||||
if (!aCache->SameRange(aCoEdgeId))
|
||||
{
|
||||
aSameRange = false;
|
||||
}
|
||||
if (!aCache->SameParameter(aCoEdgeId))
|
||||
{
|
||||
aSameParameter = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
aBB.SameParameter(aNewEdge, aSameParameter);
|
||||
aBB.SameRange(aNewEdge, aSameRange);
|
||||
|
||||
if (anEdge.StartVertexRefId.IsValid())
|
||||
{
|
||||
@@ -254,7 +277,7 @@ TopoDS_Shape BRepGraphInc_Reconstruct::Node(const BRepGraph& theGraph,
|
||||
aBB.UpdateEdge(aNewEdge, aPolygon3D, TopLoc_Location());
|
||||
}
|
||||
}
|
||||
if (anEdgeEntry.IsClosed)
|
||||
if (anIsClosed)
|
||||
{
|
||||
aNewEdge.Closed(true);
|
||||
}
|
||||
@@ -326,11 +349,7 @@ TopoDS_Shape BRepGraphInc_Reconstruct::Node(const BRepGraph& theGraph,
|
||||
aBB.Add(aNewShell, aFace);
|
||||
}
|
||||
}
|
||||
BRepGraph_CacheDerivedState::ShellEntry aShellEntry;
|
||||
if (BRepGraph_CacheDerivedState::ComputeShellStatus(theGraph,
|
||||
BRepGraph_ShellId(theNode),
|
||||
aShellEntry)
|
||||
&& aShellEntry.Status == BRepGraph_CacheDerivedState::ShellClosureStatus::Closed)
|
||||
if (BRepGraph_CacheDerivedState::ComputeShellIsClosed(theGraph, BRepGraph_ShellId(theNode)))
|
||||
{
|
||||
aNewShell.Closed(true);
|
||||
}
|
||||
@@ -441,7 +460,7 @@ TopoDS_Shape BRepGraphInc_Reconstruct::Node(const BRepGraph& theGraph,
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
TopoDS_Shape BRepGraphInc_Reconstruct::FaceWithCache(const BRepGraph& theGraph,
|
||||
TopoDS_Shape BRepGraphInc_Reconstruct::FaceWithCache(BRepGraph& theGraph,
|
||||
const BRepGraph_FaceId theFaceId,
|
||||
Cache& theCache)
|
||||
{
|
||||
@@ -516,11 +535,15 @@ TopoDS_Shape BRepGraphInc_Reconstruct::FaceWithCache(const BRepGraph& theG
|
||||
const BRepGraphInc::EdgeDef& anEdge = aStorage.Edge(theEdgeId);
|
||||
TopoDS_Edge aNewEdge;
|
||||
|
||||
BRepGraph_CacheDerivedState::EdgeEntry anEdgeEntry;
|
||||
[[maybe_unused]] const bool isEdgeStateComputed =
|
||||
BRepGraph_CacheDerivedState::ComputeEdgeStatus(theGraph, theEdgeId, anEdgeEntry);
|
||||
bool anIsDegenerated = false;
|
||||
bool anIsClosed = false;
|
||||
[[maybe_unused]] const bool isEdgeStateComputed =
|
||||
BRepGraph_CacheDerivedState::ComputeEdgeProperties(theGraph,
|
||||
theEdgeId,
|
||||
anIsDegenerated,
|
||||
anIsClosed);
|
||||
|
||||
if (anEdgeEntry.Status == BRepGraph_CacheDerivedState::EdgeGeometryStatus::DegenerateOnSurface)
|
||||
if (anIsDegenerated)
|
||||
{
|
||||
aBB.MakeEdge(aNewEdge);
|
||||
aBB.Degenerated(aNewEdge, true);
|
||||
@@ -544,8 +567,31 @@ TopoDS_Shape BRepGraphInc_Reconstruct::FaceWithCache(const BRepGraph& theG
|
||||
{
|
||||
aBB.MakeEdge(aNewEdge);
|
||||
}
|
||||
aBB.SameParameter(aNewEdge, anEdgeEntry.SameParameter);
|
||||
aBB.SameRange(aNewEdge, anEdgeEntry.SameRange);
|
||||
|
||||
// SameRange/SameParameter are per-CoEdge properties.
|
||||
// Set edge-level flags: true only if ALL coedges agree.
|
||||
{
|
||||
auto aCache = theGraph.CacheRegistry().Ensure<BRepGraph_CacheDerivedState>();
|
||||
bool aSameRange = true;
|
||||
bool aSameParameter = true;
|
||||
const BRepGraphInc::EdgeRelations& anEdgeRel = aStorage.EdgeRelations(theEdgeId);
|
||||
for (const BRepGraph_CoEdgeId& aCoEdgeId : anEdgeRel.CoEdgeIds)
|
||||
{
|
||||
if (aCoEdgeId.IsValid(aStorage.NbCoEdges()) && !aStorage.IsRemoved(aCoEdgeId))
|
||||
{
|
||||
if (!aCache->SameRange(aCoEdgeId))
|
||||
{
|
||||
aSameRange = false;
|
||||
}
|
||||
if (!aCache->SameParameter(aCoEdgeId))
|
||||
{
|
||||
aSameParameter = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
aBB.SameParameter(aNewEdge, aSameParameter);
|
||||
aBB.SameRange(aNewEdge, aSameRange);
|
||||
}
|
||||
|
||||
// Vertices (also cached).
|
||||
const auto aGetOrBuildVertex = [&](const BRepGraph_VertexId theVtxId) -> TopoDS_Shape {
|
||||
@@ -600,7 +646,7 @@ TopoDS_Shape BRepGraphInc_Reconstruct::FaceWithCache(const BRepGraph& theG
|
||||
}
|
||||
}
|
||||
|
||||
if (anEdgeEntry.IsClosed)
|
||||
if (anIsClosed)
|
||||
{
|
||||
aNewEdge.Closed(true);
|
||||
}
|
||||
@@ -740,8 +786,8 @@ TopoDS_Shape BRepGraphInc_Reconstruct::FaceWithCache(const BRepGraph& theG
|
||||
|
||||
if (!aPC1.IsNull() && !aPC2.IsNull())
|
||||
{
|
||||
gp_Pnt2d aUV1 = aPC1->Value(aPCFirst);
|
||||
gp_Pnt2d aUV2 = aPC1->Value(aPCLast);
|
||||
gp_Pnt2d aUV1 = aPC1->EvalD0(aPCFirst);
|
||||
gp_Pnt2d aUV2 = aPC1->EvalD0(aPCLast);
|
||||
aBB.UpdateEdge(anEdge,
|
||||
aPC1,
|
||||
aPC2,
|
||||
@@ -754,8 +800,8 @@ TopoDS_Shape BRepGraphInc_Reconstruct::FaceWithCache(const BRepGraph& theG
|
||||
}
|
||||
else if (!aPC1.IsNull())
|
||||
{
|
||||
gp_Pnt2d aUV1 = aPC1->Value(aPCFirst);
|
||||
gp_Pnt2d aUV2 = aPC1->Value(aPCLast);
|
||||
gp_Pnt2d aUV1 = aPC1->EvalD0(aPCFirst);
|
||||
gp_Pnt2d aUV2 = aPC1->EvalD0(aPCLast);
|
||||
aBB.UpdateEdge(anEdge,
|
||||
aPC1,
|
||||
aFaceSurface,
|
||||
|
||||
@@ -77,8 +77,7 @@ public:
|
||||
//! @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 BRepGraph& theGraph,
|
||||
const BRepGraph_NodeId theNode);
|
||||
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.
|
||||
@@ -86,7 +85,7 @@ public:
|
||||
//! @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 BRepGraph& theGraph,
|
||||
static Standard_EXPORT TopoDS_Shape Node(BRepGraph& theGraph,
|
||||
const BRepGraph_NodeId theNode,
|
||||
Cache& theCache);
|
||||
|
||||
@@ -95,7 +94,7 @@ public:
|
||||
//! @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 BRepGraph& theGraph,
|
||||
static Standard_EXPORT TopoDS_Shape FaceWithCache(BRepGraph& theGraph,
|
||||
const BRepGraph_FaceId theFaceId,
|
||||
Cache& theCache);
|
||||
|
||||
|
||||
@@ -93,6 +93,14 @@ void appendUniqueRelationId(NCollection_LinearVector<IdT>& theIds, const IdT the
|
||||
}
|
||||
}
|
||||
|
||||
// Unchecked append for rebuild paths where duplicates are structurally impossible
|
||||
// (each source ref is processed exactly once after vectors are cleared).
|
||||
template <typename IdT>
|
||||
void appendRelationIdDirect(NCollection_LinearVector<IdT>& theIds, const IdT theId)
|
||||
{
|
||||
theIds.Append(theId);
|
||||
}
|
||||
|
||||
template <typename IdT>
|
||||
bool eraseRelationId(NCollection_LinearVector<IdT>& theIds, const IdT theId)
|
||||
{
|
||||
@@ -995,11 +1003,7 @@ void BRepGraphInc_Storage::SetHasOccurrenceParent(const BRepGraph_NodeId theNode
|
||||
NCollection_LinearVector<BRepGraph_ChildRefId>& BRepGraphInc_Storage::
|
||||
ChangeCompoundRefsOfNodeInternal(const BRepGraph_NodeId theNode)
|
||||
{
|
||||
if (!myNodeToCompounds.IsBound(theNode))
|
||||
{
|
||||
myNodeToCompounds.Bind(theNode, NCollection_LinearVector<BRepGraph_ChildRefId>());
|
||||
}
|
||||
return *myNodeToCompounds.ChangeSeek(theNode);
|
||||
return myNodeToCompounds.TryBound(theNode, NCollection_LinearVector<BRepGraph_ChildRefId>());
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
@@ -1007,11 +1011,8 @@ NCollection_LinearVector<BRepGraph_ChildRefId>& BRepGraphInc_Storage::
|
||||
NCollection_LinearVector<BRepGraph_OccurrenceRefId>& BRepGraphInc_Storage::
|
||||
ChangeOccurrenceRefsOfNodeInternal(const BRepGraph_NodeId theNode)
|
||||
{
|
||||
if (!myNodeToOccurrences.IsBound(theNode))
|
||||
{
|
||||
myNodeToOccurrences.Bind(theNode, NCollection_LinearVector<BRepGraph_OccurrenceRefId>());
|
||||
}
|
||||
return *myNodeToOccurrences.ChangeSeek(theNode);
|
||||
return myNodeToOccurrences.TryBound(theNode,
|
||||
NCollection_LinearVector<BRepGraph_OccurrenceRefId>());
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
@@ -1030,6 +1031,31 @@ void BRepGraphInc_Storage::RebuildDerivedRelationsPreservingActiveCounts()
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraphInc_Storage::CopyRemovedFlagsFrom(const BRepGraphInc_Storage& theSource)
|
||||
{
|
||||
myVertices.RemovedFlags = theSource.myVertices.RemovedFlags;
|
||||
myEdges.RemovedFlags = theSource.myEdges.RemovedFlags;
|
||||
myCoEdges.RemovedFlags = theSource.myCoEdges.RemovedFlags;
|
||||
myWires.RemovedFlags = theSource.myWires.RemovedFlags;
|
||||
myFaces.RemovedFlags = theSource.myFaces.RemovedFlags;
|
||||
myShells.RemovedFlags = theSource.myShells.RemovedFlags;
|
||||
mySolids.RemovedFlags = theSource.mySolids.RemovedFlags;
|
||||
myCompounds.RemovedFlags = theSource.myCompounds.RemovedFlags;
|
||||
myCompSolids.RemovedFlags = theSource.myCompSolids.RemovedFlags;
|
||||
myProducts.RemovedFlags = theSource.myProducts.RemovedFlags;
|
||||
myOccurrences.RemovedFlags = theSource.myOccurrences.RemovedFlags;
|
||||
|
||||
myShellRefs.RemovedFlags = theSource.myShellRefs.RemovedFlags;
|
||||
myFaceRefs.RemovedFlags = theSource.myFaceRefs.RemovedFlags;
|
||||
myWireRefs.RemovedFlags = theSource.myWireRefs.RemovedFlags;
|
||||
myVertexRefs.RemovedFlags = theSource.myVertexRefs.RemovedFlags;
|
||||
mySolidRefs.RemovedFlags = theSource.mySolidRefs.RemovedFlags;
|
||||
myChildRefs.RemovedFlags = theSource.myChildRefs.RemovedFlags;
|
||||
myOccurrenceRefs.RemovedFlags = theSource.myOccurrenceRefs.RemovedFlags;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraphInc_Storage::rebuildDerivedRelationsInternal(const bool theRecountActiveCounts)
|
||||
{
|
||||
prepareRelationTable(myVertexRelations, NbVertices());
|
||||
@@ -1176,7 +1202,7 @@ void BRepGraphInc_Storage::rebuildDerivedRelationsInternal(const bool theRecount
|
||||
const BRepGraph_VertexId aVertexId = VertexRef(aStartRefId).ChildVertexId;
|
||||
if (aVertexId.IsValid(NbVertices()) && !IsRemoved(aVertexId))
|
||||
{
|
||||
appendUniqueRelationId(ChangeVertexRelationsInternal(aVertexId).EdgeIds, anEdgeId);
|
||||
appendRelationIdDirect(ChangeVertexRelationsInternal(aVertexId).EdgeIds, anEdgeId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1186,7 +1212,7 @@ void BRepGraphInc_Storage::rebuildDerivedRelationsInternal(const bool theRecount
|
||||
const BRepGraph_VertexId aVertexId = VertexRef(anEndRefId).ChildVertexId;
|
||||
if (aVertexId.IsValid(NbVertices()) && !IsRemoved(aVertexId))
|
||||
{
|
||||
appendUniqueRelationId(ChangeVertexRelationsInternal(aVertexId).EdgeIds, anEdgeId);
|
||||
appendRelationIdDirect(ChangeVertexRelationsInternal(aVertexId).EdgeIds, anEdgeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1201,7 +1227,7 @@ void BRepGraphInc_Storage::rebuildDerivedRelationsInternal(const bool theRecount
|
||||
if (aCoEdge.ChildEdgeId.IsValid(NbEdges()) && !IsRemoved(aCoEdge.ChildEdgeId))
|
||||
{
|
||||
BRepGraphInc::EdgeRelations& anEdgeRel = ChangeEdgeRelationsInternal(aCoEdge.ChildEdgeId);
|
||||
appendUniqueRelationId(anEdgeRel.CoEdgeIds, aCoEdgeId);
|
||||
appendRelationIdDirect(anEdgeRel.CoEdgeIds, aCoEdgeId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1223,7 +1249,7 @@ void BRepGraphInc_Storage::rebuildDerivedRelationsInternal(const bool theRecount
|
||||
{
|
||||
continue;
|
||||
}
|
||||
appendUniqueRelationId(ChangeWireRelationsInternal(aWireId).ParentWireRefIds, aWireRefId);
|
||||
appendRelationIdDirect(ChangeWireRelationsInternal(aWireId).ParentWireRefIds, aWireRefId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1245,7 +1271,7 @@ void BRepGraphInc_Storage::rebuildDerivedRelationsInternal(const bool theRecount
|
||||
{
|
||||
continue;
|
||||
}
|
||||
appendUniqueRelationId(ChangeFaceRelationsInternal(aFaceId).ParentFaceRefIds, aFaceRefId);
|
||||
appendRelationIdDirect(ChangeFaceRelationsInternal(aFaceId).ParentFaceRefIds, aFaceRefId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1267,7 +1293,7 @@ void BRepGraphInc_Storage::rebuildDerivedRelationsInternal(const bool theRecount
|
||||
{
|
||||
continue;
|
||||
}
|
||||
appendUniqueRelationId(ChangeShellRelationsInternal(aShellId).ParentShellRefIds, aShellRefId);
|
||||
appendRelationIdDirect(ChangeShellRelationsInternal(aShellId).ParentShellRefIds, aShellRefId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1287,7 +1313,7 @@ void BRepGraphInc_Storage::rebuildDerivedRelationsInternal(const bool theRecount
|
||||
const BRepGraph_NodeId aChildNode = ChildRef(aChildRefId).ChildNodeId;
|
||||
if (aChildNode.IsValid() && !isNodeRemoved(*this, aChildNode))
|
||||
{
|
||||
appendUniqueRelationId(ChangeCompoundRefsOfNodeInternal(aChildNode), aChildRefId);
|
||||
appendRelationIdDirect(ChangeCompoundRefsOfNodeInternal(aChildNode), aChildRefId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1310,7 +1336,7 @@ void BRepGraphInc_Storage::rebuildDerivedRelationsInternal(const bool theRecount
|
||||
{
|
||||
continue;
|
||||
}
|
||||
appendUniqueRelationId(ChangeSolidRelationsInternal(aSolidId).ParentSolidRefIds, aSolidRefId);
|
||||
appendRelationIdDirect(ChangeSolidRelationsInternal(aSolidId).ParentSolidRefIds, aSolidRefId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1333,13 +1359,13 @@ void BRepGraphInc_Storage::rebuildDerivedRelationsInternal(const bool theRecount
|
||||
{
|
||||
continue;
|
||||
}
|
||||
appendUniqueRelationId(
|
||||
appendRelationIdDirect(
|
||||
ChangeOccurrenceRelationsInternal(anOccurrenceId).ParentOccurrenceRefIds,
|
||||
anOccurrenceRefId);
|
||||
const BRepGraph_NodeId aChildNode = Occurrence(anOccurrenceId).ChildNodeId;
|
||||
if (aChildNode.IsValid() && !isNodeRemoved(*this, aChildNode))
|
||||
{
|
||||
appendUniqueRelationId(ChangeOccurrenceRefsOfNodeInternal(aChildNode), anOccurrenceRefId);
|
||||
appendRelationIdDirect(ChangeOccurrenceRefsOfNodeInternal(aChildNode), anOccurrenceRefId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1376,6 +1402,137 @@ void BRepGraphInc_Storage::rebuildDerivedRelationsInternal(const bool theRecount
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraphInc_Storage::CopyDerivedRelationsFrom(const BRepGraphInc_Storage& theSource)
|
||||
{
|
||||
prepareRelationTable(myVertexRelations, NbVertices());
|
||||
prepareRelationTable(myEdgeRelations, NbEdges());
|
||||
prepareRelationTable(myWireRelations, NbWires());
|
||||
prepareRelationTable(myFaceRelations, NbFaces());
|
||||
prepareRelationTable(myShellRelations, NbShells());
|
||||
prepareRelationTable(mySolidRelations, NbSolids());
|
||||
prepareRelationTable(myCompoundRelations, NbCompounds());
|
||||
prepareRelationTable(myCompSolidRelations, NbCompSolids());
|
||||
prepareRelationTable(myProductRelations, NbProducts());
|
||||
prepareRelationTable(myOccurrenceRelations, NbOccurrences());
|
||||
|
||||
for (BRepGraph_VertexId aV(0); aV.IsValid(NbVertices()); ++aV)
|
||||
{
|
||||
if (aV.IsValid(theSource.NbVertices()))
|
||||
ChangeVertexRelationsInternal(aV).EdgeIds = theSource.VertexRelations(aV).EdgeIds;
|
||||
}
|
||||
for (BRepGraph_EdgeId anE(0); anE.IsValid(NbEdges()); ++anE)
|
||||
{
|
||||
if (anE.IsValid(theSource.NbEdges()))
|
||||
ChangeEdgeRelationsInternal(anE).CoEdgeIds = theSource.EdgeRelations(anE).CoEdgeIds;
|
||||
}
|
||||
for (BRepGraph_WireId aW(0); aW.IsValid(NbWires()); ++aW)
|
||||
{
|
||||
if (aW.IsValid(theSource.NbWires()))
|
||||
{
|
||||
ChangeWireRelationsInternal(aW).CoEdgeIds = theSource.WireRelations(aW).CoEdgeIds;
|
||||
ChangeWireRelationsInternal(aW).ParentWireRefIds =
|
||||
theSource.WireRelations(aW).ParentWireRefIds;
|
||||
}
|
||||
}
|
||||
for (BRepGraph_FaceId aF(0); aF.IsValid(NbFaces()); ++aF)
|
||||
{
|
||||
if (aF.IsValid(theSource.NbFaces()))
|
||||
{
|
||||
ChangeFaceRelationsInternal(aF).WireRefIds = theSource.FaceRelations(aF).WireRefIds;
|
||||
ChangeFaceRelationsInternal(aF).ParentFaceRefIds =
|
||||
theSource.FaceRelations(aF).ParentFaceRefIds;
|
||||
}
|
||||
}
|
||||
for (BRepGraph_ShellId aS(0); aS.IsValid(NbShells()); ++aS)
|
||||
{
|
||||
if (aS.IsValid(theSource.NbShells()))
|
||||
{
|
||||
ChangeShellRelationsInternal(aS).FaceRefIds = theSource.ShellRelations(aS).FaceRefIds;
|
||||
ChangeShellRelationsInternal(aS).ParentShellRefIds =
|
||||
theSource.ShellRelations(aS).ParentShellRefIds;
|
||||
}
|
||||
}
|
||||
for (BRepGraph_SolidId aS(0); aS.IsValid(NbSolids()); ++aS)
|
||||
{
|
||||
if (aS.IsValid(theSource.NbSolids()))
|
||||
{
|
||||
ChangeSolidRelationsInternal(aS).ShellRefIds = theSource.SolidRelations(aS).ShellRefIds;
|
||||
ChangeSolidRelationsInternal(aS).ParentSolidRefIds =
|
||||
theSource.SolidRelations(aS).ParentSolidRefIds;
|
||||
}
|
||||
}
|
||||
for (BRepGraph_CompSolidId aCS(0); aCS.IsValid(NbCompSolids()); ++aCS)
|
||||
{
|
||||
if (aCS.IsValid(theSource.NbCompSolids()))
|
||||
ChangeCompSolidRelationsInternal(aCS).SolidRefIds =
|
||||
theSource.CompSolidRelations(aCS).SolidRefIds;
|
||||
}
|
||||
for (BRepGraph_CompoundId aC(0); aC.IsValid(NbCompounds()); ++aC)
|
||||
{
|
||||
if (aC.IsValid(theSource.NbCompounds()))
|
||||
ChangeCompoundRelationsInternal(aC).ChildRefIds = theSource.CompoundRelations(aC).ChildRefIds;
|
||||
}
|
||||
for (BRepGraph_ProductId aP(0); aP.IsValid(NbProducts()); ++aP)
|
||||
{
|
||||
if (aP.IsValid(theSource.NbProducts()))
|
||||
ChangeProductRelationsInternal(aP).OccurrenceRefIds =
|
||||
theSource.ProductRelations(aP).OccurrenceRefIds;
|
||||
}
|
||||
for (BRepGraph_OccurrenceId anO(0); anO.IsValid(NbOccurrences()); ++anO)
|
||||
{
|
||||
if (anO.IsValid(theSource.NbOccurrences()))
|
||||
ChangeOccurrenceRelationsInternal(anO).ParentOccurrenceRefIds =
|
||||
theSource.OccurrenceRelations(anO).ParentOccurrenceRefIds;
|
||||
}
|
||||
|
||||
// Copy sparse reverse maps (node -> compound/occurrence child refs).
|
||||
myNodeToCompounds.Clear();
|
||||
for (NCollection_DataMap<BRepGraph_NodeId,
|
||||
NCollection_LinearVector<BRepGraph_ChildRefId>>::Iterator
|
||||
anIt(theSource.myNodeToCompounds);
|
||||
anIt.More();
|
||||
anIt.Next())
|
||||
{
|
||||
myNodeToCompounds.Bind(anIt.Key(), anIt.Value());
|
||||
}
|
||||
myNodeToOccurrences.Clear();
|
||||
for (NCollection_DataMap<BRepGraph_NodeId,
|
||||
NCollection_LinearVector<BRepGraph_OccurrenceRefId>>::Iterator
|
||||
anIt(theSource.myNodeToOccurrences);
|
||||
anIt.More();
|
||||
anIt.Next())
|
||||
{
|
||||
myNodeToOccurrences.Bind(anIt.Key(), anIt.Value());
|
||||
}
|
||||
|
||||
// Copy compound/occurrence parent bit-planes for all node kinds.
|
||||
// These are indexed by the same type IDs in source and destination (identity copy).
|
||||
myVertices.HasCompoundParentFlags = theSource.myVertices.HasCompoundParentFlags;
|
||||
myVertices.HasOccurrenceParentFlags = theSource.myVertices.HasOccurrenceParentFlags;
|
||||
myEdges.HasCompoundParentFlags = theSource.myEdges.HasCompoundParentFlags;
|
||||
myEdges.HasOccurrenceParentFlags = theSource.myEdges.HasOccurrenceParentFlags;
|
||||
myCoEdges.HasCompoundParentFlags = theSource.myCoEdges.HasCompoundParentFlags;
|
||||
myCoEdges.HasOccurrenceParentFlags = theSource.myCoEdges.HasOccurrenceParentFlags;
|
||||
myWires.HasCompoundParentFlags = theSource.myWires.HasCompoundParentFlags;
|
||||
myWires.HasOccurrenceParentFlags = theSource.myWires.HasOccurrenceParentFlags;
|
||||
myFaces.HasCompoundParentFlags = theSource.myFaces.HasCompoundParentFlags;
|
||||
myFaces.HasOccurrenceParentFlags = theSource.myFaces.HasOccurrenceParentFlags;
|
||||
myShells.HasCompoundParentFlags = theSource.myShells.HasCompoundParentFlags;
|
||||
myShells.HasOccurrenceParentFlags = theSource.myShells.HasOccurrenceParentFlags;
|
||||
mySolids.HasCompoundParentFlags = theSource.mySolids.HasCompoundParentFlags;
|
||||
mySolids.HasOccurrenceParentFlags = theSource.mySolids.HasOccurrenceParentFlags;
|
||||
myCompounds.HasCompoundParentFlags = theSource.myCompounds.HasCompoundParentFlags;
|
||||
myCompounds.HasOccurrenceParentFlags = theSource.myCompounds.HasOccurrenceParentFlags;
|
||||
myCompSolids.HasCompoundParentFlags = theSource.myCompSolids.HasCompoundParentFlags;
|
||||
myCompSolids.HasOccurrenceParentFlags = theSource.myCompSolids.HasOccurrenceParentFlags;
|
||||
myProducts.HasCompoundParentFlags = theSource.myProducts.HasCompoundParentFlags;
|
||||
myProducts.HasOccurrenceParentFlags = theSource.myProducts.HasOccurrenceParentFlags;
|
||||
myOccurrences.HasCompoundParentFlags = theSource.myOccurrences.HasCompoundParentFlags;
|
||||
myOccurrences.HasOccurrenceParentFlags = theSource.myOccurrences.HasOccurrenceParentFlags;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraphInc_Storage::ValidateRelations() const
|
||||
{
|
||||
for (BRepGraph_CoEdgeId aCoEdgeId(0); aCoEdgeId.IsValid(NbCoEdges()); ++aCoEdgeId)
|
||||
@@ -2587,12 +2744,12 @@ void BRepGraphInc_Storage::ClearUIDIndexes()
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myUIDToNodeIdMutex);
|
||||
myUIDToNodeId.Clear();
|
||||
myUIDToNodeIdDirty = false;
|
||||
myUIDToNodeIdDirty.store(false, std::memory_order_relaxed);
|
||||
}
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myRefUIDToRefIdMutex);
|
||||
myRefUIDToRefId.Clear();
|
||||
myRefUIDToRefIdDirty = false;
|
||||
myRefUIDToRefIdDirty.store(false, std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2613,6 +2770,20 @@ void BRepGraphInc_Storage::ClearCurrentShapes()
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraphInc_Storage::CopyShapeBindingsFrom(const BRepGraphInc_Storage& theSource)
|
||||
{
|
||||
theSource.ForEachTShapeBinding(
|
||||
[this](const TopoDS_TShape* aTShape, const BRepGraph_NodeId aNodeId) {
|
||||
myTShapeToNodeId.Bind(aTShape, aNodeId);
|
||||
});
|
||||
theSource.ForEachOriginalBinding(
|
||||
[this](const BRepGraph_NodeId aNodeId, const TopoDS_Shape& aShape) {
|
||||
myOriginalShapes.Bind(aNodeId, aShape);
|
||||
});
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraphInc_Storage::UnbindCurrentShape(const BRepGraph_NodeId theNode)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myCurrentShapesMutex);
|
||||
@@ -2741,7 +2912,11 @@ void BRepGraphInc_Storage::Clear()
|
||||
|
||||
void BRepGraphInc_Storage::PrepareForLoad(const BRepGraphInc_Load::Counts& theCounts)
|
||||
{
|
||||
Clear();
|
||||
// Skip full Clear() when storage is already empty - avoids allocator reset + reallocation.
|
||||
if (!IsEmpty())
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
prepareDefStore(myVertices, theCounts.NbVertices, myAllocator);
|
||||
prepareDefStore(myEdges, theCounts.NbEdges, myAllocator);
|
||||
@@ -2785,6 +2960,72 @@ void BRepGraphInc_Storage::PrepareForLoad(const BRepGraphInc_Load::Counts& theCo
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
BRepGraphInc_Load::Counts BRepGraphInc_Storage::Counts() const
|
||||
{
|
||||
BRepGraphInc_Load::Counts aCounts;
|
||||
aCounts.NbVertices = NbVertices();
|
||||
aCounts.NbEdges = NbEdges();
|
||||
aCounts.NbCoEdges = NbCoEdges();
|
||||
aCounts.NbWires = NbWires();
|
||||
aCounts.NbFaces = NbFaces();
|
||||
aCounts.NbShells = NbShells();
|
||||
aCounts.NbSolids = NbSolids();
|
||||
aCounts.NbCompounds = NbCompounds();
|
||||
aCounts.NbCompSolids = NbCompSolids();
|
||||
aCounts.NbProducts = NbProducts();
|
||||
aCounts.NbOccurrences = NbOccurrences();
|
||||
aCounts.NbShellRefs = NbShellRefs();
|
||||
aCounts.NbFaceRefs = NbFaceRefs();
|
||||
aCounts.NbWireRefs = NbWireRefs();
|
||||
aCounts.NbVertexRefs = NbVertexRefs();
|
||||
aCounts.NbSolidRefs = NbSolidRefs();
|
||||
aCounts.NbChildRefs = NbChildRefs();
|
||||
aCounts.NbOccurrenceRefs = NbOccurrenceRefs();
|
||||
aCounts.NbFaceSurfaceReps = NbFaceSurfaces();
|
||||
aCounts.NbEdgeCurve3DReps = NbEdgeCurves3D();
|
||||
aCounts.NbCoEdgeCurve2DReps = NbCoEdgeCurves2D();
|
||||
aCounts.NbFaceTriangulationReps = NbFaceTriangulations();
|
||||
aCounts.NbEdgePolygon3DReps = NbEdgePolygons3D();
|
||||
aCounts.NbCoEdgePolygon2DReps = NbCoEdgePolygons2D();
|
||||
aCounts.NbCoEdgePolygonOnTriReps = NbCoEdgePolygonsOnTri();
|
||||
return aCounts;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
BRepGraphInc_Load::Counts BRepGraphInc_Storage::ActiveCounts() const
|
||||
{
|
||||
BRepGraphInc_Load::Counts aCounts;
|
||||
aCounts.NbVertices = NbActiveVertices();
|
||||
aCounts.NbEdges = NbActiveEdges();
|
||||
aCounts.NbCoEdges = NbActiveCoEdges();
|
||||
aCounts.NbWires = NbActiveWires();
|
||||
aCounts.NbFaces = NbActiveFaces();
|
||||
aCounts.NbShells = NbActiveShells();
|
||||
aCounts.NbSolids = NbActiveSolids();
|
||||
aCounts.NbCompounds = NbActiveCompounds();
|
||||
aCounts.NbCompSolids = NbActiveCompSolids();
|
||||
aCounts.NbProducts = NbActiveProducts();
|
||||
aCounts.NbOccurrences = NbActiveOccurrences();
|
||||
aCounts.NbShellRefs = NbActiveShellRefs();
|
||||
aCounts.NbFaceRefs = NbActiveFaceRefs();
|
||||
aCounts.NbWireRefs = NbActiveWireRefs();
|
||||
aCounts.NbVertexRefs = NbActiveVertexRefs();
|
||||
aCounts.NbSolidRefs = NbActiveSolidRefs();
|
||||
aCounts.NbChildRefs = NbActiveChildRefs();
|
||||
aCounts.NbOccurrenceRefs = NbActiveOccurrenceRefs();
|
||||
aCounts.NbFaceSurfaceReps = NbActiveFaceSurfaces();
|
||||
aCounts.NbEdgeCurve3DReps = NbActiveEdgeCurves3D();
|
||||
aCounts.NbCoEdgeCurve2DReps = NbActiveCoEdgeCurves2D();
|
||||
aCounts.NbFaceTriangulationReps = NbActiveFaceTriangulations();
|
||||
aCounts.NbEdgePolygon3DReps = NbActiveEdgePolygons3D();
|
||||
aCounts.NbCoEdgePolygon2DReps = NbActiveCoEdgePolygons2D();
|
||||
aCounts.NbCoEdgePolygonOnTriReps = NbActiveCoEdgePolygonsOnTri();
|
||||
return aCounts;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraphInc_Storage::SetActiveCounts(const BRepGraphInc_Load::Counts& theCounts)
|
||||
{
|
||||
myVertices.NbActive = theCounts.NbVertices;
|
||||
@@ -3047,12 +3288,12 @@ void BRepGraphInc_Storage::MarkUIDReverseIndexesDirty()
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myUIDToNodeIdMutex);
|
||||
myUIDToNodeId.Clear();
|
||||
myUIDToNodeIdDirty = true;
|
||||
myUIDToNodeIdDirty.store(true, std::memory_order_release);
|
||||
}
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myRefUIDToRefIdMutex);
|
||||
myRefUIDToRefId.Clear();
|
||||
myRefUIDToRefIdDirty = true;
|
||||
myRefUIDToRefIdDirty.store(true, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3060,8 +3301,14 @@ void BRepGraphInc_Storage::MarkUIDReverseIndexesDirty()
|
||||
|
||||
void BRepGraphInc_Storage::EnsureUIDReverseIndex() const
|
||||
{
|
||||
// Lock-free fast path: skip if not dirty.
|
||||
if (!myUIDToNodeIdDirty.load(std::memory_order_acquire))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock<std::shared_mutex> aLock(myUIDToNodeIdMutex);
|
||||
if (!myUIDToNodeIdDirty)
|
||||
if (!myUIDToNodeIdDirty.load(std::memory_order_relaxed))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -3181,15 +3428,21 @@ void BRepGraphInc_Storage::EnsureUIDReverseIndex() const
|
||||
break;
|
||||
}
|
||||
}
|
||||
myUIDToNodeIdDirty = false;
|
||||
myUIDToNodeIdDirty.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraphInc_Storage::EnsureRefUIDReverseIndex() const
|
||||
{
|
||||
// Lock-free fast path: skip if not dirty.
|
||||
if (!myRefUIDToRefIdDirty.load(std::memory_order_acquire))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock<std::shared_mutex> aLock(myRefUIDToRefIdMutex);
|
||||
if (!myRefUIDToRefIdDirty)
|
||||
if (!myRefUIDToRefIdDirty.load(std::memory_order_relaxed))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -3279,7 +3532,7 @@ void BRepGraphInc_Storage::EnsureRefUIDReverseIndex() const
|
||||
break;
|
||||
}
|
||||
}
|
||||
myRefUIDToRefIdDirty = false;
|
||||
myRefUIDToRefIdDirty.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
@@ -1289,6 +1289,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
//! Copy TShape-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);
|
||||
|
||||
//! Return the generation-validated node-to-shape reconstruction cache.
|
||||
[[nodiscard]] const NCollection_FlatDataMap<BRepGraph_NodeId, CachedShape>& CurrentShapes() const
|
||||
{
|
||||
@@ -1334,6 +1338,12 @@ public:
|
||||
//! @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();
|
||||
|
||||
@@ -1345,6 +1355,10 @@ public:
|
||||
//! 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;
|
||||
@@ -1393,6 +1407,10 @@ public:
|
||||
//! 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;
|
||||
@@ -1868,8 +1886,8 @@ private:
|
||||
mutable std::shared_mutex myUIDToNodeIdMutex;
|
||||
mutable NCollection_FlatDataMap<BRepGraph_RefUID, BRepGraph_RefId> myRefUIDToRefId;
|
||||
mutable std::shared_mutex myRefUIDToRefIdMutex;
|
||||
mutable bool myUIDToNodeIdDirty = false;
|
||||
mutable bool myRefUIDToRefIdDirty = false;
|
||||
mutable std::atomic<bool> myUIDToNodeIdDirty{false};
|
||||
mutable std::atomic<bool> myRefUIDToRefIdDirty{false};
|
||||
|
||||
//! Bindings from reconstructed / source OCCT shapes back to backend ids.
|
||||
NCollection_FlatDataMap<const TopoDS_TShape*, BRepGraph_NodeId> myTShapeToNodeId;
|
||||
|
||||
@@ -493,10 +493,14 @@ TEST(BRepGraphIncTest, Box_Relations_EdgesToFaces)
|
||||
for (BRepGraph_EdgeId anEdgeId(0); anEdgeId.IsValid(aNbEdges); ++anEdgeId)
|
||||
{
|
||||
// Skip degenerate edges (e.g. sphere poles with no 3D curve).
|
||||
BRepGraph_CacheDerivedState::EdgeEntry anEdgeState;
|
||||
[[maybe_unused]] const bool isEdgeStateComputed =
|
||||
BRepGraph_CacheDerivedState::ComputeEdgeStatus(aGraph, anEdgeId, anEdgeState);
|
||||
if (anEdgeState.Status == BRepGraph_CacheDerivedState::EdgeGeometryStatus::DegenerateOnSurface)
|
||||
bool anIsDegenerated = false;
|
||||
bool anIsClosed = false;
|
||||
[[maybe_unused]] const bool isEdgeStateComputed =
|
||||
BRepGraph_CacheDerivedState::ComputeEdgeProperties(aGraph,
|
||||
anEdgeId,
|
||||
anIsDegenerated,
|
||||
anIsClosed);
|
||||
if (anIsDegenerated)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -688,11 +692,15 @@ TEST(BRepGraphIncTest, Sphere_DegenerateEdges_Preserved)
|
||||
const uint32_t aNbEdges = aGraph.Topo().Edges().Nb();
|
||||
for (BRepGraph_EdgeId anEdgeId(0); anEdgeId.IsValid(aNbEdges); ++anEdgeId)
|
||||
{
|
||||
const BRepGraphInc::EdgeDef& anEdge = aGraph.Topo().Edges().Definition(anEdgeId);
|
||||
BRepGraph_CacheDerivedState::EdgeEntry anEdgeState;
|
||||
[[maybe_unused]] const bool isEdgeStateComputed =
|
||||
BRepGraph_CacheDerivedState::ComputeEdgeStatus(aGraph, anEdgeId, anEdgeState);
|
||||
if (anEdgeState.Status == BRepGraph_CacheDerivedState::EdgeGeometryStatus::DegenerateOnSurface)
|
||||
const BRepGraphInc::EdgeDef& anEdge = aGraph.Topo().Edges().Definition(anEdgeId);
|
||||
bool anIsDegenerated = false;
|
||||
bool anIsClosed = false;
|
||||
[[maybe_unused]] const bool isEdgeStateComputed =
|
||||
BRepGraph_CacheDerivedState::ComputeEdgeProperties(aGraph,
|
||||
anEdgeId,
|
||||
anIsDegenerated,
|
||||
anIsClosed);
|
||||
if (anIsDegenerated)
|
||||
{
|
||||
++aDegenerateCount;
|
||||
EXPECT_FALSE(anEdge.Curve3DRepId.IsValid())
|
||||
|
||||
@@ -61,6 +61,32 @@
|
||||
namespace
|
||||
{
|
||||
|
||||
bool edgeSameParameter(const BRepGraph& theGraph, BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
const auto& aRel = theGraph.Topo().Edges().Relations(theEdge);
|
||||
for (const auto& aCoEdgeId : aRel.CoEdgeIds)
|
||||
{
|
||||
if (!BRepGraph_Tool::CoEdge::SameParameter(theGraph, aCoEdgeId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool edgeSameRange(const BRepGraph& theGraph, BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
const auto& aRel = theGraph.Topo().Edges().Relations(theEdge);
|
||||
for (const auto& aCoEdgeId : aRel.CoEdgeIds)
|
||||
{
|
||||
if (!BRepGraph_Tool::CoEdge::SameRange(theGraph, aCoEdgeId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class CopyTestCacheService : public BRepGraph_Cache
|
||||
{
|
||||
public:
|
||||
@@ -940,9 +966,9 @@ TEST(BRepGraph_CopyTest, CopyBox_SameParameter_Preserved)
|
||||
const uint32_t aNbEdges = aCopyGraph.Topo().Edges().Nb();
|
||||
for (BRepGraph_EdgeId anEdgeId(0); anEdgeId.IsValid(aNbEdges); ++anEdgeId)
|
||||
{
|
||||
EXPECT_TRUE(BRepGraph_Tool::Edge::SameParameter(aCopyGraph, anEdgeId))
|
||||
EXPECT_TRUE(edgeSameParameter(aCopyGraph, anEdgeId))
|
||||
<< "Copied edge " << anEdgeId.Index << " lost SameParameter flag";
|
||||
EXPECT_TRUE(BRepGraph_Tool::Edge::SameRange(aCopyGraph, anEdgeId))
|
||||
EXPECT_TRUE(edgeSameRange(aCopyGraph, anEdgeId))
|
||||
<< "Copied edge " << anEdgeId.Index << " lost SameRange flag";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,32 @@
|
||||
namespace
|
||||
{
|
||||
|
||||
bool edgeSameParameter(const BRepGraph& theGraph, BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
const auto& aRel = theGraph.Topo().Edges().Relations(theEdge);
|
||||
for (const auto& aCoEdgeId : aRel.CoEdgeIds)
|
||||
{
|
||||
if (!BRepGraph_Tool::CoEdge::SameParameter(theGraph, aCoEdgeId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool edgeSameRange(const BRepGraph& theGraph, BRepGraph_EdgeId theEdge)
|
||||
{
|
||||
const auto& aRel = theGraph.Topo().Edges().Relations(theEdge);
|
||||
for (const auto& aCoEdgeId : aRel.CoEdgeIds)
|
||||
{
|
||||
if (!BRepGraph_Tool::CoEdge::SameRange(theGraph, aCoEdgeId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int componentKey(const BRepGraph_NodeId theNode)
|
||||
{
|
||||
return theNode.Index * BRepGraph_NodeId::THE_KIND_COUNT + static_cast<int>(theNode.NodeKind);
|
||||
@@ -768,7 +794,7 @@ TEST(BRepGraph_GeometryTest, Box_EdgeDef_SameParameter_IsSet)
|
||||
// Box edges are well-formed; SameParameter should be true for all.
|
||||
for (BRepGraph_EdgeIterator anEdgeIt(aGraph); anEdgeIt.More(); anEdgeIt.Next())
|
||||
{
|
||||
EXPECT_TRUE(BRepGraph_Tool::Edge::SameParameter(aGraph, anEdgeIt.CurrentId()))
|
||||
EXPECT_TRUE(edgeSameParameter(aGraph, anEdgeIt.CurrentId()))
|
||||
<< "Edge def " << anEdgeIt.CurrentId().Index << " has SameParameter=false";
|
||||
}
|
||||
}
|
||||
@@ -784,7 +810,7 @@ TEST(BRepGraph_GeometryTest, Box_EdgeDef_SameRange_IsSet)
|
||||
|
||||
for (BRepGraph_EdgeIterator anEdgeIt(aGraph); anEdgeIt.More(); anEdgeIt.Next())
|
||||
{
|
||||
EXPECT_TRUE(BRepGraph_Tool::Edge::SameRange(aGraph, anEdgeIt.CurrentId()))
|
||||
EXPECT_TRUE(edgeSameRange(aGraph, anEdgeIt.CurrentId()))
|
||||
<< "Edge def " << anEdgeIt.CurrentId().Index << " has SameRange=false";
|
||||
}
|
||||
}
|
||||
@@ -817,14 +843,14 @@ TEST(BRepGraph_GeometryTest, DerivedStateCache_LazyAndFreshAfterPCurveRangeMutat
|
||||
ASSERT_TRUE(anEdgeId.IsValid(aGraph.Topo().Edges().Nb()));
|
||||
ASSERT_TRUE(aCoEdgeId.IsValid(aGraph.Topo().CoEdges().Nb()));
|
||||
|
||||
ASSERT_TRUE(BRepGraph_Tool::Edge::SameRange(aGraph, anEdgeId));
|
||||
ASSERT_TRUE(edgeSameRange(aGraph, anEdgeId));
|
||||
EXPECT_FALSE(aGraph.CacheRegistry().Find<BRepGraph_CacheDerivedState>().IsNull());
|
||||
|
||||
const std::pair<double, double> anEdgeRange = BRepGraph_Tool::Edge::Range(aGraph, anEdgeId);
|
||||
aGraph.Editor().CoEdges().SetParamRange(aCoEdgeId, anEdgeRange.first + 1.0, anEdgeRange.second);
|
||||
|
||||
EXPECT_FALSE(BRepGraph_Tool::Edge::SameRange(aGraph, anEdgeId));
|
||||
EXPECT_FALSE(BRepGraph_Tool::Edge::SameParameter(aGraph, anEdgeId));
|
||||
EXPECT_FALSE(edgeSameRange(aGraph, anEdgeId));
|
||||
EXPECT_FALSE(edgeSameParameter(aGraph, anEdgeId));
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
|
||||
Reference in New Issue
Block a user