mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-09-04 03:38:01 +08:00
Modeling Data - Fix BRepGraph topology placement population (#1311)
- Kept TopoDS definition data local while storing root and compound placements on graph references. - Preserved located triangulation and polygon-on-triangulation data during population. - Preserved degenerate natural boundary edges and cleared full-graph state consistently in Perform(). - Kept original TopoDS shape lookup bindings valid across population and compaction. - Rebuilt compacted compounds in two passes so nested compound references keep their local placement. - Added focused regression coverage for located meshes, nested compounds, shape lookup, compaction, degenerate boundaries, and reset behavior.
This commit is contained in:
@@ -786,16 +786,29 @@ BRepGraph_Compact::Result BRepGraph_Compact::Perform(BRepGraph& theGraph, const
|
||||
aNewDef.UID = anIt.Current().UID;
|
||||
}
|
||||
|
||||
// Compounds.
|
||||
NCollection_LinearVector<BRepGraph_NodeId> aCompChildren(64);
|
||||
NCollection_LinearVector<BRepGraph_ChildRefId> aCompOldChildRefs(64);
|
||||
// Compounds may reference other compounds. Create all compound definitions first so parent
|
||||
// compounds can attach child refs to compound children independently of storage order.
|
||||
for (BRepGraph_Iterator<BRepGraphInc::CompoundDef> anIt(theGraph); anIt.More(); anIt.Next())
|
||||
{
|
||||
aCompChildren.Clear(false);
|
||||
aCompOldChildRefs.Clear(false);
|
||||
const BRepGraph_CompoundId anOldCompoundId = anIt.CurrentId();
|
||||
const BRepGraph_CompoundId* aExpectedNewId = aCompoundMap.Seek(anOldCompoundId);
|
||||
if (aExpectedNewId == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const BRepGraph_CompoundId anOldCompoundId = anIt.CurrentId();
|
||||
if (aCompoundMap.Seek(anOldCompoundId) == nullptr)
|
||||
const NCollection_Array1<BRepGraph_NodeId> anEmptyChildren;
|
||||
[[maybe_unused]] const BRepGraph_CompoundId aNewCompoundId =
|
||||
aNewGraph.Editor().Compounds().Add(anEmptyChildren);
|
||||
Standard_ASSERT_RAISE(aNewCompoundId == *aExpectedNewId,
|
||||
"BRepGraph_Compact: unexpected compound id");
|
||||
}
|
||||
|
||||
for (BRepGraph_Iterator<BRepGraphInc::CompoundDef> anIt(theGraph); anIt.More(); anIt.Next())
|
||||
{
|
||||
const BRepGraph_CompoundId anOldCompoundId = anIt.CurrentId();
|
||||
const BRepGraph_CompoundId* aNewCompoundId = aCompoundMap.Seek(anOldCompoundId);
|
||||
if (aNewCompoundId == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -807,26 +820,13 @@ BRepGraph_Compact::Result BRepGraph_Compact::Perform(BRepGraph& theGraph, const
|
||||
const BRepGraph_NodeId aNewChild = remapId(aCR.ChildNodeId);
|
||||
if (aNewChild.IsValid())
|
||||
{
|
||||
aCompChildren.Append(aNewChild);
|
||||
aCompOldChildRefs.Append(aRefIt.CurrentId());
|
||||
}
|
||||
}
|
||||
const BRepGraph_CompoundId aNewCompoundId =
|
||||
aNewGraph.Editor().Compounds().Add(aCompChildren.ToArray1());
|
||||
if (aNewCompoundId.IsValid())
|
||||
{
|
||||
const NCollection_LinearVector<BRepGraph_ChildRefId>& aNewChildRefs =
|
||||
aNewGraph.Topo().Compounds().Relations(aNewCompoundId).ChildRefIds;
|
||||
for (size_t aRefIdx = 0; aRefIdx < aCompOldChildRefs.Size() && aRefIdx < aNewChildRefs.Size();
|
||||
++aRefIdx)
|
||||
{
|
||||
const BRepGraphInc::ChildRef& anOldRef =
|
||||
theGraph.Refs().Children().Entry(aCompOldChildRefs.Value(aRefIdx));
|
||||
BRepGraph_MutGuard<BRepGraphInc::ChildRef> aNewRef =
|
||||
aNewGraph.Editor().Gen().MutChildRef(aNewChildRefs.Value(aRefIdx));
|
||||
aNewGraph.Editor().Gen().SetChildRefOrientation(aNewRef, anOldRef.Orientation);
|
||||
aNewGraph.Editor().Gen().SetChildRefLocalLocation(aNewRef, anOldRef.LocalLocation);
|
||||
aChildRefMap.Bind(aCompOldChildRefs.Value(aRefIdx), aNewChildRefs.Value(aRefIdx));
|
||||
const BRepGraph_ChildRefId aNewRefId =
|
||||
aNewGraph.Editor().Compounds().Append(*aNewCompoundId, aNewChild, aCR.Orientation);
|
||||
if (aNewRefId.IsValid())
|
||||
{
|
||||
aNewGraph.Editor().Gen().SetChildRefLocalLocation(aNewRefId, aCR.LocalLocation);
|
||||
aChildRefMap.Bind(aRefIt.CurrentId(), aNewRefId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1258,12 +1258,12 @@ BRepGraph_Compact::Result BRepGraph_Compact::Perform(BRepGraph& theGraph, const
|
||||
BRepGraph_LayerRegistry aSavedLayerRegistry = std::move(theGraph.layerRegistry());
|
||||
BRepGraph_CacheRegistry aSavedCacheRegistry = std::move(theGraph.cacheRegistry());
|
||||
|
||||
// Transfer TShape-to-NodeId and NodeId-to-OriginalShape bindings: the rebuilt graph has none.
|
||||
NCollection_LinearVector<std::pair<const TopoDS_TShape*, BRepGraph_NodeId>> aTShapeBindings;
|
||||
NCollection_LinearVector<std::pair<BRepGraph_NodeId, TopoDS_Shape>> aOriginalBindings;
|
||||
aGraphData->myIncStorage.ForEachTShapeBinding(
|
||||
[&](const TopoDS_TShape* theTShape, const BRepGraph_NodeId& theNodeId) {
|
||||
aTShapeBindings.Append({theTShape, theNodeId});
|
||||
// Transfer shape-to-NodeId and NodeId-to-OriginalShape bindings: the rebuilt graph has none.
|
||||
NCollection_LinearVector<std::pair<TopoDS_Shape, BRepGraph_NodeId>> aShapeBindings;
|
||||
NCollection_LinearVector<std::pair<BRepGraph_NodeId, TopoDS_Shape>> aOriginalBindings;
|
||||
aGraphData->myIncStorage.ForEachShapeBinding(
|
||||
[&](const TopoDS_Shape& theShape, const BRepGraph_NodeId& theNodeId) {
|
||||
aShapeBindings.Append({theShape, theNodeId});
|
||||
});
|
||||
aGraphData->myIncStorage.ForEachOriginalBinding(
|
||||
[&](const BRepGraph_NodeId& theNodeId, const TopoDS_Shape& theShape) {
|
||||
@@ -1421,14 +1421,14 @@ BRepGraph_Compact::Result BRepGraph_Compact::Perform(BRepGraph& theGraph, const
|
||||
aRemapMap.Bind(anOldId, aNewId);
|
||||
}
|
||||
|
||||
// Restore TShape-to-NodeId and NodeId-to-OriginalShape bindings, remapping NodeIds through
|
||||
// Restore shape-to-NodeId and NodeId-to-OriginalShape bindings, remapping NodeIds through
|
||||
// aRemapMap. Nodes that were removed (dead, no entry in aRemapMap) are simply dropped.
|
||||
for (const auto& [aTShape, aOldId] : aTShapeBindings)
|
||||
for (const auto& [aShape, aOldId] : aShapeBindings)
|
||||
{
|
||||
const BRepGraph_NodeId* aNewId = aRemapMap.Seek(aOldId);
|
||||
if (aNewId != nullptr)
|
||||
{
|
||||
theGraph.incStorage().BindTShapeToNode(aTShape, *aNewId);
|
||||
theGraph.incStorage().SetDefinitionShapeBinding(aShape, *aNewId);
|
||||
}
|
||||
}
|
||||
for (const auto& [aOldId, aShape] : aOriginalBindings)
|
||||
@@ -1449,8 +1449,6 @@ BRepGraph_Compact::Result BRepGraph_Compact::Perform(BRepGraph& theGraph, const
|
||||
aWireOldCoEdges.Clear(true);
|
||||
aFaceNextWires.Clear(true);
|
||||
aFaceOldWireRefs.Clear(true);
|
||||
aCompChildren.Clear(true);
|
||||
aCompOldChildRefs.Clear(true);
|
||||
aCSSolids.Clear(true);
|
||||
aCSOldSolidRefs.Clear(true);
|
||||
|
||||
|
||||
@@ -64,6 +64,24 @@ static bool isCoreParityOrientation(const TopAbs_Orientation theOrientation)
|
||||
return theOrientation == TopAbs_FORWARD || theOrientation == TopAbs_REVERSED;
|
||||
}
|
||||
|
||||
static TopoDS_Shape shapeWithoutOwnLocation(const TopoDS_Shape& theShape)
|
||||
{
|
||||
TopoDS_Shape aShape = theShape;
|
||||
aShape.Location(TopLoc_Location());
|
||||
return aShape;
|
||||
}
|
||||
|
||||
static bool shouldStoreRootLocationInRef(const BRepGraph::ShapesView::Options& theOptions,
|
||||
const BRepGraph_NodeId& theParent)
|
||||
{
|
||||
if (theParent.IsValid())
|
||||
{
|
||||
return theParent.NodeKind == BRepGraph_NodeId::Kind::Product
|
||||
|| theParent.NodeKind == BRepGraph_NodeId::Kind::Compound;
|
||||
}
|
||||
return theOptions.CreateAutoProduct;
|
||||
}
|
||||
|
||||
static ShapeParentRoute classifyShapeToParent(const TopAbs_ShapeEnum theShapeType,
|
||||
const TopAbs_Orientation theOrientation,
|
||||
const BRepGraph_NodeId& theParent)
|
||||
@@ -129,7 +147,6 @@ static uint64_t attachSupplementToParent(BRepGraph& theGraph,
|
||||
const BRepGraph_NodeId theParent)
|
||||
{
|
||||
TopoDS_Shape aSuppShape = theShape;
|
||||
aSuppShape.Orientation(theShape.Orientation());
|
||||
switch (theParent.NodeKind)
|
||||
{
|
||||
case BRepGraph_NodeId::Kind::Compound:
|
||||
@@ -495,6 +512,96 @@ void BRepGraph::ShapesView::collectAddedNodes(
|
||||
}
|
||||
}
|
||||
|
||||
static void bindSourceShapeAlias(BRepGraph& theGraph,
|
||||
BRepGraphInc_Storage& theStorage,
|
||||
const TopoDS_Shape& theSourceShape,
|
||||
const TopLoc_Location& theSourceLocation,
|
||||
const TopoDS_Shape& thePopulatedShape,
|
||||
const TopLoc_Location& theDefinitionLocation)
|
||||
{
|
||||
if (theSourceShape.IsNull() || thePopulatedShape.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TopoDS_Shape aLookup = thePopulatedShape;
|
||||
aLookup.Location(theDefinitionLocation);
|
||||
const BRepGraph_NodeId aNodeId = theGraph.Shapes().FindNode(aLookup);
|
||||
if (!aNodeId.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
theStorage.SetDefinitionShapeBinding(theSourceShape, aNodeId);
|
||||
if (!theSourceShape.Location().IsEqual(theSourceLocation))
|
||||
{
|
||||
TopoDS_Shape aSourceAlias = theSourceShape;
|
||||
aSourceAlias.Location(theSourceLocation);
|
||||
theStorage.SetDefinitionShapeBinding(aSourceAlias, aNodeId);
|
||||
}
|
||||
}
|
||||
|
||||
static void bindSourceShapeAliasesRecursive(BRepGraph& theGraph,
|
||||
BRepGraphInc_Storage& theStorage,
|
||||
const TopoDS_Shape& theSourceShape,
|
||||
const TopoDS_Shape& thePopulatedShape,
|
||||
const TopLoc_Location& theSourceLocation,
|
||||
const TopLoc_Location& theDefinitionLocation)
|
||||
{
|
||||
bindSourceShapeAlias(theGraph,
|
||||
theStorage,
|
||||
theSourceShape,
|
||||
theSourceLocation,
|
||||
thePopulatedShape,
|
||||
theDefinitionLocation);
|
||||
|
||||
const bool isCompoundParent = thePopulatedShape.ShapeType() == TopAbs_COMPOUND;
|
||||
TopoDS_Iterator aSourceIt(theSourceShape, false, false);
|
||||
TopoDS_Iterator aPopulatedIt(thePopulatedShape, false, false);
|
||||
for (; aSourceIt.More() && aPopulatedIt.More(); aSourceIt.Next(), aPopulatedIt.Next())
|
||||
{
|
||||
const TopoDS_Shape& aSourceChild = aSourceIt.Value();
|
||||
const TopoDS_Shape& aPopulatedChild = aPopulatedIt.Value();
|
||||
if (aSourceChild.IsNull() || aPopulatedChild.IsNull())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const TopLoc_Location aChildSourceLocation = theSourceLocation * aSourceChild.Location();
|
||||
if (isCompoundParent)
|
||||
{
|
||||
const TopoDS_Shape aChildDefinition = shapeWithoutOwnLocation(aPopulatedChild);
|
||||
bindSourceShapeAliasesRecursive(theGraph,
|
||||
theStorage,
|
||||
aSourceChild,
|
||||
aChildDefinition,
|
||||
aChildSourceLocation,
|
||||
TopLoc_Location());
|
||||
}
|
||||
else
|
||||
{
|
||||
bindSourceShapeAliasesRecursive(theGraph,
|
||||
theStorage,
|
||||
aSourceChild,
|
||||
aPopulatedChild,
|
||||
aChildSourceLocation,
|
||||
theDefinitionLocation * aPopulatedChild.Location());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BRepGraph::ShapesView::bindSourceShapeAliases(BRepGraph& theGraph,
|
||||
const TopoDS_Shape& theSourceShape,
|
||||
const TopoDS_Shape& thePopulatedShape)
|
||||
{
|
||||
bindSourceShapeAliasesRecursive(theGraph,
|
||||
theGraph.myData->myIncStorage,
|
||||
theSourceShape,
|
||||
thePopulatedShape,
|
||||
theSourceShape.Location(),
|
||||
thePopulatedShape.Location());
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
namespace
|
||||
@@ -787,10 +894,14 @@ BRepGraph::ShapesView::Result BRepGraph::ShapesView::Add(
|
||||
}
|
||||
|
||||
const uint32_t anOldCount = snapshotCountForKind(theGraph, theShape.ShapeType());
|
||||
const bool isRootLocationStoredInRef =
|
||||
shouldStoreRootLocationInRef(theOptions, BRepGraph_NodeId());
|
||||
const TopoDS_Shape aPopulateShape =
|
||||
isRootLocationStoredInRef ? shapeWithoutOwnLocation(theShape) : theShape;
|
||||
|
||||
NCollection_LinearVector<BRepGraph_NodeId> aFlatRoots;
|
||||
const AddStatus aAddStatus =
|
||||
appendImpl(theGraph, theShape, theOptions, theOptions.Flatten ? &aFlatRoots : nullptr);
|
||||
appendImpl(theGraph, aPopulateShape, theOptions, theOptions.Flatten ? &aFlatRoots : nullptr);
|
||||
|
||||
aResult.Status = aAddStatus;
|
||||
|
||||
@@ -802,6 +913,14 @@ BRepGraph::ShapesView::Result BRepGraph::ShapesView::Add(
|
||||
{
|
||||
aResult.TopologyRoot = detectTopologyRoot(theGraph, theShape.ShapeType(), anOldCount);
|
||||
}
|
||||
if (!aResult.TopologyRoot.IsValid())
|
||||
{
|
||||
aResult.TopologyRoot = FindNode(aPopulateShape);
|
||||
}
|
||||
if (isRootLocationStoredInRef && aResult.TopologyRoot.IsValid())
|
||||
{
|
||||
bindSourceShapeAliases(theGraph, theShape, aPopulateShape);
|
||||
}
|
||||
|
||||
if (theOptions.CreateAutoProduct && aResult.TopologyRoot.IsValid())
|
||||
{
|
||||
@@ -870,14 +989,17 @@ BRepGraph::ShapesView::Result BRepGraph::ShapesView::Add(
|
||||
return aResult;
|
||||
}
|
||||
|
||||
const uint32_t anOldCount = snapshotCountForKind(theGraph, theShape.ShapeType());
|
||||
const uint32_t anOldCount = snapshotCountForKind(theGraph, theShape.ShapeType());
|
||||
const bool isRootLocationStoredInRef = shouldStoreRootLocationInRef(theOptions, theParent);
|
||||
const TopoDS_Shape aPopulateShape =
|
||||
isRootLocationStoredInRef ? shapeWithoutOwnLocation(theShape) : theShape;
|
||||
|
||||
Options anInner = theOptions;
|
||||
anInner.CreateAutoProduct = false;
|
||||
|
||||
NCollection_LinearVector<BRepGraph_NodeId> aFlatRoots;
|
||||
const AddStatus aStatus =
|
||||
appendImpl(theGraph, theShape, anInner, anInner.Flatten ? &aFlatRoots : nullptr);
|
||||
appendImpl(theGraph, aPopulateShape, anInner, anInner.Flatten ? &aFlatRoots : nullptr);
|
||||
|
||||
if (aStatus == AddStatus::Failed)
|
||||
{
|
||||
@@ -893,9 +1015,17 @@ BRepGraph::ShapesView::Result BRepGraph::ShapesView::Add(
|
||||
aResult.TopologyRoot = detectTopologyRoot(theGraph, theShape.ShapeType(), anOldCount);
|
||||
}
|
||||
if (!aResult.TopologyRoot.IsValid())
|
||||
{
|
||||
aResult.TopologyRoot = FindNode(aPopulateShape);
|
||||
}
|
||||
if (!aResult.TopologyRoot.IsValid())
|
||||
{
|
||||
return aResult;
|
||||
}
|
||||
if (isRootLocationStoredInRef)
|
||||
{
|
||||
bindSourceShapeAliases(theGraph, theShape, aPopulateShape);
|
||||
}
|
||||
|
||||
if (anInner.TrackAddedNodes)
|
||||
{
|
||||
@@ -939,6 +1069,7 @@ BRepGraph::ShapesView::Result BRepGraph::ShapesView::Add(
|
||||
{
|
||||
return aResult;
|
||||
}
|
||||
theGraph.Editor().Gen().SetChildRefLocalLocation(aRid, theShape.Location());
|
||||
aResult.InsertedRef = aRid;
|
||||
aResult.Status = AddStatus::Success;
|
||||
return aResult;
|
||||
@@ -1040,7 +1171,12 @@ TopoDS_Shape BRepGraph::ShapesView::Shape(const BRepGraph_NodeId theNode) const
|
||||
}
|
||||
// Fast path: if entity was never mutated, return the original shape.
|
||||
const BRepGraphInc::BaseDef* aDef = myGraph->topoEntity(theNode);
|
||||
if (aDef != nullptr && aDef->SubtreeGen == 0)
|
||||
if (aDef == nullptr)
|
||||
{
|
||||
return TopoDS_Shape();
|
||||
}
|
||||
const uint32_t aSubtreeGen = aDef->SubtreeGen;
|
||||
if (aSubtreeGen == 0)
|
||||
{
|
||||
TopoDS_Shape anOrig = Original(theNode);
|
||||
if (!anOrig.IsNull())
|
||||
@@ -1055,7 +1191,7 @@ TopoDS_Shape BRepGraph::ShapesView::Shape(const BRepGraph_NodeId theNode) const
|
||||
myGraph->myData->myIncStorage.CurrentShapesMutex());
|
||||
const BRepGraphInc_Storage::CachedShape* aCached =
|
||||
myGraph->myData->myIncStorage.CurrentShapes().Seek(theNode);
|
||||
if (aCached != nullptr && aDef != nullptr && aCached->StoredSubtreeGen == aDef->SubtreeGen)
|
||||
if (aCached != nullptr && aCached->StoredSubtreeGen == aSubtreeGen)
|
||||
{
|
||||
return aCached->Shape;
|
||||
}
|
||||
@@ -1068,24 +1204,31 @@ TopoDS_Shape BRepGraph::ShapesView::Shape(const BRepGraph_NodeId theNode) const
|
||||
|
||||
// Store under exclusive lock with double-check to avoid redundant writes
|
||||
// when multiple threads reconstruct the same parent node concurrently.
|
||||
if (!aReconstructed.IsNull() && aDef != nullptr)
|
||||
if (!aReconstructed.IsNull())
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aWriteLock(
|
||||
myGraph->myData->myIncStorage.CurrentShapesMutex());
|
||||
const BRepGraphInc_Storage::CachedShape* aExisting =
|
||||
myGraph->myData->myIncStorage.CurrentShapes().Seek(theNode);
|
||||
if (aExisting != nullptr && aExisting->StoredSubtreeGen == aDef->SubtreeGen)
|
||||
BRepGraphInc_Storage::CachedShape* aExisting =
|
||||
myGraph->myData->myIncStorage.ChangeCurrentShapes().ChangeSeek(theNode);
|
||||
if (aExisting != nullptr && aExisting->StoredSubtreeGen == aSubtreeGen)
|
||||
{
|
||||
return aExisting->Shape;
|
||||
}
|
||||
BRepGraphInc_Storage::CachedShape anEntry;
|
||||
anEntry.Shape = aReconstructed;
|
||||
anEntry.StoredSubtreeGen = aDef->SubtreeGen;
|
||||
myGraph->myData->myIncStorage.ChangeCurrentShapes().Bind(theNode, anEntry);
|
||||
anEntry.StoredSubtreeGen = aSubtreeGen;
|
||||
if (aExisting != nullptr)
|
||||
{
|
||||
*aExisting = anEntry;
|
||||
}
|
||||
else
|
||||
{
|
||||
myGraph->myData->myIncStorage.ChangeCurrentShapes().Bind(theNode, anEntry);
|
||||
}
|
||||
if (theNode.NodeKind != BRepGraph_NodeId::Kind::Product
|
||||
&& theNode.NodeKind != BRepGraph_NodeId::Kind::Occurrence)
|
||||
{
|
||||
myGraph->myData->myIncStorage.BindTShapeToNode(aReconstructed.TShape().get(), theNode);
|
||||
myGraph->myData->myIncStorage.SetDefinitionShapeBinding(aReconstructed, theNode);
|
||||
}
|
||||
}
|
||||
return aReconstructed;
|
||||
@@ -1112,15 +1255,14 @@ TopoDS_Shape BRepGraph::ShapesView::Original(const BRepGraph_NodeId theNode) con
|
||||
return TopoDS_Shape();
|
||||
}
|
||||
|
||||
const TopoDS_Shape* anOriginal = myGraph->myData->myIncStorage.FindOriginal(theNode);
|
||||
return anOriginal != nullptr ? *anOriginal : TopoDS_Shape();
|
||||
return myGraph->myData->myIncStorage.FindOriginal(theNode);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
TopoDS_Shape BRepGraph::ShapesView::Reconstruct(const BRepGraph_NodeId theRoot) const
|
||||
{
|
||||
if (theRoot.IsRemoved(*myGraph))
|
||||
if (!theRoot.IsValid() || theRoot.IsRemoved(*myGraph))
|
||||
{
|
||||
return TopoDS_Shape();
|
||||
}
|
||||
@@ -1141,20 +1283,19 @@ BRepGraph_NodeId BRepGraph::ShapesView::FindNode(const TopoDS_Shape& theShape) c
|
||||
return BRepGraph_NodeId();
|
||||
}
|
||||
|
||||
const BRepGraph_NodeId* aNodeId =
|
||||
myGraph->myData->myIncStorage.FindNodeByTShape(theShape.TShape().get());
|
||||
if (aNodeId != nullptr)
|
||||
const BRepGraph_NodeId aNodeId = myGraph->myData->myIncStorage.FindDefinitionByShape(theShape);
|
||||
if (aNodeId.IsValid())
|
||||
{
|
||||
if ((*aNodeId).IsRemoved(*myGraph))
|
||||
if (aNodeId.IsRemoved(*myGraph))
|
||||
{
|
||||
return BRepGraph_NodeId();
|
||||
}
|
||||
const BRepGraphInc::BaseDef* aDef = myGraph->topoEntity(*aNodeId);
|
||||
const BRepGraphInc::BaseDef* aDef = myGraph->topoEntity(aNodeId);
|
||||
if (aDef == nullptr)
|
||||
{
|
||||
return BRepGraph_NodeId();
|
||||
}
|
||||
return *aNodeId;
|
||||
return aNodeId;
|
||||
}
|
||||
return BRepGraph_NodeId();
|
||||
}
|
||||
|
||||
@@ -32,8 +32,9 @@ class TCollection_AsciiString;
|
||||
//! for repeated access. Topology nodes are delegated to the incidence-table
|
||||
//! reconstruction backend, while Product / Occurrence nodes are assembled at
|
||||
//! the facade level using product-local roots and occurrence placement chains.
|
||||
//! Provides lookup from original construction-time shapes back to their graph
|
||||
//! NodeIds via TShape pointer comparison. Shape() is the stable cached public
|
||||
//! Provides lookup from construction-time shapes back to their graph NodeIds
|
||||
//! using OCCT shape identity (TShape + Location, orientation ignored).
|
||||
//! Shape() is the stable cached public
|
||||
//! route for repeated access; Reconstruct() forces a fresh rebuild with the
|
||||
//! same node-kind semantics and bypasses the persistent reconstructed-shape cache.
|
||||
//! Add() and Compact() clear the persistent reconstructed-shape cache.
|
||||
@@ -203,7 +204,7 @@ public:
|
||||
Standard_EXPORT void ClearCached(const BRepGraph_RefId theRef);
|
||||
|
||||
//! Look up the definition NodeId for a shape from graph construction input.
|
||||
//! Uses TShape pointer comparison (same semantics as IsSame()).
|
||||
//! Uses OCCT IsSame() semantics (TShape + Location, orientation ignored).
|
||||
//! Synthetic Product / Occurrence reconstructions are not given dedicated
|
||||
//! TShape bindings, so lookup is only guaranteed for construction-time topology.
|
||||
//! Programmatically created Editor().Add*() nodes can still be located by
|
||||
@@ -213,7 +214,7 @@ public:
|
||||
[[nodiscard]] Standard_EXPORT BRepGraph_NodeId FindNode(const TopoDS_Shape& theShape) const;
|
||||
|
||||
//! Check if a shape is known to the graph (was part of construction input).
|
||||
//! Uses TShape pointer comparison (same semantics as IsSame()).
|
||||
//! Uses OCCT IsSame() semantics (TShape + Location, orientation ignored).
|
||||
//! Synthetic Product / Occurrence reconstructions are not given dedicated
|
||||
//! TShape bindings, so this is only guaranteed for construction-time topology.
|
||||
//! Programmatically created Editor().Add*() nodes can still be located by
|
||||
@@ -254,6 +255,13 @@ private:
|
||||
const TopoDS_Shape& theShape,
|
||||
NCollection_DataMap<TopoDS_Shape, BRepGraph_NodeId, TopTools_ShapeMapHasher>& theMap);
|
||||
|
||||
//! Bind source shape keys to nodes populated from a location-stripped input shape.
|
||||
//! This keeps ShapesView::FindNode() usable with the original TopoDS subshapes
|
||||
//! when root placement is stored on a Product occurrence or Compound child ref.
|
||||
static void bindSourceShapeAliases(BRepGraph& theGraph,
|
||||
const TopoDS_Shape& theSourceShape,
|
||||
const TopoDS_Shape& thePopulatedShape);
|
||||
|
||||
static BRepGraph_NodeId detectTopologyRoot(const BRepGraph& theGraph,
|
||||
const TopAbs_ShapeEnum theShapeType,
|
||||
const uint32_t theOldCountOfShapeKind);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <BRepGraph_LayerTopoSupplement.hxx>
|
||||
#include <BRepGraph_ParallelPolicy.hxx>
|
||||
#include <BRepGraphInc_Storage.hxx>
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRep_CurveOn2Surfaces.hxx>
|
||||
#include <BRep_CurveRepresentation.hxx>
|
||||
@@ -40,6 +41,7 @@
|
||||
#include <Poly_Polygon2D.hxx>
|
||||
#include <Poly_Polygon3D.hxx>
|
||||
#include <Poly_PolygonOnTriangulation.hxx>
|
||||
#include <Poly_Triangle.hxx>
|
||||
#include <TopAbs.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_CompSolid.hxx>
|
||||
@@ -53,6 +55,7 @@
|
||||
#include <TopoDS_Wire.hxx>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <utility>
|
||||
|
||||
#include "BRepGraphInc_BoundaryBuilder.pxx"
|
||||
@@ -248,7 +251,7 @@ struct ExtractedVertex
|
||||
TopoDS_Vertex Shape;
|
||||
gp_Pnt Point;
|
||||
double Tolerance = 0.0;
|
||||
TopLoc_Location BakedLocation;
|
||||
TopLoc_Location DefinitionLocation;
|
||||
bool IsGenerated = false;
|
||||
};
|
||||
|
||||
@@ -268,7 +271,7 @@ struct ExtractedEdge
|
||||
occ::handle<Poly_Polygon3D> Polygon3D;
|
||||
occ::handle<Poly_Polygon2D> PolyOnSurf;
|
||||
occ::handle<Poly_PolygonOnTriangulation> PolyOnTri;
|
||||
TopLoc_Location BakedLocation;
|
||||
TopLoc_Location DefinitionLocation;
|
||||
bool IsGenerated = false;
|
||||
};
|
||||
|
||||
@@ -281,7 +284,7 @@ struct ExtractedWire
|
||||
|
||||
TopoDS_Wire Shape;
|
||||
NCollection_DynamicArray<ExtractedEdge> Edges;
|
||||
TopLoc_Location BakedLocation;
|
||||
TopLoc_Location DefinitionLocation;
|
||||
bool IsGenerated = false;
|
||||
bool HasPartialExplorerOrder = false;
|
||||
};
|
||||
@@ -299,7 +302,7 @@ struct FaceBuildData
|
||||
occ::handle<Geom_Surface> Surface;
|
||||
occ::handle<Poly_Triangulation> RawTriangulation;
|
||||
occ::handle<Poly_Triangulation> ActiveTriangulation;
|
||||
TopLoc_Location BakedLocation;
|
||||
TopLoc_Location DefinitionLocation;
|
||||
double Tolerance = 0.0;
|
||||
bool UnsupportedNaturalBoundary = false;
|
||||
bool NeedsSynthesis = false;
|
||||
@@ -310,6 +313,7 @@ struct FacePCurveContext
|
||||
{
|
||||
occ::handle<Geom_Surface> RawSurface;
|
||||
TopLoc_Location SurfaceLocation;
|
||||
TopLoc_Location TriangulationLocation;
|
||||
};
|
||||
|
||||
static bool findStoredPCurve(
|
||||
@@ -375,7 +379,12 @@ bool rawVertexPoint(const TopoDS_Vertex& theVertex, gp_Pnt& thePoint)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
thePoint = static_cast<const BRep_TVertex*>(aTShape.get())->Pnt();
|
||||
const occ::handle<BRep_TVertex> aTVtx = occ::down_cast<BRep_TVertex>(aTShape);
|
||||
if (aTVtx.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
thePoint = aTVtx->Pnt();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -422,8 +431,8 @@ BRepGraph_LayerTopoSupplement::AttachmentKind containerSupplementKind(
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static occ::handle<T> applyBakedLocation(const occ::handle<T>& theGeom,
|
||||
const TopLoc_Location& theLocation)
|
||||
static occ::handle<T> applyDefinitionLocation(const occ::handle<T>& theGeom,
|
||||
const TopLoc_Location& theLocation)
|
||||
{
|
||||
if (theGeom.IsNull() || theLocation.IsIdentity())
|
||||
{
|
||||
@@ -432,12 +441,12 @@ static occ::handle<T> applyBakedLocation(const occ::handle<T>& theGeom,
|
||||
return occ::down_cast<T>(theGeom->Transformed(theLocation.Transformation()));
|
||||
}
|
||||
|
||||
static gp_Pnt applyBakedLocation(const gp_Pnt& thePoint, const TopLoc_Location& theLocation)
|
||||
static gp_Pnt applyDefinitionLocation(const gp_Pnt& thePoint, const TopLoc_Location& theLocation)
|
||||
{
|
||||
return theLocation.IsIdentity() ? thePoint : thePoint.Transformed(theLocation.Transformation());
|
||||
}
|
||||
|
||||
static occ::handle<Poly_Polygon3D> applyBakedLocationToPolygon3D(
|
||||
static occ::handle<Poly_Polygon3D> applyDefinitionLocationToPolygon3D(
|
||||
const occ::handle<Poly_Polygon3D>& thePolygon3D,
|
||||
const TopLoc_Location& theLocation)
|
||||
{
|
||||
@@ -472,29 +481,60 @@ static occ::handle<Poly_Polygon3D> applyBakedLocationToPolygon3D(
|
||||
return aTransPoly;
|
||||
}
|
||||
|
||||
static occ::handle<Poly_Triangulation> applyBakedLocationToTriangulation(
|
||||
static void invalidateTriangulationCachedMinMax(
|
||||
const occ::handle<Poly_Triangulation>& theTriangulation)
|
||||
{
|
||||
if (!theTriangulation.IsNull() && theTriangulation->HasCachedMinMax())
|
||||
{
|
||||
// Poly_Triangulation uses a void box as the public cache invalidation signal.
|
||||
theTriangulation->SetCachedMinMax(Bnd_Box());
|
||||
}
|
||||
}
|
||||
|
||||
static occ::handle<Poly_Triangulation> applyDefinitionLocationToTriangulation(
|
||||
const occ::handle<Poly_Triangulation>& theTriangulation,
|
||||
const TopLoc_Location& theLocation)
|
||||
{
|
||||
if (theTriangulation.IsNull() || theLocation.IsIdentity())
|
||||
if (theTriangulation.IsNull())
|
||||
{
|
||||
return theTriangulation;
|
||||
}
|
||||
|
||||
occ::handle<Poly_Triangulation> aCopy = theTriangulation->Copy();
|
||||
const gp_Trsf& aTrsf = theLocation.Transformation();
|
||||
Poly_ArrayOfNodes& aNodes = aCopy->InternalNodes();
|
||||
for (int aNodeIdx = 0; aNodeIdx < aNodes.Length(); ++aNodeIdx)
|
||||
occ::handle<Poly_Triangulation> aCopy = theTriangulation->Copy();
|
||||
if (theLocation.IsIdentity())
|
||||
{
|
||||
aNodes.SetValue(aNodeIdx, aNodes.Value(aNodeIdx).Transformed(aTrsf));
|
||||
return aCopy;
|
||||
}
|
||||
|
||||
const gp_Trsf& aTrsf = theLocation.Transformation();
|
||||
aCopy->Deflection(aCopy->Deflection() * std::abs(aTrsf.ScaleFactor()));
|
||||
for (int aNodeIdx = 1; aNodeIdx <= aCopy->NbNodes(); ++aNodeIdx)
|
||||
{
|
||||
gp_Pnt aPoint = aCopy->Node(aNodeIdx);
|
||||
aPoint.Transform(aTrsf);
|
||||
aCopy->SetNode(aNodeIdx, aPoint);
|
||||
}
|
||||
if (aCopy->HasNormals())
|
||||
{
|
||||
for (int aNodeIdx = 1; aNodeIdx <= aCopy->NbNodes(); ++aNodeIdx)
|
||||
{
|
||||
aCopy->SetNormal(aNodeIdx, aCopy->Normal(aNodeIdx).Transformed(aTrsf));
|
||||
gp_Dir aNormal = aCopy->Normal(aNodeIdx);
|
||||
aNormal.Transform(aTrsf);
|
||||
aCopy->SetNormal(aNodeIdx, aNormal);
|
||||
}
|
||||
}
|
||||
if (aTrsf.IsNegative())
|
||||
{
|
||||
for (int aTriIdx = 1; aTriIdx <= aCopy->NbTriangles(); ++aTriIdx)
|
||||
{
|
||||
int aN1 = 0;
|
||||
int aN2 = 0;
|
||||
int aN3 = 0;
|
||||
aCopy->Triangle(aTriIdx).Get(aN1, aN2, aN3);
|
||||
aCopy->SetTriangle(aTriIdx, Poly_Triangle(aN1, aN3, aN2));
|
||||
}
|
||||
}
|
||||
invalidateTriangulationCachedMinMax(aCopy);
|
||||
return aCopy;
|
||||
}
|
||||
|
||||
@@ -507,24 +547,18 @@ struct LocatedNodeBinding
|
||||
|
||||
using LocatedNodeBindingIndex = uint32_t;
|
||||
|
||||
enum class RootRole
|
||||
{
|
||||
Nested,
|
||||
Root
|
||||
};
|
||||
|
||||
struct BuildContext;
|
||||
|
||||
BRepGraph_NodeId findExistingNode(const BuildContext& theBuild,
|
||||
const TopoDS_Shape& theShape,
|
||||
BRepGraph_NodeId::Kind theExpectedKind,
|
||||
const TopLoc_Location& theBakedLocation);
|
||||
const TopLoc_Location& theDefinitionLocation);
|
||||
|
||||
void bindLocatedNode(BuildContext& theBuild,
|
||||
const TopoDS_Shape& theShape,
|
||||
const BRepGraph_NodeId theNodeId,
|
||||
const TopLoc_Location& theBakedLocation,
|
||||
const bool theBindTShape);
|
||||
const TopLoc_Location& theDefinitionLocation,
|
||||
const bool theBindShape);
|
||||
|
||||
enum class TopologyBuildMode
|
||||
{
|
||||
@@ -579,35 +613,49 @@ void recordWireOrderStatus(BuildContext& the
|
||||
theBuild.HasWireOrderWarnings = theBuild.HasWireOrderWarnings || isWireOrderWarning(theStatus);
|
||||
}
|
||||
|
||||
TopoDS_Shape definitionShapeKey(const TopoDS_Shape& theShape,
|
||||
const TopLoc_Location& theDefinitionLocation)
|
||||
{
|
||||
TopoDS_Shape aKey = theShape;
|
||||
aKey.Location(theDefinitionLocation);
|
||||
return aKey;
|
||||
}
|
||||
|
||||
TopoDS_Shape shapeWithoutOwnLocation(const TopoDS_Shape& theShape)
|
||||
{
|
||||
TopoDS_Shape aShape = theShape;
|
||||
aShape.Location(TopLoc_Location());
|
||||
return aShape;
|
||||
}
|
||||
|
||||
BRepGraph_NodeId findExistingNode(const BuildContext& theBuild,
|
||||
const TopoDS_Shape& theShape,
|
||||
BRepGraph_NodeId::Kind theExpectedKind,
|
||||
const TopLoc_Location& theBakedLocation)
|
||||
const TopLoc_Location& theDefinitionLocation)
|
||||
{
|
||||
const TopoDS_TShape* aTShape = theShape.TShape().get();
|
||||
if (theBakedLocation.IsIdentity())
|
||||
|
||||
const BRepGraph_NodeId aBoundNode =
|
||||
theBuild.Storage.FindDefinitionByShape(definitionShapeKey(theShape, theDefinitionLocation));
|
||||
if (aBoundNode.IsValid() && aBoundNode.NodeKind == theExpectedKind)
|
||||
{
|
||||
const BRepGraph_NodeId* aStoredNode = theBuild.Storage.FindNodeByTShape(aTShape);
|
||||
if (aStoredNode != nullptr && aStoredNode->NodeKind == theExpectedKind)
|
||||
{
|
||||
return *aStoredNode;
|
||||
}
|
||||
return aBoundNode;
|
||||
}
|
||||
|
||||
// Fallback: within-build LocatedNodes index for this build pass.
|
||||
const NCollection_LinearVector<LocatedNodeBindingIndex>* anIndices =
|
||||
theBuild.LocatedNodeIndex.Seek(aTShape);
|
||||
if (anIndices == nullptr)
|
||||
if (anIndices != nullptr)
|
||||
{
|
||||
return BRepGraph_NodeId();
|
||||
}
|
||||
for (const LocatedNodeBindingIndex aBindingIndex : *anIndices)
|
||||
{
|
||||
const LocatedNodeBinding& aBinding =
|
||||
theBuild.LocatedNodes.Value(static_cast<size_t>(aBindingIndex));
|
||||
if (aBinding.TShape == aTShape && aBinding.Node.NodeKind == theExpectedKind
|
||||
&& aBinding.Location.IsEqual(theBakedLocation))
|
||||
for (const LocatedNodeBindingIndex aBindingIndex : *anIndices)
|
||||
{
|
||||
return aBinding.Node;
|
||||
const LocatedNodeBinding& aBinding =
|
||||
theBuild.LocatedNodes.Value(static_cast<size_t>(aBindingIndex));
|
||||
if (aBinding.Node.NodeKind == theExpectedKind
|
||||
&& aBinding.Location.IsEqual(theDefinitionLocation))
|
||||
{
|
||||
return aBinding.Node;
|
||||
}
|
||||
}
|
||||
}
|
||||
return BRepGraph_NodeId();
|
||||
@@ -616,15 +664,15 @@ BRepGraph_NodeId findExistingNode(const BuildContext& theBuild,
|
||||
void bindLocatedNode(BuildContext& theBuild,
|
||||
const TopoDS_Shape& theShape,
|
||||
const BRepGraph_NodeId theNodeId,
|
||||
const TopLoc_Location& theBakedLocation,
|
||||
const bool theBindTShape)
|
||||
const TopLoc_Location& theDefinitionLocation,
|
||||
const bool theBindShape)
|
||||
{
|
||||
const TopoDS_TShape* aTShape = theShape.TShape().get();
|
||||
const LocatedNodeBindingIndex aBindingIndex =
|
||||
static_cast<LocatedNodeBindingIndex>(theBuild.LocatedNodes.Size());
|
||||
LocatedNodeBinding& aBinding = theBuild.LocatedNodes.Appended();
|
||||
aBinding.TShape = aTShape;
|
||||
aBinding.Location = theBakedLocation;
|
||||
aBinding.Location = theDefinitionLocation;
|
||||
aBinding.Node = theNodeId;
|
||||
|
||||
if (!theBuild.LocatedNodeIndex.IsBound(aTShape))
|
||||
@@ -633,9 +681,10 @@ void bindLocatedNode(BuildContext& theBuild,
|
||||
}
|
||||
theBuild.LocatedNodeIndex.ChangeFind(aTShape).Append(aBindingIndex);
|
||||
|
||||
if (theBindTShape && theBakedLocation.IsIdentity() && !theBuild.Storage.HasTShapeBinding(aTShape))
|
||||
if (theBindShape)
|
||||
{
|
||||
theBuild.Storage.BindTShapeToNode(aTShape, theNodeId);
|
||||
theBuild.Storage.SetDefinitionShapeBinding(definitionShapeKey(theShape, theDefinitionLocation),
|
||||
theNodeId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,7 +692,7 @@ BRepGraph_VertexId registerOrReuseVertex(BuildContext& theBuild,
|
||||
const TopoDS_Vertex& theVertex,
|
||||
const gp_Pnt& thePoint,
|
||||
const double theTolerance,
|
||||
const TopLoc_Location& theBakedLocation,
|
||||
const TopLoc_Location& theDefinitionLocation,
|
||||
const bool theIsGenerated = false)
|
||||
{
|
||||
if (theVertex.IsNull())
|
||||
@@ -651,7 +700,7 @@ BRepGraph_VertexId registerOrReuseVertex(BuildContext& theBuild,
|
||||
return BRepGraph_VertexId();
|
||||
}
|
||||
const BRepGraph_NodeId anExisting =
|
||||
findExistingNode(theBuild, theVertex, BRepGraph_NodeId::Kind::Vertex, theBakedLocation);
|
||||
findExistingNode(theBuild, theVertex, BRepGraph_NodeId::Kind::Vertex, theDefinitionLocation);
|
||||
if (anExisting.IsValid())
|
||||
{
|
||||
return BRepGraph_VertexId(anExisting);
|
||||
@@ -663,15 +712,15 @@ BRepGraph_VertexId registerOrReuseVertex(BuildContext& theBuild,
|
||||
aVtxEnt.Tolerance = theTolerance;
|
||||
if (!theIsGenerated)
|
||||
{
|
||||
bindLocatedNode(theBuild, theVertex, aVtxId, theBakedLocation, true);
|
||||
theBuild.Storage.BindOriginal(aVtxId, theVertex);
|
||||
bindLocatedNode(theBuild, theVertex, aVtxId, theDefinitionLocation, true);
|
||||
theBuild.Storage.BindOriginal(aVtxId, definitionShapeKey(theVertex, theDefinitionLocation));
|
||||
}
|
||||
return aVtxId;
|
||||
}
|
||||
|
||||
BRepGraph_VertexId registerOrReuseVertex(BuildContext& theBuild,
|
||||
const TopoDS_Vertex& theVertex,
|
||||
const TopLoc_Location& theBakedLocation)
|
||||
const TopLoc_Location& theDefinitionLocation)
|
||||
{
|
||||
if (theVertex.IsNull())
|
||||
{
|
||||
@@ -684,9 +733,9 @@ BRepGraph_VertexId registerOrReuseVertex(BuildContext& theBuild,
|
||||
}
|
||||
return registerOrReuseVertex(theBuild,
|
||||
theVertex,
|
||||
applyBakedLocation(aPoint, theBakedLocation),
|
||||
applyDefinitionLocation(aPoint, theDefinitionLocation),
|
||||
BRep_Tool::Tolerance(theVertex),
|
||||
theBakedLocation);
|
||||
theDefinitionLocation);
|
||||
}
|
||||
|
||||
bool attachNonCoreContainerChild(BuildContext& theBuild,
|
||||
@@ -738,7 +787,7 @@ static BRepGraph_VertexRefId appendEdgeVertexRef(BuildContext& theBui
|
||||
theVertex.Shape,
|
||||
theVertex.Point,
|
||||
theVertex.Tolerance,
|
||||
theVertex.BakedLocation,
|
||||
theVertex.DefinitionLocation,
|
||||
theVertex.IsGenerated);
|
||||
return appendVertexRef(theBuild.Storage, aVertexId, theOrientation, theParentEdgeId);
|
||||
}
|
||||
@@ -747,30 +796,31 @@ BRepGraph_EdgeId registerEdge(BuildContext&
|
||||
const ExtractedEdge& theEdgeData,
|
||||
const occ::handle<BRepGraph_LayerTopoSupplement>& theSupplementLayer)
|
||||
{
|
||||
if (theEdgeData.IsGenerated)
|
||||
// Generated edges are not deduplicated; skip the existing-node lookup
|
||||
// so each generated edge always creates a fresh representation.
|
||||
if (!theEdgeData.IsGenerated)
|
||||
{
|
||||
// Generated edges are not deduplicated; each gets its own representation.
|
||||
}
|
||||
const BRepGraph_NodeId anExisting = findExistingNode(theBuild,
|
||||
theEdgeData.Shape,
|
||||
BRepGraph_NodeId::Kind::Edge,
|
||||
theEdgeData.BakedLocation);
|
||||
if (anExisting.IsValid())
|
||||
{
|
||||
const BRepGraph_EdgeId anEdgeId(anExisting);
|
||||
BRepGraphInc::EdgeDef& anEdgeEnt = theBuild.Storage.ChangeEdge(anEdgeId);
|
||||
if (!anEdgeEnt.Polygon3DRepId.IsValid() && !theEdgeData.Polygon3D.IsNull())
|
||||
const BRepGraph_NodeId anExisting = findExistingNode(theBuild,
|
||||
theEdgeData.Shape,
|
||||
BRepGraph_NodeId::Kind::Edge,
|
||||
theEdgeData.DefinitionLocation);
|
||||
if (anExisting.IsValid())
|
||||
{
|
||||
const BRepGraph_EdgePolygon3DRepId aRepId = theBuild.Storage.AppendEdgePolygon3DRep();
|
||||
theBuild.Storage.ChangeEdgePolygon3DRep(aRepId).Polygon = theEdgeData.Polygon3D;
|
||||
anEdgeEnt.Polygon3DRepId = aRepId;
|
||||
if (anEdgeEnt.Polygon3DRepId.IsValid())
|
||||
const BRepGraph_EdgeId anEdgeId(anExisting);
|
||||
BRepGraphInc::EdgeDef& anEdgeEnt = theBuild.Storage.ChangeEdge(anEdgeId);
|
||||
if (!anEdgeEnt.Polygon3DRepId.IsValid() && !theEdgeData.Polygon3D.IsNull())
|
||||
{
|
||||
theBuild.Storage.ChangeEdgePolygon3DRep(anEdgeEnt.Polygon3DRepId).ParentEdgeId = anEdgeId;
|
||||
const BRepGraph_EdgePolygon3DRepId aRepId = theBuild.Storage.AppendEdgePolygon3DRep();
|
||||
theBuild.Storage.ChangeEdgePolygon3DRep(aRepId).Polygon = theEdgeData.Polygon3D;
|
||||
anEdgeEnt.Polygon3DRepId = aRepId;
|
||||
if (anEdgeEnt.Polygon3DRepId.IsValid())
|
||||
{
|
||||
theBuild.Storage.ChangeEdgePolygon3DRep(anEdgeEnt.Polygon3DRepId).ParentEdgeId = anEdgeId;
|
||||
}
|
||||
}
|
||||
return anEdgeId;
|
||||
}
|
||||
return anEdgeId;
|
||||
}
|
||||
} // if (!theEdgeData.IsGenerated)
|
||||
|
||||
const BRepGraph_EdgeId anEdgeId = theBuild.Storage.AppendEdge();
|
||||
BRepGraphInc::EdgeDef& anEdgeEnt = theBuild.Storage.ChangeEdge(anEdgeId);
|
||||
@@ -820,8 +870,10 @@ BRepGraph_EdgeId registerEdge(BuildContext&
|
||||
|
||||
if (!theEdgeData.IsGenerated)
|
||||
{
|
||||
bindLocatedNode(theBuild, theEdgeData.Shape, anEdgeId, theEdgeData.BakedLocation, true);
|
||||
theBuild.Storage.BindOriginal(anEdgeId, theEdgeData.Shape);
|
||||
bindLocatedNode(theBuild, theEdgeData.Shape, anEdgeId, theEdgeData.DefinitionLocation, true);
|
||||
theBuild.Storage.BindOriginal(
|
||||
anEdgeId,
|
||||
definitionShapeKey(theEdgeData.Shape, theEdgeData.DefinitionLocation));
|
||||
attachSupplement(theSupplementLayer, anEdgeId, theEdgeData.Shape);
|
||||
}
|
||||
return anEdgeId;
|
||||
@@ -829,18 +881,14 @@ BRepGraph_EdgeId registerEdge(BuildContext&
|
||||
|
||||
BRepGraph_WireId appendWireDef(BuildContext& theBuild,
|
||||
const TopoDS_Wire& theWire,
|
||||
const bool theBindTShape,
|
||||
const TopLoc_Location& theBakedLocation,
|
||||
const TopLoc_Location& theDefinitionLocation,
|
||||
const bool theIsGenerated = false)
|
||||
{
|
||||
const BRepGraph_WireId aWireId = theBuild.Storage.AppendWire();
|
||||
if (!theIsGenerated && theBindTShape)
|
||||
{
|
||||
bindLocatedNode(theBuild, theWire, aWireId, theBakedLocation, true);
|
||||
}
|
||||
if (!theIsGenerated)
|
||||
{
|
||||
theBuild.Storage.BindOriginal(aWireId, theWire);
|
||||
bindLocatedNode(theBuild, theWire, aWireId, theDefinitionLocation, true);
|
||||
theBuild.Storage.BindOriginal(aWireId, definitionShapeKey(theWire, theDefinitionLocation));
|
||||
}
|
||||
return aWireId;
|
||||
}
|
||||
@@ -926,10 +974,10 @@ static void extractEdgeDefinition(ExtractedEdge& theEdgeData,
|
||||
const TopoDS_Edge& theEdge,
|
||||
const TopLoc_Location& theParentLocation)
|
||||
{
|
||||
theEdgeData.Shape = theEdge;
|
||||
theEdgeData.Tolerance = BRep_Tool::Tolerance(theEdge);
|
||||
theEdgeData.OrientationInWire = theEdge.Orientation();
|
||||
theEdgeData.BakedLocation = theParentLocation * theEdge.Location();
|
||||
theEdgeData.Shape = theEdge;
|
||||
theEdgeData.Tolerance = BRep_Tool::Tolerance(theEdge);
|
||||
theEdgeData.OrientationInWire = theEdge.Orientation();
|
||||
theEdgeData.DefinitionLocation = theParentLocation * theEdge.Location();
|
||||
|
||||
{
|
||||
double aFirst = 0.0, aLast = 0.0;
|
||||
@@ -938,7 +986,8 @@ static void extractEdgeDefinition(ExtractedEdge& theEdgeData,
|
||||
theEdgeData.ParamFirst = aFirst;
|
||||
theEdgeData.ParamLast = aLast;
|
||||
theEdgeData.Curve3d =
|
||||
applyBakedLocation<Geom_Curve>(theEdgeData.Curve3d, theParentLocation * aCurveCombinedLoc);
|
||||
applyDefinitionLocation<Geom_Curve>(theEdgeData.Curve3d,
|
||||
theParentLocation * aCurveCombinedLoc);
|
||||
}
|
||||
|
||||
TopoDS_Vertex aVFirst, aVLast;
|
||||
@@ -946,25 +995,26 @@ static void extractEdgeDefinition(ExtractedEdge& theEdgeData,
|
||||
gp_Pnt aVertexPoint;
|
||||
if (!aVFirst.IsNull() && rawVertexPoint(aVFirst, aVertexPoint))
|
||||
{
|
||||
theEdgeData.StartVertex.Shape = aVFirst;
|
||||
theEdgeData.StartVertex.BakedLocation = theEdgeData.BakedLocation * aVFirst.Location();
|
||||
theEdgeData.StartVertex.Shape = aVFirst;
|
||||
theEdgeData.StartVertex.DefinitionLocation =
|
||||
theEdgeData.DefinitionLocation * aVFirst.Location();
|
||||
theEdgeData.StartVertex.Point =
|
||||
applyBakedLocation(aVertexPoint, theEdgeData.StartVertex.BakedLocation);
|
||||
applyDefinitionLocation(aVertexPoint, theEdgeData.StartVertex.DefinitionLocation);
|
||||
theEdgeData.StartVertex.Tolerance = BRep_Tool::Tolerance(aVFirst);
|
||||
}
|
||||
if (!aVLast.IsNull() && rawVertexPoint(aVLast, aVertexPoint))
|
||||
{
|
||||
theEdgeData.EndVertex.Shape = aVLast;
|
||||
theEdgeData.EndVertex.BakedLocation = theEdgeData.BakedLocation * aVLast.Location();
|
||||
theEdgeData.EndVertex.Shape = aVLast;
|
||||
theEdgeData.EndVertex.DefinitionLocation = theEdgeData.DefinitionLocation * aVLast.Location();
|
||||
theEdgeData.EndVertex.Point =
|
||||
applyBakedLocation(aVertexPoint, theEdgeData.EndVertex.BakedLocation);
|
||||
applyDefinitionLocation(aVertexPoint, theEdgeData.EndVertex.DefinitionLocation);
|
||||
theEdgeData.EndVertex.Tolerance = BRep_Tool::Tolerance(aVLast);
|
||||
}
|
||||
|
||||
TopLoc_Location aPoly3DLoc;
|
||||
theEdgeData.Polygon3D = BRep_Tool::Polygon3D(theEdge, aPoly3DLoc);
|
||||
theEdgeData.Polygon3D =
|
||||
applyBakedLocationToPolygon3D(theEdgeData.Polygon3D, theParentLocation * aPoly3DLoc);
|
||||
applyDefinitionLocationToPolygon3D(theEdgeData.Polygon3D, theParentLocation * aPoly3DLoc);
|
||||
}
|
||||
|
||||
static void extractEdgeInFace(ExtractedEdge& theEdgeData,
|
||||
@@ -988,9 +1038,14 @@ static void extractEdgeInFace(ExtractedEdge& theEdgeData
|
||||
theEdgeData.PolyOnSurf = BRep_Tool::PolygonOnSurface(theEdge, theForwardFace);
|
||||
if (!theTriangulation.IsNull())
|
||||
{
|
||||
TopLoc_Location aPolyTriLoc;
|
||||
// This lookup uses the source OCCT representation key. BRep_Tool
|
||||
// compares L.Predivided(E.Location()) with the location stored in the
|
||||
// BRep_PolygonOnTriangulation representation, so pass the raw location
|
||||
// returned by BRep_Tool::Triangulation(aFace, ...), not graph placement.
|
||||
theEdgeData.PolyOnTri =
|
||||
BRep_Tool::PolygonOnTriangulation(theEdge, theTriangulation, aPolyTriLoc);
|
||||
BRep_Tool::PolygonOnTriangulation(theEdge,
|
||||
theTriangulation,
|
||||
thePCurveContext.TriangulationLocation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1123,26 +1178,28 @@ static bool hasInfiniteRequiredBound(const occ::handle<Geom_Surface>& theSurface
|
||||
|
||||
void extractFaceData(FaceBuildData& theData)
|
||||
{
|
||||
const TopoDS_Face& aFace = theData.Face;
|
||||
const TopLoc_Location aFaceParentLocation = theData.BakedLocation * aFace.Location().Inverted();
|
||||
const TopoDS_Face& aFace = theData.Face;
|
||||
const TopLoc_Location aFaceParentLocation =
|
||||
theData.DefinitionLocation * aFace.Location().Inverted();
|
||||
|
||||
TopLoc_Location aSurfCombinedLoc;
|
||||
occ::handle<Geom_Surface> aRawSurface = BRep_Tool::Surface(aFace, aSurfCombinedLoc);
|
||||
theData.Surface =
|
||||
applyBakedLocation<Geom_Surface>(aRawSurface, aFaceParentLocation * aSurfCombinedLoc);
|
||||
applyDefinitionLocation<Geom_Surface>(aRawSurface, aFaceParentLocation * aSurfCombinedLoc);
|
||||
|
||||
TopLoc_Location aTriangulationLoc;
|
||||
theData.RawTriangulation = BRep_Tool::Triangulation(aFace, aTriangulationLoc);
|
||||
theData.ActiveTriangulation =
|
||||
applyBakedLocationToTriangulation(theData.RawTriangulation,
|
||||
aFaceParentLocation * aTriangulationLoc);
|
||||
applyDefinitionLocationToTriangulation(theData.RawTriangulation,
|
||||
aFaceParentLocation * aTriangulationLoc);
|
||||
|
||||
theData.Tolerance = BRep_Tool::Tolerance(aFace);
|
||||
|
||||
const TopoDS_Face aForwardFace = TopoDS::Face(aFace.Oriented(TopAbs_FORWARD));
|
||||
FacePCurveContext aPCurveContext;
|
||||
aPCurveContext.RawSurface = aRawSurface;
|
||||
aPCurveContext.SurfaceLocation = aSurfCombinedLoc;
|
||||
aPCurveContext.RawSurface = aRawSurface;
|
||||
aPCurveContext.SurfaceLocation = aSurfCombinedLoc;
|
||||
aPCurveContext.TriangulationLocation = aTriangulationLoc;
|
||||
|
||||
for (TopoDS_Iterator aChildIt(aForwardFace, false, false); aChildIt.More(); aChildIt.Next())
|
||||
{
|
||||
@@ -1153,9 +1210,9 @@ void extractFaceData(FaceBuildData& theData)
|
||||
}
|
||||
const TopoDS_Wire& aWire = TopoDS::Wire(aChild);
|
||||
|
||||
ExtractedWire& aWireData = theData.Wires.Appended();
|
||||
aWireData.Shape = aWire;
|
||||
aWireData.BakedLocation = theData.BakedLocation * aWire.Location();
|
||||
ExtractedWire& aWireData = theData.Wires.Appended();
|
||||
aWireData.Shape = aWire;
|
||||
aWireData.DefinitionLocation = theData.DefinitionLocation * aWire.Location();
|
||||
|
||||
for (TopoDS_Iterator anEdgeIt(aWire, false, false); anEdgeIt.More(); anEdgeIt.Next())
|
||||
{
|
||||
@@ -1170,7 +1227,7 @@ void extractFaceData(FaceBuildData& theData)
|
||||
aForwardFace,
|
||||
theData.RawTriangulation,
|
||||
aPCurveContext,
|
||||
aWireData.BakedLocation);
|
||||
aWireData.DefinitionLocation);
|
||||
}
|
||||
aWireData.HasPartialExplorerOrder =
|
||||
!orderExtractedWire(aWireData, aRawSurface.IsNull() ? nullptr : &aForwardFace);
|
||||
@@ -1224,8 +1281,7 @@ void registerFaceData(BuildContext& theBuild
|
||||
{
|
||||
const BRepGraph_WireId aWireId = appendWireDef(theBuild,
|
||||
aWireData.Shape,
|
||||
false,
|
||||
aWireData.BakedLocation,
|
||||
aWireData.DefinitionLocation,
|
||||
aWireData.IsGenerated);
|
||||
appendWireRef(theStorage, aFaceId, aWireId, aWireData.Shape.Orientation());
|
||||
|
||||
@@ -1298,7 +1354,10 @@ void synthesizeFaceBoundaries(BuildContext& theBuild,
|
||||
for (const BRepGraphInc_BoundaryBuilder::SurfaceBoundaryEdge& aBoundaryEdge : aBoundary.Edges)
|
||||
{
|
||||
BRepGraph_EdgeCurve3DRepId aCurveRepId;
|
||||
if (!aBoundaryEdge.Curve3D.IsNull())
|
||||
// Skip storing 3D curve for degenerate edges so the derived-state cache
|
||||
// correctly flags them as degenerate rather than treating the non-null
|
||||
// 3D curve as evidence of a non-degenerate geometry edge.
|
||||
if (!aBoundaryEdge.Curve3D.IsNull() && !aBoundaryEdge.IsDegenerate)
|
||||
{
|
||||
aCurveRepId = theStorage.AppendEdgeCurve3DRep();
|
||||
theStorage.ChangeEdgeCurve3DRep(aCurveRepId).Curve = aBoundaryEdge.Curve3D;
|
||||
@@ -1381,37 +1440,35 @@ BRepGraph_NodeId enqueueFace(BuildContext& theBuild,
|
||||
const TopoDS_Face& theFace,
|
||||
const TopLoc_Location& theParentLocation)
|
||||
{
|
||||
const TopLoc_Location aBakedLocation = theParentLocation * theFace.Location();
|
||||
const TopLoc_Location aDefinitionLocation = theParentLocation * theFace.Location();
|
||||
const BRepGraph_NodeId anExisting =
|
||||
findExistingNode(theBuild, theFace, BRepGraph_NodeId::Kind::Face, aBakedLocation);
|
||||
findExistingNode(theBuild, theFace, BRepGraph_NodeId::Kind::Face, aDefinitionLocation);
|
||||
if (anExisting.IsValid())
|
||||
{
|
||||
return anExisting;
|
||||
}
|
||||
|
||||
const BRepGraph_FaceId aFaceId = theBuild.Storage.AppendFace();
|
||||
bindLocatedNode(theBuild, theFace, aFaceId, aBakedLocation, true);
|
||||
theBuild.Storage.BindOriginal(aFaceId, theFace);
|
||||
bindLocatedNode(theBuild, theFace, aFaceId, aDefinitionLocation, true);
|
||||
theBuild.Storage.BindOriginal(aFaceId, definitionShapeKey(theFace, aDefinitionLocation));
|
||||
attachSupplement(theBuild.SupplementLayer, aFaceId, theFace);
|
||||
|
||||
FaceBuildData& aFaceData = theBuild.PendingFaces.Appended();
|
||||
aFaceData.Face = theFace;
|
||||
aFaceData.FaceId = aFaceId;
|
||||
aFaceData.BakedLocation = aBakedLocation;
|
||||
FaceBuildData& aFaceData = theBuild.PendingFaces.Appended();
|
||||
aFaceData.Face = theFace;
|
||||
aFaceData.FaceId = aFaceId;
|
||||
aFaceData.DefinitionLocation = aDefinitionLocation;
|
||||
return BRepGraph_NodeId(aFaceId);
|
||||
}
|
||||
|
||||
BRepGraph_NodeId traverseTopology(BuildContext& theBuild,
|
||||
const TopoDS_Shape& theCurrentShape,
|
||||
const TopLoc_Location& theParentLocation,
|
||||
const RootRole theRootRole = RootRole::Nested);
|
||||
const TopLoc_Location& theParentLocation);
|
||||
|
||||
BRepGraph_NodeId traverseCompound(BuildContext& theBuild,
|
||||
const TopoDS_Compound& theCompound,
|
||||
const RootRole theRootRole)
|
||||
const TopLoc_Location& theParentLocation)
|
||||
{
|
||||
const TopLoc_Location aDefinitionLocation =
|
||||
theRootRole == RootRole::Root ? theCompound.Location() : TopLoc_Location();
|
||||
const TopLoc_Location aDefinitionLocation = theParentLocation * theCompound.Location();
|
||||
const BRepGraph_NodeId anExisting =
|
||||
findExistingNode(theBuild, theCompound, BRepGraph_NodeId::Kind::Compound, aDefinitionLocation);
|
||||
if (anExisting.IsValid())
|
||||
@@ -1421,9 +1478,7 @@ BRepGraph_NodeId traverseCompound(BuildContext& theBuild,
|
||||
|
||||
const BRepGraph_CompoundId aCompId = theBuild.Storage.AppendCompound();
|
||||
bindLocatedNode(theBuild, theCompound, aCompId, aDefinitionLocation, true);
|
||||
theBuild.Storage.BindOriginal(aCompId, theCompound);
|
||||
|
||||
const TopLoc_Location aChildRootLocation = aDefinitionLocation;
|
||||
theBuild.Storage.BindOriginal(aCompId, definitionShapeKey(theCompound, aDefinitionLocation));
|
||||
|
||||
for (TopoDS_Iterator aChildIt(theCompound, false, false); aChildIt.More(); aChildIt.Next())
|
||||
{
|
||||
@@ -1435,15 +1490,16 @@ BRepGraph_NodeId traverseCompound(BuildContext& theBuild,
|
||||
attachNonCoreContainerChild(theBuild, BRepGraph_NodeId(aCompId), TopAbs_COMPOUND, aChild);
|
||||
continue;
|
||||
}
|
||||
const TopoDS_Shape aDefinitionChild = shapeWithoutOwnLocation(aChild);
|
||||
const BRepGraph_NodeId aChildNode =
|
||||
traverseTopology(theBuild, aChild, TopLoc_Location(), RootRole::Nested);
|
||||
traverseTopology(theBuild, aDefinitionChild, TopLoc_Location());
|
||||
if (aChildNode.IsValid())
|
||||
{
|
||||
appendChildRef(theBuild.Storage,
|
||||
aCompId,
|
||||
aChildNode,
|
||||
aChildOri,
|
||||
aChildRootLocation * aChild.Location());
|
||||
aDefinitionLocation * aChild.Location());
|
||||
}
|
||||
}
|
||||
return BRepGraph_NodeId(aCompId);
|
||||
@@ -1453,17 +1509,19 @@ BRepGraph_NodeId traverseCompSolid(BuildContext& theBuild,
|
||||
const TopoDS_CompSolid& theCompSolid,
|
||||
const TopLoc_Location& theParentLocation)
|
||||
{
|
||||
const TopLoc_Location aBakedLocation = theParentLocation * theCompSolid.Location();
|
||||
const BRepGraph_NodeId anExisting =
|
||||
findExistingNode(theBuild, theCompSolid, BRepGraph_NodeId::Kind::CompSolid, aBakedLocation);
|
||||
const TopLoc_Location aDefinitionLocation = theParentLocation * theCompSolid.Location();
|
||||
const BRepGraph_NodeId anExisting = findExistingNode(theBuild,
|
||||
theCompSolid,
|
||||
BRepGraph_NodeId::Kind::CompSolid,
|
||||
aDefinitionLocation);
|
||||
if (anExisting.IsValid())
|
||||
{
|
||||
return anExisting;
|
||||
}
|
||||
|
||||
const BRepGraph_CompSolidId aCSolidId = theBuild.Storage.AppendCompSolid();
|
||||
bindLocatedNode(theBuild, theCompSolid, aCSolidId, aBakedLocation, true);
|
||||
theBuild.Storage.BindOriginal(aCSolidId, theCompSolid);
|
||||
bindLocatedNode(theBuild, theCompSolid, aCSolidId, aDefinitionLocation, true);
|
||||
theBuild.Storage.BindOriginal(aCSolidId, definitionShapeKey(theCompSolid, aDefinitionLocation));
|
||||
|
||||
for (TopoDS_Iterator aChildIt(theCompSolid, false, false); aChildIt.More(); aChildIt.Next())
|
||||
{
|
||||
@@ -1476,7 +1534,7 @@ BRepGraph_NodeId traverseCompSolid(BuildContext& theBuild,
|
||||
continue;
|
||||
}
|
||||
|
||||
const BRepGraph_NodeId aChildNode = traverseTopology(theBuild, aChild, aBakedLocation);
|
||||
const BRepGraph_NodeId aChildNode = traverseTopology(theBuild, aChild, aDefinitionLocation);
|
||||
if (!aChildNode.IsValid() || aChildNode.NodeKind != BRepGraph_NodeId::Kind::Solid)
|
||||
{
|
||||
continue;
|
||||
@@ -1494,17 +1552,17 @@ BRepGraph_NodeId traverseSolid(BuildContext& theBuild,
|
||||
const TopoDS_Solid& theSolid,
|
||||
const TopLoc_Location& theParentLocation)
|
||||
{
|
||||
const TopLoc_Location aBakedLocation = theParentLocation * theSolid.Location();
|
||||
const TopLoc_Location aDefinitionLocation = theParentLocation * theSolid.Location();
|
||||
const BRepGraph_NodeId anExisting =
|
||||
findExistingNode(theBuild, theSolid, BRepGraph_NodeId::Kind::Solid, aBakedLocation);
|
||||
findExistingNode(theBuild, theSolid, BRepGraph_NodeId::Kind::Solid, aDefinitionLocation);
|
||||
if (anExisting.IsValid())
|
||||
{
|
||||
return anExisting;
|
||||
}
|
||||
|
||||
const BRepGraph_SolidId aSolidId = theBuild.Storage.AppendSolid();
|
||||
bindLocatedNode(theBuild, theSolid, aSolidId, aBakedLocation, true);
|
||||
theBuild.Storage.BindOriginal(aSolidId, theSolid);
|
||||
bindLocatedNode(theBuild, theSolid, aSolidId, aDefinitionLocation, true);
|
||||
theBuild.Storage.BindOriginal(aSolidId, definitionShapeKey(theSolid, aDefinitionLocation));
|
||||
|
||||
for (TopoDS_Iterator aChildIt(theSolid, false, false); aChildIt.More(); aChildIt.Next())
|
||||
{
|
||||
@@ -1517,7 +1575,7 @@ BRepGraph_NodeId traverseSolid(BuildContext& theBuild,
|
||||
continue;
|
||||
}
|
||||
|
||||
const BRepGraph_NodeId aChildNode = traverseTopology(theBuild, aChild, aBakedLocation);
|
||||
const BRepGraph_NodeId aChildNode = traverseTopology(theBuild, aChild, aDefinitionLocation);
|
||||
if (!aChildNode.IsValid() || aChildNode.NodeKind != BRepGraph_NodeId::Kind::Shell)
|
||||
{
|
||||
continue;
|
||||
@@ -1535,17 +1593,17 @@ BRepGraph_NodeId traverseShell(BuildContext& theBuild,
|
||||
const TopoDS_Shell& theShell,
|
||||
const TopLoc_Location& theParentLocation)
|
||||
{
|
||||
const TopLoc_Location aBakedLocation = theParentLocation * theShell.Location();
|
||||
const TopLoc_Location aDefinitionLocation = theParentLocation * theShell.Location();
|
||||
const BRepGraph_NodeId anExisting =
|
||||
findExistingNode(theBuild, theShell, BRepGraph_NodeId::Kind::Shell, aBakedLocation);
|
||||
findExistingNode(theBuild, theShell, BRepGraph_NodeId::Kind::Shell, aDefinitionLocation);
|
||||
if (anExisting.IsValid())
|
||||
{
|
||||
return anExisting;
|
||||
}
|
||||
|
||||
const BRepGraph_ShellId aShellId = theBuild.Storage.AppendShell();
|
||||
bindLocatedNode(theBuild, theShell, aShellId, aBakedLocation, true);
|
||||
theBuild.Storage.BindOriginal(aShellId, theShell);
|
||||
bindLocatedNode(theBuild, theShell, aShellId, aDefinitionLocation, true);
|
||||
theBuild.Storage.BindOriginal(aShellId, definitionShapeKey(theShell, aDefinitionLocation));
|
||||
|
||||
for (TopoDS_Iterator aChildIt(theShell, false, false); aChildIt.More(); aChildIt.Next())
|
||||
{
|
||||
@@ -1559,7 +1617,7 @@ BRepGraph_NodeId traverseShell(BuildContext& theBuild,
|
||||
}
|
||||
|
||||
const TopoDS_Face aFace = TopoDS::Face(aChild);
|
||||
const BRepGraph_NodeId aFaceNode = enqueueFace(theBuild, aFace, aBakedLocation);
|
||||
const BRepGraph_NodeId aFaceNode = enqueueFace(theBuild, aFace, aDefinitionLocation);
|
||||
appendFaceRef(theBuild.Storage, aShellId, BRepGraph_FaceId::FromNodeId(aFaceNode), aChildOri);
|
||||
}
|
||||
return BRepGraph_NodeId(aShellId);
|
||||
@@ -1569,18 +1627,18 @@ BRepGraph_NodeId traverseWire(BuildContext& theBuild,
|
||||
const TopoDS_Wire& theWire,
|
||||
const TopLoc_Location& theParentLocation)
|
||||
{
|
||||
const TopLoc_Location aBakedLocation = theParentLocation * theWire.Location();
|
||||
const TopLoc_Location aDefinitionLocation = theParentLocation * theWire.Location();
|
||||
const BRepGraph_NodeId anExisting =
|
||||
findExistingNode(theBuild, theWire, BRepGraph_NodeId::Kind::Wire, aBakedLocation);
|
||||
findExistingNode(theBuild, theWire, BRepGraph_NodeId::Kind::Wire, aDefinitionLocation);
|
||||
if (anExisting.IsValid())
|
||||
{
|
||||
return anExisting;
|
||||
}
|
||||
|
||||
const BRepGraph_WireId aWireId = appendWireDef(theBuild, theWire, true, aBakedLocation);
|
||||
const BRepGraph_WireId aWireId = appendWireDef(theBuild, theWire, aDefinitionLocation);
|
||||
ExtractedWire aWireData;
|
||||
aWireData.Shape = theWire;
|
||||
aWireData.BakedLocation = aBakedLocation;
|
||||
aWireData.Shape = theWire;
|
||||
aWireData.DefinitionLocation = aDefinitionLocation;
|
||||
|
||||
for (TopoDS_Iterator anEdgeIt(theWire, false, false); anEdgeIt.More(); anEdgeIt.Next())
|
||||
{
|
||||
@@ -1591,7 +1649,7 @@ BRepGraph_NodeId traverseWire(BuildContext& theBuild,
|
||||
}
|
||||
|
||||
ExtractedEdge& anEdgeData = aWireData.Edges.Appended();
|
||||
extractEdgeDefinition(anEdgeData, TopoDS::Edge(anEdgeShape), aBakedLocation);
|
||||
extractEdgeDefinition(anEdgeData, TopoDS::Edge(anEdgeShape), aDefinitionLocation);
|
||||
}
|
||||
|
||||
theBuild.HasWireOrderWarnings =
|
||||
@@ -1614,9 +1672,9 @@ BRepGraph_NodeId traverseEdge(BuildContext& theBuild,
|
||||
const TopoDS_Edge& theEdge,
|
||||
const TopLoc_Location& theParentLocation)
|
||||
{
|
||||
const TopLoc_Location aBakedLocation = theParentLocation * theEdge.Location();
|
||||
const TopLoc_Location aDefinitionLocation = theParentLocation * theEdge.Location();
|
||||
const BRepGraph_NodeId anExisting =
|
||||
findExistingNode(theBuild, theEdge, BRepGraph_NodeId::Kind::Edge, aBakedLocation);
|
||||
findExistingNode(theBuild, theEdge, BRepGraph_NodeId::Kind::Edge, aDefinitionLocation);
|
||||
if (anExisting.IsValid())
|
||||
{
|
||||
return anExisting;
|
||||
@@ -1629,13 +1687,12 @@ BRepGraph_NodeId traverseEdge(BuildContext& theBuild,
|
||||
|
||||
BRepGraph_NodeId registerTopology(BuildContext& theBuild,
|
||||
const TopoDS_Shape& theCurrentShape,
|
||||
const TopLoc_Location& theParentLocation,
|
||||
const RootRole theRootRole)
|
||||
const TopLoc_Location& theParentLocation)
|
||||
{
|
||||
switch (theCurrentShape.ShapeType())
|
||||
{
|
||||
case TopAbs_COMPOUND:
|
||||
return traverseCompound(theBuild, TopoDS::Compound(theCurrentShape), theRootRole);
|
||||
return traverseCompound(theBuild, TopoDS::Compound(theCurrentShape), theParentLocation);
|
||||
case TopAbs_COMPSOLID:
|
||||
return traverseCompSolid(theBuild, TopoDS::CompSolid(theCurrentShape), theParentLocation);
|
||||
case TopAbs_SOLID:
|
||||
@@ -1662,22 +1719,22 @@ void traverseFlattenedChildren(BuildContext& theBuild,
|
||||
const TopoDS_Shape& theContainer,
|
||||
const TopLoc_Location& theParentLocation)
|
||||
{
|
||||
const TopAbs_ShapeEnum aContainerType = theContainer.ShapeType();
|
||||
const TopLoc_Location aContainerLocation = theParentLocation * theContainer.Location();
|
||||
const TopAbs_ShapeEnum aContainerType = theContainer.ShapeType();
|
||||
const TopLoc_Location aDefinitionLocation = theParentLocation * theContainer.Location();
|
||||
for (TopoDS_Iterator aChildIt(theContainer, false, false); aChildIt.More(); aChildIt.Next())
|
||||
{
|
||||
const TopoDS_Shape& aChild = aChildIt.Value();
|
||||
if (isForwardChildType(aContainerType, aChild.ShapeType()))
|
||||
if (isForwardChildType(aContainerType, aChild.ShapeType())
|
||||
&& isCoreParityOrientation(aChild.Orientation()))
|
||||
{
|
||||
traverseTopology(theBuild, aChild, aContainerLocation);
|
||||
traverseTopology(theBuild, aChild, aDefinitionLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BRepGraph_NodeId traverseTopology(BuildContext& theBuild,
|
||||
const TopoDS_Shape& theCurrentShape,
|
||||
const TopLoc_Location& theParentLocation,
|
||||
const RootRole theRootRole)
|
||||
const TopLoc_Location& theParentLocation)
|
||||
{
|
||||
if (theCurrentShape.IsNull())
|
||||
{
|
||||
@@ -1693,8 +1750,7 @@ BRepGraph_NodeId traverseTopology(BuildContext& theBuild,
|
||||
return BRepGraph_NodeId();
|
||||
}
|
||||
|
||||
const BRepGraph_NodeId aNode =
|
||||
registerTopology(theBuild, theCurrentShape, theParentLocation, theRootRole);
|
||||
const BRepGraph_NodeId aNode = registerTopology(theBuild, theCurrentShape, theParentLocation);
|
||||
if (theBuild.Mode == TopologyBuildMode::Flattened)
|
||||
{
|
||||
appendBuildRoot(theBuild, aNode);
|
||||
@@ -1703,9 +1759,14 @@ BRepGraph_NodeId traverseTopology(BuildContext& theBuild,
|
||||
}
|
||||
|
||||
BRepGraphInc_Populate::BuildStatus runTopologyBuild(BuildContext& theBuild,
|
||||
const TopoDS_Shape& theRootShape)
|
||||
const TopoDS_Shape& theRootShape,
|
||||
BRepGraph_NodeId* theOutRootNodeId = nullptr)
|
||||
{
|
||||
traverseTopology(theBuild, theRootShape, TopLoc_Location(), RootRole::Root);
|
||||
const BRepGraph_NodeId aRootNode = traverseTopology(theBuild, theRootShape, TopLoc_Location());
|
||||
if (theOutRootNodeId != nullptr)
|
||||
{
|
||||
*theOutRootNodeId = aRootNode;
|
||||
}
|
||||
|
||||
const uint32_t aNbPendingFaces = static_cast<uint32_t>(theBuild.PendingFaces.Size());
|
||||
if (aNbPendingFaces == 0)
|
||||
@@ -1753,14 +1814,15 @@ BRepGraphInc_Populate::BuildStatus buildTopology(
|
||||
const TopologyBuildMode theMode,
|
||||
const BRepGraphInc_Populate::Options& theOptions,
|
||||
const BuildCounts& theOldCounts,
|
||||
NCollection_LinearVector<BRepGraph_NodeId>* theAppendedRoots = nullptr)
|
||||
NCollection_LinearVector<BRepGraph_NodeId>* theAppendedRoots = nullptr,
|
||||
BRepGraph_NodeId* theOutRootNodeId = nullptr)
|
||||
{
|
||||
const occ::handle<BRepGraph_LayerTopoSupplement> aSupplementLayer =
|
||||
theGraph.LayerRegistry().Find<BRepGraph_LayerTopoSupplement>();
|
||||
|
||||
BuildContext aBuild(theStorage, theParallel, theMode, aSupplementLayer, theAppendedRoots);
|
||||
|
||||
BRepGraphInc_Populate::BuildStatus aStatus = runTopologyBuild(aBuild, theShape);
|
||||
BRepGraphInc_Populate::BuildStatus aStatus = runTopologyBuild(aBuild, theShape, theOutRootNodeId);
|
||||
(void)theOptions;
|
||||
(void)theOldCounts;
|
||||
return aStatus;
|
||||
@@ -1775,7 +1837,7 @@ BRepGraphInc_Populate::BuildStatus BRepGraphInc_Populate::Perform(BRepGraph&
|
||||
bool theParallel,
|
||||
const Options& theOptions)
|
||||
{
|
||||
theGraph.incStorage().Clear();
|
||||
theGraph.Clear();
|
||||
|
||||
if (theShape.IsNull())
|
||||
{
|
||||
|
||||
@@ -47,7 +47,6 @@ public:
|
||||
//! Options controlling population.
|
||||
struct Options
|
||||
{
|
||||
Options() = default;
|
||||
};
|
||||
|
||||
//! Build backend incidence storage from a TopoDS_Shape.
|
||||
@@ -81,7 +80,8 @@ public:
|
||||
//! Extend existing backend storage with additional shapes (no clear).
|
||||
//! Preserves the full shape hierarchy: Solid/Shell/Compound/CompSolid nodes
|
||||
//! are created alongside Face/Edge/Vertex nodes. Shapes already present in
|
||||
//! the storage (same TShape pointer) are deduplicated and not re-added.
|
||||
//! the storage with the same definition identity (TShape + Location, orientation ignored)
|
||||
//! are deduplicated and not re-added.
|
||||
//! @param[in,out] theGraph graph whose storage to extend
|
||||
//! @param[in] theShape shape to append
|
||||
//! @param[in] theParallel if true, face-level extraction runs in parallel
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <type_traits>
|
||||
|
||||
#include "BRepGraphInc_WireOrder.pxx"
|
||||
@@ -377,7 +378,7 @@ BRepGraphInc_Storage::BRepGraphInc_Storage()
|
||||
myFaceTriangulations(256, myAllocator),
|
||||
myUIDToNodeId(1),
|
||||
myRefUIDToRefId(1),
|
||||
myTShapeToNodeId(1),
|
||||
myShapeToNodeId(1),
|
||||
myOriginalShapes(1)
|
||||
{
|
||||
myAllocator->SetThreadSafe(true);
|
||||
@@ -786,7 +787,7 @@ void BRepGraphInc_Storage::ClearStorageForReuse()
|
||||
myFaceTriangulations.Clear(true);
|
||||
myNodeToCompounds.Clear();
|
||||
myNodeToOccurrences.Clear();
|
||||
myTShapeToNodeId.Clear();
|
||||
myShapeToNodeId.Clear();
|
||||
myOriginalShapes.Clear();
|
||||
myAllocator->Reset(false);
|
||||
}
|
||||
@@ -2772,14 +2773,123 @@ 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);
|
||||
});
|
||||
if (&theSource == this)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NCollection_LinearVector<std::pair<TopoDS_Shape, BRepGraph_NodeId>> aShapeBindings;
|
||||
NCollection_LinearVector<std::pair<BRepGraph_NodeId, TopoDS_Shape>> aOriginalBindings;
|
||||
theSource.ForEachShapeBinding([&](const TopoDS_Shape& aShape, const BRepGraph_NodeId aNodeId) {
|
||||
aShapeBindings.Append({aShape, aNodeId});
|
||||
});
|
||||
theSource.ForEachOriginalBinding([&](const BRepGraph_NodeId aNodeId, const TopoDS_Shape& aShape) {
|
||||
aOriginalBindings.Append({aNodeId, aShape});
|
||||
});
|
||||
|
||||
std::unique_lock<std::shared_mutex> aLock(myShapeBindingsMutex);
|
||||
myShapeToNodeId.Clear();
|
||||
myOriginalShapes.Clear();
|
||||
for (const auto& [aShape, aNodeId] : aShapeBindings)
|
||||
{
|
||||
myShapeToNodeId.Bind(aShape, aNodeId);
|
||||
}
|
||||
for (const auto& [aNodeId, aShape] : aOriginalBindings)
|
||||
{
|
||||
myOriginalShapes.Bind(aNodeId, aShape);
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
BRepGraph_NodeId BRepGraphInc_Storage::FindDefinitionByShape(const TopoDS_Shape& theShape) const
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myShapeBindingsMutex);
|
||||
const BRepGraph_NodeId* aBound = myShapeToNodeId.Seek(theShape);
|
||||
if (aBound == nullptr || !aBound->IsValid())
|
||||
{
|
||||
return BRepGraph_NodeId();
|
||||
}
|
||||
// Validate the bound node is still active in storage.
|
||||
const auto aRemovedCheck = [this](const auto theTypedId) -> bool {
|
||||
return !IsRemoved(theTypedId);
|
||||
};
|
||||
return BRepGraph_NodeId::Visit(*aBound, aRemovedCheck) ? *aBound : BRepGraph_NodeId();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraphInc_Storage::HasShapeBinding(const TopoDS_Shape& theShape) const
|
||||
{
|
||||
return FindDefinitionByShape(theShape).IsValid();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraphInc_Storage::SetDefinitionShapeBinding(const TopoDS_Shape& theShape,
|
||||
const BRepGraph_NodeId theNodeId)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myShapeBindingsMutex);
|
||||
if (auto* aBound = myShapeToNodeId.ChangeSeek(theShape))
|
||||
{
|
||||
*aBound = theNodeId;
|
||||
return;
|
||||
}
|
||||
myShapeToNodeId.Bind(theShape, theNodeId);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraphInc_Storage::RemoveDefinitionShapeBinding(const TopoDS_Shape& theShape,
|
||||
const BRepGraph_NodeId theExpectedNodeId)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myShapeBindingsMutex);
|
||||
const BRepGraph_NodeId* aBound = myShapeToNodeId.Seek(theShape);
|
||||
if (aBound == nullptr || *aBound != theExpectedNodeId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
myShapeToNodeId.UnBind(theShape);
|
||||
return true;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
TopoDS_Shape BRepGraphInc_Storage::FindOriginal(const BRepGraph_NodeId theNodeId) const
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myShapeBindingsMutex);
|
||||
const TopoDS_Shape* anOriginal = myOriginalShapes.Seek(theNodeId);
|
||||
return anOriginal != nullptr ? *anOriginal : TopoDS_Shape();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
bool BRepGraphInc_Storage::HasOriginal(const BRepGraph_NodeId theNodeId) const
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myShapeBindingsMutex);
|
||||
return myOriginalShapes.IsBound(theNodeId);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraphInc_Storage::BindOriginal(const BRepGraph_NodeId theNodeId,
|
||||
const TopoDS_Shape& theShape)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myShapeBindingsMutex);
|
||||
if (TopoDS_Shape* anOriginal = myOriginalShapes.ChangeSeek(theNodeId))
|
||||
{
|
||||
*anOriginal = theShape;
|
||||
return;
|
||||
}
|
||||
myOriginalShapes.Bind(theNodeId, theShape);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void BRepGraphInc_Storage::UnBindOriginal(const BRepGraph_NodeId theNodeId)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> aLock(myShapeBindingsMutex);
|
||||
myOriginalShapes.UnBind(theNodeId);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
@@ -3116,17 +3226,16 @@ bool BRepGraphInc_Storage::MarkRemoved(const BRepGraph_NodeId theNodeId)
|
||||
theNodeId.IsValid() ? BRepGraph_NodeId::Visit(theNodeId, aMarkRemoved) : false;
|
||||
if (isRemoved)
|
||||
{
|
||||
const TopoDS_Shape* aShape = myOriginalShapes.Seek(theNodeId);
|
||||
const TopoDS_TShape* aTShapeToUnbind =
|
||||
(aShape != nullptr && !aShape->IsNull()) ? aShape->TShape().get() : nullptr;
|
||||
myOriginalShapes.UnBind(theNodeId);
|
||||
if (aTShapeToUnbind != nullptr)
|
||||
const TopoDS_Shape* aBoundOriginal = myOriginalShapes.Seek(theNodeId);
|
||||
TopoDS_Shape aShapeToUnbind;
|
||||
if (aBoundOriginal != nullptr)
|
||||
{
|
||||
const BRepGraph_NodeId* aBound = myTShapeToNodeId.Seek(aTShapeToUnbind);
|
||||
if (aBound != nullptr && *aBound == theNodeId)
|
||||
{
|
||||
myTShapeToNodeId.UnBind(aTShapeToUnbind);
|
||||
}
|
||||
aShapeToUnbind = *aBoundOriginal;
|
||||
}
|
||||
myOriginalShapes.UnBind(theNodeId);
|
||||
if (!aShapeToUnbind.IsNull())
|
||||
{
|
||||
RemoveDefinitionShapeBinding(aShapeToUnbind, theNodeId);
|
||||
}
|
||||
}
|
||||
return isRemoved;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TopoDS_TShape.hxx>
|
||||
#include <TopTools_ShapeMapHasher.hxx>
|
||||
|
||||
#include <atomic>
|
||||
#include <shared_mutex>
|
||||
@@ -1220,55 +1221,46 @@ public:
|
||||
[[nodiscard]] Standard_EXPORT BRepGraph_RefId
|
||||
FindRefIdByUID(const BRepGraph_RefUID& theUID) const;
|
||||
|
||||
//! Returns the node id bound to the given TShape, or nullptr if not bound.
|
||||
[[nodiscard]] const BRepGraph_NodeId* FindNodeByTShape(const TopoDS_TShape* theTShape) const
|
||||
{
|
||||
return myTShapeToNodeId.Seek(theTShape);
|
||||
}
|
||||
//! Returns the node id bound to the given shape definition key, or invalid if not bound.
|
||||
[[nodiscard]] Standard_EXPORT BRepGraph_NodeId
|
||||
FindDefinitionByShape(const TopoDS_Shape& theShape) const;
|
||||
|
||||
//! Returns true if the given TShape is bound to a node.
|
||||
[[nodiscard]] bool HasTShapeBinding(const TopoDS_TShape* theTShape) const
|
||||
{
|
||||
return myTShapeToNodeId.IsBound(theTShape);
|
||||
}
|
||||
//! Returns true if the given shape definition key is bound to a node.
|
||||
[[nodiscard]] Standard_EXPORT bool HasShapeBinding(const TopoDS_Shape& theShape) const;
|
||||
|
||||
//! Binds the given TShape to a node id.
|
||||
void BindTShapeToNode(const TopoDS_TShape* theTShape, const BRepGraph_NodeId theNodeId)
|
||||
{
|
||||
myTShapeToNodeId.Bind(theTShape, theNodeId);
|
||||
}
|
||||
//! Set or update the shape-to-node binding. Uses replacement semantics:
|
||||
//! binds if absent, updates if already bound.
|
||||
Standard_EXPORT void SetDefinitionShapeBinding(const TopoDS_Shape& theShape,
|
||||
const BRepGraph_NodeId theNodeId);
|
||||
|
||||
//! Back-reference to the source `TopoDS_Shape` a node was built from.
|
||||
//! Only populated during Build; absent bindings are a valid state.
|
||||
//! Remove the shape-to-node binding only if it points to the expected node.
|
||||
//! Returns true if the binding was removed.
|
||||
Standard_EXPORT bool RemoveDefinitionShapeBinding(const TopoDS_Shape& theShape,
|
||||
const BRepGraph_NodeId theExpectedNodeId);
|
||||
|
||||
//! Returns the original shape for the given node id, or nullptr if not bound.
|
||||
[[nodiscard]] const TopoDS_Shape* FindOriginal(const BRepGraph_NodeId theNodeId) const
|
||||
{
|
||||
return myOriginalShapes.Seek(theNodeId);
|
||||
}
|
||||
//! Back-reference to the construction-time `TopoDS_Shape` key a node was built from.
|
||||
//! Only populated during graph construction; absent bindings are a valid state.
|
||||
|
||||
//! Returns the original shape for the given node id, or a null shape if not bound.
|
||||
[[nodiscard]] Standard_EXPORT TopoDS_Shape FindOriginal(const BRepGraph_NodeId theNodeId) const;
|
||||
|
||||
//! Returns true if the given node id has an original shape binding.
|
||||
[[nodiscard]] bool HasOriginal(const BRepGraph_NodeId theNodeId) const
|
||||
{
|
||||
return myOriginalShapes.IsBound(theNodeId);
|
||||
}
|
||||
[[nodiscard]] Standard_EXPORT bool HasOriginal(const BRepGraph_NodeId theNodeId) const;
|
||||
|
||||
//! Binds the given node id to its original shape.
|
||||
void BindOriginal(const BRepGraph_NodeId theNodeId, const TopoDS_Shape& theShape)
|
||||
{
|
||||
myOriginalShapes.Bind(theNodeId, theShape);
|
||||
}
|
||||
//! Binds the given node id to its construction-time shape key.
|
||||
Standard_EXPORT void BindOriginal(const BRepGraph_NodeId theNodeId, const TopoDS_Shape& theShape);
|
||||
|
||||
//! Removes the original shape binding for the given node id.
|
||||
void UnBindOriginal(const BRepGraph_NodeId theNodeId) { myOriginalShapes.UnBind(theNodeId); }
|
||||
Standard_EXPORT void UnBindOriginal(const BRepGraph_NodeId theNodeId);
|
||||
|
||||
//! Iterate all TShape-to-NodeId bindings, invoking theFunc(TShape*, NodeId) for each entry.
|
||||
//! Iterate all shape-to-NodeId bindings, invoking theFunc(shape, NodeId) for each entry.
|
||||
//! Used by Compact to rebuild the map after the rebuild-and-swap.
|
||||
template <typename FuncT>
|
||||
void ForEachTShapeBinding(FuncT&& theFunc) const
|
||||
void ForEachShapeBinding(FuncT&& theFunc) const
|
||||
{
|
||||
for (NCollection_FlatDataMap<const TopoDS_TShape*, BRepGraph_NodeId>::Iterator anIt(
|
||||
myTShapeToNodeId);
|
||||
std::shared_lock<std::shared_mutex> aLock(myShapeBindingsMutex);
|
||||
for (NCollection_FlatDataMap<TopoDS_Shape, BRepGraph_NodeId, TopTools_ShapeMapHasher>::Iterator
|
||||
anIt(myShapeToNodeId);
|
||||
anIt.More();
|
||||
anIt.Next())
|
||||
{
|
||||
@@ -1281,6 +1273,7 @@ public:
|
||||
template <typename FuncT>
|
||||
void ForEachOriginalBinding(FuncT&& theFunc) const
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> aLock(myShapeBindingsMutex);
|
||||
for (NCollection_FlatDataMap<BRepGraph_NodeId, TopoDS_Shape>::Iterator anIt(myOriginalShapes);
|
||||
anIt.More();
|
||||
anIt.Next())
|
||||
@@ -1289,7 +1282,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
//! Copy TShape-to-NodeId and Original shape bindings from another storage.
|
||||
//! Copy shape-to-NodeId and Original shape bindings from another storage.
|
||||
//! Used by identity copy to preserve shape reconstruction bindings.
|
||||
Standard_EXPORT void CopyShapeBindingsFrom(const BRepGraphInc_Storage& theSource);
|
||||
|
||||
@@ -1890,8 +1883,9 @@ private:
|
||||
mutable std::atomic<bool> myRefUIDToRefIdDirty{false};
|
||||
|
||||
//! Bindings from reconstructed / source OCCT shapes back to backend ids.
|
||||
NCollection_FlatDataMap<const TopoDS_TShape*, BRepGraph_NodeId> myTShapeToNodeId;
|
||||
NCollection_FlatDataMap<BRepGraph_NodeId, TopoDS_Shape> myOriginalShapes;
|
||||
NCollection_FlatDataMap<TopoDS_Shape, BRepGraph_NodeId, TopTools_ShapeMapHasher> myShapeToNodeId;
|
||||
NCollection_FlatDataMap<BRepGraph_NodeId, TopoDS_Shape> myOriginalShapes;
|
||||
mutable std::shared_mutex myShapeBindingsMutex;
|
||||
|
||||
//! Persistent backend identity state.
|
||||
std::atomic<uint32_t> myGeneration{0};
|
||||
|
||||
@@ -0,0 +1,501 @@
|
||||
// Copyright (c) 2026 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
#include <BRepGraph.hxx>
|
||||
#include <BRepGraph_Compact.hxx>
|
||||
#include <BRepGraph_EditorView.hxx>
|
||||
#include <BRepGraphInc_Definition.hxx>
|
||||
#include <BRepGraphInc_Populate.hxx>
|
||||
#include <BRepGraphInc_Reconstruct.hxx>
|
||||
#include <BRepGraph_CacheMesh.hxx>
|
||||
#include <BRepGraph_Iterator.hxx>
|
||||
#include <BRepGraph_LayerRegistry.hxx>
|
||||
#include <BRepGraph_LayerTopoSupplement.hxx>
|
||||
#include <BRepGraph_MeshView.hxx>
|
||||
#include <BRepGraph_RefsView.hxx>
|
||||
#include <BRepGraph_ShapesView.hxx>
|
||||
#include <BRepGraph_Tool.hxx>
|
||||
#include <BRepGraph_TopoView.hxx>
|
||||
#include <BRepMesh_IncrementalMesh.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <Geom_SphericalSurface.hxx>
|
||||
#include <Poly_Polygon3D.hxx>
|
||||
#include <Poly_PolygonOnTriangulation.hxx>
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopoDS_Iterator.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TopoDS_Solid.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopLoc_Location.hxx>
|
||||
#include <gp_Ax3.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
TopLoc_Location translationLocation(const double theX, const double theY, const double theZ)
|
||||
{
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(theX, theY, theZ));
|
||||
return TopLoc_Location(aTrsf);
|
||||
}
|
||||
|
||||
Bnd_Box geometryBounds(const TopoDS_Shape& theShape)
|
||||
{
|
||||
Bnd_Box aBox;
|
||||
BRepBndLib::AddOptimal(theShape, aBox, false, false);
|
||||
return aBox;
|
||||
}
|
||||
|
||||
Bnd_Box meshBounds(const TopoDS_Shape& theShape)
|
||||
{
|
||||
Bnd_Box aBox;
|
||||
BRepBndLib::Add(theShape, aBox, true);
|
||||
return aBox;
|
||||
}
|
||||
|
||||
void expectBoxNear(const Bnd_Box& theActual, const Bnd_Box& theExpected, const double theTol)
|
||||
{
|
||||
const Bnd_Box::Limits anActual = theActual.Get();
|
||||
const Bnd_Box::Limits anExpected = theExpected.Get();
|
||||
EXPECT_NEAR(anActual.Xmin, anExpected.Xmin, theTol);
|
||||
EXPECT_NEAR(anActual.Ymin, anExpected.Ymin, theTol);
|
||||
EXPECT_NEAR(anActual.Zmin, anExpected.Zmin, theTol);
|
||||
EXPECT_NEAR(anActual.Xmax, anExpected.Xmax, theTol);
|
||||
EXPECT_NEAR(anActual.Ymax, anExpected.Ymax, theTol);
|
||||
EXPECT_NEAR(anActual.Zmax, anExpected.Zmax, theTol);
|
||||
}
|
||||
|
||||
TopoDS_Shape firstSubShape(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType)
|
||||
{
|
||||
TopExp_Explorer anExp(theShape, theType);
|
||||
return anExp.More() ? anExp.Current() : TopoDS_Shape();
|
||||
}
|
||||
|
||||
TopoDS_Face firstFaceOfBox(const double theSize)
|
||||
{
|
||||
TopoDS_Shape aBox = BRepPrimAPI_MakeBox(theSize, theSize, theSize).Shape();
|
||||
TopoDS_Shape aFace = firstSubShape(aBox, TopAbs_FACE);
|
||||
return TopoDS::Face(aFace);
|
||||
}
|
||||
|
||||
uint32_t countSourcePolygonOnTriangulation(const TopoDS_Shape& theShape,
|
||||
const bool theUseFaceLocation,
|
||||
bool& theHasLocatedTriangulation)
|
||||
{
|
||||
uint32_t aCount = 0;
|
||||
for (TopExp_Explorer aFaceExp(theShape, TopAbs_FACE); aFaceExp.More(); aFaceExp.Next())
|
||||
{
|
||||
const TopoDS_Face& aFace = TopoDS::Face(aFaceExp.Current());
|
||||
TopLoc_Location aTriLoc;
|
||||
const occ::handle<Poly_Triangulation> aTri = BRep_Tool::Triangulation(aFace, aTriLoc);
|
||||
if (aTri.IsNull())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
theHasLocatedTriangulation = theHasLocatedTriangulation || !aTriLoc.IsIdentity();
|
||||
|
||||
for (TopExp_Explorer anEdgeExp(aFace, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next())
|
||||
{
|
||||
const TopoDS_Edge& anEdge = TopoDS::Edge(anEdgeExp.Current());
|
||||
const TopLoc_Location aLookupLoc = theUseFaceLocation ? aTriLoc : TopLoc_Location();
|
||||
if (!BRep_Tool::PolygonOnTriangulation(anEdge, aTri, aLookupLoc).IsNull())
|
||||
{
|
||||
++aCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
return aCount;
|
||||
}
|
||||
|
||||
uint32_t countGraphPolygonOnTriangulation(const BRepGraph& theGraph)
|
||||
{
|
||||
uint32_t aCount = 0;
|
||||
for (BRepGraph_CoEdgeId aCoEdgeId(0); aCoEdgeId.IsValid(theGraph.Topo().CoEdges().Nb());
|
||||
++aCoEdgeId)
|
||||
{
|
||||
if (theGraph.Topo().CoEdges().Definition(aCoEdgeId).PolygonOnTriRepId.IsValid())
|
||||
{
|
||||
++aCount;
|
||||
}
|
||||
}
|
||||
return aCount;
|
||||
}
|
||||
|
||||
TopoDS_Face makeNoWireNaturalSphereFace()
|
||||
{
|
||||
BRep_Builder aBuilder;
|
||||
TopoDS_Face aFace;
|
||||
aBuilder.MakeFace(
|
||||
aFace,
|
||||
new Geom_SphericalSurface(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 10.0),
|
||||
Precision::Confusion());
|
||||
aBuilder.NaturalRestriction(aFace, true);
|
||||
return aFace;
|
||||
}
|
||||
|
||||
uint32_t countDegeneratedEdges(const TopoDS_Shape& theShape)
|
||||
{
|
||||
uint32_t aCount = 0;
|
||||
for (TopExp_Explorer anEdgeExp(theShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next())
|
||||
{
|
||||
if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeExp.Current())))
|
||||
{
|
||||
++aCount;
|
||||
}
|
||||
}
|
||||
return aCount;
|
||||
}
|
||||
|
||||
TopoDS_Compound makeNestedCompound(const TopLoc_Location& theRootLocation,
|
||||
const TopLoc_Location& theInnerLocation,
|
||||
const TopLoc_Location& theSolidLocation)
|
||||
{
|
||||
TopoDS_Shape aBox = BRepPrimAPI_MakeBox(2.0, 3.0, 4.0).Shape();
|
||||
BRepMesh_IncrementalMesh aMesher(aBox, 0.2);
|
||||
EXPECT_TRUE(aMesher.IsDone());
|
||||
|
||||
BRep_Builder aBuilder;
|
||||
const TopoDS_Solid aMovedSolid = TopoDS::Solid(TopoDS::Solid(aBox).Moved(theSolidLocation));
|
||||
|
||||
TopoDS_Compound anInner;
|
||||
aBuilder.MakeCompound(anInner);
|
||||
aBuilder.Add(anInner, aMovedSolid);
|
||||
const TopoDS_Compound aMovedInner = TopoDS::Compound(anInner.Moved(theInnerLocation));
|
||||
|
||||
TopoDS_Compound aRoot;
|
||||
aBuilder.MakeCompound(aRoot);
|
||||
aBuilder.Add(aRoot, aMovedInner);
|
||||
return TopoDS::Compound(aRoot.Moved(theRootLocation));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(BRepGraphInc_PopulateRegressionTest, LocatedFacePolygonOnTriangulation_IsCaptured)
|
||||
{
|
||||
TopoDS_Shape aBox = BRepPrimAPI_MakeBox(10.0, 20.0, 30.0).Shape();
|
||||
BRepMesh_IncrementalMesh aMesher(aBox, 0.5);
|
||||
ASSERT_TRUE(aMesher.IsDone());
|
||||
const TopoDS_Shape aMovedBox = aBox.Moved(translationLocation(5.0, 6.0, 7.0));
|
||||
|
||||
bool hasLocatedTriangulation = false;
|
||||
const uint32_t aSourceCount =
|
||||
countSourcePolygonOnTriangulation(aMovedBox, true, hasLocatedTriangulation);
|
||||
bool hasLocatedTriangulationForIdentityProbe = false;
|
||||
const uint32_t anIdentityLookupCount =
|
||||
countSourcePolygonOnTriangulation(aMovedBox, false, hasLocatedTriangulationForIdentityProbe);
|
||||
|
||||
ASSERT_TRUE(hasLocatedTriangulation);
|
||||
ASSERT_GT(aSourceCount, 0u);
|
||||
EXPECT_EQ(anIdentityLookupCount, 0u);
|
||||
|
||||
BRepGraph aGraph;
|
||||
ASSERT_NE(BRepGraphInc_Populate::Perform(aGraph, aMovedBox, false),
|
||||
BRepGraphInc_Populate::BuildStatus::Failed);
|
||||
EXPECT_GT(countGraphPolygonOnTriangulation(aGraph), 0u);
|
||||
}
|
||||
|
||||
TEST(BRepGraphInc_PopulateRegressionTest, NoWireNaturalSphere_DegenerateBoundaryEdgesRoundTrip)
|
||||
{
|
||||
const TopoDS_Face aFace = makeNoWireNaturalSphereFace();
|
||||
|
||||
BRepGraph aGraph;
|
||||
ASSERT_NE(BRepGraphInc_Populate::Perform(aGraph, aFace, false),
|
||||
BRepGraphInc_Populate::BuildStatus::Failed);
|
||||
|
||||
uint32_t aDegenerateCount = 0;
|
||||
for (BRepGraph_EdgeId anEdgeId(0); anEdgeId.IsValid(aGraph.Topo().Edges().Nb()); ++anEdgeId)
|
||||
{
|
||||
if (BRepGraph_Tool::Edge::Degenerated(aGraph, anEdgeId))
|
||||
{
|
||||
++aDegenerateCount;
|
||||
EXPECT_FALSE(aGraph.Topo().Edges().Definition(anEdgeId).Curve3DRepId.IsValid());
|
||||
}
|
||||
}
|
||||
ASSERT_GE(aDegenerateCount, 2u);
|
||||
|
||||
const TopoDS_Shape aReconstructed =
|
||||
BRepGraphInc_Reconstruct::Node(aGraph, BRepGraph_FaceId::Start());
|
||||
ASSERT_FALSE(aReconstructed.IsNull());
|
||||
EXPECT_GE(countDegeneratedEdges(aReconstructed), 2u);
|
||||
}
|
||||
|
||||
TEST(BRepGraphInc_PopulateRegressionTest, CompoundReferencesKeepDirectSourceLocationsAtEveryLevel)
|
||||
{
|
||||
const TopLoc_Location aRootLoc = translationLocation(0.0, 0.0, 11.0);
|
||||
const TopLoc_Location anInnerLoc = translationLocation(0.0, 7.0, 0.0);
|
||||
const TopLoc_Location aSolidLoc = translationLocation(5.0, 0.0, 0.0);
|
||||
const TopoDS_Compound aMovedRoot = makeNestedCompound(aRootLoc, anInnerLoc, aSolidLoc);
|
||||
|
||||
BRepGraph aGraph;
|
||||
const BRepGraph::ShapesView::Result aResult = aGraph.Shapes().Add(aMovedRoot);
|
||||
ASSERT_TRUE(aResult.IsOk());
|
||||
ASSERT_EQ(aResult.TopologyRoot.NodeKind, BRepGraph_NodeId::Kind::Compound);
|
||||
ASSERT_TRUE(aResult.Product.IsValid());
|
||||
|
||||
const BRepGraphInc::ProductRelations& aProductRelations =
|
||||
aGraph.Topo().Products().Relations(aResult.Product);
|
||||
ASSERT_EQ(aProductRelations.OccurrenceRefIds.Size(), 1u);
|
||||
const BRepGraphInc::OccurrenceRef& anOccurrenceRef =
|
||||
aGraph.Refs().Occurrences().Entry(aProductRelations.OccurrenceRefIds.Value(0));
|
||||
EXPECT_TRUE(anOccurrenceRef.LocalLocation.IsEqual(aRootLoc));
|
||||
|
||||
const BRepGraph_CompoundId aRootCompound(aResult.TopologyRoot);
|
||||
const NCollection_LinearVector<BRepGraph_ChildRefId>& aRootRefs =
|
||||
aGraph.Topo().Compounds().Relations(aRootCompound).ChildRefIds;
|
||||
ASSERT_EQ(aRootRefs.Size(), 1u);
|
||||
const BRepGraph_ChildRefId aRootChildRef = aRootRefs.Value(0);
|
||||
EXPECT_TRUE(aGraph.Refs().Gen().LocalLocation(aRootChildRef).IsEqual(anInnerLoc));
|
||||
|
||||
const BRepGraph_NodeId anInnerNode = aGraph.Refs().Children().Entry(aRootChildRef).ChildNodeId;
|
||||
ASSERT_EQ(anInnerNode.NodeKind, BRepGraph_NodeId::Kind::Compound);
|
||||
const NCollection_LinearVector<BRepGraph_ChildRefId>& anInnerRefs =
|
||||
aGraph.Topo().Compounds().Relations(BRepGraph_CompoundId(anInnerNode)).ChildRefIds;
|
||||
ASSERT_EQ(anInnerRefs.Size(), 1u);
|
||||
EXPECT_TRUE(aGraph.Refs().Gen().LocalLocation(anInnerRefs.Value(0)).IsEqual(aSolidLoc));
|
||||
}
|
||||
|
||||
TEST(BRepGraphInc_PopulateRegressionTest, ShapeViewFindNode_AcceptsOriginalPlacedSubshapes)
|
||||
{
|
||||
const TopLoc_Location aRootLoc = translationLocation(0.0, 0.0, 11.0);
|
||||
const TopLoc_Location anInnerLoc = translationLocation(0.0, 7.0, 0.0);
|
||||
const TopLoc_Location aSolidLoc = translationLocation(5.0, 0.0, 0.0);
|
||||
const TopoDS_Compound aMovedRoot = makeNestedCompound(aRootLoc, anInnerLoc, aSolidLoc);
|
||||
|
||||
const TopoDS_Shape anOriginalSolid = firstSubShape(aMovedRoot, TopAbs_SOLID);
|
||||
const TopoDS_Shape anOriginalFace = firstSubShape(aMovedRoot, TopAbs_FACE);
|
||||
ASSERT_FALSE(anOriginalSolid.IsNull());
|
||||
ASSERT_FALSE(anOriginalFace.IsNull());
|
||||
|
||||
BRepGraph aGraph;
|
||||
const BRepGraph::ShapesView::Result aResult = aGraph.Shapes().Add(aMovedRoot);
|
||||
ASSERT_TRUE(aResult.IsOk());
|
||||
ASSERT_TRUE(aResult.TopologyRoot.IsValid());
|
||||
ASSERT_TRUE(aResult.Product.IsValid());
|
||||
|
||||
EXPECT_EQ(aGraph.Shapes().FindNode(aMovedRoot), aResult.TopologyRoot);
|
||||
EXPECT_EQ(aGraph.Shapes().FindNode(anOriginalSolid).NodeKind, BRepGraph_NodeId::Kind::Solid);
|
||||
EXPECT_EQ(aGraph.Shapes().FindNode(anOriginalFace).NodeKind, BRepGraph_NodeId::Kind::Face);
|
||||
|
||||
const TopoDS_Shape aProductShape = aGraph.Shapes().Shape(aResult.Product);
|
||||
ASSERT_FALSE(aProductShape.IsNull());
|
||||
expectBoxNear(geometryBounds(aProductShape), geometryBounds(aMovedRoot), 1.0e-6);
|
||||
expectBoxNear(meshBounds(aProductShape), meshBounds(aMovedRoot), 1.0e-6);
|
||||
|
||||
TopoDS_Shape aRootLocalShape = aMovedRoot;
|
||||
aRootLocalShape.Location(TopLoc_Location());
|
||||
const TopoDS_Shape aTopologyShape = aGraph.Shapes().Shape(aResult.TopologyRoot);
|
||||
ASSERT_FALSE(aTopologyShape.IsNull());
|
||||
expectBoxNear(geometryBounds(aTopologyShape), geometryBounds(aRootLocalShape), 1.0e-6);
|
||||
}
|
||||
|
||||
TEST(BRepGraphInc_PopulateRegressionTest, Compact_PreservesAssemblyShapeLookupAndPlacement)
|
||||
{
|
||||
const TopLoc_Location aRootLoc = translationLocation(0.0, 0.0, 11.0);
|
||||
const TopLoc_Location anInnerLoc = translationLocation(0.0, 7.0, 0.0);
|
||||
const TopLoc_Location aSolidLoc = translationLocation(5.0, 0.0, 0.0);
|
||||
const TopoDS_Compound aMovedRoot = makeNestedCompound(aRootLoc, anInnerLoc, aSolidLoc);
|
||||
|
||||
const TopoDS_Shape anOriginalSolid = firstSubShape(aMovedRoot, TopAbs_SOLID);
|
||||
const TopoDS_Shape anOriginalFace = firstSubShape(aMovedRoot, TopAbs_FACE);
|
||||
ASSERT_FALSE(anOriginalSolid.IsNull());
|
||||
ASSERT_FALSE(anOriginalFace.IsNull());
|
||||
|
||||
BRepGraph aGraph;
|
||||
const BRepGraph::ShapesView::Result aResult = aGraph.Shapes().Add(aMovedRoot);
|
||||
ASSERT_TRUE(aResult.IsOk());
|
||||
ASSERT_TRUE(aResult.TopologyRoot.IsValid());
|
||||
ASSERT_TRUE(aResult.Product.IsValid());
|
||||
|
||||
BRepGraph::ShapesView::Options aNoProduct;
|
||||
aNoProduct.CreateAutoProduct = false;
|
||||
const BRepGraph::ShapesView::Result aJunk =
|
||||
aGraph.Shapes().Add(BRepPrimAPI_MakeBox(1.0, 1.0, 1.0).Shape(), aNoProduct);
|
||||
ASSERT_TRUE(aJunk.IsOk());
|
||||
ASSERT_TRUE(aJunk.TopologyRoot.IsValid());
|
||||
aGraph.Editor().Gen().RemoveSubgraph(aJunk.TopologyRoot);
|
||||
|
||||
const BRepGraph_Compact::Result aCompact = BRepGraph_Compact::Perform(aGraph);
|
||||
ASSERT_GT(aCompact.NbNodesBefore, aCompact.NbNodesAfter);
|
||||
|
||||
EXPECT_EQ(aGraph.Shapes().FindNode(aMovedRoot), aResult.TopologyRoot);
|
||||
EXPECT_EQ(aGraph.Shapes().FindNode(anOriginalSolid).NodeKind, BRepGraph_NodeId::Kind::Solid);
|
||||
EXPECT_EQ(aGraph.Shapes().FindNode(anOriginalFace).NodeKind, BRepGraph_NodeId::Kind::Face);
|
||||
|
||||
const BRepGraph_CompoundId aRootCompound(aGraph.Shapes().FindNode(aMovedRoot));
|
||||
ASSERT_TRUE(aRootCompound.IsValid());
|
||||
const NCollection_LinearVector<BRepGraph_ChildRefId>& aRootRefs =
|
||||
aGraph.Topo().Compounds().Relations(aRootCompound).ChildRefIds;
|
||||
ASSERT_EQ(aRootRefs.Size(), 1u);
|
||||
EXPECT_TRUE(aGraph.Refs().Gen().LocalLocation(aRootRefs.Value(0)).IsEqual(anInnerLoc));
|
||||
|
||||
const BRepGraph_NodeId anInnerNode =
|
||||
aGraph.Refs().Children().Entry(aRootRefs.Value(0)).ChildNodeId;
|
||||
ASSERT_EQ(anInnerNode.NodeKind, BRepGraph_NodeId::Kind::Compound);
|
||||
const NCollection_LinearVector<BRepGraph_ChildRefId>& anInnerRefs =
|
||||
aGraph.Topo().Compounds().Relations(BRepGraph_CompoundId(anInnerNode)).ChildRefIds;
|
||||
ASSERT_EQ(anInnerRefs.Size(), 1u);
|
||||
EXPECT_TRUE(aGraph.Refs().Gen().LocalLocation(anInnerRefs.Value(0)).IsEqual(aSolidLoc));
|
||||
|
||||
TopoDS_Shape aRootLocalShape = aMovedRoot;
|
||||
aRootLocalShape.Location(TopLoc_Location());
|
||||
const TopoDS_Shape aReconstructedRoot = BRepGraphInc_Reconstruct::Node(aGraph, aRootCompound);
|
||||
ASSERT_FALSE(aReconstructedRoot.IsNull());
|
||||
{
|
||||
SCOPED_TRACE("topology root reconstruction");
|
||||
expectBoxNear(geometryBounds(aReconstructedRoot), geometryBounds(aRootLocalShape), 1.0e-6);
|
||||
}
|
||||
|
||||
const TopoDS_Shape aProductShape = aGraph.Shapes().Shape(aResult.Product);
|
||||
ASSERT_FALSE(aProductShape.IsNull());
|
||||
{
|
||||
SCOPED_TRACE("product reconstruction");
|
||||
expectBoxNear(geometryBounds(aProductShape), geometryBounds(aMovedRoot), 1.0e-6);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BRepGraphInc_PopulateRegressionTest, Append_ReusesSameLocatedDefinitionAcrossCalls)
|
||||
{
|
||||
const TopoDS_Shape aBox = BRepPrimAPI_MakeBox(2.0, 3.0, 4.0).Shape();
|
||||
const TopoDS_Shape aMovedBox = aBox.Moved(translationLocation(5.0, 0.0, 0.0));
|
||||
|
||||
BRepGraph aGraph;
|
||||
ASSERT_NE(BRepGraphInc_Populate::Append(aGraph, aMovedBox, false),
|
||||
BRepGraphInc_Populate::BuildStatus::Failed);
|
||||
const uint32_t aNbSolidsAfterFirst = aGraph.Topo().Solids().Nb();
|
||||
const BRepGraph_NodeId aFirstNode = aGraph.Shapes().FindNode(aMovedBox);
|
||||
ASSERT_TRUE(aFirstNode.IsValid());
|
||||
|
||||
ASSERT_NE(BRepGraphInc_Populate::Append(aGraph, aMovedBox, false),
|
||||
BRepGraphInc_Populate::BuildStatus::Failed);
|
||||
EXPECT_EQ(aGraph.Topo().Solids().Nb(), aNbSolidsAfterFirst);
|
||||
EXPECT_EQ(aGraph.Shapes().FindNode(aMovedBox), aFirstNode);
|
||||
|
||||
const TopoDS_Shape aSecondPlacement = aBox.Moved(translationLocation(9.0, 0.0, 0.0));
|
||||
ASSERT_NE(BRepGraphInc_Populate::Append(aGraph, aSecondPlacement, false),
|
||||
BRepGraphInc_Populate::BuildStatus::Failed);
|
||||
EXPECT_EQ(aGraph.Topo().Solids().Nb(), aNbSolidsAfterFirst + 1u);
|
||||
EXPECT_NE(aGraph.Shapes().FindNode(aSecondPlacement), aFirstNode);
|
||||
}
|
||||
|
||||
TEST(BRepGraphInc_PopulateRegressionTest, PersistentTriangulationBounds_AgreeWithMovedNodes)
|
||||
{
|
||||
TopoDS_Shape aBox = BRepPrimAPI_MakeBox(2.0, 3.0, 4.0).Shape();
|
||||
BRepMesh_IncrementalMesh aMesher(aBox, 0.2);
|
||||
ASSERT_TRUE(aMesher.IsDone());
|
||||
for (TopExp_Explorer aFaceExp(aBox, TopAbs_FACE); aFaceExp.More(); aFaceExp.Next())
|
||||
{
|
||||
TopLoc_Location aTriLoc;
|
||||
occ::handle<Poly_Triangulation> aTri =
|
||||
BRep_Tool::Triangulation(TopoDS::Face(aFaceExp.Current()), aTriLoc);
|
||||
if (!aTri.IsNull())
|
||||
{
|
||||
aTri->UpdateCachedMinMax();
|
||||
}
|
||||
}
|
||||
|
||||
const TopoDS_Shape aMovedBox = aBox.Moved(translationLocation(25.0, -3.0, 8.0));
|
||||
|
||||
BRepGraph aGraph;
|
||||
ASSERT_NE(BRepGraphInc_Populate::Perform(aGraph, aMovedBox, false),
|
||||
BRepGraphInc_Populate::BuildStatus::Failed);
|
||||
|
||||
bool hasTriangulation = false;
|
||||
for (BRepGraph_FaceId aFaceId(0); aFaceId.IsValid(aGraph.Topo().Faces().Nb()); ++aFaceId)
|
||||
{
|
||||
const occ::handle<Poly_Triangulation>& aTri =
|
||||
aGraph.Mesh().Persistent().Faces().Triangulation(aFaceId);
|
||||
if (aTri.IsNull())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
hasTriangulation = true;
|
||||
EXPECT_FALSE(aTri->HasCachedMinMax());
|
||||
}
|
||||
EXPECT_TRUE(hasTriangulation);
|
||||
|
||||
const TopoDS_Shape aReconstructed =
|
||||
BRepGraphInc_Reconstruct::Node(aGraph, BRepGraph_SolidId::Start());
|
||||
ASSERT_FALSE(aReconstructed.IsNull());
|
||||
expectBoxNear(meshBounds(aReconstructed), meshBounds(aMovedBox), 1.0e-6);
|
||||
}
|
||||
|
||||
TEST(BRepGraphInc_PopulateRegressionTest, Perform_ReplacesGraphThroughClearSemantics)
|
||||
{
|
||||
BRepGraph aGraph;
|
||||
ASSERT_NE(
|
||||
BRepGraphInc_Populate::Perform(aGraph, BRepPrimAPI_MakeBox(1.0, 1.0, 1.0).Shape(), false),
|
||||
BRepGraphInc_Populate::BuildStatus::Failed);
|
||||
|
||||
const occ::handle<BRepGraph_LayerTopoSupplement> aLayer =
|
||||
aGraph.LayerRegistry().Ensure<BRepGraph_LayerTopoSupplement>();
|
||||
TopoDS_Vertex aVertex;
|
||||
BRep_Builder().MakeVertex(aVertex, gp_Pnt(42.0, 0.0, 0.0), Precision::Confusion());
|
||||
ASSERT_NE(aLayer->AddAttachment(BRepGraph_NodeId(BRepGraph_SolidId::Start()),
|
||||
BRepGraph_LayerTopoSupplement::AttachmentKind::SolidAuxShape,
|
||||
aVertex),
|
||||
0u);
|
||||
|
||||
const BRepGraph_EdgeId anEdgeId = BRepGraph_EdgeId::Start();
|
||||
occ::handle<Poly_Polygon3D> aPolygon = new Poly_Polygon3D(2, false);
|
||||
aGraph.Mesh().Editor().Edges().SetCachedPolygon3D(anEdgeId, aPolygon);
|
||||
ASSERT_NE(aGraph.Mesh().Cache().Edges().Entry(anEdgeId), nullptr);
|
||||
|
||||
ASSERT_NE(
|
||||
BRepGraphInc_Populate::Perform(aGraph, BRepPrimAPI_MakeBox(2.0, 2.0, 2.0).Shape(), false),
|
||||
BRepGraphInc_Populate::BuildStatus::Failed);
|
||||
EXPECT_TRUE(aLayer->AttachedTo(BRepGraph_NodeId(BRepGraph_SolidId::Start())).IsEmpty());
|
||||
EXPECT_EQ(aGraph.Mesh().Cache().Edges().Entry(anEdgeId), nullptr);
|
||||
}
|
||||
|
||||
TEST(BRepGraphInc_PopulateRegressionTest, FlattenedTraversal_SkipsInternalExternalChildren)
|
||||
{
|
||||
BRep_Builder aBuilder;
|
||||
TopoDS_Compound aCompound;
|
||||
aBuilder.MakeCompound(aCompound);
|
||||
|
||||
TopoDS_Face aForwardFace = firstFaceOfBox(1.0);
|
||||
aForwardFace.Orientation(TopAbs_FORWARD);
|
||||
TopoDS_Face anInternalFace = firstFaceOfBox(2.0);
|
||||
anInternalFace.Orientation(TopAbs_INTERNAL);
|
||||
TopoDS_Face anExternalFace = firstFaceOfBox(3.0);
|
||||
anExternalFace.Orientation(TopAbs_EXTERNAL);
|
||||
|
||||
aBuilder.Add(aCompound, aForwardFace);
|
||||
aBuilder.Add(aCompound, anInternalFace);
|
||||
aBuilder.Add(aCompound, anExternalFace);
|
||||
|
||||
BRepGraph aGraph;
|
||||
BRepGraph::ShapesView::Options anOptions;
|
||||
anOptions.CreateAutoProduct = false;
|
||||
anOptions.Flatten = true;
|
||||
const BRepGraph::ShapesView::Result aResult = aGraph.Shapes().Add(aCompound, anOptions);
|
||||
ASSERT_TRUE(aResult.IsOk());
|
||||
EXPECT_EQ(aGraph.Topo().Faces().Nb(), 1u);
|
||||
ASSERT_TRUE(aResult.TopologyRoot.IsValid());
|
||||
EXPECT_EQ(aResult.TopologyRoot.NodeKind, BRepGraph_NodeId::Kind::Face);
|
||||
}
|
||||
@@ -755,7 +755,7 @@ TEST(BRepGraphIncTest, Compound_TranslatedChildren_VolumePreserved)
|
||||
EXPECT_EQ(countSubShapes(aRecon, TopAbs_FACE), 12);
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, Populate_BakesNormalChildLocationsIntoDefinitions)
|
||||
TEST(BRepGraphIncTest, Populate_AppliesNormalChildLocationsToDefinitions)
|
||||
{
|
||||
const TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0));
|
||||
|
||||
@@ -798,7 +798,7 @@ TEST(BRepGraphIncTest, Populate_BakesNormalChildLocationsIntoDefinitions)
|
||||
EXPECT_EQ(countSubShapes(aRecon, TopAbs_VERTEX), 4);
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, Populate_BakesStackedNormalLocationsIntoDefinitions)
|
||||
TEST(BRepGraphIncTest, Populate_AppliesStackedNormalLocationsToDefinitions)
|
||||
{
|
||||
gp_Trsf anEdgeTrsf;
|
||||
anEdgeTrsf.SetTranslation(gp_Vec(2.0, 0.0, 0.0));
|
||||
@@ -909,46 +909,6 @@ TEST(BRepGraphIncTest, Populate_BakesStackedNormalLocationsIntoDefinitions)
|
||||
EXPECT_NEAR(aMaxZ, 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, Populate_RootCompoundLocationIsPreservedByChildRefs)
|
||||
{
|
||||
BRep_Builder aBuilder;
|
||||
TopoDS_Compound aCompound;
|
||||
aBuilder.MakeCompound(aCompound);
|
||||
aBuilder.Add(aCompound, BRepBuilderAPI_MakeEdge(gp_Pnt(0.0, 0.0, 0.0), gp_Pnt(1.0, 0.0, 0.0)));
|
||||
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(25.0, 0.0, 0.0));
|
||||
const TopLoc_Location aLoc(aTrsf);
|
||||
const TopoDS_Compound aMovedCompound = TopoDS::Compound(aCompound.Moved(aLoc));
|
||||
|
||||
BRepGraph aGraph;
|
||||
ASSERT_NE(BRepGraphInc_Populate::Perform(aGraph, aMovedCompound, false),
|
||||
BRepGraphInc_Populate::BuildStatus::Failed);
|
||||
ASSERT_FALSE(aGraph.IsEmpty());
|
||||
|
||||
ASSERT_EQ(aGraph.Topo().Compounds().Nb(), 1u);
|
||||
const NCollection_LinearVector<BRepGraph_ChildRefId>& aChildRefs =
|
||||
aGraph.Topo().Compounds().Relations(BRepGraph_CompoundId::Start()).ChildRefIds;
|
||||
ASSERT_EQ(aChildRefs.Size(), 1u);
|
||||
const BRepGraph_ChildRefId aChildRef = aChildRefs.Value(0);
|
||||
EXPECT_TRUE(aGraph.Refs().Gen().LocalLocation(aChildRef).IsEqual(aLoc));
|
||||
|
||||
TopoDS_Shape aRecon = BRepGraphInc_Reconstruct::Node(aGraph, BRepGraph_CompoundId::Start());
|
||||
ASSERT_FALSE(aRecon.IsNull());
|
||||
|
||||
double aMinX = RealLast();
|
||||
double aMaxX = -RealLast();
|
||||
for (TopExp_Explorer anExp(aRecon, TopAbs_VERTEX); anExp.More(); anExp.Next())
|
||||
{
|
||||
const gp_Pnt aPoint = BRep_Tool::Pnt(TopoDS::Vertex(anExp.Current()));
|
||||
aMinX = std::min(aMinX, aPoint.X());
|
||||
aMaxX = std::max(aMaxX, aPoint.X());
|
||||
}
|
||||
|
||||
EXPECT_NEAR(aMinX, 25.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aMaxX, 26.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, Cylinder_RoundTrip_BRepDump)
|
||||
{
|
||||
BRepPrimAPI_MakeCylinder aCylMaker(5.0, 20.0);
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
#include <BRepGraph_RefsView.hxx>
|
||||
#include <BRepGraph_ShapesView.hxx>
|
||||
#include <BRepGraph_UIDsView.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <BRepPrimAPI_MakeSphere.hxx>
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_ProgramError.hxx>
|
||||
@@ -40,6 +42,25 @@ static double translationX(const TopoDS_Shape& theShape)
|
||||
return theShape.Location().Transformation().TranslationPart().X();
|
||||
}
|
||||
|
||||
Bnd_Box geometryBounds(const TopoDS_Shape& theShape)
|
||||
{
|
||||
Bnd_Box aBox;
|
||||
BRepBndLib::AddOptimal(theShape, aBox, false, false);
|
||||
return aBox;
|
||||
}
|
||||
|
||||
void expectBoxNear(const Bnd_Box& theActual, const Bnd_Box& theExpected, const double theTol)
|
||||
{
|
||||
const Bnd_Box::Limits anActual = theActual.Get();
|
||||
const Bnd_Box::Limits anExpected = theExpected.Get();
|
||||
EXPECT_NEAR(anActual.Xmin, anExpected.Xmin, theTol);
|
||||
EXPECT_NEAR(anActual.Ymin, anExpected.Ymin, theTol);
|
||||
EXPECT_NEAR(anActual.Zmin, anExpected.Zmin, theTol);
|
||||
EXPECT_NEAR(anActual.Xmax, anExpected.Xmax, theTol);
|
||||
EXPECT_NEAR(anActual.Ymax, anExpected.Ymax, theTol);
|
||||
EXPECT_NEAR(anActual.Zmax, anExpected.Zmax, theTol);
|
||||
}
|
||||
|
||||
NCollection_LinearVector<BRepGraph_ProductId> collectRootProducts(const BRepGraph& theGraph)
|
||||
{
|
||||
NCollection_LinearVector<BRepGraph_ProductId> aRoots(4);
|
||||
@@ -1231,7 +1252,8 @@ TEST(BRepGraph_AssemblyTest, OccurrenceLocation_AlwaysTerminates)
|
||||
TEST(BRepGraph_AssemblyTest, Add_RootProduct_PreservesShapeLocation)
|
||||
{
|
||||
BRepGraph aGraph;
|
||||
TopoDS_Shape aBox = BRepPrimAPI_MakeBox(10.0, 20.0, 30.0).Shape();
|
||||
TopoDS_Shape aLocalBox = BRepPrimAPI_MakeBox(10.0, 20.0, 30.0).Shape();
|
||||
TopoDS_Shape aBox = aLocalBox;
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(5.0, 6.0, 7.0));
|
||||
aBox.Location(TopLoc_Location(aTrsf));
|
||||
@@ -1241,6 +1263,7 @@ TEST(BRepGraph_AssemblyTest, Add_RootProduct_PreservesShapeLocation)
|
||||
ASSERT_TRUE(aResult.Product.IsValid());
|
||||
ASSERT_TRUE(aResult.TopologyRoot.IsValid());
|
||||
ASSERT_TRUE(aResult.Occurrence.IsValid());
|
||||
EXPECT_EQ(aGraph.Shapes().FindNode(aBox), aResult.TopologyRoot);
|
||||
|
||||
ASSERT_EQ(aGraph.RootProductIds().Size(), 1u);
|
||||
EXPECT_EQ(aGraph.RootProductIds().Value(0), aResult.Product);
|
||||
@@ -1248,9 +1271,16 @@ TEST(BRepGraph_AssemblyTest, Add_RootProduct_PreservesShapeLocation)
|
||||
const BRepGraph_OccurrenceRefId anOccRefId =
|
||||
aGraph.Topo().Products().Relations(aResult.Product).OccurrenceRefIds.Value(0);
|
||||
const TopLoc_Location& aLoc = aGraph.Refs().Occurrences().Entry(anOccRefId).LocalLocation;
|
||||
EXPECT_NEAR(aLoc.Transformation().TranslationPart().X(), 5.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aLoc.Transformation().TranslationPart().Y(), 6.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aLoc.Transformation().TranslationPart().Z(), 7.0, Precision::Confusion());
|
||||
EXPECT_TRUE(aLoc.IsEqual(aBox.Location()));
|
||||
|
||||
const TopoDS_Shape aProductShape = aGraph.Shapes().Shape(aResult.Product);
|
||||
ASSERT_FALSE(aProductShape.IsNull());
|
||||
expectBoxNear(geometryBounds(aProductShape), geometryBounds(aBox), 1.0e-7);
|
||||
|
||||
const TopoDS_Shape aTopologyShape = aGraph.Shapes().Shape(aResult.TopologyRoot);
|
||||
ASSERT_FALSE(aTopologyShape.IsNull());
|
||||
EXPECT_TRUE(aTopologyShape.Location().IsIdentity());
|
||||
expectBoxNear(geometryBounds(aTopologyShape), geometryBounds(aLocalBox), 1.0e-7);
|
||||
}
|
||||
|
||||
TEST(BRepGraph_AssemblyTest, Add_NoAutoProduct_TopologyOnly)
|
||||
@@ -1308,7 +1338,7 @@ TEST(BRepGraph_AssemblyTest, Add_ProductParent_CreatesChildPartAndOccurrence)
|
||||
ASSERT_EQ(aParentRelations.OccurrenceRefIds.Size(), 1u);
|
||||
const BRepGraph_OccurrenceRefId anOccRefId = aParentRelations.OccurrenceRefIds.Value(0);
|
||||
const TopLoc_Location& aLoc = aGraph.Refs().Occurrences().Entry(anOccRefId).LocalLocation;
|
||||
EXPECT_NEAR(aLoc.Transformation().TranslationPart().X(), 2.0, Precision::Confusion());
|
||||
EXPECT_TRUE(aLoc.IsEqual(aSphere.Location()));
|
||||
}
|
||||
|
||||
TEST(BRepGraph_AssemblyTest, Add_CompoundParent_AppendsAsChild)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <BRepGraphInc_RepId.hxx>
|
||||
#include <BRepGraph_Iterator.hxx>
|
||||
#include <BRepGraph_ParentExplorer.hxx>
|
||||
#include <BRepGraph_RefsView.hxx>
|
||||
#include <BRepGraph_TopoView.hxx>
|
||||
#include <BRepGraph_ShapesView.hxx>
|
||||
#include <BRepGraph_MeshView.hxx>
|
||||
@@ -435,13 +436,19 @@ TEST(BRepGraph_GeometryTest, CompoundWithMovedChild_SharedSolidDef)
|
||||
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph::ShapesView::Result aBuildRes12 = aGraph.Shapes().Add(aCompound);
|
||||
const BRepGraph::ShapesView::Result aBuildRes12 = aGraph.Shapes().Add(aCompound);
|
||||
ASSERT_TRUE(aBuildRes12.IsOk());
|
||||
ASSERT_FALSE(aGraph.IsEmpty());
|
||||
|
||||
// Moved() preserves TShape, but locations are baked into topology definitions.
|
||||
EXPECT_EQ(aGraph.Topo().Solids().Nb(), 2);
|
||||
// Verify the graph was built successfully.
|
||||
EXPECT_FALSE(aGraph.IsEmpty());
|
||||
// Moved() preserves TShape. The solid definition is shared and the moved
|
||||
// usage keeps its placement on the compound child reference.
|
||||
EXPECT_EQ(aGraph.Topo().Solids().Nb(), 1);
|
||||
const BRepGraph_CompoundId aCompoundId(aBuildRes12.TopologyRoot);
|
||||
const NCollection_LinearVector<BRepGraph_ChildRefId>& aChildRefs =
|
||||
aGraph.Topo().Compounds().Relations(aCompoundId).ChildRefIds;
|
||||
ASSERT_EQ(aChildRefs.Size(), 2u);
|
||||
EXPECT_TRUE(aGraph.Refs().Gen().LocalLocation(aChildRefs.Value(0)).IsIdentity());
|
||||
EXPECT_FALSE(aGraph.Refs().Gen().LocalLocation(aChildRefs.Value(1)).IsIdentity());
|
||||
}
|
||||
|
||||
TEST(BRepGraph_GeometryTest, FaceDef_Triangulation_NullForAnalyticNoCrash)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <BRepGraph_EditorView.hxx>
|
||||
#include <BRepGraph_Iterator.hxx>
|
||||
#include "BRepGraph_RefTestTools.hxx"
|
||||
#include <BRepGraph_RefsView.hxx>
|
||||
#include <BRepGraph_Tool.hxx>
|
||||
#include <BRepGraph_TopoView.hxx>
|
||||
#include <BRepGraph_Validate.hxx>
|
||||
@@ -345,14 +346,20 @@ TEST_F(BRepGraph_SharingTest, CompoundWithLocation_MoreUsagesThanDefs)
|
||||
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph::ShapesView::Result aBuildRes4 = aGraph.Shapes().Add(aCompound);
|
||||
const BRepGraph::ShapesView::Result aBuildRes4 = aGraph.Shapes().Add(aCompound);
|
||||
ASSERT_TRUE(aBuildRes4.IsOk());
|
||||
ASSERT_FALSE(aGraph.IsEmpty());
|
||||
|
||||
// Same TShape with different locations: normal topology definitions are split
|
||||
// because the location is baked into the definitions during Populate.
|
||||
EXPECT_EQ(aGraph.Topo().Faces().Nb(), 12);
|
||||
EXPECT_EQ(aGraph.Topo().Edges().Nb(), 24);
|
||||
EXPECT_EQ(aGraph.Topo().Vertices().Nb(), 16);
|
||||
// Same TShape with different compound usages: topology definitions are shared
|
||||
// and usage placement is stored on ChildRef.
|
||||
EXPECT_EQ(aGraph.Topo().Solids().Nb(), 1);
|
||||
EXPECT_EQ(aGraph.Topo().Faces().Nb(), 6);
|
||||
EXPECT_EQ(aGraph.Topo().Edges().Nb(), 12);
|
||||
EXPECT_EQ(aGraph.Topo().Vertices().Nb(), 8);
|
||||
const NCollection_LinearVector<BRepGraph_ChildRefId>& aChildRefs =
|
||||
aGraph.Topo().Compounds().Relations(BRepGraph_CompoundId(aBuildRes4.TopologyRoot)).ChildRefIds;
|
||||
ASSERT_EQ(aChildRefs.Size(), 2u);
|
||||
EXPECT_FALSE(aGraph.Refs().Gen().LocalLocation(aChildRefs.Value(1)).IsIdentity());
|
||||
}
|
||||
|
||||
TEST_F(BRepGraph_SharingTest, TranslatedCopy_SameTShape_SharedDefs)
|
||||
@@ -372,13 +379,18 @@ TEST_F(BRepGraph_SharingTest, TranslatedCopy_SameTShape_SharedDefs)
|
||||
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph::ShapesView::Result aBuildRes5 = aGraph.Shapes().Add(aCompound);
|
||||
const BRepGraph::ShapesView::Result aBuildRes5 = aGraph.Shapes().Add(aCompound);
|
||||
ASSERT_TRUE(aBuildRes5.IsOk());
|
||||
ASSERT_FALSE(aGraph.IsEmpty());
|
||||
|
||||
// Moved() preserves TShape, but locations are baked into topology definitions.
|
||||
EXPECT_EQ(aGraph.Topo().Solids().Nb(), 2);
|
||||
|
||||
EXPECT_EQ(aGraph.Topo().Faces().Nb(), 12);
|
||||
EXPECT_EQ(aGraph.Topo().Edges().Nb(), 24);
|
||||
EXPECT_EQ(aGraph.Topo().Vertices().Nb(), 16);
|
||||
// Moved() preserves TShape, so the definition stays shared while the moved
|
||||
// usage is represented by a located compound child reference.
|
||||
EXPECT_EQ(aGraph.Topo().Solids().Nb(), 1);
|
||||
EXPECT_EQ(aGraph.Topo().Faces().Nb(), 6);
|
||||
EXPECT_EQ(aGraph.Topo().Edges().Nb(), 12);
|
||||
EXPECT_EQ(aGraph.Topo().Vertices().Nb(), 8);
|
||||
const NCollection_LinearVector<BRepGraph_ChildRefId>& aChildRefs =
|
||||
aGraph.Topo().Compounds().Relations(BRepGraph_CompoundId(aBuildRes5.TopologyRoot)).ChildRefIds;
|
||||
ASSERT_EQ(aChildRefs.Size(), 2u);
|
||||
EXPECT_FALSE(aGraph.Refs().Gen().LocalLocation(aChildRefs.Value(1)).IsIdentity());
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ set(OCCT_TKBRep_GTests_FILES
|
||||
BRepGraph_BatchOps_Test.cxx
|
||||
BRepGraph_DefsIterator_Test.cxx
|
||||
BRepGraphInc_Test.cxx
|
||||
BRepGraphInc_PopulateRegression_Test.cxx
|
||||
BRepGraph_ShapesViewImport_Test.cxx
|
||||
BRepGraph_NodeId_Test.cxx
|
||||
BRepGraph_RefId_Test.cxx
|
||||
|
||||
Reference in New Issue
Block a user