0024876: Add protection of shapes against modification of geometry
authorink <ink@opencascade.com>
Thu, 10 Jul 2014 10:42:12 +0000 (14:42 +0400)
committerapn <apn@opencascade.com>
Thu, 10 Jul 2014 10:42:49 +0000 (14:42 +0400)
Added flag "locked" for protection of geometric data in the shapes (including tolerances).
Modification test case to avoid regression.

src/BRep/BRep_Builder.cxx
src/DBRep/DBRep.cxx
src/TopoDS/TopoDS.cdl
src/TopoDS/TopoDS_Shape.cdl
src/TopoDS/TopoDS_Shape.lxx
src/TopoDS/TopoDS_TShape.cdl
src/TopoDS/TopoDS_TShape.lxx
tests/boolean/bopcut_2d/D5 [new file with mode: 0644]

index 26997ea..c556d6a 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <TopoDS.hxx>
 #include <TopoDS_Iterator.hxx>
+#include <TopoDS_LockedShape.hxx>
 
 #include <Precision.hxx>
 
@@ -424,6 +425,10 @@ void  BRep_Builder::MakeFace(TopoDS_Face& F,
                              const Standard_Real Tol) const 
 {
   Handle(BRep_TFace) TF = new BRep_TFace();
+  if(!F.IsNull() && F.Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::MakeFace");
+  }
   TF->Surface(S);
   TF->Tolerance(Tol);
   MakeShape(F,TF);
@@ -439,6 +444,10 @@ void  BRep_Builder::MakeFace(TopoDS_Face&                      F,
                              const Handle(Poly_Triangulation)& T) const
 {
   Handle(BRep_TFace) TF = new BRep_TFace();
+  if(!F.IsNull() && F.Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::MakeFace");
+  }
   TF->Triangulation(T);
   MakeShape(F, TF);
 }
@@ -455,6 +464,10 @@ void  BRep_Builder::MakeFace(TopoDS_Face& F,
                              const Standard_Real Tol) const 
 {
   Handle(BRep_TFace) TF = new BRep_TFace();
+  if(!F.IsNull() && F.Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::MakeFace");
+  }
   TF->Surface(S);
   TF->Tolerance(Tol);
   TF->Location(L);
@@ -473,6 +486,10 @@ void  BRep_Builder::UpdateFace(const TopoDS_Face& F,
                                const Standard_Real Tol) const
 {
   const Handle(BRep_TFace)& TF = *((Handle(BRep_TFace)*) &F.TShape());
+  if(TF->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateFace");
+  }
   TF->Surface(S);
   TF->Tolerance(Tol);
   TF->Location(L.Predivided(F.Location()));
@@ -488,7 +505,12 @@ void  BRep_Builder::UpdateFace(const TopoDS_Face& F,
 void  BRep_Builder::UpdateFace(const TopoDS_Face& F,
                                const Handle(Poly_Triangulation)& T) const
 {
-  (*((Handle(BRep_TFace)*) &F.TShape()))->Triangulation(T);
+  const Handle(BRep_TFace)& TF = *((Handle(BRep_TFace)*) &F.TShape());
+  if(TF->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateFace");
+  }
+  TF->Triangulation(T);
   F.TShape()->Modified(Standard_True);
 }
 
@@ -501,7 +523,12 @@ void  BRep_Builder::UpdateFace(const TopoDS_Face& F,
 void  BRep_Builder::UpdateFace(const TopoDS_Face& F,
                                const Standard_Real Tol) const 
 {
-  (*((Handle(BRep_TFace)*) &F.TShape()))->Tolerance(Tol);
+  const Handle(BRep_TFace)& TF = *((Handle(BRep_TFace)*) &F.TShape());
+  if(TF->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateFace");
+  }
+  TF->Tolerance(Tol);
   F.TShape()->Modified(Standard_True);
 }
 
@@ -514,7 +541,12 @@ void  BRep_Builder::UpdateFace(const TopoDS_Face& F,
 void  BRep_Builder::NaturalRestriction(const TopoDS_Face& F,
                                        const Standard_Boolean N) const 
 {
-  (*((Handle(BRep_TFace)*) &F.TShape()))->NaturalRestriction(N);
+  const Handle(BRep_TFace)& TF = (*((Handle(BRep_TFace)*) &F.TShape()));
+  if(TF->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::NaturalRestriction");
+  }
+  TF->NaturalRestriction(N);
   F.TShape()->Modified(Standard_True);
 }
 
@@ -527,6 +559,10 @@ void  BRep_Builder::NaturalRestriction(const TopoDS_Face& F,
 void  BRep_Builder::MakeEdge(TopoDS_Edge& E) const
 {
   Handle(BRep_TEdge) TE = new BRep_TEdge();
+  if(!E.IsNull() && E.Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::MakeEdge");
+  }
   TE->Closed(Standard_False);
   MakeShape(E,TE);
 }
@@ -543,6 +579,10 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
                                const Standard_Real Tol) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateEdge");
+  }
   const TopLoc_Location l = L.Predivided(E.Location());
 
   UpdateCurves(TE->ChangeCurves(),C,l);
@@ -565,6 +605,10 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
                                const Standard_Real Tol) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateEdge");
+  }
   const TopLoc_Location l = L.Predivided(E.Location());
 
   UpdateCurves(TE->ChangeCurves(),C,S,l);
@@ -588,6 +632,10 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
                                const gp_Pnt2d& Pl) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateEdge");
+  }
   const TopLoc_Location l = L.Predivided(E.Location());
 
   UpdateCurves(TE->ChangeCurves(),C,S,l,Pf,Pl);
@@ -610,6 +658,10 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
                                const Standard_Real Tol) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateEdge");
+  }
   const TopLoc_Location l = L.Predivided(E.Location());
 
   UpdateCurves(TE->ChangeCurves(),C1,C2,S,l);
@@ -636,6 +688,10 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
                                const gp_Pnt2d& Pl) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateEdge");
+  }
   const TopLoc_Location l = L.Predivided(E.Location());
 
   UpdateCurves(TE->ChangeCurves(),C1,C2,S,l,Pf,Pl);
@@ -657,7 +713,10 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
                                const TopLoc_Location& L) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
-
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateEdge");
+  }
   BRep_ListOfCurveRepresentation& lcr = TE->ChangeCurves();
   BRep_ListIteratorOfListOfCurveRepresentation itcr(lcr);
 
@@ -694,6 +753,10 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
                                const TopLoc_Location& L) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateEdge");
+  }
   const TopLoc_Location l = L.Predivided(E.Location());
 
   Standard_Boolean isModified = Standard_False;
@@ -741,6 +804,10 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
                                const TopLoc_Location& L) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateEdge");
+  }
   const TopLoc_Location l = L.Predivided(E.Location());
 
   Standard_Boolean isModified = Standard_False;
@@ -800,6 +867,10 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge&            E,
                                const TopLoc_Location&        L) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateEdge");
+  }
   TopLoc_Location l = L.Predivided(E.Location());
 
   BRep_ListOfCurveRepresentation& lcr = TE->ChangeCurves();
@@ -854,6 +925,10 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge&            E,
                                const TopLoc_Location&        L) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateEdge");
+  }
   TopLoc_Location l = L.Predivided(E.Location());
   
   BRep_ListOfCurveRepresentation& lcr = TE->ChangeCurves();
@@ -890,6 +965,10 @@ void  BRep_Builder::UpdateEdge(const TopoDS_Edge& E,
                                const Standard_Real Tol) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateEdge");
+  }
   TE->UpdateTolerance(Tol);
   TE->Modified(Standard_True);
 }
@@ -924,7 +1003,10 @@ void  BRep_Builder::Continuity(const TopoDS_Edge& E,
                                const GeomAbs_Shape C)const 
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
-
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::Continuity");
+  }
   const TopLoc_Location l1 = L1.Predivided(E.Location());
   const TopLoc_Location l2 = L2.Predivided(E.Location());
 
@@ -942,6 +1024,10 @@ void  BRep_Builder::SameParameter(const TopoDS_Edge& E,
                                   const Standard_Boolean S) const 
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::SameParameter");
+  }
   TE->SameParameter(S);
   TE->Modified(Standard_True);
 }
@@ -955,6 +1041,10 @@ void  BRep_Builder::SameRange(const TopoDS_Edge& E,
                               const Standard_Boolean S) const 
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::SameRange");
+  }
   TE->SameRange(S);
   TE->Modified(Standard_True);
 }
@@ -968,6 +1058,10 @@ void  BRep_Builder::Degenerated(const TopoDS_Edge& E,
                                 const Standard_Boolean D) const 
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::Degenerated");
+  }
   TE->Degenerated(D);
   if (D) {
     // set a null 3d curve
@@ -989,7 +1083,10 @@ void  BRep_Builder::Range(const TopoDS_Edge&  E,
 {
   //  set the range to all the representations if Only3d=FALSE
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
-  
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::Range");
+  }
   BRep_ListOfCurveRepresentation& lcr = TE->ChangeCurves();
   BRep_ListIteratorOfListOfCurveRepresentation itcr(lcr);
   Handle(BRep_GCurve) GC;
@@ -1032,6 +1129,10 @@ void  BRep_Builder::Range(const TopoDS_Edge& E,
                           const Standard_Real Last) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::Range");
+  }
   const TopLoc_Location l = L.Predivided(E.Location());
 
   BRep_ListOfCurveRepresentation& lcr = TE->ChangeCurves();
@@ -1074,9 +1175,12 @@ void  BRep_Builder::Transfert(const TopoDS_Edge& Ein,
                               const TopoDS_Edge& Eout) const
 {
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &Ein.TShape());
-
+  if(TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::Transfert");
+  }
   const Standard_Real tol = TE->Tolerance();
-  
+
   BRep_ListOfCurveRepresentation& lcr = TE->ChangeCurves();
   BRep_ListIteratorOfListOfCurveRepresentation itcr(lcr);
   
@@ -1123,7 +1227,10 @@ void  BRep_Builder::UpdateVertex(const TopoDS_Vertex& V,
                                  const Standard_Real Tol) const 
 {
   const Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &V.TShape());
-
+  if(TV->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateVertex");
+  }
   TV->Pnt(P.Transformed(V.Location().Inverted().Transformation()));
   TV->UpdateTolerance(Tol);
   TV->Modified(Standard_True);
@@ -1147,6 +1254,11 @@ void  BRep_Builder::UpdateVertex(const TopoDS_Vertex& V,
   const Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &V.TShape());
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
 
+  if(TV->Locked() || TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateVertex");
+  }
+
   TopLoc_Location L = E.Location().Predivided(V.Location());
 
   // Search the vertex in the edge
@@ -1228,6 +1340,10 @@ void  BRep_Builder::UpdateVertex(const TopoDS_Vertex& V,
   const Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &V.TShape());
   const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &E.TShape());
   
+  if(TV->Locked() || TE->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateVertex");
+  }
   
   // Search the vertex in the edge
   TopAbs_Orientation ori = TopAbs_INTERNAL;
@@ -1295,6 +1411,11 @@ void  BRep_Builder::UpdateVertex(const TopoDS_Vertex& Ve,
 {
   const Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &Ve.TShape());
   
+  if(TV->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateVertex");
+  }
+  
   TopLoc_Location L;
   const Handle(Geom_Surface)& S = BRep_Tool::Surface(F,L);
   L = L.Predivided(Ve.Location());
@@ -1314,6 +1435,12 @@ void  BRep_Builder::UpdateVertex(const TopoDS_Vertex& V,
                                  const Standard_Real Tol) const
 {
   const Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &V.TShape());
+    
+  if(TV->Locked())
+  {
+    TopoDS_LockedShape::Raise("BRep_Builder::UpdateVertex");
+  }
+  
   TV->UpdateTolerance(Tol);
   TV->Modified(Standard_True);
 }
index ba76b73..944ef26 100644 (file)
@@ -34,6 +34,7 @@
 #include <BRepTools_WireExplorer.hxx>
 #include <BRepTools_ShapeSet.hxx>
 #include <BRepAdaptor_Surface.hxx>
+#include <BRep_TEdge.hxx>
 #include <Precision.hxx>
 #include <Poly_Triangulation.hxx>
 #include <gp_Ax2.hxx>
@@ -969,6 +970,112 @@ static Standard_Integer countshapes(Draw_Interpretor& di,
 }
 
 //=======================================================================
+// 
+//=======================================================================
+void setProp(TopoDS_Shape Sh, const char** a, Standard_Integer n)
+{
+  Standard_Integer i;
+  for(i = 2; i < n; i++) {
+    if (strstr ( a[i], "free" )) {
+      if(a[i][0] == '-') {
+        Sh.Free(Standard_False);
+      }
+      else {
+        Sh.Free(Standard_True);
+      }
+    }
+    if (strstr ( a[i], "modified" )) {
+      if(a[i][0] == '-') {
+        Sh.Modified(Standard_False);
+      }
+      else {
+        Sh.Modified(Standard_True);
+      }
+    }
+    if (strstr ( a[i], "checked" )) {
+      if(a[i][0] == '-') {
+        Sh.Checked(Standard_False);
+      }
+      else {
+        Sh.Checked(Standard_True);
+      }
+    }
+    if (strstr ( a[i], "orientable" )) {
+      if(a[i][0] == '-') {
+        Sh.Orientable(Standard_False);
+      }
+      else {
+        Sh.Orientable(Standard_True);
+      }
+    }
+    if (strstr ( a[i], "closed" )) {
+      if(a[i][0] == '-') {
+        Sh.Closed(Standard_False);
+      }
+      else {
+        Sh.Closed(Standard_True);
+      }
+    }
+    if (strstr ( a[i], "infinite" )) {
+      if(a[i][0] == '-') {
+        Sh.Infinite(Standard_False);
+      }
+      else {
+        Sh.Infinite(Standard_True);
+      }
+    }
+    if (strstr ( a[i], "convex" )) {
+      if(a[i][0] == '-') {
+        Sh.Convex(Standard_False);
+      }
+      else {
+        Sh.Convex(Standard_True);
+      }
+    }
+    if (strstr ( a[i], "locked" )) {
+      if(a[i][0] == '-') {
+        Sh.Locked(Standard_False);
+      }
+      else {
+        Sh.Locked(Standard_True);
+      }
+    }
+  }
+}
+
+//=======================================================================
+// 
+//=======================================================================
+static Standard_Integer setFlags(Draw_Interpretor& ,
+                                    Standard_Integer n, const char** a)
+{
+  if (n < 3) return 1;
+
+  TopExp_Explorer ex;
+  TopoDS_Shape Sh = DBRep::Get(a[1]);
+
+  if (Sh.IsNull()) return 1;
+
+  setProp(Sh, a, n);
+  for (ex.Init (Sh,TopAbs_VERTEX); ex.More(); ex.Next()) {
+    TopoDS_Shape S = ex.Current();
+    setProp(S, a, n);
+  }
+
+  for (ex.Init (Sh,TopAbs_EDGE); ex.More(); ex.Next()) {
+    TopoDS_Shape S = ex.Current();
+    setProp(S, a, n);
+  }
+
+  for (ex.Init (Sh,TopAbs_FACE); ex.More(); ex.Next()) {
+    TopoDS_Shape S = ex.Current();
+    setProp(S, a, n);
+  }
+
+  return 0;
+}
+
+//=======================================================================
 //memory management
 //=======================================================================
 static Standard_Integer purgemmgt(Draw_Interpretor&, Standard_Integer , const char**) {
@@ -1200,6 +1307,9 @@ void  DBRep::BasicCommands(Draw_Interpretor& theCommands)
                   __FILE__,nbshapes,g);
   theCommands.Add("numshapes","numshapes s; size of shape",__FILE__,numshapes,g);
   theCommands.Add("countshapes","countshapes s; count of shape",__FILE__,countshapes,g);
+  theCommands.Add("setflags",
+                  "setflags shape_name flag1[flag2...]\n sets flags for shape(free, modidfied, checked, orientable, closed, infinite, convex, locked), for exmple <setflags a free> or <setflags a -free> if necessary unflag ",
+                  __FILE__,setFlags,g);
 
 //  theCommands.Add("dumpmmgt",
 //               "dump le contenu du gestionnaire de memoire",__FILE__,dumpmmgt,g);
index 92aa8cf..560339d 100644 (file)
@@ -35,6 +35,10 @@ is
     exception FrozenShape inherits DomainError;
        ---Purpose: An  attempt was  made to   modify  a Shape  already
        --          shared or protected.
+
+    exception LockedShape inherits DomainError;
+       ---Purpose: An attempt was made to modify a geometry of Shape already
+       --          shared or protected.
        
     exception UnCompatibleShapes inherits DomainError;
        ---Purpose: An incorrect insertion was attempted.
index b7caa00..c996e4b 100644 (file)
@@ -131,6 +131,20 @@ is
     raises NullObject from Standard
     is static;
     
+    Locked(me) returns Boolean
+       ---Purpose: Returns the locked flag.
+       --          
+       ---C++: inline
+    raises NullObject from Standard
+    is static;
+    
+    Locked(me : in out; F : Boolean)
+       ---Purpose: Sets the locked flag.
+       --          
+       ---C++: inline
+    raises NullObject from Standard
+    is static;
+
     Modified(me) returns Boolean
        ---Purpose: Returns the modification flag.
        --          
index d9a4de3..7ff7a32 100644 (file)
@@ -153,6 +153,26 @@ inline void TopoDS_Shape::Free (const Standard_Boolean B)
 }
 
 //=======================================================================
+//function : Locked
+//purpose  : 
+//=======================================================================
+
+inline Standard_Boolean TopoDS_Shape::Locked () const
+{
+  return myTShape->Locked();
+}
+
+//=======================================================================
+//function : Locked
+//purpose  : 
+//=======================================================================
+
+inline void TopoDS_Shape::Locked (const Standard_Boolean B)
+{
+  myTShape->Locked(B);
+}
+
+//=======================================================================
 //function : Modified
 //purpose  : 
 //=======================================================================
index 2a90ab2..b177a6b 100644 (file)
@@ -72,6 +72,16 @@ is
     ---C++: inline
        ---Purpose: Sets the free flag.
     is static;
+
+    Locked(me) returns Boolean
+    ---C++: inline
+       ---Purpose: Returns the locked flag.
+    is static;
+    
+    Locked(me : mutable; F : Boolean)
+    ---C++: inline
+       ---Purpose: Sets the locked flag.
+    is static;
     
     Modified(me) returns Boolean
     ---C++: inline
index a57ba2f..9bf1eeb 100644 (file)
@@ -26,6 +26,7 @@
 #define TopoDS_TShape_Flags_Closed     (1<<4)
 #define TopoDS_TShape_Flags_Infinite   (1<<5)
 #define TopoDS_TShape_Flags_Convex     (1<<6)
+#define TopoDS_TShape_Flags_Locked     (1<<7)
 
 
 //=======================================================================
@@ -62,6 +63,26 @@ inline void TopoDS_TShape::Free(const Standard_Boolean F)
 }
 
 //=======================================================================
+//function : Locked
+//purpose  : 
+//=======================================================================
+inline Standard_Boolean TopoDS_TShape::Locked() const
+{
+  return ((myFlags & TopoDS_TShape_Flags_Locked) != 0);
+}
+
+//=======================================================================
+//function : Locked
+//purpose  : 
+//=======================================================================
+
+inline void TopoDS_TShape::Locked(const Standard_Boolean F)
+{
+  if (F) myFlags |=  TopoDS_TShape_Flags_Locked;
+  else   myFlags &= ~TopoDS_TShape_Flags_Locked;
+}
+
+//=======================================================================
 //function : Modified
 //purpose  : 
 //=======================================================================
diff --git a/tests/boolean/bopcut_2d/D5 b/tests/boolean/bopcut_2d/D5
new file mode 100644 (file)
index 0000000..b069a32
--- /dev/null
@@ -0,0 +1,11 @@
+puts "TODO #23876 ALL: Error : The bopcut cannot be built."
+
+restore [locate_data_file case_9_edge.brep] a
+restore [locate_data_file case_9_wire3.brep] b
+settolerance a 0.1
+setflags b locked
+bop a b
+bopcut result
+set length 613.678
+set nbsh_v 3
+set nbsh_e 2