]> SALOME platform Git repositories - modules/geom.git/commitdiff
Salome HOME
0023197: [CEA] Extract and rebuild: algo + TUI + some fixes
authorskv <skv@opencascade.com>
Wed, 25 Nov 2015 13:34:14 +0000 (16:34 +0300)
committerskv <skv@opencascade.com>
Wed, 25 Nov 2015 13:34:14 +0000 (16:34 +0300)
resources/extract.png
src/GEOMAlgo/GEOMAlgo_Extractor.cxx
src/GEOMAlgo/GEOMAlgo_Extractor.hxx
src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
src/GEOM_I/GEOM_IShapesOperations_i.cc
src/GEOM_SWIG/geomBuilder.py
src/OperationGUI/OperationGUI_ExtractionDlg.cxx

index 528fe308a45b25256eb4a6d9035120708837d3d7..cdbe85a83aa372ea6a754730285f7629f3145ccf 100644 (file)
Binary files a/resources/extract.png and b/resources/extract.png differ
index 34d92d0ab842e8710d3b9deebf7faa99a3c0f556..bdbadab6954bd750d5a479ad194bc0e7f10c342b 100644 (file)
 
 #include <GEOMAlgo_Extractor.hxx>
 
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepClass3d.hxx>
+#include <BRepTools.hxx>
+#include <BRepTools_WireExplorer.hxx>
+#include <NCollection_Sequence.hxx>
 #include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TColStd_MapOfInteger.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Iterator.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_MapIteratorOfMapOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
 
 
 //=======================================================================
@@ -56,6 +70,7 @@ GEOMAlgo_Extractor::~GEOMAlgo_Extractor()
 void GEOMAlgo_Extractor::SetShape(const TopoDS_Shape &theShape)
 {
   myShape = theShape;
+  myMapShapeAnc.Clear();
   clear();
 }
 
@@ -90,6 +105,37 @@ void GEOMAlgo_Extractor::Perform()
     myResult = myShape;
     return;
   }
+
+  // Mark sub-shapes as removed and modified.
+  markShapes();
+
+  // Process Edges.
+  processShapes(TopAbs_EDGE);
+
+  // Process Wires.
+  processShapes(TopAbs_WIRE);
+
+  // Process Faces.
+  processShapes(TopAbs_FACE);
+
+  // Process Shells.
+  processShapes(TopAbs_SHELL);
+
+  // Process Solids.
+  processShapes(TopAbs_SOLID);
+
+  // Process Comp-Solids.
+  processShapes(TopAbs_COMPSOLID);
+
+  // Process Compounds.
+  processShapes(TopAbs_COMPOUND);
+
+  // Make the result.
+  myResult = makeResult(myShape);
+
+  TopTools_MapOfShape aMapFence;
+
+  makeHistory(myShape, aMapFence);
 }
 
 //=======================================================================
@@ -113,6 +159,9 @@ void GEOMAlgo_Extractor::clear()
   myRemoved.Clear();
   myModified.Clear();
   myNew.Clear();
+  myMapRemoved.Clear();
+  myMapModified.Clear();
+  myMapNewShapeAnc.Clear();
 }
 
 //=======================================================================
@@ -133,15 +182,1233 @@ void GEOMAlgo_Extractor::checkData()
 
   TopTools_ListIteratorOfListOfShape anIter(mySubShapes);
   TopTools_IndexedMapOfShape         anIndices;
+  TopTools_MapOfShape                aMapFence;
 
   TopExp::MapShapes(myShape, anIndices);
 
+  while (anIter.More()) {
+    const TopoDS_Shape &aSubShape = anIter.Value();
+
+    if (aMapFence.Add(aSubShape)) {
+      // Check if it is a sub-shape of the given shape.
+      if (!anIndices.Contains(aSubShape)) {
+        myErrorStatus = 11;
+        return;
+      }
+
+      // Check if it is a main shape.
+      if (aSubShape.IsSame(myShape)) {
+        myErrorStatus = 12;
+        return;
+      }
+
+      anIter.Next();
+    } else {
+      // Remove duplicated index.
+      mySubShapes.Remove(anIter);
+    }
+  }
+
+  if (myMapShapeAnc.IsEmpty()) {
+    // Fill the map of shapes - ancestors.
+    makeMapShapeAncestors(myShape);
+  }
+
+  // Check if there are seam or degenerated edges on faces.
+  for (anIter.Initialize(mySubShapes); anIter.More(); anIter.Next()) {
+    const TopoDS_Shape &aSubShape = anIter.Value();
+
+    if (aSubShape.ShapeType() == TopAbs_EDGE) {
+      // Get the list of ancestor wires.
+      TopTools_ListOfShape               anAncWires;
+      TopTools_ListIteratorOfListOfShape anAncIt;
+
+      if (myMapShapeAnc.IsBound(aSubShape)) {
+        anAncIt.Initialize(myMapShapeAnc.Find(aSubShape));
+
+        for (; anAncIt.More(); anAncIt.Next()) {
+          const TopoDS_Shape &anAncShape = anAncIt.Value();
+
+          if (anAncShape.ShapeType() == TopAbs_WIRE) {
+            anAncWires.Append(anAncShape);
+          }
+        }
+      }
+
+      if (!anAncWires.IsEmpty()) {
+        // Check the ancestor faces.
+        Standard_Boolean hasFaces = Standard_False;
+        TopoDS_Edge      anEdge   = TopoDS::Edge(aSubShape);
+
+        for (anAncIt.Initialize(anAncWires); anAncIt.More(); anAncIt.Next()) {
+          const TopoDS_Shape &anAncShape = anAncIt.Value();
+
+          if (anAncShape.ShapeType() == TopAbs_FACE) {
+            TopoDS_Face aFace = TopoDS::Face(anAncShape);
+
+            if (BRepTools::IsReallyClosed(anEdge, aFace)) {
+              // Deletion of face's seam edge is not allowed
+              myErrorStatus = 13;
+              return;
+            }
+
+            hasFaces = Standard_True;
+          }
+        }
+
+        if (hasFaces && BRep_Tool::Degenerated(anEdge)) {
+          myErrorStatus = 14;
+          return;
+        }
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : makeMapShapeAncestors
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::makeMapShapeAncestors(const TopoDS_Shape &theShape)
+{
+  if (theShape.ShapeType() == TopAbs_VERTEX) {
+    // Vertex is the lowest type. It has no ancestors.
+    return;
+  }
+
+  TopoDS_Iterator     anIter(theShape);
+  TopTools_MapOfShape aMapFence;
+
+  for (; anIter.More(); anIter.Next()) {
+    const TopoDS_Shape &aSubShape = anIter.Value();
+
+    if (aMapFence.Add(aSubShape)) {
+      // Add theShape as an ancestor shape.
+      if (!myMapShapeAnc.IsBound(aSubShape)) {
+        myMapShapeAnc.Bind(aSubShape, TopTools_ListOfShape());
+      }
+
+      myMapShapeAnc.ChangeFind(aSubShape).Append(theShape);
+
+      // Recursively call this method for a sub-shape.
+      makeMapShapeAncestors(aSubShape);
+    }
+  }
+}
+
+//=======================================================================
+//function : markShapes
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::markShapes()
+{
+  TopTools_ListIteratorOfListOfShape anIter(mySubShapes);
+
+  // Mark sub-shapes as removed.
   for (; anIter.More(); anIter.Next()) {
     const TopoDS_Shape &aSubShape = anIter.Value();
 
-    if (!anIndices.Contains(aSubShape)) {
-      myErrorStatus = 11;
-      return;
+    markRemoved(aSubShape);
+  }
+
+  // Mark undestors of sub-shapes as modified.
+  for (anIter.Initialize(mySubShapes); anIter.More(); anIter.Next()) {
+    const TopoDS_Shape &aSubShape = anIter.Value();
+
+    markAncestorsModified(aSubShape);
+  }
+}
+
+//=======================================================================
+//function : markRemoved
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::markRemoved(const TopoDS_Shape &theShape)
+{
+  if (myMapRemoved.Add(theShape)) {
+    // Check sub-shapes.
+    TopoDS_Iterator     anIter(theShape);
+    TopTools_MapOfShape aMapFence;
+
+    for (; anIter.More(); anIter.Next()) {
+      const TopoDS_Shape &aSubShape = anIter.Value();
+
+      if (aMapFence.Add(aSubShape)) {
+        TopTools_ListIteratorOfListOfShape anAncIt
+                                (myMapShapeAnc.Find(aSubShape));
+        Standard_Boolean                   isToRm = Standard_True;
+
+        for (; anAncIt.More(); anAncIt.Next()) {
+          const TopoDS_Shape &anAncShape = anAncIt.Value();
+
+          if (!myMapRemoved.Contains(anAncShape)) {
+            isToRm = Standard_False;
+            break;
+          }
+        }
+
+        if (isToRm) {
+          // Mark sub-shape as removed.
+          markRemoved(aSubShape);
+        }
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : markAncestorsModified
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::markAncestorsModified(const TopoDS_Shape &theShape)
+{
+  if (myMapShapeAnc.IsBound(theShape)) {
+    TopTools_ListIteratorOfListOfShape anAncIt(myMapShapeAnc.Find(theShape));
+
+    for (; anAncIt.More(); anAncIt.Next()) {
+      const TopoDS_Shape &anAncShape = anAncIt.Value();
+
+      if (!myMapRemoved.Contains(anAncShape) &&
+          !myMapModified.IsBound(anAncShape)) {
+        // Mark anAncShape as modified.
+        myMapModified.Bind(anAncShape, TopTools_ListOfShape());
+
+        // Mark its ancestors as modified.
+        markAncestorsModified(anAncShape);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : processShapes
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::processShapes(const TopAbs_ShapeEnum &theType)
+{
+  TopExp_Explorer     anExp(myShape, theType);
+  TopTools_MapOfShape aMapFence;
+
+  for (; anExp.More(); anExp.Next()) {
+    TopoDS_Shape aShape = anExp.Current(); // Copy
+
+    if (aMapFence.Add(aShape)) {
+      if (myMapRemoved.Contains(aShape) ||
+          !myMapModified.IsBound(aShape)) {
+        // Skip removed or not modified shape.
+        continue;
+      }
+
+      aShape.Orientation(TopAbs_FORWARD);
+
+      switch(theType) {
+        case TopAbs_EDGE:
+          processEdge(aShape);
+          break;
+        case TopAbs_WIRE:
+          processWire(aShape);
+          break;
+        case TopAbs_FACE:
+        case TopAbs_SOLID:
+          processFOrSo(aShape);
+          break;
+        case TopAbs_SHELL:
+        case TopAbs_COMPSOLID:
+          processShOrCS(aShape);
+          break;
+        case TopAbs_COMPOUND:
+          processCompound(aShape);
+          break;
+        default:
+          break;
+      }
+    }
+  }
+
+  if (theType == TopAbs_FACE || theType == TopAbs_SOLID) {
+    // Clear duplicated edges from the faces and faces from solids
+    removeBoundsOnFOrSo(theType);
+  }
+}
+
+//=======================================================================
+//function : processEdge
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::processEdge(const TopoDS_Shape &theEdge)
+{
+  TopoDS_Iterator      anIter(theEdge);
+  TopTools_MapOfShape  aMapFence;
+  TopTools_ListOfShape aVtxList;
+
+  for (; anIter.More(); anIter.Next()) {
+    const TopoDS_Shape &aShapeVertex = anIter.Value();
+
+    if (aMapFence.Add(aShapeVertex)) {
+      if (myMapRemoved.Contains(aShapeVertex)) {
+        // This vertex is removed.
+        const TopAbs_Orientation anOri = aShapeVertex.Orientation();
+
+        if (anOri == TopAbs_FORWARD || anOri == TopAbs_REVERSED) {
+          // This edge will disappear from the result.
+          return;
+        }
+      } else {
+        // This vertex is not removed.
+        aVtxList.Append(aShapeVertex);
+      }
+    }
+  }
+
+  TopoDS_Shape aNewEdge = makeShape(theEdge, aVtxList);
+
+  myMapModified.ChangeFind(theEdge).Append(aNewEdge);
+}
+
+//=======================================================================
+//function : processWire
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::processWire(const TopoDS_Shape &theWire)
+{
+  // Get parent face for the wire.
+  TopoDS_Face aFace;
+
+  if (myMapShapeAnc.IsBound(theWire)) {
+    TopTools_ListIteratorOfListOfShape anIter(myMapShapeAnc.Find(theWire));
+
+    for (; anIter.More(); anIter.Next()) {
+      const TopoDS_Shape &aParent = anIter.Value();
+
+      if (aParent.ShapeType() == TopAbs_FACE) {
+        aFace = TopoDS::Face(aParent.Oriented(TopAbs_FORWARD));
+        break;
+      }
+    }
+  }
+
+  TopoDS_Wire                            aWire = TopoDS::Wire(theWire);
+  BRepTools_WireExplorer                 anExp(aWire, aFace);
+  NCollection_List<TopTools_ListOfShape> aListListEdges;
+  TopTools_ListOfShape                   aListEdges;
+
+  for (; anExp.More(); anExp.Next()) {
+    const TopoDS_Edge &anEdge = anExp.Current();
+
+    if (myMapRemoved.Contains(anEdge)) {
+      // This edge is removed.
+      if (!aListEdges.IsEmpty()) {
+        aListListEdges.Append(aListEdges);
+        aListEdges.Clear();
+      }
+    } else if (myMapModified.IsBound(anEdge)) {
+      // This edge is modified.
+      TopTools_ListOfShape aModifEdges;
+
+      getModified(anEdge, aModifEdges);
+
+      if (aModifEdges.IsEmpty()) {
+        // This edge is not created.
+        if (!aListEdges.IsEmpty()) {
+          aListListEdges.Append(aListEdges);
+          aListEdges.Clear();
+        }
+      } else {
+        const TopoDS_Shape aModifEdge = oriented(aModifEdges.First(), anEdge);
+
+        aListEdges.Append(aModifEdge);
+      }
+    } else {
+      // Get an edge as it is.
+      aListEdges.Append(anEdge);
+    }
+  }
+
+  if (!aListEdges.IsEmpty()) {
+    aListListEdges.Append(aListEdges);
+  }
+
+  if (!aListListEdges.IsEmpty()) {
+    TopTools_ListOfShape aListWires;
+
+    makeWires(theWire, aListListEdges, aListWires);
+    myMapModified.ChangeFind(theWire) = aListWires;
+  }
+}
+
+//=======================================================================
+//function : processFOrSo
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::processFOrSo(const TopoDS_Shape &theFOrSo)
+{
+  Standard_Boolean     isToCreate = Standard_True;
+  TopTools_ListOfShape aClosedSubShapes;
+  TopTools_ListOfShape aNewShapes;
+  TopoDS_Shape         anOuterSubShape;
+  TopAbs_ShapeEnum     aShapeType;
+  TopAbs_ShapeEnum     aSubShapeType;
+
+  if (theFOrSo.ShapeType() == TopAbs_FACE) {
+    aShapeType      = TopAbs_FACE;
+    aSubShapeType   = TopAbs_WIRE;
+    anOuterSubShape = BRepTools::OuterWire(TopoDS::Face(theFOrSo));
+  } else {
+    aShapeType      = TopAbs_SOLID;
+    aSubShapeType   = TopAbs_SHELL;
+    anOuterSubShape = BRepClass3d::OuterShell(TopoDS::Solid(theFOrSo));
+  }
+
+  // Process an outer sub-shape.
+  if (myMapRemoved.Contains(anOuterSubShape)) {
+    isToCreate = Standard_False;
+  } else if (myMapModified.IsBound(anOuterSubShape)) {
+    TopTools_ListOfShape aModifSubShapes;
+
+    getModified(anOuterSubShape, aModifSubShapes);
+
+    // Check if there is a closed direct sub-shape.
+    TopTools_ListIteratorOfListOfShape anIter(aModifSubShapes);
+    TopoDS_Shape                       aClosedSubShape;
+
+    for (isToCreate = Standard_False; anIter.More(); anIter.Next()) {
+      const TopoDS_Shape &aSubShape = anIter.Value();
+
+      if (aSubShape.ShapeType() == aSubShapeType && aSubShape.Closed()) {
+        if (isToCreate) {
+          // There is another closed sub-shape. NEVERREACHED.
+          // No need to create a new shape.
+          isToCreate = Standard_False;
+          break;
+        } else {
+          // Remember the closed sub-shape.
+          isToCreate      = Standard_True;
+          aClosedSubShape = aSubShape;
+        }
+      }
+    }
+
+    if (isToCreate) {
+      // Add a closed sub-shape.
+      const TopoDS_Shape aNewSubShape =
+        oriented(aClosedSubShape, anOuterSubShape);
+
+      aClosedSubShapes.Append(aNewSubShape);
+    }
+
+    // Copy shapes to the list of other shapes.
+    for (anIter.Initialize(aModifSubShapes); anIter.More(); anIter.Next()) {
+      const TopoDS_Shape aNewShape = oriented(anIter.Value(), anOuterSubShape);
+
+      if (!isToCreate || !aNewShape.IsSame(aClosedSubShape)) {
+        aNewShapes.Append(aNewShape);
+      }
+    }
+  } else {
+    aClosedSubShapes.Append(anOuterSubShape);
+  }
+
+  // Treat holes.
+  TopoDS_Iterator anIter(theFOrSo);
+
+  for (; anIter.More(); anIter.Next()) {
+    const TopoDS_Shape &aSubShape = anIter.Value();
+
+    if (aSubShape.IsSame(anOuterSubShape)) {
+      // Skip an outer sub-shape.
+      continue;
+    }
+
+    if (myMapModified.IsBound(aSubShape)) {
+      // This is a modified sub-shape.
+      TopTools_ListOfShape aModifSubShapes;
+
+      getModified(aSubShape, aModifSubShapes);
+
+      TopTools_ListIteratorOfListOfShape anIter(aModifSubShapes);
+
+      for (; anIter.More(); anIter.Next()) {
+        const TopoDS_Shape aNewShape = oriented(anIter.Value(), aSubShape);
+
+        if (isToCreate) {
+          if (aNewShape.ShapeType() == aSubShapeType && aNewShape.Closed()) {
+            // This is a closed sub-shape.
+            aClosedSubShapes.Append(aNewShape);
+          } else {
+            aNewShapes.Append(aNewShape);
+          }
+        } else {
+          aNewShapes.Append(aNewShape);
+        }
+      }
+    } else if (!myMapRemoved.Contains(aSubShape)) {
+      // The shape is not modified.
+      if (isToCreate) {
+        aClosedSubShapes.Append(aSubShape);
+      } else {
+        aNewShapes.Append(aSubShape);
+      }
+    }
+  }
+
+  if (isToCreate) {
+    // Create a new shape.
+    TopoDS_Shape aNewShape = makeShape(theFOrSo, aClosedSubShapes);
+
+    aNewShapes.Prepend(aNewShape);
+  }
+
+  if (!aNewShapes.IsEmpty()) {
+    // Store modified shapes.
+    myMapModified.ChangeFind(theFOrSo) = aNewShapes;
+  }
+}
+
+//=======================================================================
+//function : processShOrCS
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::processShOrCS(const TopoDS_Shape &theShOrCS)
+{
+  // Treat sub-shapes.
+  TopoDS_Iterator      anIter(theShOrCS);
+  TopTools_ListOfShape aNewSubShapes;
+  TopTools_ListOfShape aNewOtherShapes;
+  TopAbs_ShapeEnum     aSubShapeType;
+  TopAbs_ShapeEnum     aSubSubShapeType;
+
+  if (theShOrCS.ShapeType() == TopAbs_SHELL) {
+    aSubShapeType    = TopAbs_FACE;
+    aSubSubShapeType = TopAbs_EDGE;
+  } else { // comp-solid
+    aSubShapeType    = TopAbs_SOLID;
+    aSubSubShapeType = TopAbs_FACE;
+  }
+
+  for (; anIter.More(); anIter.Next()) {
+    const TopoDS_Shape &aSubShape = anIter.Value();
+
+    if (myMapModified.IsBound(aSubShape)) {
+      TopTools_ListOfShape aModifList;
+
+      getModified(aSubShape, aModifList);
+
+      // Copy shapes to the list of other shapes.
+      TopTools_ListIteratorOfListOfShape anIter(aModifList);
+
+      for (; anIter.More(); anIter.Next()) {
+        const TopoDS_Shape aNewShape = oriented(anIter.Value(), aSubShape);
+
+        if (aNewShape.ShapeType() == aSubShapeType) {
+          aNewSubShapes.Append(aNewShape);
+        } else {
+          aNewOtherShapes.Append(aNewShape);
+        }
+      }
+    } else if (!myMapRemoved.Contains(aSubShape)) {
+      // Shape is neither removed nor modified. Add it as it is.
+      if (aSubShape.ShapeType() == aSubShapeType) {
+        aNewSubShapes.Append(aSubShape);
+      } else {
+        aNewOtherShapes.Append(aSubShape);
+      }
+    }
+  }
+
+  // Group sub-shapes via bounds
+  TopTools_ListOfShape aNewShapes;
+
+  groupViaBounds(theShOrCS, aNewSubShapes, aNewShapes);
+  aNewOtherShapes.Prepend(aNewShapes);
+
+  if (!aNewOtherShapes.IsEmpty()) {
+    // Store modified shapes.
+    myMapModified.ChangeFind(theShOrCS) = aNewOtherShapes;
+  }
+}
+
+//=======================================================================
+//function : processCompound
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::processCompound(const TopoDS_Shape &theCompound)
+{
+  // Treat sub-shapes.
+  TopoDS_Iterator      anIter(theCompound);
+  TopTools_ListOfShape aNewSubShapes;
+
+  for (; anIter.More(); anIter.Next()) {
+    const TopoDS_Shape &aSubShape = anIter.Value();
+
+    if (myMapModified.IsBound(aSubShape)) {
+      TopTools_ListOfShape aModifList;
+
+      getModified(aSubShape, aModifList);
+
+      // Copy shapes to the list of other shapes.
+      TopTools_ListIteratorOfListOfShape anIter(aModifList);
+
+      for (; anIter.More(); anIter.Next()) {
+        const TopoDS_Shape aNewShape = oriented(anIter.Value(), aSubShape);
+
+        aNewSubShapes.Append(aNewShape);
+      }
+    } else if (!myMapRemoved.Contains(aSubShape)) {
+      // Shape is neither removed nor modified. Add it as it is.
+      aNewSubShapes.Append(aSubShape);
+    }
+  }
+
+  if (!aNewSubShapes.IsEmpty()) {
+    if (aNewSubShapes.Extent() == 1) {
+      // Avoid creation of new compound for a single sub-shape.
+      myMapModified.ChangeFind(theCompound).Append(aNewSubShapes.First());
+    } else {
+      TopoDS_Shape aNewShape = makeShape(theCompound, aNewSubShapes);
+
+      // Store modified shapes.
+      myMapModified.ChangeFind(theCompound).Append(aNewShape);
+    }
+  }
+}
+
+//=======================================================================
+//function : removeBoundsOnFOrSo
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::removeBoundsOnFOrSo(const TopAbs_ShapeEnum theType)
+{
+  // Get bounds on faces or solids.
+  TopExp_Explorer            anExp(myShape, theType);
+  TopTools_MapOfShape        aMapFence;
+  TopAbs_ShapeEnum           aBoundType;
+  TopAbs_ShapeEnum           aComplexBndType;
+  TopTools_IndexedMapOfShape aMapBounds;
+
+  if (theType == TopAbs_FACE) {
+    aBoundType      = TopAbs_EDGE;
+    aComplexBndType = TopAbs_WIRE;
+  } else { // solid
+    aBoundType      = TopAbs_FACE;
+    aComplexBndType = TopAbs_SHELL;
+  }
+
+  for (; anExp.More(); anExp.Next()) {
+    const TopoDS_Shape &aShape = anExp.Current();
+
+    if (aMapFence.Add(aShape)) {
+      if (myMapRemoved.Contains(aShape)) {
+        continue;
+      }
+
+      if (myMapModified.IsBound(aShape)) {
+        TopTools_ListOfShape aNewShapes;
+
+        getModified(aShape, aNewShapes);
+
+        if (!aNewShapes.IsEmpty()) {
+          const TopoDS_Shape &aNewShape = aNewShapes.First();
+
+          if (aNewShape.ShapeType() == theType) {
+            // Get bounds from the modified shape.
+            TopExp::MapShapes(aNewShape, aBoundType, aMapBounds);
+          }
+        }
+      } else {
+        // Get bounds from the original shapes.
+        TopExp::MapShapes(aShape, aBoundType, aMapBounds);
+      }
+    }
+  }
+
+  // Remove duplicated bounds from the faces or solids
+  aMapFence.Clear();
+
+  for (anExp.Init(myShape, theType); anExp.More(); anExp.Next()) {
+    const TopoDS_Shape &aShape = anExp.Current();
+
+    if (aMapFence.Add(aShape)) {
+      if (myMapModified.IsBound(aShape)) {
+        TopTools_ListOfShape               &aNewShapes =
+                                       myMapModified.ChangeFind(aShape);
+        TopTools_ListIteratorOfListOfShape  anIter(aNewShapes);
+
+        while (anIter.More()) {
+          const TopoDS_Shape &aSubShape = anIter.Value();
+          Standard_Boolean    isToRm    = Standard_False;
+
+          if (aSubShape.ShapeType() == aBoundType) {
+            // edge or face
+            isToRm = aMapBounds.Contains(aSubShape);
+          } else if (aSubShape.ShapeType() == aComplexBndType) {
+            // wire or shell
+            TopTools_ListOfShape aNewBounds;
+            Standard_Boolean     isModified;
+
+            if (theType == TopAbs_FACE) {
+              isModified = removeCommonEdges(aSubShape, aMapBounds, aNewBounds);
+            } else {
+              isModified = removeCommonFaces(aSubShape, aMapBounds, aNewBounds);
+            }
+
+            if (isModified) {
+              myMapModified.Bind(aSubShape, aNewBounds);
+              aNewShapes.InsertBefore(aNewBounds, anIter);
+              isToRm = Standard_True; // To remove unmodified bound.
+            }
+          }
+
+          if (isToRm) {
+            aNewShapes.Remove(anIter);
+          } else {
+            anIter.Next();
+          }
+        }
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : oriented
+//purpose  :
+//=======================================================================
+TopoDS_Shape GEOMAlgo_Extractor::oriented(const TopoDS_Shape &theShape,
+                                          const TopoDS_Shape &theContext)
+{
+  const TopAbs_Orientation aShapeOri   = theShape.Orientation();
+  const TopAbs_Orientation aContextOri = theContext.Orientation();
+  TopoDS_Shape             aResult     = theShape;
+
+  aResult.Orientation(TopAbs::Compose(aShapeOri, aContextOri));
+
+  return aResult;
+}
+
+//=======================================================================
+//function : makeShape
+//purpose  :
+//=======================================================================
+TopoDS_Shape GEOMAlgo_Extractor::makeShape
+                        (const TopoDS_Shape         &theShape,
+                         const TopTools_ListOfShape &theSubShapes)
+{
+  TopoDS_Shape aResult = getShapeFromSubShapes(theShape, theSubShapes);
+
+  if (aResult.IsNull()) {
+    // Create a new shape.
+    BRep_Builder                       aBuilder;
+    TopTools_ListIteratorOfListOfShape anIter(theSubShapes);
+    TopTools_MapOfShape                aMapFence;
+
+    aResult = theShape.EmptyCopied();
+    aMapFence.Clear();
+
+    for (; anIter.More(); anIter.Next()) {
+      const TopoDS_Shape &aSubShape = anIter.Value();
+
+      if (aMapFence.Add(aSubShape)) {
+        aBuilder.Add(aResult, aSubShape);
+
+        // Fill the map of new shape - ancestors.
+        if (!myMapNewShapeAnc.IsBound(aSubShape)) {
+          myMapNewShapeAnc.Bind(aSubShape, TopTools_ListOfShape());
+        }
+
+        myMapNewShapeAnc.ChangeFind(aSubShape).Append(aResult);
+      }
+    }
+  }
+
+  return aResult;
+}
+
+//=======================================================================
+//function : getShapeFromSubShapes
+//purpose  :
+//=======================================================================
+TopoDS_Shape GEOMAlgo_Extractor::getShapeFromSubShapes
+                              (const TopoDS_Shape         &theShape,
+                               const TopTools_ListOfShape &theSubShapes)
+{
+  // Fill the map of sub-shapes.
+  TopTools_ListIteratorOfListOfShape anIter(theSubShapes);
+  TopTools_MapOfShape                aMapSubShapes;
+  TopoDS_Shape                       aFirstSubShape = theSubShapes.First();
+  TopoDS_Shape                       aResult;
+
+  for (; anIter.More(); anIter.Next()) {
+    aMapSubShapes.Add(anIter.Value());
+  }
+
+  // Check if such a shape is already created.
+  if (!aMapSubShapes.IsEmpty()) {
+    TopTools_MapIteratorOfMapOfShape aMapIt(aMapSubShapes);
+    Standard_Boolean                 isFirst = Standard_True;
+    TopTools_MapOfShape              aMapAncs[2];
+    Standard_Integer                 iCur    = 0;
+    Standard_Integer                 iPrev   = 1;
+
+    for (; aMapIt.More(); aMapIt.Next()) {
+      const TopoDS_Shape &aSubShape = aMapIt.Key();
+
+      // Switch iCur and iPrev.
+      iCur  = iCur  ? 0 : 1;
+      iPrev = iPrev ? 0 : 1;
+
+      if (myMapNewShapeAnc.IsBound(aSubShape)) {
+        TopTools_ListIteratorOfListOfShape
+                      anAncIt(myMapNewShapeAnc.Find(aSubShape));
+
+        if (isFirst) {
+          // This is a first loop. Just fill the map of ancestors.
+          for (; anAncIt.More(); anAncIt.Next()) {
+            aMapAncs[iCur].Add(anAncIt.Value());
+          }
+        } else {
+          // Add in aMapAnc[iCur] elements that are only in aMapAnc[iPrev].
+          for (aMapAncs[iCur].Clear(); anAncIt.More(); anAncIt.Next()) {
+            const TopoDS_Shape &anAncestor = anAncIt.Value();
+
+            if (aMapAncs[iPrev].Contains(anAncestor)) {
+              aMapAncs[iCur].Add(anAncIt.Value());
+            }
+          }
+        }
+
+        if (aMapAncs[iCur].IsEmpty()) {
+          // There is no common shape. It means that
+          // the result should be a new shape.
+          aMapAncs[iCur].Clear();
+          break;
+        }
+      } else {
+        // This is a new sub-shape. So the result shape is new.
+        aMapAncs[iCur].Clear();
+        break;
+      }
+    }
+
+    if (!aMapAncs[iCur].IsEmpty()) {
+      // Get exactly the same shape.
+      const TopAbs_ShapeEnum aType = theShape.ShapeType();
+
+      for (aMapIt.Initialize(aMapAncs[iCur]); aMapIt.More(); aMapIt.Next()) {
+        const TopoDS_Shape &aShape = aMapIt.Key();
+
+        if (aShape.ShapeType() == aType) {
+          // Check sub-shapes.
+          TopoDS_Iterator    aSubShIt(aShape);
+          TopAbs_Orientation aNewOri       = TopAbs_FORWARD;
+          Standard_Boolean   isComposedOri = Standard_False;
+
+          for (; aSubShIt.More(); aSubShIt.Next()) {
+            const TopoDS_Shape &aSubSh = aSubShIt.Value();
+
+            if (!aMapSubShapes.Contains(aSubSh)) {
+              // There are another sub-shapes in the ancestor.
+              break;
+            }
+
+            if (!isComposedOri && aSubSh.IsSame(aFirstSubShape)) {
+              // Compose orientaiton.
+              isComposedOri = Standard_True;
+              aNewOri       = TopAbs::Compose
+                (aFirstSubShape.Orientation(), aSubSh.Orientation());
+            }
+          }
+
+          if (!aSubShIt.More()) {
+            // That is the same shape. Compose the orientation.
+            aResult = aShape;
+            aResult.Orientation(aNewOri);
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  return aResult;
+}
+
+//=======================================================================
+//function : makeResult
+//purpose  :
+//=======================================================================
+TopoDS_Shape GEOMAlgo_Extractor::makeResult(const TopoDS_Shape &theShape)
+{
+  TopoDS_Shape aResult;
+
+  if (!myMapRemoved.Contains(theShape)) {
+    if (myMapModified.IsBound(theShape)) {
+      // The shape is modified.
+      TopTools_ListOfShape aListModif;
+
+      getModified(theShape, aListModif);
+
+      const Standard_Integer aNbShapes = aListModif.Extent();
+
+      if (aNbShapes == 1) {
+        aResult = oriented(aListModif.First(), theShape);
+      } else if (aNbShapes > 1) {
+        // Build a result as a compound
+        TopTools_ListIteratorOfListOfShape anIter(aListModif);
+        BRep_Builder                       aBuilder;
+        TopoDS_Compound                    aCompound;
+        TopTools_MapOfShape                aMapFence;
+
+        aBuilder.MakeCompound(aCompound);
+
+        for (; anIter.More(); anIter.Next()) {
+          const TopoDS_Shape aModifShape = oriented(anIter.Value(), theShape);
+
+          if (aMapFence.Add(aModifShape)) {
+            aBuilder.Add(aCompound, aModifShape);
+          }
+        }
+
+        aResult = aCompound;
+      }
+    } else {
+      // The result is not modified shape.
+      aResult = theShape;
+    }
+  }
+
+  return aResult;
+}
+
+//=======================================================================
+//function : makeHistory
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::makeHistory(const TopoDS_Shape        &theShape,
+                                           TopTools_MapOfShape &theMapFence)
+{
+  if (theMapFence.Add(theShape)) {
+    Standard_Boolean isKept = Standard_True;
+
+    if (myMapRemoved.Contains(theShape)) {
+      myRemoved.Append(theShape);
+      isKept = Standard_False;
+    } else if (myMapModified.IsBound(theShape)) {
+      TopTools_ListOfShape aListModif;
+
+      getModified(theShape, aListModif, theShape.ShapeType());
+
+      Standard_Boolean       isModif = !aListModif.IsEmpty();
+      const TopAbs_ShapeEnum aType   = theShape.ShapeType();
+
+      if (isModif) {
+        // Add the new shapes.
+        TopTools_ListIteratorOfListOfShape anIter(aListModif);
+
+        // Skip the first shape.
+        for (anIter.Next(); anIter.More(); anIter.Next()) {
+          myNew.Append(anIter.Value());
+        }
+      }
+
+      if (isModif) {
+        myModified.Append(theShape);
+      } else {
+        myRemoved.Append(theShape);
+      }
+
+      isKept = Standard_False;
+    }
+
+    if (!isKept) {
+      // Collect history for children.
+      TopoDS_Iterator anIter(theShape);
+
+      for (; anIter.More(); anIter.Next()) {
+        const TopoDS_Shape &aSubShape = anIter.Value();
+
+        makeHistory(aSubShape, theMapFence);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : removeCommonEdges
+//purpose  :
+//=======================================================================
+Standard_Boolean GEOMAlgo_Extractor::removeCommonEdges
+                     (const TopoDS_Shape               &theWire,
+                      const TopTools_IndexedMapOfShape &theMapEdgesToRm,
+                            TopTools_ListOfShape       &theNewWires)
+{
+  TopExp_Explorer                        anExp(theWire, TopAbs_EDGE);
+  NCollection_List<TopTools_ListOfShape> aListListEdges;
+  TopTools_ListOfShape                   aListEdges;
+  Standard_Boolean                       isModified = Standard_False;
+  TopoDS_Vertex                          aVtx[2];
+
+  for (; anExp.More(); anExp.Next()) {
+    const TopoDS_Shape &anEdge = anExp.Current();
+
+    if (theMapEdgesToRm.Contains(anEdge)) {
+      // This edge is removed.
+      TopExp::Vertices(TopoDS::Edge(anEdge), aVtx[0], aVtx[1]);
+
+      // Skip edges that have same first and last vertices.
+      if (aVtx[0].IsNull() || !aVtx[0].IsSame(aVtx[1])) {
+        if (!aListEdges.IsEmpty()) {
+          aListListEdges.Append(aListEdges);
+          aListEdges.Clear();
+        }
+      }
+
+      isModified = Standard_True;
+    } else {
+      aListEdges.Append(anEdge);
+    }
+  }
+
+  if (!aListEdges.IsEmpty()) {
+    aListListEdges.Append(aListEdges);
+  }
+
+  if (isModified && !aListListEdges.IsEmpty()) {
+    // Make wires.
+    makeWires(theWire, aListListEdges, theNewWires);
+  }
+
+  return isModified;
+}
+
+//=======================================================================
+//function : removeCommonFaces
+//purpose  :
+//=======================================================================
+Standard_Boolean GEOMAlgo_Extractor::removeCommonFaces
+                     (const TopoDS_Shape               &theShell,
+                      const TopTools_IndexedMapOfShape &theMapFacesToRm,
+                            TopTools_ListOfShape       &theNewShells)
+{
+  TopExp_Explorer      anExp(theShell, TopAbs_FACE);
+  TopTools_ListOfShape aListFaces;
+  Standard_Boolean     isModified = Standard_False;
+
+  for (; anExp.More(); anExp.Next()) {
+    const TopoDS_Shape &aFace = anExp.Current();
+
+    if (theMapFacesToRm.Contains(aFace)) {
+      isModified = Standard_True;
+    } else {
+      aListFaces.Append(aFace);
+    }
+  }
+
+  if (isModified && !aListFaces.IsEmpty()) {
+    // Create new shells.
+    groupViaBounds(theShell, aListFaces, theNewShells);
+  }
+
+  return isModified;
+}
+
+//=======================================================================
+//function : makeWires
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::makeWires
+            (const TopoDS_Shape                           &theWire,
+                   NCollection_List<TopTools_ListOfShape> &theListListEdges,
+                   TopTools_ListOfShape                   &theWires)
+{
+  if (theListListEdges.Size() > 1) {
+    // Check if it is possible to merge first and last lists of edges.
+    TopoDS_Edge   anEdgeFirst = TopoDS::Edge(theListListEdges.First().First());
+    TopoDS_Edge   anEdgeLast  = TopoDS::Edge(theListListEdges.Last().Last());
+    TopoDS_Vertex aCommonVtx;
+
+    if (TopExp::CommonVertex(anEdgeFirst, anEdgeLast, aCommonVtx)) {
+      // Merge First and last lists of edges.
+      theListListEdges.First().Prepend(theListListEdges.Last());
+      // Remove the last list.
+      NCollection_List<TopTools_ListOfShape>::Iterator anIter(theListListEdges);
+
+      for (;anIter.More(); anIter.Next()) {
+        if (anIter.Value().IsEmpty()) {
+          theListListEdges.Remove(anIter);
+          break;
+        }
+      }
+    }
+  }
+
+  // Create wires.
+  NCollection_List<TopTools_ListOfShape>::Iterator anIter(theListListEdges);
+
+  for (;anIter.More(); anIter.Next()) {
+    const TopTools_ListOfShape &anEdges       = anIter.Value();
+    TopoDS_Shape                aNewWireShape = makeShape(theWire, anEdges);
+    TopoDS_Wire                 aNewWire      = TopoDS::Wire(aNewWireShape);
+    TopoDS_Vertex               aV[2];
+
+    TopExp::Vertices(aNewWire, aV[0], aV[1]);
+
+    if (!aV[0].IsNull() && !aV[1].IsNull()) {
+      aNewWire.Closed(aV[0].IsSame(aV[1]));
+    }
+
+    theWires.Append(aNewWire);
+  }
+}
+
+//=======================================================================
+//function : groupViaBounds
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::groupViaBounds
+                       (const TopoDS_Shape         &theShape,
+                        const TopTools_ListOfShape &theSubShapes,
+                              TopTools_ListOfShape &theNewShapes)
+{
+  const Standard_Boolean isShell = theShape.ShapeType() == TopAbs_SHELL;
+  TopAbs_ShapeEnum       aBoundType;
+
+  if (isShell) {
+    aBoundType = TopAbs_EDGE;
+  } else { // comp-solid
+    aBoundType = TopAbs_FACE;
+  }
+
+  // Group connected sub-shapes.
+  NCollection_Sequence<TopTools_ListOfShape> aGroupedSubShapes;
+  NCollection_Sequence<TopTools_MapOfShape>  aBounds;
+  TopTools_ListIteratorOfListOfShape         anIt(theSubShapes);
+  Standard_Integer                           i;
+
+  for (; anIt.More(); anIt.Next()) {
+    // Find a zone a sub-shape is connected to.
+    const TopoDS_Shape     &aSubShape = anIt.Value();
+    TColStd_MapOfInteger    aMapIndices;
+    const Standard_Integer  aNbZones  = aBounds.Size();
+    TopExp_Explorer         anExp(aSubShape, aBoundType);
+    Standard_Integer        j;
+
+    for (; anExp.More(); anExp.Next()) {
+      const TopoDS_Shape &aSubSubShape = anExp.Current();
+
+      // Check each zone.
+      for (i = 1; i <= aNbZones; ++i) {
+        if (!aMapIndices.Contains(i)) {
+          if (aBounds.Value(i).Contains(aSubSubShape)) {
+            // The current sub-shape belongs to this zone.
+            aMapIndices.Add(i);
+            break;
+          }
+        }
+      }
+    }
+
+    if (aMapIndices.IsEmpty()) {
+      // Create a new zone.
+      aGroupedSubShapes.Append(TopTools_ListOfShape());
+      aBounds.Append(TopTools_MapOfShape());
+      aGroupedSubShapes.ChangeLast().Append(aSubShape);
+      anExp.Init(aSubShape, aBoundType);
+
+      TopTools_MapOfShape &aLastZoneBound = aBounds.ChangeLast();
+
+      for (; anExp.More(); anExp.Next()) {
+        aLastZoneBound.Add(anExp.Current());
+      }
+    } else {
+      // Merge zones. Get the first zone.
+      for (i = 1; i <= aNbZones; ++i) {
+        if (aMapIndices.Contains(i)) {
+          break;
+        }
+      }
+
+      // Merge other zones with the first one.
+      TopTools_ListOfShape &aZoneSubShapes = aGroupedSubShapes.ChangeValue(i);
+      TopTools_MapOfShape  &aZoneBounds    = aBounds.ChangeValue(i);
+
+      for (j = i + 1; j <= aNbZones; ++j) {
+        if (aMapIndices.Contains(j)) {
+          aZoneSubShapes.Append(aGroupedSubShapes.ChangeValue(j));
+
+          TopTools_MapIteratorOfMapOfShape aMapIt(aBounds.Value(j));
+
+          for (; aMapIt.More(); aMapIt.Next()) {
+            aZoneBounds.Add(aMapIt.Key());
+          }
+        }
+      }
+
+      // Remove merged zones.
+      for (j = aNbZones; j > i; --j) {
+        aGroupedSubShapes.Remove(j);
+        aBounds.Remove(j);
+      }
+
+      // Add aSubShape to merged zone.
+      aZoneSubShapes.Append(aSubShape);
+      anExp.Init(aSubShape, aBoundType);
+
+      for (; anExp.More(); anExp.Next()) {
+        const TopoDS_Shape &aSubSubShape = anExp.Current();
+
+        if (!aZoneBounds.Add(aSubSubShape)) {
+          aZoneBounds.Remove(aSubSubShape);
+        }
+      }
+    }
+  }
+
+  // Construct new shapes from sub-shapes.
+  const Standard_Integer aNbGroups = aGroupedSubShapes.Size();
+  TopTools_ListOfShape   aNewSubShapes;
+
+  for (i = 1; i <= aNbGroups; ++i) {
+    const TopTools_ListOfShape &aListSubShapes = aGroupedSubShapes.Value(i);
+
+    if (!isShell && aListSubShapes.Extent() == 1) {
+      // Avoid creation of comp-solid with a single solid.
+      aNewSubShapes.Append(aListSubShapes.First());
+    } else {
+      TopoDS_Shape aNewShape = makeShape(theShape, aListSubShapes);
+
+      if (aBounds.Value(i).IsEmpty()) {
+        // This is a closed shape.
+        aNewShape.Closed(Standard_True);
+      }
+
+      theNewShapes.Append(aNewShape);
+    }
+  }
+
+  // Append the list of single solids (if it is filled).
+  theNewShapes.Append(aNewSubShapes);
+}
+
+//=======================================================================
+//function : getModified
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::getModified(const TopoDS_Shape         &theShape,
+                                           TopTools_ListOfShape &theModifShapes,
+                                     const TopAbs_ShapeEnum      theShapeType)
+{
+  // This shape is modified.
+  TopTools_ListIteratorOfListOfShape anIt(myMapModified.Find(theShape));
+
+  for (; anIt.More(); anIt.Next()) {
+    const TopoDS_Shape &aSubShape = anIt.Value();
+
+    if (theShapeType == TopAbs_SHAPE || aSubShape.ShapeType() == theShapeType) {
+      if (myMapModified.IsBound(aSubShape)) {
+        getModified(aSubShape, theModifShapes);
+      } else {
+        theModifShapes.Append(aSubShape);
+      }
     }
   }
 }
@@ -152,6 +1419,9 @@ void GEOMAlgo_Extractor::checkData()
 //
 // 10 -myShape=NULL
 // 11 -mySubShapes contains not only sub-shapes of myShape.
+// 12 -Can't remove the main shape.
+// 13 -mySubShapes contains seam edges in context of faces.
+// 14 -mySubShapes contains degenerated edges in context of faces.
 //
 // myWarningStatus :
 //
index 2b9696ad1470fb9359e1e1bd1b1159d802832817..9e9215334efd60ec20d71229a1aa0cb25a7029e0 100644 (file)
 
 #include <GEOMAlgo_Algo.hxx>
 
+#include <NCollection_List.hxx>
 #include <TopoDS_Shape.hxx>
+#include <TopTools_DataMapOfShapeListOfShape.hxx>
 #include <TopTools_ListOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
+
+class TopTools_IndexedMapOfShape;
 
 
 /**
@@ -124,23 +129,234 @@ public:
 private:
 
   /**
-   * This method reinitializes the shape.
+   * \brief This method reinitializes the shape.
    */
   void clear();
 
   /**
-   * This method checks the input data.
+   * \brief This method checks the input data.
    */
   void checkData();
 
+  /**
+   * \brief This method fills the map of shapes and ancestors for the whole
+   * sub-shapes of theShape. This method is recursively called up to the lowest
+   * level of sub-shapes i.e. vertices.
+   *
+   * \param theShape the shape.
+   */
+  void makeMapShapeAncestors(const TopoDS_Shape &theShape);
+
+  /**
+   * \brief This method marks shapes to be removed and to be modified.
+   */
+  void markShapes();
+
+  /**
+   * \brief This method marks theShape to be removed. If it is required, it
+   * recursively marks its sub-shapes to be removed.
+   *
+   * \param theShape the shape.
+   */
+  void markRemoved(const TopoDS_Shape &theShape);
+
+  /**
+   * \brief This method marks ancestors of theShape to be modified. It is
+   * recursively called up to the level of main shape.
+   *
+   * \param theShape the shape.
+   */
+  void markAncestorsModified(const TopoDS_Shape &theShape);
+
+  /**
+   * \brief This method performs computation of modified shapes of
+   *  the provided type.
+   *
+   * \param theType the processed shape type.
+   */
+  void processShapes(const TopAbs_ShapeEnum &theType);
+
+  /**
+   * \brief This method performs computation of a modified edge. 
+   *
+   * \param theEdge the modified edge (should be forward).
+   */
+  void processEdge(const TopoDS_Shape &theEdge);
+
+  /**
+   * \brief This method performs computation of a modified wire.
+   *
+   * \param theWire the modified wire (should be forward).
+   */
+  void processWire(const TopoDS_Shape &theWire);
+
+  /**
+   * \brief This method performs computation of a modified face or solid.
+   *
+   * \param theFOrSo the modified face or solid (should be forward).
+   */
+  void processFOrSo(const TopoDS_Shape &theFOrSo);
+
+  /**
+   * \brief This method performs computation of a modified shell or comp-solid.
+   *
+   * \param theShOrCS the modified shell or comp-solid (should be forward).
+   */
+  void processShOrCS(const TopoDS_Shape &theShOrCS);
+
+  /**
+   * \brief This method performs computation of a modified compound.
+   *
+   * \param theCompound the modified compound (should be forward).
+   */
+  void processCompound(const TopoDS_Shape &theCompound);
+
+  /**
+   * \brief This method removes hanging edges (faces) built for faces (solids)
+   * if they lie on created faces (solids).
+   *
+   * \param theType the shape type. Should be either face or solid.
+   */
+  void removeBoundsOnFOrSo(const TopAbs_ShapeEnum theType);
+
+  /**
+   * \brief Returns theShape with an orientation composed with theContext's
+   * orientation.
+   *
+   * \param theShape the shape to be re-oriented.
+   * \param theContext the context shape.
+   */
+  TopoDS_Shape oriented(const TopoDS_Shape &theShape,
+                        const TopoDS_Shape &theContext);
+
+  /**
+   * \brief This method makes a shape as an empty copy of theShape adding
+   * subshapes to it.
+   *
+   * \param theShape the shape to be copied (should be forward).
+   * \param theSubShapes the sub-shapes (should be oriented correctly).
+   * \return the modified shape.
+   */
+  TopoDS_Shape makeShape(const TopoDS_Shape         &theShape,
+                         const TopTools_ListOfShape &theSubShapes);
+
+  /**
+   * \brief This method returns the shape from the list of sub-shapes
+   * if there is any shape created already with these sub-shapes.
+   * If there is no such shape, null shape is returned.
+   *
+   * \param theShape the shape to be copied (should be forward).
+   * \param theSubShapes the sub-shapes (should be oriented correctly).
+   * \return the modified shape (or null if it is not found).
+   */
+  TopoDS_Shape getShapeFromSubShapes(const TopoDS_Shape         &theShape,
+                                     const TopTools_ListOfShape &theSubShapes);
+
+  /**
+   * \brief This method makes the result for the given shape. If it is removed
+   * the result is a compound of its modified sub-shapes (or a single
+   * modified sub-shape if it in only one).
+   *
+   * \param theShape the shape.
+   * \return the result.
+   */
+  TopoDS_Shape makeResult(const TopoDS_Shape &theShape);
+
+  /**
+   * \brief This method fills the lists of shapes myRemoved, myModified and
+   * myNew with removed, modified and newly created shapes correspondingly.
+   * This method is called recursively for sub-shapes of the shape.
+   *
+   * \param theShape the shape.
+   * \param theMapFence the map of already treated shapes.
+   */
+  void makeHistory(const TopoDS_Shape        &theShape,
+                         TopTools_MapOfShape &theMapFence);
+
+  /**
+   * \brief This method removes edges that are in theMapEdgesToRm from
+   * theWire and re-creates one or more wires from the rest edges. theNewWires
+   * contains the modified wire(s).
+   *
+   * \param theWire the input wire.
+   * \param theMapEdgesToRm the map of edges to be extracted from theWire.
+   * \param theNewWires is the list of new wires. Output parameter.
+   * \return Standard_True if theWire is modified; Standard_False otherwise.
+   */
+  Standard_Boolean removeCommonEdges
+                     (const TopoDS_Shape               &theWire,
+                      const TopTools_IndexedMapOfShape &theMapEdgesToRm,
+                            TopTools_ListOfShape       &theNewWires);
+
+  /**
+   * \brief This method removes faces that are in theMapFacesToRm from
+   * theShell and re-creates one or more shells from the rest faces.
+   * theNewShells contains the modified shell(s).
+   *
+   * \param theShell the input shell.
+   * \param theMapFacesToRm the map of faces to be extracted from theShell.
+   * \param theNewShells is the list of new shells. Output parameter.
+   * \return Standard_True if theShell is modified; Standard_False otherwise.
+   */
+  Standard_Boolean removeCommonFaces
+                     (const TopoDS_Shape               &theShell,
+                      const TopTools_IndexedMapOfShape &theMapFacesToRm,
+                            TopTools_ListOfShape       &theNewShells);
+
+  /**
+   * \brief This method creates wires from the list of list of edges.
+   *
+   * \param theWire the input wire.
+   * \param theListListEdges the list of list of edges. Can be modified
+   *        on output.
+   * \param theWires the list of created wires. Output parameter.
+   */
+  void makeWires(const TopoDS_Shape                           &theWire,
+                       NCollection_List<TopTools_ListOfShape> &theListListEdges,
+                       TopTools_ListOfShape                   &theWires);
+
+  /**
+   * \brief This method collects the shapes in theShapes via common bounds.
+   * This method is used to group faces into shells via common edges or
+   * solids into compsolids via common faces. Collected lists of shapes
+   * are used to create new shapes from theShape that are returned in
+   * theNewShapes. theNewShapes is not cleared at first.
+   *
+   * \param theShape the original shape.
+   * \param theSubShapes the list of shapes to be connected.
+   * \param theNewShapes the list of newly created shapes. Output parameter.
+   */
+  void groupViaBounds(const TopoDS_Shape         &theShape,
+                      const TopTools_ListOfShape &theSubShapes,
+                            TopTools_ListOfShape &theNewShapes);
+
+  /**
+   * \brief This method returns the list of modified shapes obtained
+   * from theShape. It performs recursive search in myMapModified.
+   * theModifShapes is not cleared at first. If theShapeType filter is equal
+   * to TopAbs_SHAPE (default value) all modified shapes will be returned,
+   * otherwise shapes of particular type will only be returned.
+   *
+   * \param theShape the shape examined.
+   * \param theModifShapes the list of modified shapes. Output parameter.
+   * \param theShapeType the shape type filter.
+   */
+  void getModified(const TopoDS_Shape         &theShape,
+                         TopTools_ListOfShape &theModifShapes,
+                   const TopAbs_ShapeEnum      theShapeType = TopAbs_SHAPE);
+
 protected:
 
-  TopoDS_Shape         myShape;
-  TopoDS_Shape         myResult;
-  TopTools_ListOfShape mySubShapes;
-  TopTools_ListOfShape myRemoved;
-  TopTools_ListOfShape myModified;
-  TopTools_ListOfShape myNew;
+  TopoDS_Shape                       myShape;
+  TopoDS_Shape                       myResult;
+  TopTools_ListOfShape               mySubShapes;
+  TopTools_ListOfShape               myRemoved;
+  TopTools_ListOfShape               myModified;
+  TopTools_ListOfShape               myNew;
+  TopTools_DataMapOfShapeListOfShape myMapShapeAnc;
+  TopTools_MapOfShape                myMapRemoved;
+  TopTools_DataMapOfShapeListOfShape myMapModified;
+  TopTools_DataMapOfShapeListOfShape myMapNewShapeAnc;
 
 };
 
index 71e3c7042dd6ae15ddada4ac8c5af515f2039a26..11614e3783eec6d2974c54239c7e11ce19f39072 100644 (file)
@@ -841,10 +841,21 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const
 
     if (!anIDs.IsNull()) {
       const int anUpperID = anIDs->Upper();
+      const int aNbShapes = anIndices.Extent();
 
       for (i = anIDs->Lower(); i <= anUpperID; ++i) {
-        const Standard_Integer  anIndex   = anIDs->Value(i);
-        const TopoDS_Shape     &aSubShape = anIndices.FindKey(anIndex);
+        const Standard_Integer anIndex = anIDs->Value(i);
+
+        if (anIndex < 1 || anIndex > aNbShapes) {
+          TCollection_AsciiString aMsg(" Invalid index: ");
+
+          aMsg += TCollection_AsciiString(anIndex);
+          StdFail_NotDone::Raise(aMsg.ToCString());
+          return 0;
+        }
+
+        const TopoDS_Shape &aSubShape = anIndices.FindKey(anIndex);
+
         aListSubShapes.Append(aSubShape);
       }
     }
index 3244013116237c76247abb2271b0f472e1b174a8..c6c30b2285da4df041ebe563849f2a38b14b5d95 100644 (file)
@@ -2244,6 +2244,7 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeExtraction
   GEOM::GEOM_Object_var aGEOMObject;
 
   //Set a not done flag
+  theStats = new GEOM::GEOM_IShapesOperations::ExtractionStats;
   GetOperations()->SetNotDone();
 
   //Get the reference object
@@ -2253,7 +2254,12 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeExtraction
     return aGEOMObject._retn();
   }
 
-  const int                        aNbIDs  = theSubShapeIDs.length();
+  const int aNbIDs = theSubShapeIDs.length();
+
+  if (aNbIDs == 0) {
+    return aGEOMObject._retn();
+  }
+
   int                              i;
   Handle(TColStd_HArray1OfInteger) anArray =
     new TColStd_HArray1OfInteger (1, aNbIDs);
@@ -2272,11 +2278,9 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeExtraction
   }
 
   // Convert statistics.
-  GEOM::GEOM_IShapesOperations::ExtractionStats_var aResStats =
-                       new GEOM::GEOM_IShapesOperations::ExtractionStats;
-  const int                                         aNbStats  = aStats.size();
+  const int aNbStats = aStats.size();
 
-  aResStats->length(aNbStats);
+  theStats->length(aNbStats);
 
   // fill the local CORBA array with values from lists
   std::list<GEOMImpl_IShapesOperations::ExtractionStat>::const_iterator
@@ -2316,11 +2320,8 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeExtraction
 
     aResStat->indices = aResIDList;
 
-    aResStats[i] = aResStat;
+    theStats[i] = aResStat;
   }
 
-  // initialize out-parameter with local array
-  theStats = aResStats._retn();
-
   return GetObject(aResult);
 }
index 16e9ea4caaf52505634d018bf378a14720974106..03de44164ff626c446aa7c221672e5eeb4ed1334 100644 (file)
@@ -6657,6 +6657,35 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
             RaiseIfFailed("IsSubShapeBelongsTo", self.ShapesOp)
             return IsOk
 
+        ## Perform extraction of sub-shapes from the main shape.
+        #
+        #  @param theShape the main shape
+        #  @param theListOfID the list of sub-shape IDs to be extracted from
+        #         the main shape.
+        #  @return New GEOM.GEOM_Object, containing the shape without
+        #          extracted sub-shapes.
+        #
+        #  @ref tui_multi_transformation "Example"
+        @ManageTransactions("ShapesOp")
+        def MakeExtraction(self, theShape, theListOfID, theName=None):
+            """
+            Perform extraction of sub-shapes from the main shape.
+
+            Parameters:
+                theShape the main shape
+                theListOfID the list of sub-shape IDs to be extracted from
+                            the main shape.
+
+            Returns
+                New GEOM.GEOM_Object, containing the shape without
+                extracted sub-shapes.
+            """
+            # Example: see GEOM_TestAll.py
+            (anObj, aStat) = self.ShapesOp.MakeExtraction(theShape, theListOfID)
+            RaiseIfFailed("MakeExtraction", self.ShapesOp)
+            self._autoPublish(anObj, theName, "Extraction")
+            return anObj
+
         # end of l4_decompose
         ## @}
 
index 6885ff728e0eece0641886af70a4f2e8957a06fc..47f2e722b398f69abfbbfb10f47b527a257e829f 100644 (file)
@@ -319,6 +319,8 @@ OperationGUI_ExtractionDlg::OperationGUI_ExtractionDlg
   /***************************************************************/
   myHelpFileName = "extract_and_rebuild_page.html";
 
+  resize(525, 600);
+
   /* Initialisation */
   Init();
 }
@@ -1005,7 +1007,7 @@ void OperationGUI_ExtractionDlg::onRebuild()
 
     QStringList aStrList;
 
-    for (j = 1; j < 8; ++j) {
+    for (j = 0; j < 8; ++j) {
       if (aNbShapes[j] >= 1) {
         const char *aShapeType = aNbShapes[j] == 1 ?
           SINGLE_SHAPE_TYPE_TR_CODES[j] : PLURAL_SHAPE_TYPE_TR_CODES[j];