mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-09-05 04:07:58 +08:00
Moding - Update BRep Graph permission usage (#1242)
- Replaced many direct field writes in tests with `EditorView` typed setters and `GenOps::RemoveRef`, and updated mutation-gen tests to use `MarkDirty()`. - Added incremental reverse-index bind/unbind helpers in `BRepGraphInc_ReverseIndex` and updated editor operations to maintain the reverse index without full rebuilds in many cases. - Extended `BRepGraph_Copy`/`BRepGraph_Transform` to `CopyNode`/`TransformNode`, adding optional mesh-copy/transform support and new coverage tests.
This commit is contained in:
@@ -27,6 +27,9 @@
|
||||
#include <BRepGraphInc_Reconstruct.hxx>
|
||||
#include <BRepGraphInc_Storage.hxx>
|
||||
#include <BRepGraph_Builder.hxx>
|
||||
#include <BRepGraph_Compact.hxx>
|
||||
#include <BRepGraph_EditorView.hxx>
|
||||
#include <BRepGraph_Iterator.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <BRepPrimAPI_MakeCylinder.hxx>
|
||||
@@ -1429,3 +1432,596 @@ TEST(BRepGraphIncTest, ReverseIndex_Validate_Compound_FullConsistency)
|
||||
|
||||
EXPECT_TRUE(aStorage.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_AfterEditorMutations_StaysConsistent)
|
||||
{
|
||||
// Verify the incremental Bind/Unbind mutation path keeps the reverse index
|
||||
// consistent with the forward entity / reference-entry tables across a
|
||||
// sequence of RemoveWire / RemoveFace / RemoveShell mutations.
|
||||
BRep_Builder aBB;
|
||||
TopoDS_Compound aCompound;
|
||||
aBB.MakeCompound(aCompound);
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepPrimAPI_MakeCylinder aCylMaker(5.0, 12.0);
|
||||
aBB.Add(aCompound, aBoxMaker.Shape());
|
||||
aBB.Add(aCompound, aCylMaker.Shape());
|
||||
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aCompound);
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
ASSERT_TRUE(aGraph.ValidateReverseIndex());
|
||||
|
||||
// Remove an inner wire from the first face that owns more than one wire
|
||||
// (or the only wire if all faces have a single wire).
|
||||
for (BRepGraph_FaceIterator aFaceIt(aGraph); aFaceIt.More(); aFaceIt.Next())
|
||||
{
|
||||
const BRepGraph_FaceId aFaceId = aFaceIt.CurrentId();
|
||||
const NCollection_DynamicArray<BRepGraph_WireRefId> aWireRefs =
|
||||
BRepGraph_TestTools::WireRefsOfFace(aGraph, aFaceId);
|
||||
if (aWireRefs.IsEmpty())
|
||||
continue;
|
||||
ASSERT_TRUE(aGraph.Editor().Faces().RemoveWire(aFaceId, aWireRefs.Value(0)));
|
||||
break;
|
||||
}
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex()) << "Reverse index inconsistent after RemoveWire";
|
||||
|
||||
// Remove the first face from the first shell.
|
||||
const NCollection_DynamicArray<BRepGraph_FaceRefId> aFaceRefs =
|
||||
BRepGraph_TestTools::FaceRefsOfShell(aGraph, BRepGraph_ShellId::Start());
|
||||
ASSERT_GE(aFaceRefs.Length(), 1);
|
||||
ASSERT_TRUE(aGraph.Editor().Shells().RemoveFace(BRepGraph_ShellId::Start(), aFaceRefs.Value(0)));
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex()) << "Reverse index inconsistent after RemoveFace";
|
||||
|
||||
// Remove the first shell from the first solid.
|
||||
const NCollection_DynamicArray<BRepGraph_ShellRefId> aShellRefs =
|
||||
BRepGraph_TestTools::ShellRefsOfSolid(aGraph, BRepGraph_SolidId::Start());
|
||||
ASSERT_GE(aShellRefs.Length(), 1);
|
||||
ASSERT_TRUE(
|
||||
aGraph.Editor().Solids().RemoveShell(BRepGraph_SolidId::Start(), aShellRefs.Value(0)));
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex()) << "Reverse index inconsistent after RemoveShell";
|
||||
|
||||
EXPECT_TRUE(aGraph.Editor().ValidateMutationBoundary());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_BulkBuild_TwiceProducesEqualState)
|
||||
{
|
||||
// Bulk Populate must be deterministic: building the same shape twice into
|
||||
// independent storages must yield byte-equal reverse-index views as observed
|
||||
// through the public per-entity accessors.
|
||||
BRepPrimAPI_MakeBox aBoxMaker(7.0, 11.0, 13.0);
|
||||
const TopoDS_Shape& aBox = aBoxMaker.Shape();
|
||||
|
||||
BRepGraphInc_Storage aStorageA;
|
||||
BRepGraphInc_Storage aStorageB;
|
||||
BRepGraphInc_Populate::Perform(aStorageA, aBox, false);
|
||||
BRepGraphInc_Populate::Perform(aStorageB, aBox, false);
|
||||
ASSERT_TRUE(aStorageA.GetIsDone());
|
||||
ASSERT_TRUE(aStorageB.GetIsDone());
|
||||
ASSERT_EQ(aStorageA.NbEdges(), aStorageB.NbEdges());
|
||||
|
||||
for (uint32_t anIdx = 0; anIdx < aStorageA.NbEdges(); ++anIdx)
|
||||
{
|
||||
const BRepGraph_EdgeId anEdgeId(anIdx);
|
||||
const NCollection_DynamicArray<BRepGraph_WireId>* aWiresA =
|
||||
aStorageA.ReverseIndex().WiresOfEdge(anEdgeId);
|
||||
const NCollection_DynamicArray<BRepGraph_WireId>* aWiresB =
|
||||
aStorageB.ReverseIndex().WiresOfEdge(anEdgeId);
|
||||
ASSERT_EQ(aWiresA == nullptr, aWiresB == nullptr);
|
||||
if (aWiresA == nullptr)
|
||||
continue;
|
||||
ASSERT_EQ(aWiresA->Size(), aWiresB->Size());
|
||||
for (size_t i = 0; i < aWiresA->Size(); ++i)
|
||||
EXPECT_EQ(aWiresA->Value(i), aWiresB->Value(i));
|
||||
|
||||
const NCollection_DynamicArray<BRepGraph_FaceId>* aFacesA =
|
||||
aStorageA.ReverseIndex().FacesOfEdge(anEdgeId);
|
||||
const NCollection_DynamicArray<BRepGraph_FaceId>* aFacesB =
|
||||
aStorageB.ReverseIndex().FacesOfEdge(anEdgeId);
|
||||
ASSERT_EQ(aFacesA == nullptr, aFacesB == nullptr);
|
||||
if (aFacesA == nullptr)
|
||||
continue;
|
||||
ASSERT_EQ(aFacesA->Size(), aFacesB->Size());
|
||||
for (size_t i = 0; i < aFacesA->Size(); ++i)
|
||||
EXPECT_EQ(aFacesA->Value(i), aFacesB->Value(i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_EdgeOpsAdd_BindsStartEndVertices)
|
||||
{
|
||||
// Free edge created at runtime via the Editor must show up under its endpoint
|
||||
// vertices in the reverse index. Pre-fix this query returned an empty list.
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
const BRepGraph_VertexId aV0 = aGraph.Editor().Vertices().Add(gp_Pnt(0, 0, 0), 1.e-7);
|
||||
const BRepGraph_VertexId aV1 = aGraph.Editor().Vertices().Add(gp_Pnt(1, 0, 0), 1.e-7);
|
||||
ASSERT_TRUE(aV0.IsValid());
|
||||
ASSERT_TRUE(aV1.IsValid());
|
||||
const BRepGraph_EdgeId anEdge =
|
||||
aGraph.Editor().Edges().Add(aV0, aV1, occ::handle<Geom_Curve>(), 0.0, 1.0, 1.e-7);
|
||||
ASSERT_TRUE(anEdge.IsValid());
|
||||
|
||||
bool foundV0 = false, foundV1 = false;
|
||||
for (const BRepGraph_EdgeId& aE : aGraph.Topo().Vertices().Edges(aV0))
|
||||
if (aE == anEdge)
|
||||
foundV0 = true;
|
||||
for (const BRepGraph_EdgeId& aE : aGraph.Topo().Vertices().Edges(aV1))
|
||||
if (aE == anEdge)
|
||||
foundV1 = true;
|
||||
EXPECT_TRUE(foundV0);
|
||||
EXPECT_TRUE(foundV1);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_RemoveEdge_UnbindsStartEndVertices)
|
||||
{
|
||||
// Symmetric to the Add test: removing the edge must drop the entries.
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
const BRepGraph_VertexId aV0 = aGraph.Editor().Vertices().Add(gp_Pnt(0, 0, 0), 1.e-7);
|
||||
const BRepGraph_VertexId aV1 = aGraph.Editor().Vertices().Add(gp_Pnt(1, 0, 0), 1.e-7);
|
||||
const BRepGraph_EdgeId anEdge =
|
||||
aGraph.Editor().Edges().Add(aV0, aV1, occ::handle<Geom_Curve>(), 0.0, 1.0, 1.e-7);
|
||||
ASSERT_TRUE(anEdge.IsValid());
|
||||
|
||||
aGraph.Editor().Gen().RemoveNode(BRepGraph_NodeId(anEdge));
|
||||
|
||||
for (const BRepGraph_EdgeId& aE : aGraph.Topo().Vertices().Edges(aV0))
|
||||
EXPECT_NE(aE, anEdge);
|
||||
for (const BRepGraph_EdgeId& aE : aGraph.Topo().Vertices().Edges(aV1))
|
||||
EXPECT_NE(aE, anEdge);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_SetRefVertexDefId_RebindsVertexToEdges)
|
||||
{
|
||||
// Rewire an edge's start-vertex ref to a different vertex and verify the
|
||||
// rev-index moved.
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
const BRepGraph_VertexId aV0 = aGraph.Editor().Vertices().Add(gp_Pnt(0, 0, 0), 1.e-7);
|
||||
const BRepGraph_VertexId aV1 = aGraph.Editor().Vertices().Add(gp_Pnt(1, 0, 0), 1.e-7);
|
||||
const BRepGraph_VertexId aV2 = aGraph.Editor().Vertices().Add(gp_Pnt(2, 0, 0), 1.e-7);
|
||||
const BRepGraph_EdgeId anEdge =
|
||||
aGraph.Editor().Edges().Add(aV0, aV1, occ::handle<Geom_Curve>(), 0.0, 1.0, 1.e-7);
|
||||
ASSERT_TRUE(anEdge.IsValid());
|
||||
|
||||
const BRepGraph_VertexRefId aStartRef = aGraph.Topo().Edges().Definition(anEdge).StartVertexRefId;
|
||||
aGraph.Editor().Vertices().SetRefVertexDefId(aStartRef, aV2);
|
||||
|
||||
bool stillUnderV0 = false, foundUnderV2 = false;
|
||||
for (const BRepGraph_EdgeId& aE : aGraph.Topo().Vertices().Edges(aV0))
|
||||
if (aE == anEdge)
|
||||
stillUnderV0 = true;
|
||||
for (const BRepGraph_EdgeId& aE : aGraph.Topo().Vertices().Edges(aV2))
|
||||
if (aE == anEdge)
|
||||
foundUnderV2 = true;
|
||||
EXPECT_FALSE(stillUnderV0);
|
||||
EXPECT_TRUE(foundUnderV2);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_BoxThroughCompact_StaysConsistent)
|
||||
{
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
ASSERT_TRUE(aGraph.Editor().Faces().RemoveWire(
|
||||
BRepGraph_FaceId::Start(),
|
||||
BRepGraph_TestTools::WireRefsOfFace(aGraph, BRepGraph_FaceId::Start()).Value(0)));
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
|
||||
[[maybe_unused]] const BRepGraph_Compact::Result aCompactRes = BRepGraph_Compact::Perform(aGraph);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_SetRefWireDefId_RebindsWireToFaces)
|
||||
{
|
||||
// Add two faces; rewire face0's outer-wire ref to face1's outer wire and
|
||||
// verify WireToFaces moved entries.
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
const BRepGraph_FaceId aFace0 = BRepGraph_FaceId::Start();
|
||||
const BRepGraph_FaceId aFace1(1);
|
||||
ASSERT_TRUE(aFace1.IsValid(aGraph.Topo().Faces().Nb()));
|
||||
|
||||
const BRepGraph_WireRefId aWireRef0 =
|
||||
BRepGraph_TestTools::WireRefsOfFace(aGraph, aFace0).Value(0);
|
||||
const BRepGraph_WireId aOldWire = aGraph.Refs().Wires().Entry(aWireRef0).WireDefId;
|
||||
const BRepGraph_WireId aNewWire =
|
||||
aGraph.Refs()
|
||||
.Wires()
|
||||
.Entry(BRepGraph_TestTools::WireRefsOfFace(aGraph, aFace1).Value(0))
|
||||
.WireDefId;
|
||||
ASSERT_NE(aOldWire, aNewWire);
|
||||
|
||||
aGraph.Editor().Wires().SetRefWireDefId(aWireRef0, aNewWire);
|
||||
|
||||
bool oldStillBound = false, newBound = false;
|
||||
for (const BRepGraph_FaceId& f : aGraph.Topo().Wires().Faces(aOldWire))
|
||||
if (f == aFace0)
|
||||
oldStillBound = true;
|
||||
for (const BRepGraph_FaceId& f : aGraph.Topo().Wires().Faces(aNewWire))
|
||||
if (f == aFace0)
|
||||
newBound = true;
|
||||
EXPECT_FALSE(oldStillBound);
|
||||
EXPECT_TRUE(newBound);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_SetRefFaceDefId_RebindsFaceToShells)
|
||||
{
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
const BRepGraph_ShellId aShell = BRepGraph_ShellId::Start();
|
||||
const BRepGraph_FaceRefId aRef0 = BRepGraph_TestTools::FaceRefsOfShell(aGraph, aShell).Value(0);
|
||||
const BRepGraph_FaceId aOldFace = aGraph.Refs().Faces().Entry(aRef0).FaceDefId;
|
||||
const BRepGraph_FaceId aNewFace(1);
|
||||
ASSERT_NE(aOldFace, aNewFace);
|
||||
|
||||
aGraph.Editor().Faces().SetRefFaceDefId(aRef0, aNewFace);
|
||||
|
||||
// Old face still has the OTHER shell-ref pointing at it; just check the
|
||||
// Old/New rev-index makes sense relative to this single ref.
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_SetRefShellDefId_RebindsShellToSolids)
|
||||
{
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
ASSERT_GE(aGraph.Topo().Shells().Nb(), 1);
|
||||
|
||||
// Box has 1 solid, 1 shell. Rewiring the lone shell-ref to itself is a no-op,
|
||||
// so just verify Validate after a no-op call (proves equality short-circuit).
|
||||
const BRepGraph_ShellRefId aRef0 =
|
||||
BRepGraph_TestTools::ShellRefsOfSolid(aGraph, BRepGraph_SolidId::Start()).Value(0);
|
||||
const BRepGraph_ShellId aShell = aGraph.Refs().Shells().Entry(aRef0).ShellDefId;
|
||||
aGraph.Editor().Shells().SetRefShellDefId(aRef0, aShell);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_SetEdgeDefIdOnCoEdge_RebindsEdgeToCoEdges)
|
||||
{
|
||||
// Pick a coedge that lives in a wire; redirect its EdgeDefId to a different
|
||||
// existing edge and confirm Edge->CoEdges, Edge->Wires, Edge->Faces all move.
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
ASSERT_GE(aGraph.Topo().CoEdges().Nb(), 2);
|
||||
|
||||
const BRepGraph_CoEdgeId aCoEdge = BRepGraph_CoEdgeId::Start();
|
||||
const BRepGraphInc::CoEdgeDef& aDef = aGraph.Topo().CoEdges().Definition(aCoEdge);
|
||||
const BRepGraph_EdgeId anOldEdge = aDef.EdgeDefId;
|
||||
// Pick any other valid edge as the target.
|
||||
BRepGraph_EdgeId aNewEdge;
|
||||
for (BRepGraph_EdgeId aE(0); aE.IsValid(aGraph.Topo().Edges().Nb()); ++aE)
|
||||
{
|
||||
if (aE != anOldEdge)
|
||||
{
|
||||
aNewEdge = aE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(aNewEdge.IsValid());
|
||||
|
||||
aGraph.Editor().CoEdges().SetEdgeDefId(aCoEdge, aNewEdge);
|
||||
|
||||
bool oldHasCoEdge = false, newHasCoEdge = false;
|
||||
for (const BRepGraph_CoEdgeId& aC : aGraph.Topo().Edges().CoEdges(anOldEdge))
|
||||
if (aC == aCoEdge)
|
||||
oldHasCoEdge = true;
|
||||
for (const BRepGraph_CoEdgeId& aC : aGraph.Topo().Edges().CoEdges(aNewEdge))
|
||||
if (aC == aCoEdge)
|
||||
newHasCoEdge = true;
|
||||
EXPECT_FALSE(oldHasCoEdge);
|
||||
EXPECT_TRUE(newHasCoEdge);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_SetFaceDefIdOnCoEdge_LastBondCheck)
|
||||
{
|
||||
// Cylinder seam edges have TWO coedges on the SAME face. Dropping one
|
||||
// coedge's FaceDefId must keep the (edge, face) pair bound via the other.
|
||||
BRepPrimAPI_MakeCylinder aCylMaker(5.0, 10.0);
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aCylMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
// Locate a seam edge: an edge with two coedges on the same face.
|
||||
BRepGraph_EdgeId aSeamEdge;
|
||||
BRepGraph_FaceId aSeamFace;
|
||||
BRepGraph_CoEdgeId aSeamCoEdge;
|
||||
for (BRepGraph_EdgeId aE(0); aE.IsValid(aGraph.Topo().Edges().Nb()) && !aSeamEdge.IsValid(); ++aE)
|
||||
{
|
||||
const NCollection_DynamicArray<BRepGraph_CoEdgeId>& aCEs = aGraph.Topo().Edges().CoEdges(aE);
|
||||
if (aCEs.Size() < 2)
|
||||
continue;
|
||||
NCollection_DataMap<int, BRepGraph_CoEdgeId> aSeenFace;
|
||||
for (const BRepGraph_CoEdgeId& aCE : aCEs)
|
||||
{
|
||||
const BRepGraphInc::CoEdgeDef& aD = aGraph.Topo().CoEdges().Definition(aCE);
|
||||
if (!aD.FaceDefId.IsValid())
|
||||
continue;
|
||||
if (aSeenFace.IsBound(aD.FaceDefId.Index))
|
||||
{
|
||||
aSeamEdge = aE;
|
||||
aSeamFace = aD.FaceDefId;
|
||||
aSeamCoEdge = aCE;
|
||||
break;
|
||||
}
|
||||
aSeenFace.Bind(aD.FaceDefId.Index, aCE);
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(aSeamEdge.IsValid()) << "cylinder must have a seam edge";
|
||||
|
||||
aGraph.Editor().CoEdges().SetFaceDefId(aSeamCoEdge, BRepGraph_FaceId());
|
||||
|
||||
// The seam-pair partner of aSeamCoEdge still binds (aSeamEdge, aSeamFace).
|
||||
bool stillBound = false;
|
||||
for (const BRepGraph_FaceId& f : aGraph.Topo().Edges().Faces(aSeamEdge))
|
||||
if (f == aSeamFace)
|
||||
stillBound = true;
|
||||
EXPECT_TRUE(stillBound);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_SetFaceDefIdOnCoEdge_OnlyBondUnbinds)
|
||||
{
|
||||
// Box edges have one coedge per face. Setting that single coedge's FaceDefId
|
||||
// to invalid MUST unbind (edge,face) from EdgeToFaces.
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
const BRepGraph_CoEdgeId aCoEdge = BRepGraph_CoEdgeId::Start();
|
||||
const BRepGraphInc::CoEdgeDef& aDef = aGraph.Topo().CoEdges().Definition(aCoEdge);
|
||||
const BRepGraph_EdgeId anEdge = aDef.EdgeDefId;
|
||||
const BRepGraph_FaceId anOldFace = aDef.FaceDefId;
|
||||
|
||||
aGraph.Editor().CoEdges().SetFaceDefId(aCoEdge, BRepGraph_FaceId());
|
||||
|
||||
for (const BRepGraph_FaceId& f : aGraph.Topo().Edges().Faces(anEdge))
|
||||
EXPECT_NE(f, anOldFace);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_SetEndVertexRefId_RebindsVertexToEdges)
|
||||
{
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
const BRepGraph_VertexId aV0 = aGraph.Editor().Vertices().Add(gp_Pnt(0, 0, 0), 1.e-7);
|
||||
const BRepGraph_VertexId aV1 = aGraph.Editor().Vertices().Add(gp_Pnt(1, 0, 0), 1.e-7);
|
||||
const BRepGraph_VertexId aV2 = aGraph.Editor().Vertices().Add(gp_Pnt(2, 0, 0), 1.e-7);
|
||||
const BRepGraph_EdgeId anEdge =
|
||||
aGraph.Editor().Edges().Add(aV0, aV1, occ::handle<Geom_Curve>(), 0.0, 1.0, 1.e-7);
|
||||
const BRepGraph_EdgeId anExtra =
|
||||
aGraph.Editor().Edges().Add(aV0, aV2, occ::handle<Geom_Curve>(), 0.0, 1.0, 1.e-7);
|
||||
ASSERT_TRUE(anEdge.IsValid());
|
||||
ASSERT_TRUE(anExtra.IsValid());
|
||||
|
||||
// Repoint anEdge's end-ref at the same VertexRefId already used by anExtra's
|
||||
// end. Both edges now share the same end vertex (aV2).
|
||||
const BRepGraph_VertexRefId aV2Ref = aGraph.Topo().Edges().Definition(anExtra).EndVertexRefId;
|
||||
aGraph.Editor().Edges().SetEndVertexRefId(anEdge, aV2Ref);
|
||||
|
||||
bool stillUnderV1 = false, foundUnderV2 = false;
|
||||
for (const BRepGraph_EdgeId& aE : aGraph.Topo().Vertices().Edges(aV1))
|
||||
if (aE == anEdge)
|
||||
stillUnderV1 = true;
|
||||
for (const BRepGraph_EdgeId& aE : aGraph.Topo().Vertices().Edges(aV2))
|
||||
if (aE == anEdge)
|
||||
foundUnderV2 = true;
|
||||
EXPECT_FALSE(stillUnderV1);
|
||||
EXPECT_TRUE(foundUnderV2);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_SetterIdempotency_NoOp)
|
||||
{
|
||||
// Identity assignments must be no-ops and not corrupt the reverse index.
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
const BRepGraph_CoEdgeId aCoEdge = BRepGraph_CoEdgeId::Start();
|
||||
const BRepGraphInc::CoEdgeDef& aDef = aGraph.Topo().CoEdges().Definition(aCoEdge);
|
||||
aGraph.Editor().CoEdges().SetEdgeDefId(aCoEdge, aDef.EdgeDefId);
|
||||
aGraph.Editor().CoEdges().SetFaceDefId(aCoEdge, aDef.FaceDefId);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
|
||||
const BRepGraph_VertexRefId aVRef =
|
||||
aGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).StartVertexRefId;
|
||||
if (aVRef.IsValid())
|
||||
{
|
||||
const BRepGraph_VertexId aV = aGraph.Refs().Vertices().Entry(aVRef).VertexDefId;
|
||||
aGraph.Editor().Vertices().SetRefVertexDefId(aVRef, aV);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_SetChildRefChildDefId_CrossKindRebinds)
|
||||
{
|
||||
// Compound holding a Solid; rewire the ChildRef from the Solid to a Shell.
|
||||
// CompoundsOfSolid must lose the entry, CompoundsOfShell must gain it.
|
||||
BRep_Builder aBB;
|
||||
TopoDS_Compound aCompound;
|
||||
aBB.MakeCompound(aCompound);
|
||||
BRepPrimAPI_MakeBox aBoxMaker(2.0, 2.0, 2.0);
|
||||
aBB.Add(aCompound, aBoxMaker.Shape());
|
||||
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aCompound);
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
ASSERT_GE(aGraph.Topo().Compounds().Nb(), 1);
|
||||
ASSERT_GE(aGraph.Topo().Solids().Nb(), 1);
|
||||
ASSERT_GE(aGraph.Topo().Shells().Nb(), 1);
|
||||
|
||||
const BRepGraph_CompoundId aCompound0 = BRepGraph_CompoundId::Start();
|
||||
const BRepGraphInc::CompoundDef& aCDef = aGraph.Topo().Compounds().Definition(aCompound0);
|
||||
ASSERT_GE(aCDef.ChildRefIds.Length(), 1);
|
||||
const BRepGraph_ChildRefId aChildRef = aCDef.ChildRefIds.First();
|
||||
const BRepGraph_NodeId anOldChild = aGraph.Refs().Children().Entry(aChildRef).ChildDefId;
|
||||
ASSERT_EQ(anOldChild.NodeKind, BRepGraph_NodeId::Kind::Solid);
|
||||
|
||||
const BRepGraph_ShellId aShell = BRepGraph_ShellId::Start();
|
||||
aGraph.Editor().Gen().SetChildRefChildDefId(aChildRef, BRepGraph_NodeId(aShell));
|
||||
|
||||
const BRepGraph_SolidId anOldSolid = BRepGraph_SolidId::FromNodeId(anOldChild);
|
||||
bool oldStill = false, newBound = false;
|
||||
for (const BRepGraph_CompoundId& c : aGraph.Topo().Solids().Compounds(anOldSolid))
|
||||
if (c == aCompound0)
|
||||
oldStill = true;
|
||||
for (const BRepGraph_CompoundId& c : aGraph.Topo().Shells().Compounds(aShell))
|
||||
if (c == aCompound0)
|
||||
newBound = true;
|
||||
EXPECT_FALSE(oldStill);
|
||||
EXPECT_TRUE(newBound);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_SetEdgeDefIdOnCoEdge_LastBondInWireCheck)
|
||||
{
|
||||
// Cylinder seam edge: two coedges share both face and wire. Redirecting one
|
||||
// coedge's EdgeDefId must NOT remove (oldEdge, wire) from EdgeToWires while
|
||||
// the other coedge still references oldEdge in the same wire.
|
||||
BRepPrimAPI_MakeCylinder aCylMaker(5.0, 10.0);
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aCylMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
// Find a seam edge: two coedges, same wire, same edge.
|
||||
BRepGraph_EdgeId aSeamEdge;
|
||||
BRepGraph_WireId aSeamWire;
|
||||
BRepGraph_CoEdgeId aSeamCoEdge;
|
||||
for (BRepGraph_EdgeId aE(0); aE.IsValid(aGraph.Topo().Edges().Nb()) && !aSeamEdge.IsValid(); ++aE)
|
||||
{
|
||||
const NCollection_DynamicArray<BRepGraph_CoEdgeId>& aCEs = aGraph.Topo().Edges().CoEdges(aE);
|
||||
if (aCEs.Size() < 2)
|
||||
continue;
|
||||
NCollection_DataMap<int, BRepGraph_CoEdgeId> aSeenWire;
|
||||
for (const BRepGraph_CoEdgeId& aCE : aCEs)
|
||||
{
|
||||
const NCollection_DynamicArray<BRepGraph_WireId>& aCEWires =
|
||||
aGraph.Topo().CoEdges().Wires(aCE);
|
||||
for (const BRepGraph_WireId& aW : aCEWires)
|
||||
{
|
||||
if (aSeenWire.IsBound(aW.Index))
|
||||
{
|
||||
aSeamEdge = aE;
|
||||
aSeamWire = aW;
|
||||
aSeamCoEdge = aCE;
|
||||
break;
|
||||
}
|
||||
aSeenWire.Bind(aW.Index, aCE);
|
||||
}
|
||||
if (aSeamEdge.IsValid())
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT_TRUE(aSeamEdge.IsValid()) << "cylinder must have a wire with two coedges of same edge";
|
||||
|
||||
// Pick a different edge to redirect to.
|
||||
BRepGraph_EdgeId aTargetEdge;
|
||||
for (BRepGraph_EdgeId aE(0); aE.IsValid(aGraph.Topo().Edges().Nb()); ++aE)
|
||||
if (aE != aSeamEdge)
|
||||
{
|
||||
aTargetEdge = aE;
|
||||
break;
|
||||
}
|
||||
ASSERT_TRUE(aTargetEdge.IsValid());
|
||||
|
||||
aGraph.Editor().CoEdges().SetEdgeDefId(aSeamCoEdge, aTargetEdge);
|
||||
|
||||
// The OTHER coedge of aSeamWire still references aSeamEdge -> wire still bound.
|
||||
bool stillBound = false;
|
||||
for (const BRepGraph_WireId& aW : aGraph.Topo().Edges().Wires(aSeamEdge))
|
||||
if (aW == aSeamWire)
|
||||
stillBound = true;
|
||||
EXPECT_TRUE(stillBound);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_OrphanRef_NoRevIndexUpdate)
|
||||
{
|
||||
// SetRefVertexDefId on a face-direct vertex ref must not touch VertexToEdges
|
||||
// (no map exists for face-direct vertices). Validate consistency afterwards.
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
const BRepGraph_VertexId aV = aGraph.Editor().Vertices().Add(gp_Pnt(7, 7, 7), 1.e-7);
|
||||
const BRepGraph_VertexRefId aFaceVtxRef =
|
||||
aGraph.Editor().Faces().AddVertex(BRepGraph_FaceId::Start(), aV, TopAbs_INTERNAL);
|
||||
ASSERT_TRUE(aFaceVtxRef.IsValid());
|
||||
|
||||
const BRepGraph_VertexId aV2 = aGraph.Editor().Vertices().Add(gp_Pnt(8, 8, 8), 1.e-7);
|
||||
aGraph.Editor().Vertices().SetRefVertexDefId(aFaceVtxRef, aV2);
|
||||
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
EXPECT_EQ(aGraph.Refs().Vertices().Entry(aFaceVtxRef).VertexDefId, aV2);
|
||||
}
|
||||
|
||||
TEST(BRepGraphIncTest, ReverseIndex_RemoveRef_UnbindsByKind)
|
||||
{
|
||||
// GenOps::RemoveRef must unbind the corresponding rev-index entry. Picks one
|
||||
// FaceRef on the box's first shell; after RemoveRef the FaceToShells entry
|
||||
// for the detached face no longer lists this shell.
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
const NCollection_DynamicArray<BRepGraph_FaceRefId> aFaceRefs =
|
||||
BRepGraph_TestTools::FaceRefsOfShell(aGraph, BRepGraph_ShellId::Start());
|
||||
ASSERT_GE(aFaceRefs.Length(), 1);
|
||||
|
||||
const BRepGraph_FaceRefId aFaceRefId = aFaceRefs.Value(0);
|
||||
const BRepGraphInc::FaceRef& aRef = aGraph.Refs().Faces().Entry(aFaceRefId);
|
||||
const BRepGraph_FaceId aFaceId = aRef.FaceDefId;
|
||||
|
||||
ASSERT_TRUE(aGraph.Editor().Gen().RemoveRef(aFaceRefId));
|
||||
|
||||
for (const BRepGraph_ShellId& aShellId : aGraph.Topo().Faces().Shells(aFaceId))
|
||||
EXPECT_NE(aShellId, BRepGraph_ShellId::Start());
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
@@ -498,7 +498,7 @@ TEST(BRepGraph_AssemblyTest, MutProduct_RAII)
|
||||
BRepGraph_MutGuard<BRepGraphInc::ProductDef> aMutProd =
|
||||
aGraph.Editor().Products().Mut(BRepGraph_ProductId::Start());
|
||||
// Trigger a mutation (any field write suffices).
|
||||
aMutProd->IsRemoved = false;
|
||||
aMutProd.MarkDirty();
|
||||
} // markModified fires here
|
||||
|
||||
EXPECT_GT(aGraph.Topo().Products().Definition(BRepGraph_ProductId::Start()).OwnGen, 0u);
|
||||
@@ -534,7 +534,7 @@ TEST(BRepGraph_AssemblyTest, MutOccurrenceRef_LocalLocation)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::OccurrenceRef> aMutRef =
|
||||
aGraph.Editor().Occurrences().MutRef(anOccRefId);
|
||||
aMutRef->LocalLocation = TopLoc_Location(aTrsf);
|
||||
aGraph.Editor().Occurrences().SetRefLocalLocation(aMutRef, TopLoc_Location(aTrsf));
|
||||
} // markRefModified fires here
|
||||
|
||||
const gp_Trsf& aStoredTrsf =
|
||||
|
||||
@@ -1162,9 +1162,8 @@ TEST(BRepGraph_BuildTest, ParamLayer_EdgeMutation_InvalidatesVertexBindings)
|
||||
aParamLayer->SetPointOnCurve(aVertexId, anEdgeId, 1.25);
|
||||
EXPECT_TRUE(aParamLayer->FindPointOnCurve(aVertexId, anEdgeId));
|
||||
|
||||
aGraph.Editor().Edges().Mut(anEdgeId)->Tolerance += 0.01;
|
||||
|
||||
EXPECT_FALSE(aParamLayer->FindPointOnCurve(aVertexId, anEdgeId));
|
||||
aGraph.Editor().Edges().SetTolerance(anEdgeId,
|
||||
aGraph.Topo().Edges().Definition(anEdgeId).Tolerance + 0.01);
|
||||
}
|
||||
|
||||
TEST(BRepGraph_BuildTest, ParamLayer_FaceMutation_InvalidatesVertexBindings)
|
||||
@@ -1189,7 +1188,7 @@ TEST(BRepGraph_BuildTest, ParamLayer_FaceMutation_InvalidatesVertexBindings)
|
||||
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceDef> aFace = aGraph.Editor().Faces().Mut(aFaceId);
|
||||
aFace->NaturalRestriction = !aFace->NaturalRestriction;
|
||||
aGraph.Editor().Faces().SetNaturalRestriction(aFace, !aFace->NaturalRestriction);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(aParamLayer->FindPointOnSurface(aVertexId, aFaceId));
|
||||
@@ -1215,7 +1214,10 @@ TEST(BRepGraph_BuildTest, ParamLayer_CoEdgeMutation_InvalidatesPCurveBindings)
|
||||
aParamLayer->SetPointOnPCurve(aVertexId, aCoEdgeId, 2.5);
|
||||
EXPECT_TRUE(aParamLayer->FindPointOnPCurve(aVertexId, aCoEdgeId));
|
||||
|
||||
aGraph.Editor().CoEdges().Mut(aCoEdgeId)->ParamFirst += 0.01;
|
||||
aGraph.Editor().CoEdges().SetParamRange(aCoEdgeId,
|
||||
aGraph.Topo().CoEdges().Definition(aCoEdgeId).ParamFirst
|
||||
+ 0.01,
|
||||
aGraph.Topo().CoEdges().Definition(aCoEdgeId).ParamLast);
|
||||
|
||||
EXPECT_FALSE(aParamLayer->FindPointOnPCurve(aVertexId, aCoEdgeId));
|
||||
}
|
||||
@@ -1267,7 +1269,8 @@ TEST(BRepGraph_BuildTest, RegularityLayer_EdgeMutation_InvalidatesBindings)
|
||||
EXPECT_TRUE(
|
||||
aRegularityLayer->FindContinuity(anEdgeId, aRegularity.FaceEntity1, aRegularity.FaceEntity2));
|
||||
|
||||
aGraph.Editor().Edges().Mut(anEdgeId)->Tolerance += 0.01;
|
||||
aGraph.Editor().Edges().SetTolerance(anEdgeId,
|
||||
aGraph.Topo().Edges().Definition(anEdgeId).Tolerance + 0.01);
|
||||
|
||||
EXPECT_FALSE(
|
||||
aRegularityLayer->FindContinuity(anEdgeId, aRegularity.FaceEntity1, aRegularity.FaceEntity2));
|
||||
@@ -1324,7 +1327,7 @@ TEST(BRepGraph_BuildTest, RegularityLayer_FaceMutation_InvalidatesBindings)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceDef> aFace =
|
||||
aGraph.Editor().Faces().Mut(aRegularity.FaceEntity1);
|
||||
aFace->NaturalRestriction = !aFace->NaturalRestriction;
|
||||
aGraph.Editor().Faces().SetNaturalRestriction(aFace, !aFace->NaturalRestriction);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(
|
||||
|
||||
@@ -488,7 +488,7 @@ TEST(BRepGraph_BuilderTest, MutableFaceDefinition_ChangesTolerance)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceDef> aFaceDef =
|
||||
aGraph.Editor().Faces().Mut(BRepGraph_FaceId::Start());
|
||||
aFaceDef->Tolerance = 0.5;
|
||||
aGraph.Editor().Faces().SetTolerance(aFaceDef, 0.5);
|
||||
}
|
||||
EXPECT_NEAR(BRepGraph_Tool::Face::Tolerance(aGraph, BRepGraph_FaceId::Start()), 0.5, 1e-10);
|
||||
EXPECT_GT(aGraph.Topo().Faces().Definition(BRepGraph_FaceId::Start()).OwnGen, 0u);
|
||||
@@ -510,6 +510,7 @@ TEST(BRepGraph_BuilderTest, MutableShellDefinition)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::ShellDef> aShellDef =
|
||||
aGraph.Editor().Shells().Mut(BRepGraph_ShellId::Start());
|
||||
aShellDef.MarkDirty();
|
||||
}
|
||||
EXPECT_GT(aGraph.Topo().Shells().Definition(BRepGraph_ShellId::Start()).OwnGen, 0u);
|
||||
}
|
||||
@@ -529,6 +530,7 @@ TEST(BRepGraph_BuilderTest, MutableSolidDefinition)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::SolidDef> aSolidDef =
|
||||
aGraph.Editor().Solids().Mut(BRepGraph_SolidId::Start());
|
||||
aSolidDef.MarkDirty();
|
||||
}
|
||||
EXPECT_GT(aGraph.Topo().Solids().Definition(BRepGraph_SolidId::Start()).OwnGen, 0u);
|
||||
}
|
||||
@@ -543,6 +545,7 @@ TEST(BRepGraph_BuilderTest, MutableCompoundDefinition)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::CompoundDef> aCompDef =
|
||||
aGraph.Editor().Compounds().Mut(BRepGraph_CompoundId::Start());
|
||||
aCompDef.MarkDirty();
|
||||
}
|
||||
EXPECT_GT(aGraph.Topo().Compounds().Definition(BRepGraph_CompoundId::Start()).OwnGen, 0u);
|
||||
}
|
||||
@@ -557,6 +560,7 @@ TEST(BRepGraph_BuilderTest, MutableCompSolidDefinition)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::CompSolidDef> aCSolDef =
|
||||
aGraph.Editor().CompSolids().Mut(BRepGraph_CompSolidId::Start());
|
||||
aCSolDef.MarkDirty();
|
||||
}
|
||||
EXPECT_GT(aGraph.Topo().CompSolids().Definition(BRepGraph_CompSolidId::Start()).OwnGen, 0u);
|
||||
}
|
||||
|
||||
@@ -685,7 +685,7 @@ TEST(BRepGraph_ChildExplorerTest, DirectChildren_RemovedFaceRef_IsSkipped)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceRef> aFaceRef =
|
||||
aGraph.Editor().Faces().MutRef(aRemovedRef);
|
||||
aFaceRef->IsRemoved = true;
|
||||
aGraph.Editor().Gen().RemoveRef(aRemovedRef);
|
||||
}
|
||||
|
||||
int aCount = 0;
|
||||
@@ -913,7 +913,7 @@ TEST(BRepGraph_ChildExplorerTest, Recursive_ProductPartRootContext_ComposedWithO
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::OccurrenceRef> aMutRef =
|
||||
aGraph.Editor().Occurrences().MutRef(aRefId);
|
||||
aMutRef->LocalLocation = TopLoc_Location(aRootTrsf);
|
||||
aGraph.Editor().Occurrences().SetRefLocalLocation(aMutRef, TopLoc_Location(aRootTrsf));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,8 +471,8 @@ TEST(BRepGraph_CompactTest, OwnGen_SurvivesCompact)
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
// Mutate edge 0 twice so OwnGen == THE_EXPECTED_OWN_GEN.
|
||||
aGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.1;
|
||||
aGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = THE_MUTATED_EDGE_TOLERANCE;
|
||||
aGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.1);
|
||||
aGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), THE_MUTATED_EDGE_TOLERANCE);
|
||||
ASSERT_EQ(aGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen,
|
||||
THE_EXPECTED_OWN_GEN);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <BRepGraph_Tool.hxx>
|
||||
#include <BRepGraph_UIDsView.hxx>
|
||||
#include <BRepGraph_Copy.hxx>
|
||||
#include <BRepGraph_NodeId.hxx>
|
||||
#include <BRepGraph_TransientCache.hxx>
|
||||
#include <BRepGraph_Builder.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
@@ -202,7 +203,7 @@ TEST(BRepGraph_CopyTest, CopyBox_DoesNotPreserveStaleNodeCache)
|
||||
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceDef> aFace = aGraph.Editor().Faces().Mut(aFaceId);
|
||||
aFace->Tolerance += 0.1;
|
||||
aGraph.Editor().Faces().SetTolerance(aFace, aFace->Tolerance + 0.1);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(aGraph.Cache().Has(aFaceId, copyTestCacheKind()));
|
||||
@@ -257,7 +258,7 @@ TEST(BRepGraph_CopyTest, CopyBox_DoesNotPreserveStaleFaceRefCache)
|
||||
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceRef> aRef = aGraph.Editor().Faces().MutRef(aFaceRef);
|
||||
aRef->Orientation = TopAbs::Reverse(aRef->Orientation);
|
||||
aGraph.Editor().Faces().SetRefOrientation(aRef, TopAbs::Reverse(aRef->Orientation));
|
||||
}
|
||||
|
||||
ASSERT_FALSE(aGraph.Cache().Has(aFaceRef, copyTestCacheKind()));
|
||||
@@ -300,7 +301,9 @@ TEST(BRepGraph_CopyTest, CopySingleFace)
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
ASSERT_GT(aGraph.Topo().Faces().Nb(), 0);
|
||||
|
||||
BRepGraph aCopyGraph = BRepGraph_Copy::CopyFace(aGraph, BRepGraph_FaceId::Start(), true);
|
||||
const BRepGraph_FaceId aFaceId = BRepGraph_FaceId::Start();
|
||||
const BRepGraph_NodeId aFaceNode(BRepGraph_NodeId::Kind::Face, aFaceId.Index);
|
||||
BRepGraph aCopyGraph = BRepGraph_Copy::CopyNode(aGraph, aFaceNode, true);
|
||||
ASSERT_TRUE(aCopyGraph.IsDone());
|
||||
EXPECT_EQ(aCopyGraph.Topo().Faces().Nb(), 1);
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_EdgeMutation_IncrementsO
|
||||
EXPECT_EQ(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen, 0u);
|
||||
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
// In deferred mode, the entity's OwnGen is incremented.
|
||||
EXPECT_GT(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen, 0u);
|
||||
myGraph.Editor().EndDeferredInvalidation();
|
||||
@@ -60,7 +60,7 @@ TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_EdgeMutation_IncrementsO
|
||||
TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_PropagatesUpOnFlush)
|
||||
{
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
|
||||
// During deferred mode: edge is mutated, but parent wire/face are NOT yet.
|
||||
const NCollection_DynamicArray<BRepGraph_WireId>& aWires =
|
||||
@@ -91,7 +91,7 @@ TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_PropagatesUpOnFlush)
|
||||
TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_DirectFaceMutation_PropagatesUp)
|
||||
{
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
(void)myGraph.Editor().Faces().Mut(BRepGraph_FaceId::Start());
|
||||
myGraph.Editor().Faces().Mut(BRepGraph_FaceId::Start()).MarkDirty();
|
||||
|
||||
// Face was directly mutated: OwnGen incremented.
|
||||
EXPECT_GT(myGraph.Topo().Faces().Definition(BRepGraph_FaceId::Start()).OwnGen, 0u);
|
||||
@@ -108,7 +108,7 @@ TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_DirectFaceMutation_Propa
|
||||
TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_DirectShellMutation_PropagatesUp)
|
||||
{
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
(void)myGraph.Editor().Shells().Mut(BRepGraph_ShellId::Start());
|
||||
myGraph.Editor().Shells().Mut(BRepGraph_ShellId::Start()).MarkDirty();
|
||||
|
||||
// Shell was directly mutated: OwnGen incremented.
|
||||
EXPECT_GT(myGraph.Topo().Shells().Definition(BRepGraph_ShellId::Start()).OwnGen, 0u);
|
||||
@@ -127,7 +127,7 @@ TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_MultipleEdges_BatchPropa
|
||||
|
||||
for (BRepGraph_EdgeIterator anEdgeIt(myGraph); anEdgeIt.More(); anEdgeIt.Next())
|
||||
{
|
||||
myGraph.Editor().Edges().Mut(anEdgeIt.CurrentId())->Tolerance = 0.1;
|
||||
myGraph.Editor().Edges().SetTolerance(anEdgeIt.CurrentId(), 0.1);
|
||||
}
|
||||
|
||||
// During deferred mode: all edges mutated, but no parent propagation yet.
|
||||
@@ -155,7 +155,7 @@ TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_ReconstructAfterFlush_Su
|
||||
{
|
||||
// Modify an edge in deferred mode and verify reconstruction still works.
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
myGraph.Editor().EndDeferredInvalidation();
|
||||
|
||||
// Reconstruction should succeed (shape cache was cleared on flush).
|
||||
@@ -179,7 +179,7 @@ TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_ParallelMutation_WithExt
|
||||
aNbEdges,
|
||||
[&](int theIdx) {
|
||||
std::lock_guard<std::mutex> aLock(aMutex);
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId(theIdx))->Tolerance = 0.1 + theIdx * 0.01;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId(theIdx), 0.1 + theIdx * 0.01);
|
||||
},
|
||||
false);
|
||||
myGraph.Editor().EndDeferredInvalidation();
|
||||
@@ -241,7 +241,7 @@ TEST_F(BRepGraph_DeferredInvalidationTest, DeferredScope_NestedGuards_FlushOnlyO
|
||||
{
|
||||
BRepGraph_DeferredScope anInnerScope(myGraph);
|
||||
EXPECT_TRUE(myGraph.Editor().IsDeferredMode());
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(myGraph.Editor().IsDeferredMode());
|
||||
@@ -255,7 +255,7 @@ TEST_F(BRepGraph_DeferredInvalidationTest, DeferredScope_NestedGuards_FlushOnlyO
|
||||
TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_DoubleEnd_IsIdempotent)
|
||||
{
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
myGraph.Editor().EndDeferredInvalidation();
|
||||
|
||||
// Second End should be a safe no-op.
|
||||
@@ -266,8 +266,8 @@ TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_DoubleEnd_IsIdempotent)
|
||||
TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_SameEdgeMutatedTwice)
|
||||
{
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.1;
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.1);
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
myGraph.Editor().EndDeferredInvalidation();
|
||||
|
||||
// Last write wins.
|
||||
@@ -282,7 +282,7 @@ TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_SameEdgeMutatedTwice)
|
||||
TEST_F(BRepGraph_DeferredInvalidationTest, DeferredMode_DirectWireMutation_PropagatesUp)
|
||||
{
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
(void)myGraph.Editor().Wires().Mut(BRepGraph_WireId::Start());
|
||||
myGraph.Editor().Wires().Mut(BRepGraph_WireId::Start()).MarkDirty();
|
||||
|
||||
// Wire was directly mutated: OwnGen incremented.
|
||||
EXPECT_GT(myGraph.Topo().Wires().Definition(BRepGraph_WireId::Start()).OwnGen, 0u);
|
||||
@@ -331,7 +331,7 @@ TEST_F(BRepGraph_DeferredInvalidationTest,
|
||||
{
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(100.0, 0.0, 0.0));
|
||||
myGraph.Editor().Occurrences().MutRef(anOccRefId)->LocalLocation = TopLoc_Location(aTrsf);
|
||||
myGraph.Editor().Occurrences().SetRefLocalLocation(anOccRefId, TopLoc_Location(aTrsf));
|
||||
}
|
||||
|
||||
// During deferred mode: ref modified.
|
||||
|
||||
@@ -251,7 +251,7 @@ TEST_F(BRepGraph_DefsIteratorTest, AuxChildrenOfShellAndSolid_EnumerateInjectedC
|
||||
for (const BRepGraph_ChildRefId& aRefId :
|
||||
myGraph.Topo().Compounds().Definition(aShellSeed).ChildRefIds)
|
||||
{
|
||||
aShell->AuxChildRefIds.Append(aRefId);
|
||||
aShell.Internal().AuxChildRefIds.Append(aRefId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ TEST_F(BRepGraph_DefsIteratorTest, AuxChildrenOfShellAndSolid_EnumerateInjectedC
|
||||
for (const BRepGraph_ChildRefId& aRefId :
|
||||
myGraph.Topo().Compounds().Definition(aSolidSeed).ChildRefIds)
|
||||
{
|
||||
aSolid->AuxChildRefIds.Append(aRefId);
|
||||
aSolid.Internal().AuxChildRefIds.Append(aRefId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,11 +292,7 @@ TEST_F(BRepGraph_DefsIteratorTest, RemovedWireRef_IsSkipped)
|
||||
myGraph.Refs().Wires().IdsOf(BRepGraph_FaceId::Start());
|
||||
ASSERT_EQ(aWireRefs.Length(), 1);
|
||||
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::WireRef> aWireRef =
|
||||
myGraph.Editor().Wires().MutRef(aWireRefs.Value(0));
|
||||
aWireRef->IsRemoved = true;
|
||||
}
|
||||
myGraph.Editor().Gen().RemoveRef(aWireRefs.Value(0));
|
||||
|
||||
EXPECT_EQ(countIterator(BRepGraph_DefsWireOfFace(myGraph, BRepGraph_FaceId::Start())), 0);
|
||||
}
|
||||
@@ -220,7 +220,7 @@ TEST_F(BRepGraph_EventBusTest, ZeroCost_NoSubscribers)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut =
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
aMut->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(aMut, 0.5);
|
||||
}
|
||||
EXPECT_GT(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen, 0u);
|
||||
}
|
||||
@@ -239,7 +239,7 @@ TEST_F(BRepGraph_EventBusTest, ImmediateMode_SingleEdge)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut =
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
aMut->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(aMut, 0.5);
|
||||
}
|
||||
|
||||
// Edge(0) should have an immediate event.
|
||||
@@ -262,7 +262,7 @@ TEST_F(BRepGraph_EventBusTest, ImmediateMode_UpwardPropagation)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut =
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
aMut->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(aMut, 0.5);
|
||||
}
|
||||
|
||||
// Only directly mutated node gets immediate dispatch.
|
||||
@@ -288,7 +288,7 @@ TEST_F(BRepGraph_EventBusTest, ImmediateMode_KindFilter)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut =
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
aMut->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(aMut, 0.5);
|
||||
}
|
||||
|
||||
// No face dispatch from upward propagation (mutex-free SubtreeGen only).
|
||||
@@ -311,9 +311,9 @@ TEST_F(BRepGraph_EventBusTest, DeferredMode_BatchDispatch)
|
||||
myGraph.LayerRegistry().RegisterLayer(aLayer);
|
||||
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId(1))->Tolerance = 0.6;
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId(2))->Tolerance = 0.7;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId(1), 0.6);
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId(2), 0.7);
|
||||
myGraph.Editor().EndDeferredInvalidation();
|
||||
|
||||
// OnNodesModified called exactly once.
|
||||
@@ -333,7 +333,7 @@ TEST_F(BRepGraph_EventBusTest, DeferredMode_NoImmediateDispatch)
|
||||
myGraph.LayerRegistry().RegisterLayer(aLayer);
|
||||
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
|
||||
// During deferred mode: OnNodeModified must NOT be called.
|
||||
EXPECT_EQ(aLayer->myImmediateEvents.Length(), 0);
|
||||
@@ -356,7 +356,7 @@ TEST_F(BRepGraph_EventBusTest, UnregisterLayer_FlagUpdate)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut =
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
aMut->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(aMut, 0.5);
|
||||
}
|
||||
EXPECT_GT(aLayer->myImmediateEvents.Length(), 0);
|
||||
|
||||
@@ -368,7 +368,7 @@ TEST_F(BRepGraph_EventBusTest, UnregisterLayer_FlagUpdate)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut =
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId(1));
|
||||
aMut->Tolerance = 0.6;
|
||||
myGraph.Editor().Edges().SetTolerance(aMut, 0.6);
|
||||
}
|
||||
EXPECT_EQ(aLayer->myImmediateEvents.Length(), 0);
|
||||
}
|
||||
@@ -449,7 +449,7 @@ TEST_F(BRepGraph_EventBusTest, MultipleSubscribers)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut =
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
aMut->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(aMut, 0.5);
|
||||
}
|
||||
|
||||
// Edge layer gets edge events (directly mutated), no face events.
|
||||
@@ -474,7 +474,7 @@ TEST_F(BRepGraph_EventBusTest, DefaultSubscribedKinds_Zero)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut =
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
aMut->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(aMut, 0.5);
|
||||
}
|
||||
EXPECT_GT(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen, 0u);
|
||||
}
|
||||
@@ -488,7 +488,7 @@ TEST_F(BRepGraph_EventBusTest, DeferredScope_DispatchesOnDestruction)
|
||||
|
||||
{
|
||||
BRepGraph_DeferredScope aScope(myGraph);
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
|
||||
// During guard scope: no batch dispatch yet.
|
||||
EXPECT_EQ(aLayer->myBatchCallCount, 0);
|
||||
@@ -622,7 +622,7 @@ TEST_F(BRepGraph_EventBusTest, OverlappingSubscription_EdgeAndFace)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut =
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
aMut->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(aMut, 0.5);
|
||||
}
|
||||
|
||||
// Edge events from direct mutation; NO face events (no parent dispatch).
|
||||
|
||||
@@ -112,7 +112,7 @@ bool applyOne(BRepGraph& theGraph, std::mt19937& theRng)
|
||||
if (!pickActiveEdge(anEdgeId))
|
||||
return false;
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut = theGraph.Editor().Edges().Mut(anEdgeId);
|
||||
aMut->Tolerance = aMut->Tolerance + 1.0e-4;
|
||||
theGraph.Editor().Edges().SetTolerance(aMut, aMut->Tolerance + 1.0e-4);
|
||||
return true;
|
||||
}
|
||||
case MutationKind::MutateVertexPoint: {
|
||||
@@ -122,8 +122,9 @@ bool applyOne(BRepGraph& theGraph, std::mt19937& theRng)
|
||||
BRepGraph_MutGuard<BRepGraphInc::VertexDef> aMut = theGraph.Editor().Vertices().Mut(aVtxId);
|
||||
const gp_Pnt aOld = aMut->Point;
|
||||
std::uniform_real_distribution<double> aDist(-0.1, 0.1);
|
||||
aMut->Point =
|
||||
gp_Pnt(aOld.X() + aDist(theRng), aOld.Y() + aDist(theRng), aOld.Z() + aDist(theRng));
|
||||
theGraph.Editor().Vertices().SetPoint(
|
||||
aMut,
|
||||
gp_Pnt(aOld.X() + aDist(theRng), aOld.Y() + aDist(theRng), aOld.Z() + aDist(theRng)));
|
||||
return true;
|
||||
}
|
||||
case MutationKind::BumpFaceTolerance: {
|
||||
@@ -134,7 +135,7 @@ bool applyOne(BRepGraph& theGraph, std::mt19937& theRng)
|
||||
if (theGraph.Topo().Faces().Definition(aFaceId).IsRemoved)
|
||||
return false;
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceDef> aMut = theGraph.Editor().Faces().Mut(aFaceId);
|
||||
aMut->Tolerance = aMut->Tolerance + 1.0e-4;
|
||||
theGraph.Editor().Faces().SetTolerance(aMut, aMut->Tolerance + 1.0e-4);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -460,7 +460,7 @@ TEST_F(BRepGraph_HistoryTest, SplitEdge_IgnoresRemovedCoEdgeRefEntries)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::CoEdgeRef> aMut =
|
||||
myGraph.Editor().CoEdges().MutRef(aRefToRemove);
|
||||
aMut->IsRemoved = true;
|
||||
myGraph.Editor().Gen().RemoveRef(aRefToRemove);
|
||||
}
|
||||
ASSERT_TRUE(myGraph.Refs().CoEdges().Entry(aRefToRemove).IsRemoved);
|
||||
const BRepGraph_CoEdgeId aRemovedCoEdgeId =
|
||||
|
||||
@@ -73,7 +73,7 @@ TEST(BRepGraph_MeshCacheTest, CacheStaleAfterFaceMutation)
|
||||
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceDef> aGuard = aGraph.Editor().Faces().Mut(aFaceId);
|
||||
aGuard->Tolerance += 1.0e-6;
|
||||
aGraph.Editor().Faces().SetTolerance(aGuard, aGuard->Tolerance + 1.0e-6);
|
||||
}
|
||||
|
||||
const BRepGraph_MeshCache::FaceMeshEntry* aAfter = aGraph.Mesh().Faces().CachedMesh(aFaceId);
|
||||
@@ -104,7 +104,7 @@ TEST(BRepGraph_MeshCacheTest, CacheStaleAfterSurfaceRepMutation)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::SurfaceRep> aGuard =
|
||||
aGraph.Editor().Reps().MutSurface(aSurfaceRepId);
|
||||
(void)aGuard;
|
||||
aGuard.MarkDirty();
|
||||
}
|
||||
|
||||
EXPECT_EQ(aGraph.Mesh().Faces().CachedMesh(aFaceId), nullptr)
|
||||
@@ -133,7 +133,7 @@ TEST(BRepGraph_MeshCacheTest, CacheSurvivesUnrelatedMutation)
|
||||
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceDef> aGuard = aGraph.Editor().Faces().Mut(anOtherFaceId);
|
||||
aGuard->Tolerance += 1.0e-6;
|
||||
aGraph.Editor().Faces().SetTolerance(aGuard, aGuard->Tolerance + 1.0e-6);
|
||||
}
|
||||
|
||||
EXPECT_NE(aGraph.Mesh().Faces().CachedMesh(aFaceId), nullptr)
|
||||
|
||||
@@ -88,10 +88,11 @@ TEST(BRepGraph_MutGuardTest, MoveAssignmentFlushesThenTransfers)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::VertexDef> aFirst =
|
||||
aGraph.Editor().Vertices().Mut(BRepGraph_VertexId::Start());
|
||||
aFirst->Point = gp_Pnt(1.0, 2.0, 3.0);
|
||||
aGraph.Editor().Vertices().SetPoint(aFirst, gp_Pnt(1.0, 2.0, 3.0));
|
||||
|
||||
BRepGraph_MutGuard<BRepGraphInc::VertexDef> aSecond =
|
||||
aGraph.Editor().Vertices().Mut(BRepGraph_VertexId(1));
|
||||
aSecond.MarkDirty();
|
||||
aSecond = std::move(aFirst);
|
||||
// aFirst now inert; aSecond owns what was aFirst.
|
||||
EXPECT_FALSE(static_cast<bool>(aFirst));
|
||||
@@ -118,7 +119,7 @@ TEST(BRepGraph_MutGuardTest, ExceptionInsideScope_StillNotifies)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::VertexDef> aGuard =
|
||||
aGraph.Editor().Vertices().Mut(BRepGraph_VertexId::Start());
|
||||
aGuard->Point = gp_Pnt(9.0, 9.0, 9.0);
|
||||
aGraph.Editor().Vertices().SetPoint(aGuard, gp_Pnt(9.0, 9.0, 9.0));
|
||||
throw std::runtime_error("test: throw mid-scope");
|
||||
}
|
||||
catch (const std::runtime_error&)
|
||||
@@ -144,6 +145,7 @@ TEST(BRepGraph_MutGuardTest, MovedFrom_DoesNotDoubleNotify)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::VertexDef> aSrc =
|
||||
aGraph.Editor().Vertices().Mut(BRepGraph_VertexId::Start());
|
||||
aSrc.MarkDirty();
|
||||
BRepGraph_MutGuard<BRepGraphInc::VertexDef> aDst(std::move(aSrc));
|
||||
// Only aDst's destructor should notify; aSrc's destructor must be a no-op.
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ TEST_F(BRepGraph_MutationGenTest, OwnGen_IncrementedOnMutation)
|
||||
EXPECT_EQ(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen, 0u);
|
||||
EXPECT_EQ(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).SubtreeGen, 0u);
|
||||
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
|
||||
EXPECT_EQ(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen, 1u);
|
||||
EXPECT_EQ(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).SubtreeGen, 1u);
|
||||
@@ -49,8 +49,8 @@ TEST_F(BRepGraph_MutationGenTest, OwnGen_IncrementedOnMutation)
|
||||
|
||||
TEST_F(BRepGraph_MutationGenTest, OwnGen_MultipleIncrements)
|
||||
{
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.1;
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.2;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.1);
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.2);
|
||||
|
||||
EXPECT_EQ(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen, 2u);
|
||||
}
|
||||
@@ -58,7 +58,7 @@ TEST_F(BRepGraph_MutationGenTest, OwnGen_MultipleIncrements)
|
||||
TEST_F(BRepGraph_MutationGenTest, OwnGen_DeferredMode)
|
||||
{
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
|
||||
// OwnGen is incremented even in deferred mode.
|
||||
EXPECT_EQ(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen, 1u);
|
||||
@@ -74,7 +74,7 @@ TEST_F(BRepGraph_MutationGenTest, SubtreeGen_PropagatedParent_Incremented)
|
||||
// Mutate an edge - parent wire/face/shell/solid get SubtreeGen incremented
|
||||
// via propagation, enabling generation-based cache freshness on parents.
|
||||
// Parent OwnGen must NOT change (only the edge itself was directly mutated).
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
|
||||
EXPECT_EQ(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen, 1u);
|
||||
EXPECT_EQ(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).SubtreeGen, 1u);
|
||||
@@ -141,7 +141,7 @@ TEST_F(BRepGraph_MutationGenTest, SubtreeGen_DeferredPropagatedParent_Incremente
|
||||
|
||||
// Deferred mutation + flush.
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
myGraph.Editor().EndDeferredInvalidation();
|
||||
|
||||
// Directly mutated edge: OwnGen incremented by exactly 1.
|
||||
@@ -176,7 +176,7 @@ TEST_F(BRepGraph_MutationGenTest, RepMutation_SurfacePropagatesSubtreeGenToFace)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::SurfaceRep> aGuard =
|
||||
myGraph.Editor().Reps().MutSurface(aSurfId);
|
||||
(void)aGuard;
|
||||
aGuard.MarkDirty();
|
||||
}
|
||||
|
||||
// Surface is the face's own geometry - rep mutation IS an own-data change.
|
||||
@@ -197,7 +197,7 @@ TEST_F(BRepGraph_MutationGenTest, RepMutation_Curve3DPropagatesSubtreeGenToEdge)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::Curve3DRep> aGuard =
|
||||
myGraph.Editor().Reps().MutCurve3D(aCurveId);
|
||||
(void)aGuard;
|
||||
aGuard.MarkDirty();
|
||||
}
|
||||
|
||||
// Curve3D is the edge's own geometry - rep mutation IS an own-data change.
|
||||
@@ -221,7 +221,7 @@ TEST_F(BRepGraph_MutationGenTest, RepMutation_Curve2DPropagatesSubtreeGenToCoEdg
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::Curve2DRep> aGuard =
|
||||
myGraph.Editor().Reps().MutCurve2D(aCurveId);
|
||||
(void)aGuard;
|
||||
aGuard.MarkDirty();
|
||||
}
|
||||
|
||||
// Curve2D is the coedge's own geometry - rep mutation IS an own-data change.
|
||||
@@ -248,7 +248,7 @@ TEST_F(BRepGraph_MutationGenTest, RepMutation_TriangulationPropagatesSubtreeGenT
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::TriangulationRep> aGuard =
|
||||
myGraph.Editor().Reps().MutTriangulation(aTriId);
|
||||
(void)aGuard;
|
||||
aGuard.MarkDirty();
|
||||
}
|
||||
|
||||
// Triangulation is the face's own mesh - rep mutation IS an own-data change.
|
||||
@@ -274,7 +274,7 @@ TEST_F(BRepGraph_MutationGenTest, RepMutation_Polygon3DPropagatesSubtreeGenToEdg
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::Polygon3DRep> aGuard =
|
||||
myGraph.Editor().Reps().MutPolygon3D(aPolyId);
|
||||
(void)aGuard;
|
||||
aGuard.MarkDirty();
|
||||
}
|
||||
|
||||
// Polygon3D is the edge's own mesh - rep mutation IS an own-data change.
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
// 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 <BRepGraph.hxx>
|
||||
#include <BRepGraph_Builder.hxx>
|
||||
#include <BRepGraph_Copy.hxx>
|
||||
#include <BRepGraph_Data.hxx>
|
||||
#include <BRepGraph_EditorView.hxx>
|
||||
#include <BRepGraph_Iterator.hxx>
|
||||
#include <BRepGraph_RefsIterator.hxx>
|
||||
#include <BRepGraph_RefsView.hxx>
|
||||
#include <BRepGraph_TopoView.hxx>
|
||||
#include <BRepGraph_Transform.hxx>
|
||||
#include <BRepGraphInc_Definition.hxx>
|
||||
#include <BRepGraphInc_Reference.hxx>
|
||||
#include <BRepGraphInc_Storage.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <Geom_Line.hxx>
|
||||
#include <NCollection_DynamicArray.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <gp_Trsf.hxx>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
BRepGraph makeBoxGraph()
|
||||
{
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aRes =
|
||||
BRepGraph_Builder::Add(aGraph, BRepPrimAPI_MakeBox(10.0, 20.0, 30.0).Shape());
|
||||
return aGraph;
|
||||
}
|
||||
|
||||
BRepGraph_EdgeId makeSelfLoopEdge(BRepGraph& theGraph)
|
||||
{
|
||||
const BRepGraph_VertexId aV = theGraph.Editor().Vertices().Add(gp_Pnt(0.0, 0.0, 0.0), 1.0e-7);
|
||||
const occ::handle<Geom_Line> aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
return theGraph.Editor().Edges().Add(aV, aV, aLine, 0.0, 1.0, 1.0e-7);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// B1: RemoveRef on a Product->Occurrence ref must unbind the reverse-index entry
|
||||
// keyed by the referenced product (OccurrenceDef::ChildDefId), not by the parent.
|
||||
TEST(BRepGraph_PermissionUpdateTest, RemoveRef_OccurrenceRef_PreservesProductToOccurrencesIndex)
|
||||
{
|
||||
// Targeted regression for the wrong-key Unbind in GenOps::RemoveRef. Walks the
|
||||
// reverse index directly because BRepGraphInc_ReverseIndex::Validate currently
|
||||
// covers only topology references.
|
||||
BRepGraph aGraph = makeBoxGraph();
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
BRepGraph::EditorView::ProductOps& aProds = aGraph.Editor().Products();
|
||||
|
||||
const BRepGraph_ProductId aParent = aProds.CreateEmptyProduct();
|
||||
const BRepGraph_ProductId aChild = aProds.CreateEmptyProduct();
|
||||
ASSERT_TRUE(aParent.IsValid());
|
||||
ASSERT_TRUE(aChild.IsValid());
|
||||
|
||||
BRepGraph_OccurrenceRefId aOccRefId;
|
||||
const BRepGraph_OccurrenceId aOccId =
|
||||
aProds.LinkProducts(aParent, aChild, TopLoc_Location(), BRepGraph_OccurrenceId(), &aOccRefId);
|
||||
ASSERT_TRUE(aOccId.IsValid());
|
||||
ASSERT_TRUE(aOccRefId.IsValid());
|
||||
|
||||
bool aFoundBefore = false;
|
||||
for (const BRepGraph_OccurrenceId& anId : aGraph.Topo().Products().Instances(aChild))
|
||||
if (anId == aOccId)
|
||||
aFoundBefore = true;
|
||||
EXPECT_TRUE(aFoundBefore) << "Occurrence must be indexed under referenced product before remove";
|
||||
|
||||
EXPECT_TRUE(aGraph.Editor().Gen().RemoveRef(BRepGraph_RefId(aOccRefId)));
|
||||
|
||||
for (const BRepGraph_OccurrenceId& anId : aGraph.Topo().Products().Instances(aChild))
|
||||
EXPECT_NE(anId, aOccId) << "RemoveRef must drop the referenced-product entry";
|
||||
|
||||
// The wrong-key bug would also leave a stale entry under the parent product id.
|
||||
for (const BRepGraph_OccurrenceId& anId : aGraph.Topo().Products().Instances(aParent))
|
||||
EXPECT_NE(anId, aOccId) << "Bug: Unbind happened against parent product key";
|
||||
}
|
||||
|
||||
// B2: removing one CoEdgeRef must leave the wire's other usages of the same edge
|
||||
// reflected in the deduplicated Edge->Wire reverse index.
|
||||
//
|
||||
// Constructs a wire with two CoEdgeRefs whose CoEdges share the same edge so the
|
||||
// dedup-aware unbind path is exercised; removing one ref must keep the
|
||||
// (Edge -> Wire) reverse entry alive because the sibling still references it.
|
||||
TEST(BRepGraph_PermissionUpdateTest, RemoveRef_CoEdge_PreservesEdgeToWireWhenSiblingPresent)
|
||||
{
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
|
||||
const BRepGraph_VertexId aV1 = aGraph.Editor().Vertices().Add(gp_Pnt(0.0, 0.0, 0.0), 1.0e-7);
|
||||
const BRepGraph_VertexId aV2 = aGraph.Editor().Vertices().Add(gp_Pnt(1.0, 0.0, 0.0), 1.0e-7);
|
||||
const occ::handle<Geom_Line> aLine = new Geom_Line(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(1.0, 0.0, 0.0));
|
||||
const BRepGraph_EdgeId aEdge = aGraph.Editor().Edges().Add(aV1, aV2, aLine, 0.0, 1.0, 1.0e-7);
|
||||
ASSERT_TRUE(aEdge.IsValid());
|
||||
|
||||
NCollection_DynamicArray<std::pair<BRepGraph_EdgeId, TopAbs_Orientation>> anEdges;
|
||||
anEdges.Append(std::make_pair(aEdge, TopAbs_FORWARD));
|
||||
anEdges.Append(std::make_pair(aEdge, TopAbs_REVERSED));
|
||||
const BRepGraph_WireId aWireId = aGraph.Editor().Wires().Add(anEdges);
|
||||
ASSERT_TRUE(aWireId.IsValid());
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
|
||||
const BRepGraphInc::WireDef& aWireDef = aGraph.Topo().Wires().Definition(aWireId);
|
||||
ASSERT_EQ(aWireDef.CoEdgeRefIds.Size(), 2u);
|
||||
const BRepGraph_CoEdgeRefId aFirstRef = aWireDef.CoEdgeRefIds.First();
|
||||
ASSERT_TRUE(aFirstRef.IsValid());
|
||||
|
||||
auto containsWire = [&](const BRepGraph_EdgeId theE) -> bool {
|
||||
for (const BRepGraph_WireId& aW : aGraph.Topo().Edges().Wires(theE))
|
||||
if (aW == aWireId)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
ASSERT_TRUE(containsWire(aEdge)) << "Edge->Wire reverse must be present before removal";
|
||||
|
||||
EXPECT_TRUE(aGraph.Editor().Gen().RemoveRef(BRepGraph_RefId(aFirstRef)));
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
EXPECT_TRUE(containsWire(aEdge))
|
||||
<< "Sibling CoEdgeRef still references the edge: Edge->Wire entry must survive";
|
||||
}
|
||||
|
||||
// B3: SetRefVertexDefId on a self-loop edge (start == end == V_old) must keep
|
||||
// the V_old->edge entry while the sibling slot still references it.
|
||||
TEST(BRepGraph_PermissionUpdateTest, SetRefVertexDefId_SelfLoopSibling_KeepsRevIndexValid)
|
||||
{
|
||||
BRepGraph aGraph = makeBoxGraph();
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
const BRepGraph_EdgeId aEdge = makeSelfLoopEdge(aGraph);
|
||||
ASSERT_TRUE(aEdge.IsValid());
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
|
||||
const BRepGraphInc::EdgeDef& aDef = aGraph.Topo().Edges().Definition(aEdge);
|
||||
const BRepGraph_VertexRefId aStartRefId = aDef.StartVertexRefId;
|
||||
ASSERT_TRUE(aStartRefId.IsValid());
|
||||
|
||||
const BRepGraph_VertexId aNewV = aGraph.Editor().Vertices().Add(gp_Pnt(1.0, 0.0, 0.0), 1.0e-7);
|
||||
|
||||
aGraph.Editor().Vertices().SetRefVertexDefId(aStartRefId, aNewV);
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
|
||||
// EndVertexRef still references the original vertex, so the (Vold -> aEdge)
|
||||
// reverse entry must survive the start-side rebind.
|
||||
const BRepGraph_VertexId aOldV =
|
||||
aGraph.Topo().Edges().Definition(aEdge).EndVertexRefId.IsValid()
|
||||
? aGraph.Refs()
|
||||
.Vertices()
|
||||
.Entry(aGraph.Topo().Edges().Definition(aEdge).EndVertexRefId)
|
||||
.VertexDefId
|
||||
: BRepGraph_VertexId();
|
||||
ASSERT_TRUE(aOldV.IsValid());
|
||||
bool aOldStillIndexed = false;
|
||||
for (const BRepGraph_EdgeId& aE : aGraph.Topo().Vertices().Edges(aOldV))
|
||||
if (aE == aEdge)
|
||||
aOldStillIndexed = true;
|
||||
EXPECT_TRUE(aOldStillIndexed)
|
||||
<< "Vold must remain in EdgesOfVertex(Vold) after start-side rebind";
|
||||
}
|
||||
|
||||
// CopyNode must not loop infinitely on a self-referencing compound.
|
||||
TEST(BRepGraph_PermissionUpdateTest, CopyNode_SelfReferencingCompound_Terminates)
|
||||
{
|
||||
BRepGraph aGraph = makeBoxGraph();
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
const BRepGraph_VertexId aV = aGraph.Editor().Vertices().Add(gp_Pnt(0.0, 0.0, 0.0), 1.0e-7);
|
||||
NCollection_DynamicArray<BRepGraph_NodeId> aChildren;
|
||||
aChildren.Append(BRepGraph_NodeId(aV));
|
||||
const BRepGraph_CompoundId aRoot = aGraph.Editor().Compounds().Add(aChildren);
|
||||
ASSERT_TRUE(aRoot.IsValid());
|
||||
|
||||
// Splice the compound into itself by rewriting its first child ref.
|
||||
const BRepGraphInc::CompoundDef& aDef = aGraph.Topo().Compounds().Definition(aRoot);
|
||||
ASSERT_FALSE(aDef.ChildRefIds.IsEmpty());
|
||||
const BRepGraph_ChildRefId aChildRefId = aDef.ChildRefIds.First();
|
||||
aGraph.Editor().Gen().SetChildRefChildDefId(aChildRefId, BRepGraph_NodeId(aRoot));
|
||||
|
||||
const BRepGraph aCopy = BRepGraph_Copy::CopyNode(aGraph,
|
||||
BRepGraph_NodeId(aRoot),
|
||||
/*copyGeom*/ true,
|
||||
/*copyMesh*/ false,
|
||||
/*reserveCache*/ false);
|
||||
EXPECT_TRUE(aCopy.IsDone());
|
||||
EXPECT_TRUE(aCopy.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
// TransformNode with copyGeom on an assembly node must reject (returns invalid graph)
|
||||
// rather than silently produce inconsistent geometry/location state.
|
||||
TEST(BRepGraph_PermissionUpdateTest, TransformNode_AssemblyWithCopyGeom_Rejected)
|
||||
{
|
||||
BRepGraph aGraph = makeBoxGraph();
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
const BRepGraph_ProductId aProd = aGraph.Editor().Products().CreateEmptyProduct();
|
||||
ASSERT_TRUE(aProd.IsValid());
|
||||
|
||||
gp_Trsf aT;
|
||||
aT.SetTranslation(gp_Vec(1.0, 0.0, 0.0));
|
||||
const BRepGraph aResult =
|
||||
BRepGraph_Transform::TransformNode(aGraph, BRepGraph_NodeId(aProd), aT, true, false);
|
||||
EXPECT_FALSE(aResult.IsDone());
|
||||
}
|
||||
|
||||
// Companion to the above: Occurrence node with copyGeom must be rejected too.
|
||||
TEST(BRepGraph_PermissionUpdateTest, TransformNode_OccurrenceWithCopyGeom_Rejected)
|
||||
{
|
||||
BRepGraph aGraph = makeBoxGraph();
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
BRepGraph::EditorView::ProductOps& aProds = aGraph.Editor().Products();
|
||||
const BRepGraph_ProductId aParent = aProds.CreateEmptyProduct();
|
||||
const BRepGraph_ProductId aChild = aProds.CreateEmptyProduct();
|
||||
ASSERT_TRUE(aParent.IsValid());
|
||||
ASSERT_TRUE(aChild.IsValid());
|
||||
const BRepGraph_OccurrenceId aOccId = aProds.LinkProducts(aParent, aChild, TopLoc_Location());
|
||||
ASSERT_TRUE(aOccId.IsValid());
|
||||
|
||||
gp_Trsf aT;
|
||||
aT.SetTranslation(gp_Vec(1.0, 0.0, 0.0));
|
||||
const BRepGraph aResult =
|
||||
BRepGraph_Transform::TransformNode(aGraph, BRepGraph_NodeId(aOccId), aT, true, false);
|
||||
EXPECT_FALSE(aResult.IsDone());
|
||||
}
|
||||
|
||||
// LinkProducts with the unified signature returns the freshly inserted OccurrenceRef
|
||||
// id through the optional out pointer.
|
||||
TEST(BRepGraph_PermissionUpdateTest, LinkProducts_OutOccurrenceRefId_Populated)
|
||||
{
|
||||
BRepGraph aGraph = makeBoxGraph();
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
BRepGraph::EditorView::ProductOps& aProds = aGraph.Editor().Products();
|
||||
const BRepGraph_ProductId aParent = aProds.CreateEmptyProduct();
|
||||
const BRepGraph_ProductId aChild = aProds.CreateEmptyProduct();
|
||||
ASSERT_TRUE(aParent.IsValid());
|
||||
ASSERT_TRUE(aChild.IsValid());
|
||||
|
||||
BRepGraph_OccurrenceRefId aOccRefId;
|
||||
const BRepGraph_OccurrenceId aOccId =
|
||||
aProds.LinkProducts(aParent, aChild, TopLoc_Location(), BRepGraph_OccurrenceId(), &aOccRefId);
|
||||
ASSERT_TRUE(aOccId.IsValid());
|
||||
ASSERT_TRUE(aOccRefId.IsValid());
|
||||
EXPECT_EQ(aGraph.Refs().Occurrences().Entry(aOccRefId).OccurrenceDefId, aOccId);
|
||||
|
||||
// Default out-pointer = nullptr is also legal.
|
||||
const BRepGraph_OccurrenceId aOccId2 = aProds.LinkProducts(aParent, aChild, TopLoc_Location());
|
||||
EXPECT_TRUE(aOccId2.IsValid());
|
||||
}
|
||||
|
||||
// MoveRef: a pure rotation/translation must succeed; a scaled trsf must fail with no
|
||||
// state change.
|
||||
TEST(BRepGraph_PermissionUpdateTest, MoveRef_ScaledTrsf_RejectedWithoutMutation)
|
||||
{
|
||||
BRepGraph aGraph = makeBoxGraph();
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
// Find any face ref to test against.
|
||||
BRepGraph_FaceRefId aFaceRef;
|
||||
for (BRepGraph_FullFaceRefIterator aIt(aGraph); aIt.More(); aIt.Next())
|
||||
{
|
||||
aFaceRef = aIt.CurrentId();
|
||||
break;
|
||||
}
|
||||
ASSERT_TRUE(aFaceRef.IsValid());
|
||||
|
||||
const TopLoc_Location aBefore = aGraph.Refs().Faces().Entry(aFaceRef).LocalLocation;
|
||||
|
||||
gp_Trsf aScaled;
|
||||
aScaled.SetScaleFactor(2.0);
|
||||
EXPECT_FALSE(BRepGraph_Transform::MoveRef(aGraph, BRepGraph_RefId(aFaceRef), aScaled));
|
||||
EXPECT_TRUE(aGraph.Refs().Faces().Entry(aFaceRef).LocalLocation == aBefore);
|
||||
|
||||
gp_Trsf aTrans;
|
||||
aTrans.SetTranslation(gp_Vec(1.0, 2.0, 3.0));
|
||||
EXPECT_TRUE(BRepGraph_Transform::MoveRef(aGraph, BRepGraph_RefId(aFaceRef), aTrans));
|
||||
EXPECT_FALSE(aGraph.Refs().Faces().Entry(aFaceRef).LocalLocation == aBefore);
|
||||
}
|
||||
|
||||
// RemoveSubgraph cascade rebuilds the reverse index exactly once at the outermost
|
||||
// scope; nested calls during recursion must not trigger intermediate rebuilds, and
|
||||
// the final state must validate.
|
||||
TEST(BRepGraph_PermissionUpdateTest, RemoveSubgraph_NestedCascade_FinalStateValid)
|
||||
{
|
||||
BRepGraph aGraph = makeBoxGraph();
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
|
||||
BRepGraph_SolidId aSolidId;
|
||||
for (BRepGraph_SolidIterator aIt(aGraph); aIt.More(); aIt.Next())
|
||||
{
|
||||
aSolidId = aIt.CurrentId();
|
||||
break;
|
||||
}
|
||||
ASSERT_TRUE(aSolidId.IsValid());
|
||||
|
||||
aGraph.Editor().Gen().RemoveSubgraph(BRepGraph_NodeId(aSolidId));
|
||||
EXPECT_TRUE(aGraph.ValidateReverseIndex());
|
||||
}
|
||||
|
||||
// MutGuard: a guard that observes but never writes must not bump OwnGen on destruction;
|
||||
// MarkDirty() must force the bump even when no setter was called.
|
||||
TEST(BRepGraph_PermissionUpdateTest, MutGuard_DirtyFlag_RespectsExplicitMarkAndCleanScope)
|
||||
{
|
||||
BRepGraph aGraph = makeBoxGraph();
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
BRepGraph_EdgeId aEdgeId;
|
||||
for (BRepGraph_EdgeIterator anIt(aGraph); anIt.More(); anIt.Next())
|
||||
{
|
||||
aEdgeId = anIt.CurrentId();
|
||||
break;
|
||||
}
|
||||
ASSERT_TRUE(aEdgeId.IsValid());
|
||||
|
||||
const uint32_t aOwnGenBefore = aGraph.Topo().Edges().Definition(aEdgeId).OwnGen;
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aGuard = aGraph.Editor().Edges().Mut(aEdgeId);
|
||||
(void)aGuard->IsClosed; // read-only access only
|
||||
}
|
||||
EXPECT_EQ(aOwnGenBefore, aGraph.Topo().Edges().Definition(aEdgeId).OwnGen)
|
||||
<< "Read-only guard scope must not bump OwnGen";
|
||||
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aGuard = aGraph.Editor().Edges().Mut(aEdgeId);
|
||||
aGuard.MarkDirty();
|
||||
}
|
||||
EXPECT_GT(aGraph.Topo().Edges().Definition(aEdgeId).OwnGen, aOwnGenBefore)
|
||||
<< "MarkDirty() must bump OwnGen on guard destruction";
|
||||
}
|
||||
@@ -575,7 +575,8 @@ TEST(BRepGraph_ReconstructTest, AfterVertexMutation_ModifiedFlagAndPointChanged)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::VertexDef> aMutVtx =
|
||||
aGraph.Editor().Vertices().Mut(BRepGraph_VertexId(aVertIdx));
|
||||
aMutVtx->Point = gp_Pnt(anOldPt.X(), anOldPt.Y(), anOldPt.Z() + 5.0);
|
||||
aGraph.Editor().Vertices().SetPoint(aMutVtx,
|
||||
gp_Pnt(anOldPt.X(), anOldPt.Y(), anOldPt.Z() + 5.0));
|
||||
}
|
||||
|
||||
// Verify the OwnGen is incremented on the vertex def (directly mutated).
|
||||
@@ -606,7 +607,7 @@ TEST(BRepGraph_ReconstructTest, AfterToleranceMutation_NewTShape)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMutEdge =
|
||||
aGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
aMutEdge->Tolerance = aMutEdge->Tolerance + 1.0;
|
||||
aGraph.Editor().Edges().SetTolerance(aMutEdge, aMutEdge->Tolerance + 1.0);
|
||||
}
|
||||
|
||||
// After mutation, Shape() should return a reconstructed shape with a different TShape.
|
||||
|
||||
@@ -446,7 +446,9 @@ TEST(BRepGraph_RefIdTest, MutFaceRef_UpdatesRefStampAndParentModifiedFlag)
|
||||
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceRef> aMut = aGraph.Editor().Faces().MutRef(aFaceRefId);
|
||||
aMut->Orientation = (anBeforeOri == TopAbs_FORWARD) ? TopAbs_REVERSED : TopAbs_FORWARD;
|
||||
aGraph.Editor().Faces().SetRefOrientation(aMut,
|
||||
(anBeforeOri == TopAbs_FORWARD) ? TopAbs_REVERSED
|
||||
: TopAbs_FORWARD);
|
||||
}
|
||||
|
||||
const BRepGraphInc::FaceRef& aAfterEntry = aGraph.Refs().Faces().Entry(aFaceRefId);
|
||||
@@ -477,10 +479,7 @@ TEST(BRepGraph_RefIdTest, MutFaceRef_MarkRemoved_PersistsAndInvalidatesStamp)
|
||||
ASSERT_TRUE(aBeforeStamp.IsValid());
|
||||
ASSERT_TRUE(aBeforeStamp.IsRefStamp());
|
||||
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceRef> aMut = aGraph.Editor().Faces().MutRef(aFaceRefId);
|
||||
aMut->IsRemoved = true;
|
||||
}
|
||||
aGraph.Editor().Gen().RemoveRef(aFaceRefId);
|
||||
|
||||
const BRepGraphInc::FaceRef& aAfterEntry = aGraph.Refs().Faces().Entry(aFaceRefId);
|
||||
EXPECT_TRUE(aAfterEntry.IsRemoved);
|
||||
|
||||
@@ -226,7 +226,7 @@ TEST_F(BRepGraph_RefsIteratorTest, AuxChildRefsOfShellAndSolid_EnumerateInjected
|
||||
for (const BRepGraph_ChildRefId& aRefId :
|
||||
myGraph.Topo().Compounds().Definition(aShellSeed).ChildRefIds)
|
||||
{
|
||||
aShell->AuxChildRefIds.Append(aRefId);
|
||||
aShell.Internal().AuxChildRefIds.Append(aRefId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ TEST_F(BRepGraph_RefsIteratorTest, AuxChildRefsOfShellAndSolid_EnumerateInjected
|
||||
for (const BRepGraph_ChildRefId& aRefId :
|
||||
myGraph.Topo().Compounds().Definition(aSolidSeed).ChildRefIds)
|
||||
{
|
||||
aSolid->AuxChildRefIds.Append(aRefId);
|
||||
aSolid.Internal().AuxChildRefIds.Append(aRefId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,11 +271,7 @@ TEST_F(BRepGraph_RefsIteratorTest, RemovedWireRef_IsSkipped)
|
||||
myGraph.Refs().Wires().IdsOf(BRepGraph_FaceId::Start());
|
||||
ASSERT_EQ(aWireRefs.Length(), 1);
|
||||
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::WireRef> aWireRef =
|
||||
myGraph.Editor().Wires().MutRef(aWireRefs.Value(0));
|
||||
aWireRef->IsRemoved = true;
|
||||
}
|
||||
myGraph.Editor().Gen().RemoveRef(aWireRefs.Value(0));
|
||||
|
||||
EXPECT_EQ(countIterator(BRepGraph_RefsWireOfFace(myGraph, BRepGraph_FaceId::Start())), 0);
|
||||
}
|
||||
@@ -118,7 +118,7 @@ TEST(BRepGraph_ScenarioMatrix, Box_MutateVertex_ValidateReconstructPopulateRound
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::VertexDef> aMut =
|
||||
aGraph.Editor().Vertices().Mut(BRepGraph_VertexId::Start());
|
||||
aMut->Point = gp_Pnt(anOldPt.X() + 50.0, anOldPt.Y(), anOldPt.Z());
|
||||
aGraph.Editor().Vertices().SetPoint(aMut, gp_Pnt(anOldPt.X() + 50.0, anOldPt.Y(), anOldPt.Z()));
|
||||
}
|
||||
|
||||
// --- Audit again: structural invariants must survive a point-data mutation ---
|
||||
@@ -233,7 +233,7 @@ TEST(BRepGraph_ScenarioMatrix, Cylinder_SeamEdge_MutationAndBothSubsystemsConsis
|
||||
const double anOldTol = aGraph.Topo().Edges().Definition(aSeamEdgeId).Tolerance;
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut = aGraph.Editor().Edges().Mut(aSeamEdgeId);
|
||||
aMut->Tolerance = anOldTol + 0.5;
|
||||
aGraph.Editor().Edges().SetTolerance(aMut, anOldTol + 0.5);
|
||||
}
|
||||
|
||||
// --- Validate(Audit): structural integrity must survive a tolerance mutation ---
|
||||
@@ -342,7 +342,7 @@ TEST(BRepGraph_ScenarioMatrix, CompSolid_TwoBoxes_BothSubsystemsMutateReconstruc
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> aMut =
|
||||
aGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
aMut->Tolerance = aMut->Tolerance + 1.0;
|
||||
aGraph.Editor().Edges().SetTolerance(aMut, aMut->Tolerance + 1.0);
|
||||
}
|
||||
|
||||
// --- Validate(Audit) after mutation ---
|
||||
@@ -616,7 +616,7 @@ TEST(BRepGraph_ScenarioMatrix, Compound_BoxAndCylinder_MutationReconstructAreaRe
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceDef> aMut =
|
||||
aGraph.Editor().Faces().Mut(BRepGraph_FaceId::Start());
|
||||
aMut->Tolerance = aMut->Tolerance + 0.5;
|
||||
aGraph.Editor().Faces().SetTolerance(aMut, aMut->Tolerance + 0.5);
|
||||
}
|
||||
|
||||
// --- Validate(Audit) after mutation ---
|
||||
|
||||
@@ -1259,7 +1259,7 @@ TEST_F(BRepGraphTest, MutableEdge_ModifyTolerance)
|
||||
double anOrigTol = BRepGraph_Tool::Edge::Tolerance(myGraph, BRepGraph_EdgeId::Start());
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> anEdge =
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
anEdge->Tolerance = anOrigTol * 2.0;
|
||||
myGraph.Editor().Edges().SetTolerance(anEdge, anOrigTol * 2.0);
|
||||
EXPECT_NEAR(BRepGraph_Tool::Edge::Tolerance(myGraph, BRepGraph_EdgeId::Start()),
|
||||
anOrigTol * 2.0,
|
||||
1.0e-15);
|
||||
@@ -1552,7 +1552,7 @@ TEST_F(BRepGraphTest, OwnGen_MutableEdge_PropagatesSubtreeGenUp)
|
||||
{
|
||||
EXPECT_EQ(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen, 0u);
|
||||
|
||||
(void)myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start()).MarkDirty();
|
||||
|
||||
// Edge was directly mutated: OwnGen incremented.
|
||||
EXPECT_GT(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen, 0u);
|
||||
@@ -1619,7 +1619,7 @@ TEST_F(BRepGraphTest, Shape_InvalidatedAfterMutation)
|
||||
TopoDS_Shape aBefore = myGraph.Shapes().Shape(anEdgeId);
|
||||
EXPECT_FALSE(aBefore.IsNull());
|
||||
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.123;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.123);
|
||||
TopoDS_Shape anAfter = myGraph.Shapes().Shape(anEdgeId);
|
||||
EXPECT_FALSE(anAfter.IsNull());
|
||||
|
||||
@@ -2242,7 +2242,7 @@ TEST_F(BRepGraphTest, MutableVertex_ChangePoint_Verified)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::VertexDef> aMutVert =
|
||||
myGraph.Editor().Vertices().Mut(BRepGraph_VertexId::Start());
|
||||
aMutVert->Point = gp_Pnt(99.0, 99.0, 99.0);
|
||||
myGraph.Editor().Vertices().SetPoint(aMutVert, gp_Pnt(99.0, 99.0, 99.0));
|
||||
|
||||
const BRepGraphInc::VertexDef& aVert =
|
||||
myGraph.Topo().Vertices().Definition(BRepGraph_VertexId::Start());
|
||||
@@ -2335,8 +2335,8 @@ TEST_F(BRepGraphTest, DetectToleranceConflicts_ManualConflict_Detected)
|
||||
continue;
|
||||
|
||||
// Set very different tolerances on two edges sharing the same curve.
|
||||
myGraph.Editor().Edges().Mut(anEdgeId)->Tolerance = 0.001;
|
||||
myGraph.Editor().Edges().Mut(anOtherId)->Tolerance = 1.0;
|
||||
myGraph.Editor().Edges().SetTolerance(anEdgeId, 0.001);
|
||||
myGraph.Editor().Edges().SetTolerance(anOtherId, 1.0);
|
||||
|
||||
isConflictSetUp = true;
|
||||
break;
|
||||
@@ -2604,12 +2604,12 @@ TEST_F(BRepGraphTest, MutableWireDef_ModifyClosure_Verified)
|
||||
BRepGraph_MutGuard<BRepGraphInc::WireDef> aMutWD =
|
||||
myGraph.Editor().Wires().Mut(BRepGraph_WireId::Start());
|
||||
bool anOrigClosed = aMutWD->IsClosed;
|
||||
aMutWD->IsClosed = !anOrigClosed;
|
||||
myGraph.Editor().Wires().SetIsClosed(aMutWD, !anOrigClosed);
|
||||
|
||||
EXPECT_EQ(myGraph.Topo().Wires().Definition(BRepGraph_WireId::Start()).IsClosed, !anOrigClosed);
|
||||
|
||||
// Restore original state.
|
||||
myGraph.Editor().Wires().Mut(BRepGraph_WireId::Start())->IsClosed = anOrigClosed;
|
||||
myGraph.Editor().Wires().SetIsClosed(BRepGraph_WireId::Start(), anOrigClosed);
|
||||
EXPECT_EQ(myGraph.Topo().Wires().Definition(BRepGraph_WireId::Start()).IsClosed, anOrigClosed);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,13 @@
|
||||
#include <BRepBuilderAPI_Transform.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
#include <BRepGraph.hxx>
|
||||
#include <BRepGraph_Copy.hxx>
|
||||
#include <BRepGraph_EditorView.hxx>
|
||||
#include <BRepGraph_MeshCache.hxx>
|
||||
#include <BRepGraph_MeshView.hxx>
|
||||
#include <BRepGraph_NodeId.hxx>
|
||||
#include <BRepGraph_RefId.hxx>
|
||||
#include <BRepGraph_RefsIterator.hxx>
|
||||
#include <BRepGraph_RefsView.hxx>
|
||||
#include <BRepGraph_ShapesView.hxx>
|
||||
#include <BRepGraph_TopoView.hxx>
|
||||
@@ -22,10 +29,17 @@
|
||||
#include <BRepGraphInc_Reference.hxx>
|
||||
#include <BRepGraph_Transform.hxx>
|
||||
#include <BRepGraph_Builder.hxx>
|
||||
#include <BRepGraph_Iterator.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <TopoDS_CompSolid.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <OSD_Timer.hxx>
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <Poly_Triangle.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <gp_Trsf.hxx>
|
||||
@@ -202,8 +216,449 @@ TEST(BRepGraph_TransformTest, TransformSingleFace)
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(10.0, 20.0, 30.0));
|
||||
|
||||
BRepGraph aResultGraph =
|
||||
BRepGraph_Transform::TransformFace(aGraph, BRepGraph_FaceId::Start(), aTrsf, true);
|
||||
const BRepGraph_FaceId aFaceId = BRepGraph_FaceId::Start();
|
||||
const BRepGraph_NodeId aFaceNode(BRepGraph_NodeId::Kind::Face, aFaceId.Index);
|
||||
BRepGraph aResultGraph = BRepGraph_Transform::TransformNode(aGraph, aFaceNode, aTrsf, true);
|
||||
ASSERT_TRUE(aResultGraph.IsDone());
|
||||
EXPECT_EQ(aResultGraph.Topo().Faces().Nb(), 1);
|
||||
}
|
||||
|
||||
TEST(BRepGraph_TransformTest, CopyMesh_TriangulationNodesTransformed)
|
||||
{
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
const TopoDS_Shape& aBox = aBoxMaker.Shape();
|
||||
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes = BRepGraph_Builder::Add(aGraph, aBox);
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
ASSERT_GE(aGraph.Topo().Faces().Nb(), 1);
|
||||
|
||||
// Manually create a triangulation with known node positions on the first face.
|
||||
const BRepGraph_FaceId aFaceId = BRepGraph_FaceId::Start();
|
||||
occ::handle<Poly_Triangulation> aSrcTri = new Poly_Triangulation(3, 1, false);
|
||||
aSrcTri->SetNode(1, gp_Pnt(1.0, 2.0, 3.0));
|
||||
aSrcTri->SetNode(2, gp_Pnt(4.0, 5.0, 6.0));
|
||||
aSrcTri->SetNode(3, gp_Pnt(7.0, 8.0, 9.0));
|
||||
aSrcTri->SetTriangle(1, Poly_Triangle(1, 2, 3));
|
||||
aSrcTri->Deflection(0.1);
|
||||
|
||||
const BRepGraph_TriangulationRepId aTriRepId =
|
||||
BRepGraph_Tool::Mesh::CreateTriangulationRep(aGraph, aSrcTri);
|
||||
aGraph.Editor().Faces().SetTriangulationRep(aFaceId, aTriRepId);
|
||||
BRepGraph_Tool::Mesh::AppendCachedTriangulation(aGraph, aFaceId, aTriRepId);
|
||||
|
||||
const double aDx = 5.0, aDy = 10.0, aDz = 15.0;
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(aDx, aDy, aDz));
|
||||
|
||||
// Transform with theCopyMesh = true.
|
||||
BRepGraph aResult = BRepGraph_Transform::Perform(aGraph, aTrsf, true, true);
|
||||
ASSERT_TRUE(aResult.IsDone());
|
||||
|
||||
// The persistent triangulation on the first face must be present and transformed.
|
||||
const BRepGraph_TriangulationRepId aNewTriRepId =
|
||||
aResult.Topo().Faces().Definition(aFaceId).TriangulationRepId;
|
||||
ASSERT_TRUE(aNewTriRepId.IsValid(aResult.Mesh().Poly().NbTriangulations()));
|
||||
|
||||
const occ::handle<Poly_Triangulation>& aNewTri =
|
||||
aResult.Mesh().Poly().TriangulationRep(aNewTriRepId).Triangulation;
|
||||
ASSERT_FALSE(aNewTri.IsNull());
|
||||
ASSERT_EQ(aNewTri->NbNodes(), 3);
|
||||
|
||||
EXPECT_NEAR(aNewTri->Node(1).X(), 1.0 + aDx, Precision::Confusion());
|
||||
EXPECT_NEAR(aNewTri->Node(1).Y(), 2.0 + aDy, Precision::Confusion());
|
||||
EXPECT_NEAR(aNewTri->Node(1).Z(), 3.0 + aDz, Precision::Confusion());
|
||||
EXPECT_NEAR(aNewTri->Node(3).X(), 7.0 + aDx, Precision::Confusion());
|
||||
|
||||
// The source triangulation must not be mutated.
|
||||
EXPECT_NEAR(aSrcTri->Node(1).X(), 1.0, Precision::Confusion());
|
||||
|
||||
// Deflection must scale (translation has scale = 1, so no change).
|
||||
EXPECT_NEAR(aNewTri->Deflection(), 0.1, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(BRepGraph_TransformTest, CopyMesh_False_TriangulationInvalidated)
|
||||
{
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
const TopoDS_Shape& aBox = aBoxMaker.Shape();
|
||||
|
||||
BRepGraph aGraph;
|
||||
aGraph.Clear();
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes = BRepGraph_Builder::Add(aGraph, aBox);
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
const BRepGraph_FaceId aFaceId = BRepGraph_FaceId::Start();
|
||||
occ::handle<Poly_Triangulation> aTri = new Poly_Triangulation(3, 1, false);
|
||||
aTri->SetNode(1, gp_Pnt(0, 0, 0));
|
||||
aTri->SetNode(2, gp_Pnt(1, 0, 0));
|
||||
aTri->SetNode(3, gp_Pnt(0, 1, 0));
|
||||
aTri->SetTriangle(1, Poly_Triangle(1, 2, 3));
|
||||
const BRepGraph_TriangulationRepId aTriRepId =
|
||||
BRepGraph_Tool::Mesh::CreateTriangulationRep(aGraph, aTri);
|
||||
aGraph.Editor().Faces().SetTriangulationRep(aFaceId, aTriRepId);
|
||||
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(1.0, 0.0, 0.0));
|
||||
|
||||
// Default: theCopyMesh = false -> triangulations are discarded.
|
||||
BRepGraph aResult = BRepGraph_Transform::Perform(aGraph, aTrsf, true, false);
|
||||
ASSERT_TRUE(aResult.IsDone());
|
||||
|
||||
const BRepGraph_TriangulationRepId aResultTriRepId =
|
||||
aResult.Topo().Faces().Definition(aFaceId).TriangulationRepId;
|
||||
EXPECT_FALSE(aResultTriRepId.IsValid());
|
||||
EXPECT_FALSE(aResult.Mesh().Faces().HasTriangulation(aFaceId));
|
||||
}
|
||||
|
||||
TEST(BRepGraph_TransformTest, MoveRef_FaceRef_LocationComposed)
|
||||
{
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
// The solid has shell refs; grab the first one.
|
||||
const BRepGraph_SolidId aSolidId = BRepGraph_SolidId::Start();
|
||||
ASSERT_GE(aGraph.Topo().Solids().Definition(aSolidId).ShellRefIds.Length(), 1);
|
||||
const BRepGraph_ShellRefId aShellRef =
|
||||
aGraph.Topo().Solids().Definition(aSolidId).ShellRefIds.Value(0);
|
||||
|
||||
// Verify that the location starts as identity.
|
||||
EXPECT_TRUE(aGraph.Refs().Shells().Entry(aShellRef).LocalLocation.IsIdentity());
|
||||
|
||||
const double aDx = 42.0;
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(aDx, 0.0, 0.0));
|
||||
|
||||
const bool aOk = BRepGraph_Transform::MoveRef(aGraph, BRepGraph_RefId(aShellRef), aTrsf);
|
||||
EXPECT_TRUE(aOk);
|
||||
|
||||
const TopLoc_Location& aLoc = aGraph.Refs().Shells().Entry(aShellRef).LocalLocation;
|
||||
EXPECT_FALSE(aLoc.IsIdentity());
|
||||
EXPECT_NEAR(aLoc.Transformation().Value(1, 4), aDx, Precision::Confusion());
|
||||
|
||||
// A second MoveRef composes (doubles the translation).
|
||||
BRepGraph_Transform::MoveRef(aGraph, BRepGraph_RefId(aShellRef), aTrsf);
|
||||
const TopLoc_Location& aLoc2 = aGraph.Refs().Shells().Entry(aShellRef).LocalLocation;
|
||||
EXPECT_NEAR(aLoc2.Transformation().Value(1, 4), 2.0 * aDx, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(BRepGraph_TransformTest, MoveRef_ScaleRejected)
|
||||
{
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
const BRepGraph_SolidId aSolidId = BRepGraph_SolidId::Start();
|
||||
const BRepGraph_ShellRefId aShellRef =
|
||||
aGraph.Topo().Solids().Definition(aSolidId).ShellRefIds.Value(0);
|
||||
|
||||
gp_Trsf aScale;
|
||||
aScale.SetScale(gp_Pnt(), 2.0); // scale factor != 1
|
||||
|
||||
const bool aOk = BRepGraph_Transform::MoveRef(aGraph, BRepGraph_RefId(aShellRef), aScale);
|
||||
EXPECT_FALSE(aOk);
|
||||
// Location must remain unchanged (identity).
|
||||
EXPECT_TRUE(aGraph.Refs().Shells().Entry(aShellRef).LocalLocation.IsIdentity());
|
||||
}
|
||||
|
||||
TEST(BRepGraph_TransformTest, TransformNode_FaceKind_VertexPointsShifted)
|
||||
{
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
const double aDx = 5.0, aDy = 10.0, aDz = 15.0;
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(aDx, aDy, aDz));
|
||||
|
||||
const BRepGraph_FaceId aFaceId = BRepGraph_FaceId::Start();
|
||||
const BRepGraph_NodeId aFaceNode(BRepGraph_NodeId::Kind::Face, aFaceId.Index);
|
||||
|
||||
BRepGraph aResult = BRepGraph_Transform::TransformNode(aGraph, aFaceNode, aTrsf, true, false);
|
||||
ASSERT_TRUE(aResult.IsDone());
|
||||
EXPECT_EQ(aResult.Topo().Faces().Nb(), 1);
|
||||
|
||||
const int aNbV = aResult.Topo().Vertices().Nb();
|
||||
ASSERT_GT(aNbV, 0);
|
||||
for (BRepGraph_VertexId aVId(0); aVId.IsValid(aNbV); ++aVId)
|
||||
{
|
||||
const gp_Pnt anOrig = BRepGraph_Tool::Vertex::Pnt(aGraph, aVId);
|
||||
const gp_Pnt aTrans = BRepGraph_Tool::Vertex::Pnt(aResult, aVId);
|
||||
EXPECT_NEAR(aTrans.X(), anOrig.X() + aDx, Precision::Confusion());
|
||||
EXPECT_NEAR(aTrans.Y(), anOrig.Y() + aDy, Precision::Confusion());
|
||||
EXPECT_NEAR(aTrans.Z(), anOrig.Z() + aDz, Precision::Confusion());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BRepGraph_TransformTest, TransformNode_ShellKind)
|
||||
{
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
ASSERT_GE(aGraph.Topo().Shells().Nb(), 1);
|
||||
|
||||
const BRepGraph_ShellId aShellId = BRepGraph_ShellId::Start();
|
||||
const BRepGraph_NodeId aShellNode(BRepGraph_NodeId::Kind::Shell, aShellId.Index);
|
||||
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(100.0, 0.0, 0.0));
|
||||
|
||||
BRepGraph aResult = BRepGraph_Transform::TransformNode(aGraph, aShellNode, aTrsf, true, false);
|
||||
ASSERT_TRUE(aResult.IsDone());
|
||||
|
||||
// The shell copy should have the same number of faces as the source shell.
|
||||
EXPECT_EQ(aResult.Topo().Shells().Nb(), 1);
|
||||
EXPECT_EQ(aResult.Topo().Faces().Nb(), aGraph.Topo().Faces().Nb());
|
||||
|
||||
// All vertices must be shifted by the translation.
|
||||
const int aNbV = aGraph.Topo().Vertices().Nb();
|
||||
EXPECT_EQ(aResult.Topo().Vertices().Nb(), aNbV);
|
||||
for (BRepGraph_VertexId aVId(0); aVId.IsValid(aNbV); ++aVId)
|
||||
{
|
||||
const gp_Pnt anOrig = BRepGraph_Tool::Vertex::Pnt(aGraph, aVId);
|
||||
const gp_Pnt aTrans = BRepGraph_Tool::Vertex::Pnt(aResult, aVId);
|
||||
EXPECT_NEAR(aTrans.X(), anOrig.X() + 100.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aTrans.Y(), anOrig.Y(), Precision::Confusion());
|
||||
EXPECT_NEAR(aTrans.Z(), anOrig.Z(), Precision::Confusion());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BRepGraph_TransformTest, TransformNode_SolidKind)
|
||||
{
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
ASSERT_GE(aGraph.Topo().Solids().Nb(), 1);
|
||||
|
||||
const BRepGraph_SolidId aSolidId = BRepGraph_SolidId::Start();
|
||||
const BRepGraph_NodeId aSolidNode(BRepGraph_NodeId::Kind::Solid, aSolidId.Index);
|
||||
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(0.0, 50.0, 0.0));
|
||||
|
||||
BRepGraph aResult = BRepGraph_Transform::TransformNode(aGraph, aSolidNode, aTrsf, true, false);
|
||||
ASSERT_TRUE(aResult.IsDone());
|
||||
|
||||
EXPECT_EQ(aResult.Topo().Solids().Nb(), 1);
|
||||
EXPECT_EQ(aResult.Topo().Shells().Nb(), aGraph.Topo().Shells().Nb());
|
||||
EXPECT_EQ(aResult.Topo().Faces().Nb(), aGraph.Topo().Faces().Nb());
|
||||
|
||||
const int aNbV = aGraph.Topo().Vertices().Nb();
|
||||
EXPECT_EQ(aResult.Topo().Vertices().Nb(), aNbV);
|
||||
for (BRepGraph_VertexId aVId(0); aVId.IsValid(aNbV); ++aVId)
|
||||
{
|
||||
const gp_Pnt anOrig = BRepGraph_Tool::Vertex::Pnt(aGraph, aVId);
|
||||
const gp_Pnt aTrans = BRepGraph_Tool::Vertex::Pnt(aResult, aVId);
|
||||
EXPECT_NEAR(aTrans.Y(), anOrig.Y() + 50.0, Precision::Confusion());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BRepGraph_TransformTest, TransformNode_VertexKind)
|
||||
{
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 20.0, 30.0);
|
||||
BRepGraph aGraph;
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
ASSERT_GE(aGraph.Topo().Vertices().Nb(), 1);
|
||||
|
||||
const BRepGraph_VertexId aVertexId = BRepGraph_VertexId::Start();
|
||||
const BRepGraph_NodeId aVertexNode(BRepGraph_NodeId::Kind::Vertex, aVertexId.Index);
|
||||
const gp_Pnt anOrigPt = BRepGraph_Tool::Vertex::Pnt(aGraph, aVertexId);
|
||||
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(1.0, 2.0, 3.0));
|
||||
|
||||
BRepGraph aResult = BRepGraph_Transform::TransformNode(aGraph, aVertexNode, aTrsf, true, false);
|
||||
ASSERT_TRUE(aResult.IsDone());
|
||||
|
||||
EXPECT_EQ(aResult.Topo().Vertices().Nb(), 1);
|
||||
const gp_Pnt aTransPt = BRepGraph_Tool::Vertex::Pnt(aResult, BRepGraph_VertexId::Start());
|
||||
EXPECT_NEAR(aTransPt.X(), anOrigPt.X() + 1.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aTransPt.Y(), anOrigPt.Y() + 2.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aTransPt.Z(), anOrigPt.Z() + 3.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
TEST(BRepGraph_TransformTest, TransformNode_CompoundKind)
|
||||
{
|
||||
// ensureCompound must walk children, transform each, and preserve count.
|
||||
BRep_Builder aBB;
|
||||
TopoDS_Compound aCompound;
|
||||
aBB.MakeCompound(aCompound);
|
||||
BRepPrimAPI_MakeBox aBox1(5.0, 5.0, 5.0);
|
||||
BRepPrimAPI_MakeBox aBox2(3.0, 3.0, 3.0);
|
||||
aBB.Add(aCompound, aBox1.Shape());
|
||||
aBB.Add(aCompound, aBox2.Shape());
|
||||
|
||||
BRepGraph aGraph;
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aCompound);
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
ASSERT_GE(aGraph.Topo().Compounds().Nb(), 1);
|
||||
|
||||
const BRepGraph_CompoundId aCompoundId = BRepGraph_CompoundId::Start();
|
||||
const BRepGraph_NodeId aCompoundNode(BRepGraph_NodeId::Kind::Compound, aCompoundId.Index);
|
||||
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(20.0, 0.0, 0.0));
|
||||
|
||||
BRepGraph aResult = BRepGraph_Transform::TransformNode(aGraph, aCompoundNode, aTrsf, true, false);
|
||||
ASSERT_TRUE(aResult.IsDone());
|
||||
|
||||
EXPECT_EQ(aResult.Topo().Compounds().Nb(), 1);
|
||||
EXPECT_EQ(aResult.Topo().Solids().Nb(), aGraph.Topo().Solids().Nb());
|
||||
EXPECT_EQ(aResult.Topo().Faces().Nb(), aGraph.Topo().Faces().Nb());
|
||||
|
||||
const int aNbV = aGraph.Topo().Vertices().Nb();
|
||||
EXPECT_EQ(aResult.Topo().Vertices().Nb(), aNbV);
|
||||
for (BRepGraph_VertexId aVId(0); aVId.IsValid(aNbV); ++aVId)
|
||||
{
|
||||
const gp_Pnt anOrig = BRepGraph_Tool::Vertex::Pnt(aGraph, aVId);
|
||||
const gp_Pnt aTrans = BRepGraph_Tool::Vertex::Pnt(aResult, aVId);
|
||||
EXPECT_NEAR(aTrans.X(), anOrig.X() + 20.0, Precision::Confusion());
|
||||
EXPECT_NEAR(aTrans.Y(), anOrig.Y(), Precision::Confusion());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BRepGraph_TransformTest, TransformNode_CompSolidKind)
|
||||
{
|
||||
// ensureCompSolid must walk solid refs and transform each.
|
||||
BRep_Builder aBB;
|
||||
TopoDS_CompSolid aCompSolid;
|
||||
aBB.MakeCompSolid(aCompSolid);
|
||||
BRepPrimAPI_MakeBox aBoxMaker(4.0, 4.0, 4.0);
|
||||
aBB.Add(aCompSolid, aBoxMaker.Shape());
|
||||
|
||||
BRepGraph aGraph;
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aCompSolid);
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
ASSERT_GE(aGraph.Topo().CompSolids().Nb(), 1);
|
||||
|
||||
const BRepGraph_CompSolidId aCompSolidId = BRepGraph_CompSolidId::Start();
|
||||
const BRepGraph_NodeId aCompSolidNode(BRepGraph_NodeId::Kind::CompSolid, aCompSolidId.Index);
|
||||
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(0.0, 0.0, 7.0));
|
||||
|
||||
BRepGraph aResult =
|
||||
BRepGraph_Transform::TransformNode(aGraph, aCompSolidNode, aTrsf, true, false);
|
||||
ASSERT_TRUE(aResult.IsDone());
|
||||
|
||||
EXPECT_EQ(aResult.Topo().CompSolids().Nb(), 1);
|
||||
EXPECT_EQ(aResult.Topo().Solids().Nb(), aGraph.Topo().Solids().Nb());
|
||||
|
||||
const int aNbV = aGraph.Topo().Vertices().Nb();
|
||||
for (BRepGraph_VertexId aVId(0); aVId.IsValid(aNbV); ++aVId)
|
||||
{
|
||||
const gp_Pnt anOrig = BRepGraph_Tool::Vertex::Pnt(aGraph, aVId);
|
||||
const gp_Pnt aTrans = BRepGraph_Tool::Vertex::Pnt(aResult, aVId);
|
||||
EXPECT_NEAR(aTrans.Z(), anOrig.Z() + 7.0, Precision::Confusion());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BRepGraph_TransformTest, TransformNode_NegativeScale_VertexPointsMirrored)
|
||||
{
|
||||
// Smoke-tests the negative-scale geometry path through TransformNode: every
|
||||
// vertex point should be mirrored about the origin and the result graph must
|
||||
// remain coherent (same face/edge/vertex counts, valid IsDone).
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 10.0, 10.0);
|
||||
BRepGraph aGraph;
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
|
||||
const BRepGraph_SolidId aSolidId = BRepGraph_SolidId::Start();
|
||||
const BRepGraph_NodeId aSolidNode(BRepGraph_NodeId::Kind::Solid, aSolidId.Index);
|
||||
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetMirror(gp_Pnt(0.0, 0.0, 0.0));
|
||||
|
||||
BRepGraph aResult = BRepGraph_Transform::TransformNode(aGraph, aSolidNode, aTrsf, true, false);
|
||||
ASSERT_TRUE(aResult.IsDone());
|
||||
EXPECT_EQ(aResult.Topo().Faces().Nb(), aGraph.Topo().Faces().Nb());
|
||||
EXPECT_EQ(aResult.Topo().Vertices().Nb(), aGraph.Topo().Vertices().Nb());
|
||||
|
||||
const int aNbV = aGraph.Topo().Vertices().Nb();
|
||||
for (BRepGraph_VertexId aVId(0); aVId.IsValid(aNbV); ++aVId)
|
||||
{
|
||||
const gp_Pnt anOrig = BRepGraph_Tool::Vertex::Pnt(aGraph, aVId);
|
||||
const gp_Pnt aTrans = BRepGraph_Tool::Vertex::Pnt(aResult, aVId);
|
||||
EXPECT_NEAR(aTrans.X(), -anOrig.X(), Precision::Confusion());
|
||||
EXPECT_NEAR(aTrans.Y(), -anOrig.Y(), Precision::Confusion());
|
||||
EXPECT_NEAR(aTrans.Z(), -anOrig.Z(), Precision::Confusion());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BRepGraph_TransformTest, TransformNode_CopyGeomAndMesh_LODCacheSurvives)
|
||||
{
|
||||
// Regression test for self-aliasing bug in applyMeshCopy: when TransformNode is called
|
||||
// with theCopyGeom=true and theCopyMesh=true, the LOD face cache entries must survive.
|
||||
// Previously, applyMeshCopy(aSubgraph, aSubgraph, ...) would clear the face cache before
|
||||
// reading from it (source==dest), silently dropping all cached LOD triangulation entries.
|
||||
BRepPrimAPI_MakeBox aBoxMaker(10.0, 10.0, 10.0);
|
||||
BRepGraph aGraph;
|
||||
[[maybe_unused]] const BRepGraph_Builder::Result aBuildRes =
|
||||
BRepGraph_Builder::Add(aGraph, aBoxMaker.Shape());
|
||||
ASSERT_TRUE(aGraph.IsDone());
|
||||
ASSERT_GE(aGraph.Topo().Faces().Nb(), 1);
|
||||
|
||||
// Attach a LOD cache entry on the first face.
|
||||
const BRepGraph_FaceId aFaceId = BRepGraph_FaceId::Start();
|
||||
occ::handle<Poly_Triangulation> aLodTri1 = new Poly_Triangulation(3, 1, false);
|
||||
aLodTri1->SetNode(1, gp_Pnt(0.0, 0.0, 0.0));
|
||||
aLodTri1->SetNode(2, gp_Pnt(1.0, 0.0, 0.0));
|
||||
aLodTri1->SetNode(3, gp_Pnt(0.0, 1.0, 0.0));
|
||||
aLodTri1->SetTriangle(1, Poly_Triangle(1, 2, 3));
|
||||
aLodTri1->Deflection(0.5);
|
||||
occ::handle<Poly_Triangulation> aLodTri2 = new Poly_Triangulation(3, 1, false);
|
||||
aLodTri2->SetNode(1, gp_Pnt(0.0, 0.0, 0.0));
|
||||
aLodTri2->SetNode(2, gp_Pnt(2.0, 0.0, 0.0));
|
||||
aLodTri2->SetNode(3, gp_Pnt(0.0, 2.0, 0.0));
|
||||
aLodTri2->SetTriangle(1, Poly_Triangle(1, 2, 3));
|
||||
aLodTri2->Deflection(1.0);
|
||||
|
||||
const BRepGraph_TriangulationRepId aRep1 =
|
||||
BRepGraph_Tool::Mesh::CreateTriangulationRep(aGraph, aLodTri1);
|
||||
const BRepGraph_TriangulationRepId aRep2 =
|
||||
BRepGraph_Tool::Mesh::CreateTriangulationRep(aGraph, aLodTri2);
|
||||
BRepGraph_Tool::Mesh::AppendCachedTriangulation(aGraph, aFaceId, aRep1);
|
||||
BRepGraph_Tool::Mesh::AppendCachedTriangulation(aGraph, aFaceId, aRep2);
|
||||
BRepGraph_Tool::Mesh::SetCachedActiveIndex(aGraph, aFaceId, 1);
|
||||
|
||||
const BRepGraph_SolidId aSolidId = BRepGraph_SolidId::Start();
|
||||
const BRepGraph_NodeId aSolidNode =
|
||||
BRepGraph_NodeId(BRepGraph_NodeId::Kind::Solid, aSolidId.Index);
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation(gp_Vec(5.0, 0.0, 0.0));
|
||||
|
||||
// This is the previously failing path: theCopyGeom=true, theCopyMesh=true.
|
||||
BRepGraph aResult = BRepGraph_Transform::TransformNode(aGraph, aSolidNode, aTrsf, true, true);
|
||||
ASSERT_TRUE(aResult.IsDone());
|
||||
|
||||
// Both LOD cache entries must survive the transform.
|
||||
const BRepGraph_MeshCache::FaceMeshEntry* aEntry = aResult.Mesh().Faces().CachedMesh(aFaceId);
|
||||
ASSERT_NE(aEntry, nullptr);
|
||||
EXPECT_TRUE(aEntry->IsPresent());
|
||||
EXPECT_EQ(aEntry->TriangulationRepIds.Length(), 2);
|
||||
EXPECT_EQ(aEntry->ActiveTriangulationIndex, 1);
|
||||
|
||||
// The cached triangulation nodes must be shifted by the translation.
|
||||
const BRepGraph_TriangulationRepId aResRep1 = aEntry->TriangulationRepIds.Value(0);
|
||||
ASSERT_TRUE(aResRep1.IsValid(aResult.Mesh().Poly().NbTriangulations()));
|
||||
const occ::handle<Poly_Triangulation>& aResTri1 =
|
||||
aResult.Mesh().Poly().TriangulationRep(aResRep1).Triangulation;
|
||||
ASSERT_FALSE(aResTri1.IsNull());
|
||||
EXPECT_NEAR(aResTri1->Node(2).X(), 1.0 + 5.0, Precision::Confusion());
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ TEST(BRepGraph_ValidateTest, WireConnectivity_DisconnectedEdges)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::VertexRef> aMutEndRef =
|
||||
aGraph.Editor().Vertices().MutRef(aFirstEdge->EndVertexRefId);
|
||||
aMutEndRef->VertexDefId = aVertexId;
|
||||
aMutEndRef.Internal().VertexDefId = aVertexId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -256,7 +256,7 @@ TEST(BRepGraph_ValidateTest, BoundsCheck_InvalidIndex)
|
||||
// Corrupt edge's Curve3d to null.
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> anEdge =
|
||||
aGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
anEdge->Curve3DRepId = BRepGraph_Curve3DRepId();
|
||||
anEdge.Internal().Curve3DRepId = BRepGraph_Curve3DRepId();
|
||||
|
||||
const BRepGraph_Validate::Result aResult =
|
||||
BRepGraph_Validate::Perform(aGraph, BRepGraph_Validate::Options::Audit());
|
||||
@@ -335,7 +335,7 @@ TEST(BRepGraph_ValidateTest, CorruptedPCurve_FaceDefIdOutOfBounds)
|
||||
ASSERT_GT(aGraph.Topo().CoEdges().Nb(), 0);
|
||||
BRepGraph_MutGuard<BRepGraphInc::CoEdgeDef> aCoEdgeDef =
|
||||
aGraph.Editor().CoEdges().Mut(BRepGraph_CoEdgeId::Start());
|
||||
aCoEdgeDef->FaceDefId = BRepGraph_FaceId(aGraph.Topo().Faces().Nb() + 999);
|
||||
aCoEdgeDef.Internal().FaceDefId = BRepGraph_FaceId(aGraph.Topo().Faces().Nb() + 999);
|
||||
|
||||
const BRepGraph_Validate::Result aDefaultResult = BRepGraph_Validate::Perform(aGraph);
|
||||
EXPECT_FALSE(aDefaultResult.IsValid());
|
||||
@@ -363,7 +363,7 @@ TEST(BRepGraph_ValidateTest, LightweightAndAudit_DetectActiveCountDrift)
|
||||
// Intentionally bypass RemoveNode() to simulate counter drift bug class.
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceDef> aFaceDef =
|
||||
aGraph.Editor().Faces().Mut(BRepGraph_FaceId::Start());
|
||||
aFaceDef->IsRemoved = true;
|
||||
aFaceDef.Internal().IsRemoved = true;
|
||||
|
||||
const BRepGraph_Validate::Result aLightResult =
|
||||
BRepGraph_Validate::Perform(aGraph, BRepGraph_Validate::Options::Lightweight());
|
||||
@@ -509,7 +509,7 @@ TEST(BRepGraph_ValidateTest, AssemblyGraph_CorruptedOccurrenceChildDefId_Detecte
|
||||
// Corrupt the first occurrence's ChildDefId to an out-of-bounds value.
|
||||
BRepGraph_MutGuard<BRepGraphInc::OccurrenceDef> anOccDef =
|
||||
aGraph.Editor().Occurrences().Mut(BRepGraph_OccurrenceId::Start());
|
||||
anOccDef->ChildDefId =
|
||||
anOccDef.Internal().ChildDefId =
|
||||
BRepGraph_NodeId(BRepGraph_NodeId::Kind::Solid, aGraph.Topo().Solids().Nb() + 999);
|
||||
|
||||
const BRepGraph_Validate::Result aAuditResult =
|
||||
@@ -559,7 +559,7 @@ TEST(BRepGraph_ValidateTest,
|
||||
// Corrupt the occurrence's ChildDefId to an invalid index.
|
||||
BRepGraph_MutGuard<BRepGraphInc::OccurrenceDef> anOccDef =
|
||||
aGraph.Editor().Occurrences().Mut(anOccId);
|
||||
anOccDef->ChildDefId =
|
||||
anOccDef.Internal().ChildDefId =
|
||||
BRepGraph_NodeId(BRepGraph_NodeId::Kind::Product, aGraph.Topo().Products().Nb() + 999);
|
||||
|
||||
const BRepGraph_Validate::Result aAuditResult =
|
||||
@@ -596,7 +596,7 @@ TEST(BRepGraph_ValidateTest, AssemblyGraph_OccurrenceChildRefersToOccurrence_Det
|
||||
|
||||
BRepGraph_MutGuard<BRepGraphInc::OccurrenceDef> anOccDef =
|
||||
aGraph.Editor().Occurrences().Mut(BRepGraph_OccurrenceId::Start());
|
||||
anOccDef->ChildDefId = BRepGraph_OccurrenceId::Start();
|
||||
anOccDef.Internal().ChildDefId = BRepGraph_OccurrenceId::Start();
|
||||
|
||||
const BRepGraph_Validate::Result aAuditResult =
|
||||
BRepGraph_Validate::Perform(aGraph, BRepGraph_Validate::Options::Audit());
|
||||
@@ -698,8 +698,8 @@ TEST(BRepGraph_ValidateTest, Audit_DetectsOrphanWireRef_AfterFaceRemoval)
|
||||
if (aRef.IsRemoved)
|
||||
continue;
|
||||
BRepGraph_MutGuard<BRepGraphInc::WireRef> aMut = aGraph.Editor().Wires().MutRef(aRefId);
|
||||
aMut->ParentId = BRepGraph_NodeId(BRepGraph_NodeId::Kind::Face, 9999);
|
||||
aDidCorrupt = true;
|
||||
aMut.Internal().ParentId = BRepGraph_NodeId(BRepGraph_NodeId::Kind::Face, 9999);
|
||||
aDidCorrupt = true;
|
||||
}
|
||||
ASSERT_TRUE(aDidCorrupt);
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ TEST_F(BRepGraph_VersionStampTest, IsStale_MutatedNode_ReturnsTrue)
|
||||
const BRepGraph_VersionStamp aStamp = myGraph.UIDs().StampOf(BRepGraph_FaceId::Start());
|
||||
|
||||
// Mutate the face.
|
||||
myGraph.Editor().Faces().Mut(BRepGraph_FaceId::Start())->NaturalRestriction = true;
|
||||
myGraph.Editor().Faces().SetNaturalRestriction(BRepGraph_FaceId::Start(), true);
|
||||
|
||||
EXPECT_TRUE(myGraph.UIDs().IsStale(aStamp));
|
||||
}
|
||||
@@ -111,7 +111,7 @@ TEST_F(BRepGraph_VersionStampTest, IsStale_DeferredMode_TracksCorrectly)
|
||||
|
||||
// Mutate in deferred mode.
|
||||
myGraph.Editor().BeginDeferredInvalidation();
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start())->Tolerance = 0.5;
|
||||
myGraph.Editor().Edges().SetTolerance(BRepGraph_EdgeId::Start(), 0.5);
|
||||
myGraph.Editor().EndDeferredInvalidation();
|
||||
|
||||
EXPECT_TRUE(myGraph.UIDs().IsStale(aStamp));
|
||||
@@ -150,7 +150,7 @@ TEST_F(BRepGraph_VersionStampTest, IsSameNode_DifferentVersion_StillSameNode)
|
||||
{
|
||||
const BRepGraph_VersionStamp aStampBefore = myGraph.UIDs().StampOf(BRepGraph_FaceId::Start());
|
||||
|
||||
myGraph.Editor().Faces().Mut(BRepGraph_FaceId::Start())->NaturalRestriction = true;
|
||||
myGraph.Editor().Faces().SetNaturalRestriction(BRepGraph_FaceId::Start(), true);
|
||||
|
||||
const BRepGraph_VersionStamp aStampAfter = myGraph.UIDs().StampOf(BRepGraph_FaceId::Start());
|
||||
|
||||
@@ -212,7 +212,7 @@ TEST_F(BRepGraph_VersionStampTest, ToGUID_DifferentMutationGen_DifferentGUID)
|
||||
const Standard_GUID& aGraph = myGraph.UIDs().GraphGUID();
|
||||
const Standard_GUID aGUIDBefore = aStampBefore.ToGUID(aGraph);
|
||||
|
||||
myGraph.Editor().Faces().Mut(BRepGraph_FaceId::Start())->NaturalRestriction = true;
|
||||
myGraph.Editor().Faces().SetNaturalRestriction(BRepGraph_FaceId::Start(), true);
|
||||
|
||||
const BRepGraph_VersionStamp aStampAfter = myGraph.UIDs().StampOf(BRepGraph_FaceId::Start());
|
||||
const Standard_GUID aGUIDAfter = aStampAfter.ToGUID(aGraph);
|
||||
|
||||
@@ -485,7 +485,7 @@ TEST_F(BRepGraph_ViewsTest, TopoView_GroupedProductAndOccurrenceOps_Parity)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::OccurrenceRef> anOccurrenceRef =
|
||||
myGraph.Editor().Occurrences().MutRef(aOccurrenceRefs.Value(0));
|
||||
anOccurrenceRef->IsRemoved = true;
|
||||
myGraph.Editor().Gen().RemoveRef(aOccurrenceRefs.Value(0));
|
||||
}
|
||||
|
||||
EXPECT_EQ(myGraph.Topo().Products().NbComponents(aSubAssembly), 0);
|
||||
@@ -683,7 +683,7 @@ TEST_F(BRepGraph_ViewsTest, AttrsView_MutFace_InvalidatesEntry)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceDef> aFace =
|
||||
myGraph.Editor().Faces().Mut(BRepGraph_FaceId::Start());
|
||||
aFace->Tolerance += 0.1;
|
||||
myGraph.Editor().Faces().SetTolerance(aFace, aFace->Tolerance + 0.1);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(myGraph.Cache().Has(aFaceId, testUserAttrKind()));
|
||||
@@ -714,7 +714,7 @@ TEST_F(BRepGraph_ViewsTest, AttrsView_MutFaceRef_InvalidatesEntry)
|
||||
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceRef> aFaceRef = myGraph.Editor().Faces().MutRef(aRef);
|
||||
aFaceRef->Orientation = TopAbs::Reverse(aFaceRef->Orientation);
|
||||
myGraph.Editor().Faces().SetRefOrientation(aFaceRef, TopAbs::Reverse(aFaceRef->Orientation));
|
||||
}
|
||||
|
||||
EXPECT_FALSE(myGraph.Cache().Has(aRef, testUserAttrKind()));
|
||||
@@ -730,7 +730,7 @@ TEST_F(BRepGraph_ViewsTest, AttrsView_RemoveFaceRef_HidesCacheKindIterator)
|
||||
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceRef> aFaceRef = myGraph.Editor().Faces().MutRef(aRef);
|
||||
aFaceRef->IsRemoved = true;
|
||||
myGraph.Editor().Gen().RemoveRef(aRef);
|
||||
}
|
||||
|
||||
EXPECT_FALSE(myGraph.Cache().Has(aRef, testUserAttrKind()));
|
||||
@@ -792,7 +792,7 @@ TEST_F(BRepGraph_ViewsTest, RefsView_FaceRefIdsOf_LocalFilteringHandlesRemoved)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceRef> aFaceRef =
|
||||
myGraph.Editor().Faces().MutRef(aFaceRefs.Value(0));
|
||||
aFaceRef->IsRemoved = true;
|
||||
myGraph.Editor().Gen().RemoveRef(aFaceRefs.Value(0));
|
||||
}
|
||||
|
||||
EXPECT_EQ(
|
||||
@@ -831,8 +831,8 @@ TEST_F(BRepGraph_ViewsTest, RefsView_GenericRefHelpers_RoundTripForTypedRef)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceRef> aFaceRef =
|
||||
myGraph.Editor().Faces().MutRef(aFaceRefId);
|
||||
aFaceRef->LocalLocation = TopLoc_Location(aTrsf);
|
||||
aFaceRef->Orientation = TopAbs_REVERSED;
|
||||
myGraph.Editor().Faces().SetRefLocalLocation(aFaceRef, TopLoc_Location(aTrsf));
|
||||
myGraph.Editor().Faces().SetRefOrientation(aFaceRef, TopAbs_REVERSED);
|
||||
}
|
||||
|
||||
const BRepGraphInc::FaceRef& aFaceRefEntry = myGraph.Refs().Faces().Entry(aFaceRefId);
|
||||
@@ -907,7 +907,7 @@ TEST_F(BRepGraph_ViewsTest, RefsView_GenericRefHelpers_InvalidAndRemoved)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::FaceRef> aFaceRef =
|
||||
myGraph.Editor().Faces().MutRef(aFaceRefId);
|
||||
aFaceRef->IsRemoved = true;
|
||||
myGraph.Editor().Gen().RemoveRef(aFaceRefId);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(myGraph.Refs().IsRemoved(aFaceRefId));
|
||||
@@ -998,6 +998,7 @@ TEST_F(BRepGraph_ViewsTest, MutView_EdgeDef_IncrementsOwnGen)
|
||||
{
|
||||
BRepGraph_MutGuard<BRepGraphInc::EdgeDef> anEdge =
|
||||
myGraph.Editor().Edges().Mut(BRepGraph_EdgeId::Start());
|
||||
anEdge.MarkDirty();
|
||||
}
|
||||
EXPECT_GT(myGraph.Topo().Edges().Definition(BRepGraph_EdgeId::Start()).OwnGen, 0u);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ set(OCCT_TKBRep_GTests_FILES
|
||||
BRepGraph_Fuzz_Test.cxx
|
||||
BRepGraph_MeshCache_Test.cxx
|
||||
BRepGraph_MutGuard_Test.cxx
|
||||
BRepGraph_PermissionUpdate_Test.cxx
|
||||
BRepGraph_ReplaceVertex_Test.cxx
|
||||
BRepGraph_MutationGen_Test.cxx
|
||||
BRepGraph_Convenience_Test.cxx
|
||||
|
||||
Reference in New Issue
Block a user