0025957: nurbsconvert modifies original shape
authorisn <isn@opencascade.com>
Tue, 7 Jun 2016 04:20:13 +0000 (07:20 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 18 Aug 2016 11:46:13 +0000 (14:46 +0300)
- Ensure that the subshapes from the original shape will not be changed after nurbsconvert operation.
For that create the new vertexes (NewPoint(..)) as well as new curves (NewCurve(..)) and new surfaces (NewSurface(..)) before calling of Rebuild() method. Make copies of all vertexes impacted by curve or surface modifications. This eliminates necessity of creation of new vertices during recursive rebuilding of the entire shape.

- Compatibility with the old behavior of BRepTools_Modifier has been retained as an option. For that the new flag MutableInput has been added in the interface of the class.

- This patch also impacts other operations based on BRepTools_Modifier, in the sense that they also become safe regarding input shapes.

- Create new test cases. Some test cases with nurbsconvert command are changed to lock input shapes from modifications.

fix regressions

12 files changed:
src/BRepTools/BRepTools_Modifier.cxx
src/BRepTools/BRepTools_Modifier.hxx
src/BRepTools/BRepTools_NurbsConvertModification.cxx
src/ShapeProcess/ShapeProcess_OperLibrary.cxx
src/ShapeProcess/ShapeProcess_OperLibrary.hxx
tests/bugs/iges/bug25632_2
tests/bugs/modalg_5/bug25976
tests/bugs/modalg_6/bug24890
tests/bugs/modalg_6/bug25957_1 [new file with mode: 0644]
tests/bugs/modalg_6/bug25957_2 [new file with mode: 0644]
tests/bugs/moddata_2/bug466
tests/bugs/moddata_3/bug623

index e92ec7b..eb8cf01 100644 (file)
 #include <Message_ProgressSentry.hxx>
 #include <Geom_Surface.hxx>
 
+static void SetShapeFlags(const TopoDS_Shape& theInSh, TopoDS_Shape& theOutSh);
 
 //=======================================================================
 //function : BRepTools_Modifier
 //purpose  : 
 //=======================================================================
 
-BRepTools_Modifier::BRepTools_Modifier ():myDone(Standard_False)
+BRepTools_Modifier::BRepTools_Modifier (Standard_Boolean theMutableInput):
+myDone(Standard_False), myMutableInput (theMutableInput)
 {}
 
 //=======================================================================
@@ -72,9 +74,8 @@ BRepTools_Modifier::BRepTools_Modifier ():myDone(Standard_False)
 //=======================================================================
 
 BRepTools_Modifier::BRepTools_Modifier (const TopoDS_Shape& S) :
-  myShape(S),myDone(Standard_False)
+myShape(S),myDone(Standard_False), myMutableInput (Standard_False)
 {
-  myMap.Clear();
   Put(S);
 }
 
@@ -85,9 +86,10 @@ BRepTools_Modifier::BRepTools_Modifier (const TopoDS_Shape& S) :
 
 BRepTools_Modifier::BRepTools_Modifier
   (const TopoDS_Shape& S,
-   const Handle(BRepTools_Modification)& M) : myShape(S),myDone(Standard_False)
+   const Handle(BRepTools_Modification)& M)
+   : myShape(S), myDone(Standard_False), 
+     myMutableInput (Standard_False)
 {
-  myMap.Clear();
   Put(S);
   Perform(M);
 }
@@ -102,7 +104,6 @@ void BRepTools_Modifier::Init(const TopoDS_Shape& S)
 {
   myShape = S;
   myDone = Standard_False;
-  myMap.Clear();
   Put(S);
 }
 
@@ -111,34 +112,39 @@ void BRepTools_Modifier::Init(const TopoDS_Shape& S)
 //function : Perform
 //purpose  : 
 //=======================================================================
+#ifdef DEBUG_Modifier
+static TopTools_IndexedMapOfShape MapE, MapF;
+#endif
 
 void BRepTools_Modifier::Perform(const Handle(BRepTools_Modification)& M, const Handle(Message_ProgressIndicator) & aProgress)
 {
   if (myShape.IsNull()) {
     Standard_NullObject::Raise();
   }
+#ifdef DEBUG_Modifier
+  MapE.Clear(); MapF.Clear();
+  TopExp::MapShapes(myShape, TopAbs_EDGE, MapE);
+  TopExp::MapShapes(myShape, TopAbs_FACE, MapF);
+#endif
   TopTools_DataMapIteratorOfDataMapOfShapeShape theIter(myMap);
 
-  // Set to Null the value of shapes, in case when another modification is applied to the start shape.
+  Message_ProgressSentry aPSentry(aProgress, "Converting Shape", 0, 2, 1);
 
-  if (!theIter.Value().IsNull()) {
-    while (theIter.More()) {
-      myMap(theIter.Value()).Nullify();
-      theIter.Next();
-    }
-    theIter.Reset();
-  }
+  TopTools_IndexedDataMapOfShapeListOfShape aMVE, aMEF;
+  TopExp::MapShapesAndAncestors(myShape, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
+  TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, aMEF);
 
-  /*
-  while (theIter.More()) {
-    Rebuild(theIter.Key(),M);
-    theIter.Next();
-  }
-  */
+  CreateNewVertices(aMVE, M);
 
-  Message_ProgressSentry aPSentry(aProgress, "Converting Shape", 0, 2, 1);
+  FillNewCurveInfo(aMEF, M);
+
+  FillNewSurfaceInfo(M);
 
-  Rebuild(myShape, M, aProgress);
+  if (!myMutableInput)
+    CreateOtherVertices(aMVE, aMEF, M);
+
+  Standard_Boolean aNewGeom;
+  Rebuild(myShape, M, aNewGeom, aProgress);
 
   if (!aPSentry.More())
   {
@@ -162,9 +168,8 @@ void BRepTools_Modifier::Perform(const Handle(BRepTools_Modification)& M, const
 
   // Update the continuities
 
-  TopTools_IndexedDataMapOfShapeListOfShape theEFMap;
-  TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,theEFMap);
-  BRep_Builder B;
+
+  BRep_Builder aBB;
 
 /*
   Standard_Boolean RecomputeTriangles = Standard_False;
@@ -174,27 +179,13 @@ void BRepTools_Modifier::Perform(const Handle(BRepTools_Modification)& M, const
   TopLoc_Location Loc;
 */
 
-  while (theIter.More()) {
-    const TopoDS_Shape& S = theIter.Key();
-/*
-    if (S.ShapeType() == TopAbs_FACE && !S.IsSame(theIter.Value())) {
-      Tr = BRep_Tool::Triangulation(TopoDS::Face(S),Loc);
-      if (!Tr.IsNull()) {
-        RecomputeTriangles = Standard_True;
-        MaxDeflection = Max(MaxDeflection,Tr->Deflection());
-      }
-    }
-    else */ if (S.ShapeType() == TopAbs_EDGE && !S.IsSame(theIter.Value())) {
-      const TopoDS_Edge& edg = TopoDS::Edge(S);
-/*
-      Po = BRep_Tool::Polygon3D(edg,Loc);
-      if (!Po.IsNull()) {
-       RecomputeTriangles = Standard_True;
-       MaxDeflection = Max(MaxDeflection,Po->Deflection());
-      }
-*/
+  for (int ii = 1; ii <= aMEF.Extent(); ii++)
+  {
+    const TopoDS_Edge& CurE = TopoDS::Edge(aMEF.FindKey(ii));
+    const TopoDS_Edge& NewE = TopoDS::Edge(myMap(CurE));
+    if (!CurE.IsSame(NewE)) {
       TopTools_ListIteratorOfListOfShape it;
-      it.Initialize(theEFMap.FindFromKey(edg));
+      it.Initialize(aMEF.FindFromKey(CurE));
       TopoDS_Face F1,F2;
       while (it.More() && F2.IsNull()) {
         if (F1.IsNull()) {
@@ -206,12 +197,11 @@ void BRepTools_Modifier::Perform(const Handle(BRepTools_Modification)& M, const
         it.Next();
       }
       if (!F2.IsNull()) {
-        const TopoDS_Edge& newedg = TopoDS::Edge(myMap(edg));
         const TopoDS_Face& newf1  = TopoDS::Face(myMap(F1));
         const TopoDS_Face& newf2  = TopoDS::Face(myMap(F2));
-        GeomAbs_Shape Newcont = M->Continuity(edg,F1,F2,newedg,newf1,newf2);
+        GeomAbs_Shape Newcont = M->Continuity(CurE,F1,F2,NewE,newf1,newf2);
         if (Newcont > GeomAbs_C0) {
-          B.Continuity(newedg,newf1,newf2,Newcont);
+          aBB.Continuity(NewE,newf1,newf2,Newcont);
         }
       }
     }
@@ -251,11 +241,20 @@ void BRepTools_Modifier::Put(const TopoDS_Shape& S)
 Standard_Boolean BRepTools_Modifier::Rebuild
   (const TopoDS_Shape& S,
    const Handle(BRepTools_Modification)& M,
+   Standard_Boolean& theNewGeom,
    const Handle(Message_ProgressIndicator)& aProgress)
 {
+#ifdef DEBUG_Modifier
+  int iF = MapF.Contains(S) ? MapF.FindIndex(S) : 0;
+  int iE = MapE.Contains(S) ? MapE.FindIndex(S) : 0;
+#endif
+  TopAbs_ShapeEnum ts = S.ShapeType();
   TopoDS_Shape& result = myMap(S);
-//  if (!result.IsNull()) return ! S.IsEqual(result);
-  if (!result.IsNull()) return ! S.IsSame(result);
+  if (!result.IsNull())
+  {
+    theNewGeom = myHasNewGeom.Contains(S);
+    return !S.IsSame(result);
+  }
   Standard_Boolean rebuild = Standard_False, RevWires = Standard_False;
   TopAbs_Orientation ResOr = TopAbs_FORWARD;
   BRep_Builder B;
@@ -265,26 +264,21 @@ Standard_Boolean BRepTools_Modifier::Rebuild
 
   // new geometry ?
 
-  TopAbs_ShapeEnum ts = S.ShapeType();
   switch (ts) {
   case TopAbs_FACE:
     {
-      Standard_Boolean RevFace;
-      Handle(Geom_Surface) surface;
-      TopLoc_Location location;
-      rebuild = M->NewSurface(TopoDS::Face(S),surface,location,tol,
-                             RevWires,RevFace);
-      if (rebuild) {
-       B.MakeFace(TopoDS::Face(result),surface,
-                  location.Predivided(S.Location()),tol);
-       result.Location(S.Location());
-//     result.Orientation(S.Orientation());
-       if (RevFace) {
-         ResOr = TopAbs_REVERSED;
-       }
-       // set specifics flags of a Face
-       B.NaturalRestriction(TopoDS::Face(result),
-                            BRep_Tool::NaturalRestriction(TopoDS::Face(S)));
+      rebuild = myNSInfo.IsBound(TopoDS::Face(S));
+      if (rebuild) 
+      {
+        const NewSurfaceInfo& aNSinfo = myNSInfo(TopoDS::Face(S));
+        RevWires = aNSinfo.myRevWires;
+        B.MakeFace(TopoDS::Face(result),aNSinfo.mySurface,
+          aNSinfo.myLoc.Predivided(S.Location()),aNSinfo.myToler);
+        result.Location(S.Location());
+        if (aNSinfo.myRevFace) 
+          ResOr = TopAbs_REVERSED;
+        // set specifics flags of a Face
+        B.NaturalRestriction(TopoDS::Face(result), BRep_Tool::NaturalRestriction(TopoDS::Face(S)));
       }
 
       // update triangulation on the copied face
@@ -305,20 +299,20 @@ Standard_Boolean BRepTools_Modifier::Rebuild
 
   case TopAbs_EDGE:
     {
-      Handle(Geom_Curve) curve;
-      TopLoc_Location location;
-      rebuild = M->NewCurve(TopoDS::Edge(S),curve,location,tol);
-      if (rebuild) {
-       if (curve.IsNull()) {
+      rebuild = myNCInfo.IsBound(TopoDS::Edge(S));
+      if (rebuild) 
+      {
+        const NewCurveInfo& aNCinfo = myNCInfo(TopoDS::Edge(S));
+        if (aNCinfo.myCurve.IsNull()) {
          B.MakeEdge(TopoDS::Edge(result));
          B.Degenerated(TopoDS::Edge(result),
                        BRep_Tool::Degenerated(TopoDS::Edge(S)));
-         B.UpdateEdge(TopoDS::Edge(result),tol);  //OCC217
+          B.UpdateEdge(TopoDS::Edge(result),aNCinfo.myToler);  //OCC217
          No3DCurve = Standard_True;
        }
        else {
-         B.MakeEdge(TopoDS::Edge(result),curve,
-                    location.Predivided(S.Location()),tol);
+          B.MakeEdge(TopoDS::Edge(result),aNCinfo.myCurve,
+            aNCinfo.myLoc.Predivided(S.Location()),aNCinfo.myToler);
          No3DCurve = Standard_False;
        }
        result.Location(S.Location());
@@ -346,25 +340,14 @@ Standard_Boolean BRepTools_Modifier::Rebuild
       }
     }
     break;
-
-  case TopAbs_VERTEX:
-    {
-      gp_Pnt vtx;
-      rebuild = M->NewPoint(TopoDS::Vertex(S),vtx,tol);
-      if (rebuild) {
-       B.MakeVertex(TopoDS::Vertex(result),vtx,tol);
-      }
-    }
-    break;
-
   default:
-    {
-    }
+    ;
   }
 
   // rebuild sub-shapes and test new sub-shape ?
 
   Standard_Boolean newgeom = rebuild;
+  theNewGeom = rebuild;
 
   TopoDS_Iterator it;
 
@@ -378,8 +361,10 @@ Standard_Boolean BRepTools_Modifier::Rebuild
     //
     for (it.Initialize(S, Standard_False); it.More() && aPSentry.More(); it.Next(), aPSentry.Next()) {
       // always call Rebuild
-      Standard_Boolean subrebuilt = Rebuild(it.Value(), M, aProgress);
+      Standard_Boolean isSubNewGeom = Standard_False;
+      Standard_Boolean subrebuilt = Rebuild(it.Value(), M, isSubNewGeom, aProgress);
       rebuild =  subrebuilt || rebuild ;
+      theNewGeom = theNewGeom || isSubNewGeom;
     }
     if (!aPSentry.More())
     {
@@ -387,6 +372,8 @@ Standard_Boolean BRepTools_Modifier::Rebuild
       return Standard_False;
     }
   }
+  if (theNewGeom)
+    myHasNewGeom.Add(S);
 
   // make an empty copy
   if (rebuild && !newgeom) {
@@ -419,7 +406,11 @@ Standard_Boolean BRepTools_Modifier::Rebuild
       {
         const TopoDS_Edge& edge = TopoDS::Edge(ex.Current());
 
-        if (M->NewCurve2d(edge, face, TopoDS::Edge(myMap(ex.Current())), TopoDS::Face(result), curve2d, tol))
+#ifdef DEBUG_Modifier
+        iE = MapE.Contains(edge) ? MapE.FindIndex(edge) : 0;
+#endif
+        if (theNewGeom && M->NewCurve2d
+            (edge, face, TopoDS::Edge(myMap(ex.Current())), TopoDS::Face(result), curve2d, tol))
         {
           // rem dub 16/09/97 : Make constant topology or not make at all.
           // Do not make if CopySurface = 1
@@ -484,8 +475,8 @@ Standard_Boolean BRepTools_Modifier::Rebuild
               if (curve2d1.IsNull()) curve2d1 = new Geom2d_Line(gp::OX2d());
               B.UpdateEdge (CurE, curve2d, curve2d1, CurF, 0.);
             }
-            currcurv = BRep_Tool::CurveOnSurface(edge,face,f,l);
-            B.Range(edge,f,l);
+            currcurv = BRep_Tool::CurveOnSurface(CurE,CurF,f,l);
+            B.Range(CurE,f,l);
           }
           else {
             B.UpdateEdge(TopoDS::Edge(myMap(ex.Current())),
@@ -589,8 +580,8 @@ Standard_Boolean BRepTools_Modifier::Rebuild
         TopoDS_Vertex aLocalVertex = TopoDS::Vertex(myMap(vertex));
         aLocalVertex.Orientation(vtxrelat);
         //B.UpdateVertex(TopoDS::Vertex(myMap(vertex).Oriented(vtxrelat)),
-        B.UpdateVertex(aLocalVertex, param, TopoDS::Edge(result), tol);
-
+        if (myMutableInput || !aLocalVertex.IsSame(vertex))
+          B.UpdateVertex(aLocalVertex, param, TopoDS::Edge(result), tol);
         ex.Next();
       }
 
@@ -608,14 +599,193 @@ Standard_Boolean BRepTools_Modifier::Rebuild
   // Set flag of the shape.
   result.Orientation(ResOr);
 
-  result.Modified  (S.Modified());
-  result.Checked   (S.Checked());
-  result.Orientable(S.Orientable());
-  result.Closed    (S.Closed());
-  result.Infinite  (S.Infinite());
-  result.Convex    (S.Convex());
+  SetShapeFlags(S, result);
 
   return rebuild;
 }
 
+void BRepTools_Modifier::CreateNewVertices( const TopTools_IndexedDataMapOfShapeListOfShape& theMVE, const Handle(BRepTools_Modification)& M)
+{
+  double aToler;
+  BRep_Builder aBB;
+  gp_Pnt aPnt;  
+  for (int i = 1; i <= theMVE.Extent(); i++ )
+  {
+    //fill MyMap only with vertices with NewPoint == true
+    const TopoDS_Vertex& aV = TopoDS::Vertex(theMVE.FindKey(i));
+    Standard_Boolean IsNewP = M->NewPoint(aV, aPnt, aToler);
+    if (IsNewP)
+    {
+      TopoDS_Vertex aNewV;
+      aBB.MakeVertex(aNewV, aPnt, aToler);
+      SetShapeFlags(aV, aNewV);
+      myMap(aV) = aNewV;
+      myHasNewGeom.Add(aV);
+    }
+    else if (myMutableInput)
+      myMap(aV) = aV.Oriented(TopAbs_FORWARD);
+  }
+}
+
+void BRepTools_Modifier::FillNewCurveInfo(const TopTools_IndexedDataMapOfShapeListOfShape& theMEF, const Handle(BRepTools_Modification)& M)
+{
+  Handle(Geom_Curve) aCurve;
+  TopLoc_Location aLocation;
+  BRepTools_Modifier::NewCurveInfo aNCinfo;
+  double aToler;
+  for (int i = 1; i <= theMEF.Extent(); i++ )
+  {
+    const TopoDS_Edge& anE = TopoDS::Edge(theMEF.FindKey(i));
+    Standard_Boolean IsNewCur = M->NewCurve(anE, aCurve, aLocation, aToler);
+    if (IsNewCur)
+    {
+      aNCinfo.myCurve = aCurve;
+      aNCinfo.myLoc = aLocation;
+      aNCinfo.myToler = aToler;
+      myNCInfo.Bind(anE, aNCinfo);
+      myHasNewGeom.Add(anE);
+    }
+  }
+}
+
+void BRepTools_Modifier::FillNewSurfaceInfo(const Handle(BRepTools_Modification)& M)
+{
+  TopTools_IndexedMapOfShape aMF;  
+  TopExp::MapShapes(myShape, TopAbs_FACE, aMF);
+  BRepTools_Modifier::NewSurfaceInfo aNSinfo;
+  for (int i = 1; i <= aMF.Extent(); i++ )
+  {
+    const TopoDS_Face& aF = TopoDS::Face(aMF(i));
+    Standard_Boolean RevFace;
+    Standard_Boolean RevWires;
+    Handle(Geom_Surface) aSurface;
+    TopLoc_Location aLocation;
+    double aToler1;
+    Standard_Boolean IsNewSur = M->NewSurface(aF, aSurface, aLocation, aToler1, RevWires,RevFace);
+    if (IsNewSur)
+    {
+      aNSinfo.mySurface = aSurface;
+      aNSinfo.myLoc = aLocation;
+      aNSinfo.myToler = aToler1;
+      aNSinfo.myRevWires = RevWires;
+      aNSinfo.myRevFace = RevFace;
+      myNSInfo.Bind(aF, aNSinfo);
+      myHasNewGeom.Add(aF);
+    }
+    else
+    {
+      //check if subshapes will be modified 
+      Standard_Boolean notRebuilded = Standard_True;
+      TopExp_Explorer exE(aF, TopAbs_EDGE);
+      while (exE.More() && notRebuilded) 
+      {
+        const TopoDS_Edge& anEE = TopoDS::Edge(exE.Current());
+        if (myNCInfo.IsBound(anEE))
+        {
+          notRebuilded = Standard_False;
+          break;
+        }
+        TopExp_Explorer exV(anEE, TopAbs_VERTEX);
+        while (exV.More() && notRebuilded) 
+        {
+          const TopoDS_Vertex& aVV = TopoDS::Vertex(exV.Current());
+          if (!myMap(aVV).IsNull())
+          {
+            notRebuilded = Standard_False;
+            break;
+          }
+          exV.Next();
+        }
+        exE.Next();
+      }
+      if (notRebuilded)
+      {
+        //subshapes is not going to be modified
+        myNonUpdFace.Add(aF); 
+      }
+    }
+  }
+
+}
+
+void BRepTools_Modifier::CreateOtherVertices(const TopTools_IndexedDataMapOfShapeListOfShape& theMVE, 
+                                             const TopTools_IndexedDataMapOfShapeListOfShape& theMEF, 
+                                             const Handle(BRepTools_Modification)& M)
+{
+  double aToler;
+  //The following logic in some ways repeats the logic from the Rebuild() method.
+  //If the face with its subshapes is not going to be modified 
+  //(i.e. NewSurface() for this face and NewCurve(), NewPoint() for its edges/vertices returns false)
+  //then the calling of NewCurve2d() for this face with its edges is not performed. 
+  //Therefore, the updating of vertices will not present in such cases and 
+  //the EmptyCopied() operation for vertices from this face is not needed. 
+
+  for (int i = 1; i <= theMVE.Extent(); i++ )
+  {
+    const TopoDS_Vertex& aV = TopoDS::Vertex(theMVE.FindKey(i));
+    TopoDS_Vertex aNewV = TopoDS::Vertex(myMap(aV));
+    if ( aNewV.IsNull()) 
+    {
+       const TopTools_ListOfShape& aLEdges = theMVE(i);
+       Standard_Boolean toReplace = Standard_False;
+       TopTools_ListIteratorOfListOfShape it(aLEdges);
+       for (; it.More() && !toReplace; it.Next()) 
+       {
+         const TopoDS_Edge& anE = TopoDS::Edge(it.Value());
+         if (myNCInfo.IsBound(anE) && !myNCInfo(anE).myCurve.IsNull())
+            toReplace = Standard_True;
+
+         if (!toReplace)
+         {
+           const TopTools_ListOfShape& aLFaces = theMEF.FindFromKey(anE);
+           TopTools_ListIteratorOfListOfShape it2(aLFaces);
+           for (; it2.More(); it2.Next()) 
+           {
+             const TopoDS_Face& aF = TopoDS::Face(it2.Value());
+             if (!myNonUpdFace.Contains(aF))
+             {
+               Handle(Geom2d_Curve) aCurve2d;
+               //some NewCurve2d()s may use NewE arg internally, so the 
+               //null TShape as an arg may lead to the exceptions 
+               TopoDS_Edge aDummyE = TopoDS::Edge(anE.EmptyCopied());
+               if (M->NewCurve2d(anE, aF, aDummyE, TopoDS_Face(), aCurve2d, aToler))
+               {
+                 toReplace = true;
+                 break;
+               }
+             }
+           }
+         }
+       }
+       if (toReplace)
+         aNewV = TopoDS::Vertex(aV.EmptyCopied());
+       else
+         aNewV = aV;
+       aNewV.Orientation(TopAbs_FORWARD);
+       myMap(aV) = aNewV;
+    }
+  }
+}
+
+
+static void SetShapeFlags(const TopoDS_Shape& theInSh, TopoDS_Shape& theOutSh)
+{
+  theOutSh.Modified  (theInSh.Modified());
+  theOutSh.Checked   (theInSh.Checked());
+  theOutSh.Orientable(theInSh.Orientable());
+  theOutSh.Closed    (theInSh.Closed());
+  theOutSh.Infinite  (theInSh.Infinite());
+  theOutSh.Convex    (theInSh.Convex());
+}
+
+
+Standard_Boolean BRepTools_Modifier::IsMutableInput() const
+{
+  return myMutableInput;
+}
+
+void BRepTools_Modifier::SetMutableInput(Standard_Boolean theMutableInput)
+{
+  myMutableInput = theMutableInput;
+}
 
index c604279..eadab91 100644 (file)
 #include <Standard_Handle.hxx>
 
 #include <TopTools_DataMapOfShapeShape.hxx>
-#include <TopoDS_Shape.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Vertex.hxx>
 #include <Standard_Boolean.hxx>
 
 #include <Message_ProgressIndicator.hxx>
+#include <NCollection_DataMap.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopTools_ShapeMapHasher.hxx>
+#include <TopLoc_Location.hxx>
 
 class Standard_NullObject;
 class Standard_NoSuchObject;
 class TopoDS_Shape;
 class BRepTools_Modification;
 class Message_ProgressIndicator;
-
+class Geom_Curve;
+class Geom_Surface;
 
 //! Performs geometric modifications on a shape.
 class BRepTools_Modifier 
@@ -40,10 +49,9 @@ class BRepTools_Modifier
 public:
 
   DEFINE_STANDARD_ALLOC
-
   
   //! Creates an empty Modifier.
-  Standard_EXPORT BRepTools_Modifier();
+  Standard_EXPORT BRepTools_Modifier(Standard_Boolean theMutableInput = Standard_False);
   
   //! Creates a modifier on the shape <S>.
   Standard_EXPORT BRepTools_Modifier(const TopoDS_Shape& S);
@@ -60,32 +68,72 @@ public:
   
   //! Returns Standard_True if the modification has
   //! been computed successfully.
-    Standard_Boolean IsDone() const;
-  
-  //! Returns the modified shape corresponding to <S>.
-    const TopoDS_Shape& ModifiedShape (const TopoDS_Shape& S) const;
+  Standard_Boolean IsDone() const;
 
+  //! Returns the current mutable input state
+  Standard_EXPORT Standard_Boolean IsMutableInput() const;
 
+  //! Sets the mutable input state
+  //! If true then the input (original) shape can be modified 
+  //! during modification process
+  Standard_EXPORT void SetMutableInput(Standard_Boolean theMutableInput);
 
+  //! Returns the modified shape corresponding to <S>.
+  const TopoDS_Shape& ModifiedShape (const TopoDS_Shape& S) const;
+  
 
 protected:
-
-
-
+  
 
 
 private:
 
-  
+  struct NewCurveInfo
+  {
+    Handle(Geom_Curve) myCurve;
+    TopLoc_Location myLoc;
+    Standard_Real myToler;
+  };
+
+  struct NewSurfaceInfo
+  {
+    Handle(Geom_Surface) mySurface;
+    TopLoc_Location myLoc;
+    Standard_Real myToler;
+    Standard_Boolean myRevWires;
+    Standard_Boolean myRevFace;
+  };
+
   Standard_EXPORT void Put (const TopoDS_Shape& S);
   
-  Standard_EXPORT Standard_Boolean Rebuild (const TopoDS_Shape& S, const Handle(BRepTools_Modification)& M, const Handle(Message_ProgressIndicator)& aProgress = NULL);
+  Standard_EXPORT Standard_Boolean Rebuild (const TopoDS_Shape& S,
+                                            const Handle(BRepTools_Modification)& M,
+                                            Standard_Boolean& theNewGeom,
+                                            const Handle(Message_ProgressIndicator)& aProgress = NULL);
 
+  Standard_EXPORT void CreateNewVertices(
+    const TopTools_IndexedDataMapOfShapeListOfShape& theMVE, 
+    const Handle(BRepTools_Modification)& M);
+
+  Standard_EXPORT void FillNewCurveInfo(
+    const TopTools_IndexedDataMapOfShapeListOfShape& theMEF, 
+    const Handle(BRepTools_Modification)& M);
+
+  Standard_EXPORT void FillNewSurfaceInfo(const Handle(BRepTools_Modification)& M);
+
+  Standard_EXPORT void CreateOtherVertices(
+    const TopTools_IndexedDataMapOfShapeListOfShape& theMVE, 
+    const TopTools_IndexedDataMapOfShapeListOfShape& theMEF, 
+    const Handle(BRepTools_Modification)& M);
 
   TopTools_DataMapOfShapeShape myMap;
   TopoDS_Shape myShape;
   Standard_Boolean myDone;
-
+  NCollection_DataMap<TopoDS_Edge, NewCurveInfo, TopTools_ShapeMapHasher> myNCInfo;
+  NCollection_DataMap<TopoDS_Face, NewSurfaceInfo, TopTools_ShapeMapHasher> myNSInfo;
+  TopTools_MapOfShape myNonUpdFace;
+  TopTools_MapOfShape myHasNewGeom;
+  Standard_Boolean myMutableInput;
 
 };
 
index 7f678ec..698ed41 100644 (file)
@@ -662,6 +662,7 @@ Standard_Boolean BRepTools_NurbsConvertModification::NewParameter
     Standard_Real& P, 
     Standard_Real& Tol)
 {
+  Tol =  BRep_Tool::Tolerance(V);
   if(BRep_Tool::Degenerated(E))
     return Standard_False;
   Standard_Real f, l, param = BRep_Tool::Parameter(V,E);
index 316988e..a609009 100644 (file)
@@ -61,7 +61,8 @@ TopoDS_Shape ShapeProcess_OperLibrary::ApplyModifier (const TopoDS_Shape &S,
                                                       const Handle(ShapeProcess_ShapeContext)& context,
                                                       const Handle(BRepTools_Modification) &M,
                                                       TopTools_DataMapOfShapeShape &map,
-                                                      const Handle(ShapeExtend_MsgRegistrator) &msg)
+                                                      const Handle(ShapeExtend_MsgRegistrator) &msg,
+                                                      Standard_Boolean theMutableInput)
 {
   // protect against INTERNAL/EXTERNAL shapes
   TopoDS_Shape SF = S.Oriented(TopAbs_FORWARD);
@@ -81,7 +82,7 @@ TopoDS_Shape ShapeProcess_OperLibrary::ApplyModifier (const TopoDS_Shape &S,
        res = map.Find ( shape ).Oriented ( shape.Orientation() );
 
       else {
-       res = ApplyModifier (shape, context, M, map );
+       res = ApplyModifier (shape, context, M, map, 0, theMutableInput );
        map.Bind ( shape, res );
       }
       if ( ! res.IsSame ( shape ) ) locModified = Standard_True;
@@ -95,7 +96,9 @@ TopoDS_Shape ShapeProcess_OperLibrary::ApplyModifier (const TopoDS_Shape &S,
   }
 
   // Modify the shape
-  BRepTools_Modifier MD(SF,M);
+  BRepTools_Modifier MD(SF);
+  MD.SetMutableInput(theMutableInput);
+  MD.Perform(M);
   context->RecordModification ( SF, MD, msg );
   return MD.ModifiedShape(SF).Oriented(S.Orientation());
 }
@@ -118,7 +121,7 @@ static Standard_Boolean directfaces (const Handle(ShapeProcess_Context)& context
   Handle(ShapeCustom_DirectModification) DM = new ShapeCustom_DirectModification;
   DM->SetMsgRegistrator( msg );
   TopTools_DataMapOfShapeShape map;
-  TopoDS_Shape res = ShapeProcess_OperLibrary::ApplyModifier ( ctx->Result(), ctx, DM, map, msg );
+  TopoDS_Shape res = ShapeProcess_OperLibrary::ApplyModifier ( ctx->Result(), ctx, DM, map,  msg, Standard_True );
   ctx->RecordModification ( map, msg );
   ctx->SetResult ( res );
   return Standard_True;
@@ -271,7 +274,7 @@ static Standard_Boolean bsplinerestriction (const Handle(ShapeProcess_Context)&
                                         aMaxDeg, aMaxSeg, ModeDeg, Rational, aParameters );
   LD->SetMsgRegistrator( msg );
   TopTools_DataMapOfShapeShape map;
-  TopoDS_Shape res = ShapeProcess_OperLibrary::ApplyModifier ( ctx->Result(), ctx, LD, map, msg );
+  TopoDS_Shape res = ShapeProcess_OperLibrary::ApplyModifier ( ctx->Result(), ctx, LD, map,  msg, Standard_True );
   ctx->RecordModification ( map, msg );
   ctx->SetResult ( res );
   return Standard_True;
@@ -295,7 +298,7 @@ static Standard_Boolean torevol (const Handle(ShapeProcess_Context)& context)
   Handle(ShapeCustom_ConvertToRevolution) CR = new ShapeCustom_ConvertToRevolution();
   CR->SetMsgRegistrator( msg );
   TopTools_DataMapOfShapeShape map;
-  TopoDS_Shape res = ShapeProcess_OperLibrary::ApplyModifier ( ctx->Result(), ctx, CR, map, msg );
+  TopoDS_Shape res = ShapeProcess_OperLibrary::ApplyModifier ( ctx->Result(), ctx, CR, map,  msg, Standard_True );
   ctx->RecordModification ( map, msg );
   ctx->SetResult ( res );
   return Standard_True;
@@ -319,7 +322,7 @@ static Standard_Boolean swepttoelem (const Handle(ShapeProcess_Context)& context
   Handle(ShapeCustom_SweptToElementary) SE = new ShapeCustom_SweptToElementary();
   SE->SetMsgRegistrator( msg );
   TopTools_DataMapOfShapeShape map;
-  TopoDS_Shape res = ShapeProcess_OperLibrary::ApplyModifier ( ctx->Result(), ctx, SE, map, msg );
+  TopoDS_Shape res = ShapeProcess_OperLibrary::ApplyModifier ( ctx->Result(), ctx, SE, map, msg, Standard_True  );
   ctx->RecordModification ( map, msg );
   ctx->SetResult ( res );
   return Standard_True;
@@ -415,7 +418,7 @@ static Standard_Boolean converttobspline (const Handle(ShapeProcess_Context)& co
   CBspl->SetMsgRegistrator( msg );
     
   TopTools_DataMapOfShapeShape map;
-  TopoDS_Shape res = ShapeProcess_OperLibrary::ApplyModifier( ctx->Result(), ctx, CBspl, map, msg );
+  TopoDS_Shape res = ShapeProcess_OperLibrary::ApplyModifier( ctx->Result(), ctx, CBspl, map,  msg, Standard_True );
   ctx->RecordModification ( map, msg );
   ctx->SetResult ( res );
   return Standard_True;
index f57ba20..108f062 100644 (file)
@@ -57,7 +57,14 @@ public:
   
   //! Applies BRepTools_Modification to a shape,
   //! taking into account sharing of components of compounds.
-  Standard_EXPORT static TopoDS_Shape ApplyModifier (const TopoDS_Shape& S, const Handle(ShapeProcess_ShapeContext)& context, const Handle(BRepTools_Modification)& M, TopTools_DataMapOfShapeShape& map, const Handle(ShapeExtend_MsgRegistrator)& msg = 0);
+  //! if theMutableInput vat is set to true then imput shape S
+  //! can be modified during the modification process.
+  Standard_EXPORT static TopoDS_Shape ApplyModifier (const TopoDS_Shape& S, 
+                                                     const Handle(ShapeProcess_ShapeContext)& context, 
+                                                     const Handle(BRepTools_Modification)& M, 
+                                                     TopTools_DataMapOfShapeShape& map,
+                                                     const Handle(ShapeExtend_MsgRegistrator)& msg = 0,
+                                                     Standard_Boolean theMutableInput = Standard_False);
 
 
 
index 13375f3..d2a1a50 100644 (file)
@@ -12,6 +12,7 @@ mkface face p 0 100 0 100
 smallview
 donly face
 
+setflags face locked
 nurbsconvert r face
 mksurface s r
 
index d270f4d..aaa4d3a 100644 (file)
@@ -8,6 +8,7 @@ puts ""
 
 smallview
 restore [locate_data_file OCC25976-copiedFace.brep] f
+setflags f locked
 nurbsconvert r f
 fit
 checkview -screenshot -2d -path ${imagedir}/${test_image}.png
index 13018d4..f590c3b 100755 (executable)
@@ -8,6 +8,7 @@ puts ""
 
 restore [locate_data_file bug24890_f0.brep] f0
 
+setflags f0 locked
 nurbsconvert result f0
 
 checkshape result
diff --git a/tests/bugs/modalg_6/bug25957_1 b/tests/bugs/modalg_6/bug25957_1
new file mode 100644 (file)
index 0000000..78da3dd
--- /dev/null
@@ -0,0 +1,12 @@
+puts "============"
+puts "OCC25957"
+puts "============"
+puts ""
+######################################################
+# nurbsconvert modifies original shape
+######################################################
+
+psphere s 10
+setflags s locked
+nurbsconvert q s
+checkshape s
diff --git a/tests/bugs/modalg_6/bug25957_2 b/tests/bugs/modalg_6/bug25957_2
new file mode 100644 (file)
index 0000000..765690b
--- /dev/null
@@ -0,0 +1,13 @@
+puts "============"
+puts "OCC25957"
+puts "============"
+puts ""
+######################################################
+# nurbsconvert modifies original shape
+######################################################
+
+restore [locate_data_file bug25957__face2.brep] s
+checkshape s
+setflags s locked
+nurbsconvert nurbs_s s
+checkshape s
\ No newline at end of file
index 7525c05..91d1528 100755 (executable)
@@ -7,6 +7,7 @@ puts ""
 restore [locate_data_file OCC466.brep] res 
 checkshape res
 
+setflags res locked
 nurbsconvert result res
 
 checkprops result -s 693.577
index b8c7296..d3b6c85 100644 (file)
@@ -12,6 +12,7 @@ pload XDE
 
 stepread [locate_data_file OCC623.step] a *
 
+setflags a_1 locked
 dchrono h reset
 dchrono h start
 nurbsconvert result a_1