Salome HOME
0023197: [CEA] Extract and rebuild
authorskv <skv@opencascade.com>
Fri, 13 Nov 2015 06:21:54 +0000 (09:21 +0300)
committervsr <vsr@opencascade.com>
Fri, 11 Mar 2016 09:28:06 +0000 (12:28 +0300)
35 files changed:
doc/salome/gui/GEOM/CMakeLists.txt
doc/salome/gui/GEOM/images/extract_init.png [new file with mode: 0644]
doc/salome/gui/GEOM/images/extract_rebuild.png [new file with mode: 0644]
doc/salome/gui/GEOM/images/extract_result.png [new file with mode: 0644]
doc/salome/gui/GEOM/input/extract_and_rebuild.doc [new file with mode: 0644]
doc/salome/gui/GEOM/input/related_docs.doc
doc/salome/gui/GEOM/input/transforming_geom_objs.doc
doc/salome/gui/GEOM/input/tui_test_all.doc
doc/salome/gui/GEOM/static/ExtractAndRebuild.pdf [new file with mode: 0644]
idl/GEOM_Gen.idl
resources/CMakeLists.txt
resources/extract.png [new file with mode: 0644]
src/GEOMAlgo/CMakeLists.txt
src/GEOMAlgo/GEOMAlgo_Extractor.cxx [new file with mode: 0644]
src/GEOMAlgo/GEOMAlgo_Extractor.hxx [new file with mode: 0644]
src/GEOMGUI/GEOM_images.ts
src/GEOMGUI/GEOM_msg_en.ts
src/GEOMGUI/GEOM_msg_fr.ts
src/GEOMGUI/GEOM_msg_ja.ts
src/GEOMGUI/GeometryGUI.cxx
src/GEOMGUI/GeometryGUI_Operations.h
src/GEOMImpl/CMakeLists.txt
src/GEOMImpl/GEOMImpl_IExtract.hxx [new file with mode: 0644]
src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
src/GEOMImpl/GEOMImpl_IShapesOperations.hxx
src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
src/GEOMImpl/GEOMImpl_Types.hxx
src/GEOM_I/GEOM_IShapesOperations_i.cc
src/GEOM_I/GEOM_IShapesOperations_i.hh
src/GEOM_SWIG/GEOM_TestAll.py
src/GEOM_SWIG/geomBuilder.py
src/OperationGUI/CMakeLists.txt
src/OperationGUI/OperationGUI.cxx
src/OperationGUI/OperationGUI_ExtractionDlg.cxx [new file with mode: 0644]
src/OperationGUI/OperationGUI_ExtractionDlg.h [new file with mode: 0644]

index f7877081bb7c66753d436f6c24e38d52c5e160b4..b765fe7aeda81233f0d29870afbe807ce1819ab2 100644 (file)
@@ -66,6 +66,7 @@ INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/GEOM DESTINATION ${SALOME_INSTALL_
 INSTALL(FILES images/head.png DESTINATION ${SALOME_INSTALL_DOC}/gui/GEOM)
 INSTALL(FILES images/head.png DESTINATION ${SALOME_INSTALL_DOC}/gui/GEOM/geompy_doc)
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/static/SALOME_BOA_PA.pdf DESTINATION ${SALOME_INSTALL_DOC}/gui/GEOM)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/static/ExtractAndRebuild.pdf DESTINATION ${SALOME_INSTALL_DOC}/gui/GEOM)
 INSTALL(FILES input/geompy_migration.doc input/tui_auto_completion_documentation.doc input/tui_execution_distribution.doc DESTINATION ${SALOME_INSTALL_DOC}/gui/GEOM/input)
 
 FILE(GLOB tag_files ${CMAKE_CURRENT_BINARY_DIR}/*.tag)
diff --git a/doc/salome/gui/GEOM/images/extract_init.png b/doc/salome/gui/GEOM/images/extract_init.png
new file mode 100644 (file)
index 0000000..d608551
Binary files /dev/null and b/doc/salome/gui/GEOM/images/extract_init.png differ
diff --git a/doc/salome/gui/GEOM/images/extract_rebuild.png b/doc/salome/gui/GEOM/images/extract_rebuild.png
new file mode 100644 (file)
index 0000000..f553d26
Binary files /dev/null and b/doc/salome/gui/GEOM/images/extract_rebuild.png differ
diff --git a/doc/salome/gui/GEOM/images/extract_result.png b/doc/salome/gui/GEOM/images/extract_result.png
new file mode 100644 (file)
index 0000000..4148d0d
Binary files /dev/null and b/doc/salome/gui/GEOM/images/extract_result.png differ
diff --git a/doc/salome/gui/GEOM/input/extract_and_rebuild.doc b/doc/salome/gui/GEOM/input/extract_and_rebuild.doc
new file mode 100644 (file)
index 0000000..88a90da
--- /dev/null
@@ -0,0 +1,82 @@
+/*!
+
+\page extract_and_rebuild_page Extract and Rebuild
+
+
+This operation allows extraction of sub-shapes from a given
+shape.
+
+To use this operation, select in the Main Menu <b>Operations -> Extract and Rebuild</b>.
+The following dialog box appears:
+
+\image html extract_rebuild.png "Extract and Rebuild Dialog"
+
+In this dialog:
+<ul>
+<li> \b Name is a result object name.</li>
+<li> <b>Main Object</b> is the main object selected for the operation. It is
+possible to select the object in the Object Browser or in the viewer using
+"selection" button.</li>
+<li> <b>Sub-shape type</b> is the type filter for sub-shapes to be chosen
+for the extraction.</li>
+<li> <b>Filtered shapes</b> is the list of filtered sub-shape IDs available
+for the extraction.</li>
+<li> <b>Shapes to extract</b> is the list of sub-shape IDs to be extracted
+grouped by shape types.</li>
+<li> \b >> is the button to copy object IDs from <b>Filtered shapes</b> to
+<b>Shapes to extract</b>.</li>
+<li> \b << is the button to copy object IDs from <b>Shapes to extract</b> to
+<b>Filtered shapes</b>.</li>
+<li> <b>Show Only Selected</b> is the button to show objects selected in the
+<b>Filtered shapes</b> list and hide all other objects.</li>
+<li> <b>Hide Selected</b> is the button to hide objects selected in the
+<b>Filtered shapes</b> list.</li>
+<li> <b>Show all sub-shapes</b> is the button to show all objects from the
+<b>Filtered shapes</b> list.</li>
+<li> \b Rebuild is the button to perform extraction and show the operation
+statistics.</li>
+<li> The block of \b Statistics shows how many shapes of a certain type
+are \b Removed, \b Modified and \b Added.</li>
+<li> \b Apply is the button to create the result.</li>
+<li> <b>Apply and Close</b> is the button to create the result and close
+the dialog.</li>
+<li> \b Close is the button to close this dialog.</li>
+<li> \b Help is the button to show this help page.</li>
+</ul>
+
+<b>TUI Command:</b> <em>geompy.MakeExtraction(theShape, theListOfID),</em> 
+<br> where \em theShape is the main shape, \em theListOfID is a list of
+sub-shape IDs to be extracted.
+
+Our <b>TUI Scripts</b> provide you with useful example of the use of
+\ref swig_MakeExtraction "Extract and Rebuild" functionality.
+
+<b>More details</b>
+
+If a sub-shape is extracted, all its ancestors should be modified. An ancestors
+of extracted sub-shapes can be either:
+- created anew without extracted sub-shapes, or
+- extracted if it is not possible to create a valid shape without extracted
+sub-shape.
+
+E.g. it is necessary to extract the vertex from the box:
+
+\image html extract_init.png "Extraction of the vertex from the box"
+
+In this case 3 ancestor edges are removed as they can't be valid without
+this vertex. 3 faces that contain these edges are also removed. It is because
+the wires without edges are not closed and it is not possible to create
+a valid face on not closed wire. These wires should contain two remaining
+edges, but they are removed as they are the part of the remaining shell.
+So these wires become empty that means that they should be removed as well.
+
+The shell is replaced by another one that contains 3 not modified faces. As
+It is not possible to construct a valid solid from not closed shell the solid
+is removed. So the result of the extraction is a shell that contains 3 faces:
+
+\image html extract_result.png "Result shape"
+
+Please, refer to <a href="ExtractAndRebuild.pdf">this document</a> for a detailed
+description of Extract and Rebuild operation.
+
+*/
index fea4ba010074df23f3aab0f15c15e4918892f4c8..2f210676c3cadd1cfdd72ae330c0f1416728f726 100644 (file)
@@ -7,4 +7,6 @@ that can be useful for reading.
 <a href="SALOME_BOA_PA.pdf">General Fuse Algorithm, Partition
 Algorithm, Boolean Operations Algorithm. Backgrounds.</a>
 
+<a href="ExtractAndRebuild.pdf">Extract and Rebuild algorithm specification.</a>
+
 */
index 8ded8676a235a3b4ddb7d7c0805a202a6141f6b8..3a13073601da749c3686a943963d86a94a00b936 100644 (file)
@@ -27,6 +27,8 @@ special case of \b Explode operation. </li>
 special case of \b Explode operation. </li>
 <li>\subpage transfer_data_page "Transfer Data" operation, which copies
 non-topological data from one shape to another. </li>
+<li>\subpage extract_and_rebuild_page "Extract and Rebuild" operation, which
+extracts sub-shapes from the main shape. </li>
 
 
 <li>\subpage restore_presentation_parameters_page "Restore presentation parameters". 
index 5ed1334a00c422e25c2482809dafd8e1f663e5ea..7c2ddd136d8fd07f356083d766d02d82597b65a8 100644 (file)
 \until geompy.GetSubShapeEdgeSorted(Sketcher3d_2, p3, "OrderedEdges")
 
 \anchor swig_GetSubShapesWithTolerance
+\until geompy.GetSubShapesWithTolerance(Box, GEOM.FACE, GEOM.CC_LE, 1.e-7, "le")
+
+\anchor swig_MakeExtraction
 \until print "DONE"
 
 */
diff --git a/doc/salome/gui/GEOM/static/ExtractAndRebuild.pdf b/doc/salome/gui/GEOM/static/ExtractAndRebuild.pdf
new file mode 100644 (file)
index 0000000..36e4110
Binary files /dev/null and b/doc/salome/gui/GEOM/static/ExtractAndRebuild.pdf differ
index be4adbbd0c744a61047e0f35ce5c5a76181839a5..777f3bcc3fbf3ae3a716d7174a0336da774f0543 100644 (file)
@@ -2782,6 +2782,43 @@ module GEOM
                                        in comparison_condition theCondition,
                                        in double               theTolerance);
 
+    /**
+     * This enumeration represents an extraction statistics type. It is used in
+     * the interface GEOM_IShapesOperations::MakeExtraction.
+     */
+    enum ExtractionStatType
+    {
+      EST_Removed,  ///< Removed sub-shapes
+      EST_Modified, ///< Modified sub-shapes
+      EST_Added     ///< Newly created sub-shapes
+    };
+
+    /*!
+     * This structure defines a format of extraction statistics. It is used in
+     * the interface GEOM_IShapesOperations::MakeExtraction.
+     */
+    struct ExtractionStat
+    {
+      ExtractionStatType type;    ///< Type of extraction statistics.
+      ListOfLong         indices; ///< Shape indices touched by this type of modification.
+    };
+
+    typedef sequence<ExtractionStat> ExtractionStats;
+
+    /*!
+     * \brief Return the shape that is constructed from theShape without
+     * extracted sub-shapes from the input list.
+     *
+     * \param theShape the original shape.
+     * \param theSubShapeIDs the list of sub-shape IDs to be extracted from
+     *        the original shape.
+     * \param theStats the operation statistics. Output parameter.
+     * \return the shape without extracted sub-shapes.
+     */
+    GEOM_Object MakeExtraction(in GEOM_Object      theShape,
+                               in ListOfLong       theSubShapeIDs,
+                               out ExtractionStats theStats);
+
   };
 
  // # GEOM_IBlocksOperations: 
index b08b1d5b90ac3ad406a523e4dfb9e2c7407d5c74..ed58099649b17378314145dd13aca66701b25db9 100755 (executable)
@@ -94,6 +94,7 @@ SET( _res_files
   edgeextension.png
   erase.png
   eraseall.png
+  extract.png
   extruded_boss.png
   extruded_cut.png
   facetosurface.png
diff --git a/resources/extract.png b/resources/extract.png
new file mode 100644 (file)
index 0000000..cdbe85a
Binary files /dev/null and b/resources/extract.png differ
index d2b6024abadb4910378579dc3f69c441598a1cf8..38126e94bf8622c384219578989ce8f9135efe13 100755 (executable)
@@ -59,6 +59,7 @@ SET(GEOMAlgo_HEADERS
   GEOMAlgo_DataMapOfPassKeyInteger.hxx
   GEOMAlgo_DataMapOfShapeMapOfShape.hxx
   GEOMAlgo_DataMapOfShapePnt.hxx
+  GEOMAlgo_Extractor.hxx
   GEOMAlgo_FinderShapeOn.hxx
   GEOMAlgo_FinderShapeOn1.hxx
   GEOMAlgo_FinderShapeOn2.hxx
@@ -123,6 +124,7 @@ SET(GEOMAlgo_SOURCES
   GEOMAlgo_ClsfSurf.cxx
   GEOMAlgo_CoupleOfShapes.cxx
   GEOMAlgo_FinderShapeOn2.cxx
+  GEOMAlgo_Extractor.cxx
   GEOMAlgo_GetInPlace.cxx
   GEOMAlgo_GetInPlace_1.cxx
   GEOMAlgo_GetInPlace_2.cxx
diff --git a/src/GEOMAlgo/GEOMAlgo_Extractor.cxx b/src/GEOMAlgo/GEOMAlgo_Extractor.cxx
new file mode 100644 (file)
index 0000000..bdbadab
--- /dev/null
@@ -0,0 +1,1429 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// File:        GEOMAlgo_Extractor.cxx
+// Created:
+// Author:      Sergey KHROMOV
+//
+
+
+#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>
+
+
+//=======================================================================
+//function : GEOMAlgo_Extractor
+//purpose  :
+//=======================================================================
+GEOMAlgo_Extractor::GEOMAlgo_Extractor()
+{
+}
+
+//=======================================================================
+//function : ~GEOMAlgo_Extractor
+//purpose  :
+//=======================================================================
+GEOMAlgo_Extractor::~GEOMAlgo_Extractor()
+{
+}
+
+//=======================================================================
+//function : SetShape
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::SetShape(const TopoDS_Shape &theShape)
+{
+  myShape = theShape;
+  myMapShapeAnc.Clear();
+  clear();
+}
+
+//=======================================================================
+//function : SetShapesToRemove
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::SetShapesToRemove
+                        (const TopTools_ListOfShape &theSubShapes)
+{
+  mySubShapes.Assign(theSubShapes);
+  clear();
+}
+
+//=======================================================================
+//function : Perform
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::Perform()
+{
+  clear();
+  myErrorStatus = 0;
+  //
+  checkData();
+
+  if(myErrorStatus) {
+    return;
+  }
+
+  if (myWarningStatus == 10) {
+    // The result is the same shape. Nothing is modified.
+    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);
+}
+
+//=======================================================================
+//function : GetResult
+//purpose  :
+//=======================================================================
+const TopoDS_Shape &GEOMAlgo_Extractor::GetResult() const
+{
+  return myResult;
+}
+
+//=======================================================================
+//function : clear
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::clear()
+{
+  myErrorStatus   = 1;
+  myWarningStatus = 0;
+  myResult.Nullify();
+  myRemoved.Clear();
+  myModified.Clear();
+  myNew.Clear();
+  myMapRemoved.Clear();
+  myMapModified.Clear();
+  myMapNewShapeAnc.Clear();
+}
+
+//=======================================================================
+//function : checkData
+//purpose  :
+//=======================================================================
+void GEOMAlgo_Extractor::checkData()
+{
+  if (myShape.IsNull()) {
+    myErrorStatus = 10;
+    return;
+  }
+
+  if (mySubShapes.IsEmpty()) {
+    myWarningStatus = 10;
+    return;
+  }
+
+  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();
+
+    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);
+      }
+    }
+  }
+}
+
+
+//
+// myErrorStatus :
+//
+// 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 :
+//
+// 10 -mySubShapes is empty
+//
diff --git a/src/GEOMAlgo/GEOMAlgo_Extractor.hxx b/src/GEOMAlgo/GEOMAlgo_Extractor.hxx
new file mode 100644 (file)
index 0000000..9e92153
--- /dev/null
@@ -0,0 +1,363 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+// File:        GEOMAlgo_Extractor.hxx
+// Author:      Sergey KHROMOV
+
+#ifndef _GEOMAlgo_Extractor_HeaderFile
+#define _GEOMAlgo_Extractor_HeaderFile
+
+
+#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;
+
+
+/**
+ * \brief This class encapsulates an algorithm of extraction of sub-shapes
+ * from the main shape.
+ */
+class GEOMAlgo_Extractor : public GEOMAlgo_Algo
+{
+public:
+
+  /**
+   * \brief Empty constructor.
+   */
+  Standard_EXPORT GEOMAlgo_Extractor();
+
+  /**
+   * \brief Virtual destructor.
+   */
+  Standard_EXPORT virtual ~GEOMAlgo_Extractor();
+
+  /**
+   * \brief This method sets the main shape.
+   *
+   * \param theShape the main shape.
+   */
+  Standard_EXPORT void SetShape(const TopoDS_Shape &theShape);
+
+  /**
+   * \brief This method returns the main shape.
+   *
+   * \return the main shape.
+   */
+  const TopoDS_Shape &GetShape() const
+  { return myShape; }
+
+  /**
+   * \brief This method sets the list of sub-shapes to be removed
+   *  from the main shape.
+   *
+   * \param theSubShapes the sub-shapes to be removed.
+   */
+  Standard_EXPORT void SetShapesToRemove
+      (const TopTools_ListOfShape &theSubShapes);
+
+  /**
+   * \brief This method returns the list of sub-shapes to be removed
+   *  from the main shape.
+   *
+   * \return the list of sub-shapes to be removed.
+   */
+  const TopTools_ListOfShape &GetShapesToRemove() const
+  { return mySubShapes; }
+
+  /**
+   * This method performs computation of the extracted shape.
+   */
+  Standard_EXPORT virtual void Perform();
+
+  /**
+   * This method returns the result of the algorithm.
+   *
+   * \return the result of the operation.
+   */
+  Standard_EXPORT const TopoDS_Shape &GetResult() const;
+
+  /**
+   * \brief This method returns the sub-shapes removed from the main shape.
+   *
+   * \return the list of removed sub-shapes.
+   */
+  const TopTools_ListOfShape &GetRemoved() const
+  { return myRemoved; }
+
+  /**
+   * \brief This method returns the sub-shapes modified in the main shape.
+   *
+   * \return the list of modified sub-shapes.
+   */
+  const TopTools_ListOfShape &GetModified() const
+  { return myModified; }
+
+  /**
+   * \brief This method returns the newly created sub-shapes in the result
+   * shape.
+   *
+   * \return the list of new sub-shapes in result.
+   */
+  const TopTools_ListOfShape &GetNew() const
+  { return myNew; }
+
+private:
+
+  /**
+   * \brief This method reinitializes the shape.
+   */
+  void clear();
+
+  /**
+   * \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;
+  TopTools_DataMapOfShapeListOfShape myMapShapeAnc;
+  TopTools_MapOfShape                myMapRemoved;
+  TopTools_DataMapOfShapeListOfShape myMapModified;
+  TopTools_DataMapOfShapeListOfShape myMapNewShapeAnc;
+
+};
+
+#endif
index cfcccd313b526d0aa9f64ae1c859f2be4c1d67d4..5ec53885f17fe68027b6959051bbd775acefc484 100644 (file)
             <source>ICO_TRANSFER_DATA</source>
             <translation>transfer_data.png</translation>
         </message>
+        <message>
+            <source>ICO_EXTRACTION</source>
+            <translation>extract.png</translation>
+        </message>
         <message>
             <source>ICO_IMPORT_SHAPE</source>
             <translation>import.png</translation>
             <source>ICON_DLG_TRANSFER_DATA</source>
             <translation>transfer_data.png</translation>
         </message>
+        <message>
+            <source>ICON_DLG_EXTRACTION</source>
+            <translation>extract.png</translation>
+        </message>
         <message>
             <source>ICON_DLG_SCALE_ALONG_AXES</source>
             <translation>scale_along_axes.png</translation>
index 7aef53a751b3625a813ffaf0b1fbf2838fc82a75..efb543e0984a4765f271d58cd9db635ca5ee547e 100644 (file)
@@ -471,6 +471,10 @@ Please, select face, shell or solid and try again</translation>
         <source>GEOM_COMPOUNDSOLID</source>
         <translation>CompSolid</translation>
     </message>
+    <message>
+        <source>GEOM_COMPSOLIDS</source>
+        <translation>CompSolids</translation>
+    </message>
     <message>
         <source>GEOM_COMPOUND_TITLE</source>
         <translation>Create A Compound</translation>
@@ -607,6 +611,10 @@ Please, select face, shell or solid and try again</translation>
         <source>GEOM_EDGE</source>
         <translation>Edge</translation>
     </message>
+    <message>
+        <source>GEOM_EDGES</source>
+        <translation>Edges</translation>
+    </message>
     <message>
         <source>GEOM_EDGE_TITLE</source>
         <translation>Create An Edge</translation>
@@ -2024,6 +2032,10 @@ Please, select face, shell or solid and try again</translation>
         <source>GEOM_SOLID</source>
         <translation>Solid</translation>
     </message>
+    <message>
+        <source>GEOM_SOLIDS</source>
+        <translation>Solids</translation>
+    </message>
     <message>
         <source>GEOM_SOLID_TITLE</source>
         <translation>Solid Construction</translation>
@@ -5236,6 +5248,18 @@ Please, select face, shell or solid and try again</translation>
         <source>STB_TRANSFER_DATA</source>
         <translation>Transfer Data</translation>
     </message>
+    <message>
+        <source>TOP_EXTRACTION</source>
+        <translation>Extract and Rebuild</translation>
+    </message>
+    <message>
+        <source>MEN_EXTRACTION</source>
+        <translation>Extract and Rebuild</translation>
+    </message>
+    <message>
+        <source>STB_EXTRACTION</source>
+        <translation>Extract and Rebuild</translation>
+    </message>
     <message>
         <source>TOP_EXTENSION</source>
         <translation>Extend Edge or Face</translation>
@@ -7629,4 +7653,55 @@ Do you want to create new material?</translation>
         <translation>Rotation angle</translation>
     </message>
 </context>
+<context>
+    <name>OperationGUI_ExtractionDlg</name>
+    <message>
+        <source>GEOM_EXTRACT_TITLE</source>
+        <translation>Extract and Rebuild</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_TYPE</source>
+        <translation>Extraction type</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_INPUT_PARAMS</source>
+        <translation>Input parameters</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_STATISTICS</source>
+        <translation>Statistics</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_SUB_SHAPE_TYPE</source>
+        <translation>Sub-shape type</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_FILTERED_SHAPES</source>
+        <translation>Filtered shapes</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_SHAPES_TO_EXTRACT</source>
+        <translation>Shapes to extract</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_REBUILD</source>
+        <translation>Rebuild</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_REMOVED</source>
+        <translation>Removed</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_MODIFIED</source>
+        <translation>Modified</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_ADDED</source>
+        <translation>Added</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_NAME</source>
+        <translation>Extraction</translation>
+    </message>
+</context>
 </TS>
index a7111b94cdd24dccee789e52734d003a84e1fdb8..7db35f8095df7fad4ea507c466b201c5625b4272 100644 (file)
@@ -471,6 +471,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau</translation>
         <source>GEOM_COMPOUNDSOLID</source>
         <translation>Assemblage solide</translation>
     </message>
+    <message>
+        <source>GEOM_COMPSOLIDS</source>
+        <translation type="unfinished">CompSolids</translation>
+    </message>
     <message>
         <source>GEOM_COMPOUND_TITLE</source>
         <translation>Créer un assemblage</translation>
@@ -607,6 +611,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau</translation>
         <source>GEOM_EDGE</source>
         <translation>Arête</translation>
     </message>
+    <message>
+        <source>GEOM_EDGES</source>
+        <translation type="unfinished">Edges</translation>
+    </message>
     <message>
         <source>GEOM_EDGE_TITLE</source>
         <translation>Créer une arête</translation>
@@ -2016,6 +2024,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau</translation>
         <source>GEOM_SOLID</source>
         <translation>Solide</translation>
     </message>
+    <message>
+        <source>GEOM_SOLIDS</source>
+        <translation type="unfinished">Solids</translation>
+    </message>
     <message>
         <source>GEOM_SOLID_TITLE</source>
         <translation>Construction d&apos;un solide</translation>
@@ -5228,6 +5240,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau</translation>
         <source>STB_TRANSFER_DATA</source>
         <translation>Transfert de données</translation>
     </message>
+    <message>
+        <source>TOP_EXTRACTION</source>
+        <translation type="unfinished">Extract and Rebuild</translation>
+    </message>
+    <message>
+        <source>MEN_EXTRACTION</source>
+        <translation type="unfinished">Extract and Rebuild</translation>
+    </message>
+    <message>
+        <source>STB_EXTRACTION</source>
+        <translation type="unfinished">Extract and Rebuild</translation>
+    </message>
     <message>
         <source>TOP_EXTENSION</source>
         <translation>Extend Edge or Face</translation>
@@ -7605,4 +7629,55 @@ Voulez-vous en créer un nouveau ?</translation>
         <translation>Longueur de l&apos;angle</translation>
     </message>
 </context>
+<context>
+    <name>OperationGUI_ExtractionDlg</name>
+    <message>
+        <source>GEOM_EXTRACT_TITLE</source>
+        <translation type="unfinished">Extract and Rebuild</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_TYPE</source>
+        <translation type="unfinished">Extraction type</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_INPUT_PARAMS</source>
+        <translation type="unfinished">Input parameters</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_STATISTICS</source>
+        <translation type="unfinished">Statistics</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_SUB_SHAPE_TYPE</source>
+        <translation type="unfinished">Sub-shape type</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_FILTERED_SHAPES</source>
+        <translation type="unfinished">Filtered shapes</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_SHAPES_TO_EXTRACT</source>
+        <translation type="unfinished">Shapes to extract</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_REBUILD</source>
+        <translation type="unfinished">Rebuild</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_REMOVED</source>
+        <translation type="unfinished">Removed</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_MODIFIED</source>
+        <translation type="unfinished">Modified</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_ADDED</source>
+        <translation type="unfinished">Added</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_NAME</source>
+        <translation type="unfinished">Extraction</translation>
+    </message>
+</context>
 </TS>
index 0e42dfe3d1eb514175630d8ce303014118e3e316..667818994f92ddf57252dbf936926b0cae3ced15 100644 (file)
       <source>GEOM_COMPOUNDSOLID</source>
       <translation>固体のアセンブリ</translation>
     </message>
+    <message>
+      <source>GEOM_COMPSOLIDS</source>
+      <translation type="unfinished">CompSolids</translation>
+    </message>
     <message>
       <source>GEOM_COMPOUND_TITLE</source>
       <translation>コンパウンドの作成</translation>
       <source>GEOM_EDGE</source>
       <translation>Edge</translation>
     </message>
+    <message>
+      <source>GEOM_EDGES</source>
+      <translation type="unfinished">Edges</translation>
+    </message>
     <message>
       <source>GEOM_EDGE_TITLE</source>
       <translation>エッジを作成</translation>
       <source>GEOM_SOLID</source>
       <translation>ソリッド</translation>
     </message>
+    <message>
+      <source>GEOM_SOLIDS</source>
+      <translation type="unfinished">Solids</translation>
+    </message>
     <message>
       <source>GEOM_SOLID_TITLE</source>
       <translation>ソリッドの構築</translation>
       <source>STB_TRANSFER_DATA</source>
       <translation>データ転送</translation>
     </message>
+    <message>
+      <source>TOP_EXTRACTION</source>
+      <translation type="unfinished">Extract and Rebuild</translation>
+    </message>
+    <message>
+      <source>MEN_EXTRACTION</source>
+      <translation type="unfinished">Extract and Rebuild</translation>
+    </message>
+    <message>
+      <source>STB_EXTRACTION</source>
+      <translation type="unfinished">Extract and Rebuild</translation>
+    </message>
     <message>
       <source>TOP_EXTENSION</source>
       <translation>エッジまたは面の拡張</translation>
       <translation>回転角度</translation>
     </message>
   </context>
+  <context>
+    <name>OperationGUI_ExtractionDlg</name>
+    <message>
+      <source>GEOM_EXTRACT_TITLE</source>
+      <translation type="unfinished">Extract and Rebuild</translation>
+    </message>
+    <message>
+      <source>GEOM_EXTRACT_TYPE</source>
+      <translation type="unfinished">Extraction type</translation>
+    </message>
+    <message>
+      <source>GEOM_EXTRACT_INPUT_PARAMS</source>
+      <translation type="unfinished">Input parameters</translation>
+    </message>
+    <message>
+      <source>GEOM_EXTRACT_STATISTICS</source>
+      <translation type="unfinished">Statistics</translation>
+    </message>
+    <message>
+      <source>GEOM_EXTRACT_SUB_SHAPE_TYPE</source>
+      <translation type="unfinished">Sub-shape type</translation>
+    </message>
+    <message>
+      <source>GEOM_EXTRACT_FILTERED_SHAPES</source>
+      <translation type="unfinished">Filtered shapes</translation>
+    </message>
+    <message>
+      <source>GEOM_EXTRACT_SHAPES_TO_EXTRACT</source>
+      <translation type="unfinished">Shapes to extract</translation>
+    </message>
+    <message>
+      <source>GEOM_EXTRACT_REBUILD</source>
+      <translation type="unfinished">Rebuild</translation>
+    </message>
+    <message>
+      <source>GEOM_EXTRACT_REMOVED</source>
+      <translation type="unfinished">Removed</translation>
+    </message>
+    <message>
+      <source>GEOM_EXTRACT_MODIFIED</source>
+      <translation type="unfinished">Modified</translation>
+    </message>
+    <message>
+      <source>GEOM_EXTRACT_ADDED</source>
+      <translation type="unfinished">Added</translation>
+    </message>
+    <message>
+      <source>GEOM_EXTRACT_NAME</source>
+      <translation type="unfinished">Extraction</translation>
+    </message>
+  </context>
 </TS>
index 0d3f733a6bdea793139f3782842eb58bf3cb7b6f..47aeffbf8d88257676c1a8efb8d9ead0172f3863 100644 (file)
@@ -623,6 +623,7 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam )
   case GEOMOp::OpExtrudedBoss:       // MENU OPERATION - EXTRUDED BOSS
   case GEOMOp::OpExtrudedCut:        // MENU OPERATION - EXTRUDED CUT
   case GEOMOp::OpTransferData:       // MENU OPERATION - TRANSFER DATA
+  case GEOMOp::OpExtraction:         // MENU OPERATION - EXTRACT AND REBUILD
     libName = "OperationGUI";
     break;
   case GEOMOp::OpSewing:             // MENU REPAIR - SEWING
@@ -1005,6 +1006,7 @@ void GeometryGUI::initialize( CAM_Application* app )
   createGeomAction( GEOMOp::OpShapesOnShape,  "GET_SHAPES_ON_SHAPE" );
   createGeomAction( GEOMOp::OpSharedShapes,   "GET_SHARED_SHAPES" );
   createGeomAction( GEOMOp::OpTransferData,   "TRANSFER_DATA" );
+  createGeomAction( GEOMOp::OpExtraction,     "EXTRACTION" );
   createGeomAction( GEOMOp::OpExtrudedCut,    "EXTRUDED_CUT" );
   createGeomAction( GEOMOp::OpExtrudedBoss,   "EXTRUDED_BOSS" );
   createGeomAction( GEOMOp::OpFillet1d,       "FILLET_1D" );
@@ -1262,6 +1264,7 @@ void GeometryGUI::initialize( CAM_Application* app )
   createMenu( GEOMOp::OpShapesOnShape, operId, -1 );
   createMenu( GEOMOp::OpSharedShapes,  operId, -1 );
   createMenu( GEOMOp::OpTransferData,  operId, -1 );
+  createMenu( GEOMOp::OpExtraction,    operId, -1 );
 
   createMenu( separator(), operId, -1 );
 
@@ -1438,6 +1441,7 @@ void GeometryGUI::initialize( CAM_Application* app )
   createTool( GEOMOp::OpShapesOnShape,   operTbId );
   createTool( GEOMOp::OpSharedShapes,    operTbId );
   createTool( GEOMOp::OpTransferData,    operTbId );
+  createTool( GEOMOp::OpExtraction,      operTbId );
 
   int featTbId = createTool( tr( "TOOL_FEATURES" ), QString( "GEOMModification" ) );
   createTool( GEOMOp::OpFillet1d,        featTbId );
index 480b7d2fd366ebfbc47dad62cb8f21043d09529d..a80c3d093f7508f8ed567ad33e116711026c5fb0 100644 (file)
@@ -166,6 +166,7 @@ namespace GEOMOp {
     OpExtrudedBoss        = 3709,   // MENU OPERATION - ETRUDED BOSS
     OpExtrudedCut         = 3710,   // MENU OPERATION - ETRUDED CUT
     OpTransferData        = 3711,   // MENU OPERATION - TRANSFER DATA
+    OpExtraction          = 3712,   // MENU OPERATION - EXTRACT AND REBUILD
     // RepairGUI -------------------//--------------------------------
     OpSewing              = 4000,   // MENU REPAIR - SEWING
     OpSuppressFaces       = 4001,   // MENU REPAIR - SUPPRESS FACES
index 5c59b2e7257e40f61210197bbfebea6c4302cfb3..9bdce7d48c4b6b2f878c117813fefd6558d2e83a 100755 (executable)
@@ -79,6 +79,7 @@ SET(GEOMImpl_HEADERS
   GEOMImpl_ICircle.hxx
   GEOMImpl_ISpline.hxx
   GEOMImpl_IEllipse.hxx
+  GEOMImpl_IExtract.hxx
   GEOMImpl_IFillet.hxx
   GEOMImpl_IFillet1d.hxx
   GEOMImpl_IFillet2d.hxx
diff --git a/src/GEOMImpl/GEOMImpl_IExtract.hxx b/src/GEOMImpl/GEOMImpl_IExtract.hxx
new file mode 100644 (file)
index 0000000..35a2799
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//NOTE: This is an intreface to a function for the Offset creation.
+//
+#include "GEOM_Function.hxx"
+#include <TColStd_HArray1OfInteger.hxx>
+
+#define EXTRACT_SHAPE         1
+#define EXTRACT_IDS           2
+#define EXTRACT_REMOVED_IDS   3
+#define EXTRACT_MODIFIED_IDS  4
+#define EXTRACT_ADDED_IDS     5
+
+class GEOMImpl_IExtract
+{
+ public:
+
+  GEOMImpl_IExtract(Handle(GEOM_Function) theFunction): _func(theFunction) {}
+
+  void SetShape(Handle(GEOM_Function) theShape)
+    { _func->SetReference(EXTRACT_SHAPE, theShape); }
+
+  Handle(GEOM_Function) GetShape()
+    { return _func->GetReference(EXTRACT_SHAPE); }
+
+  void SetSubShapeIDs(const Handle(TColStd_HArray1OfInteger)& theSubShapeIDs)
+    { _func->SetIntegerArray(EXTRACT_IDS, theSubShapeIDs); }
+
+  Handle(TColStd_HArray1OfInteger) GetSubShapeIDs()
+    { return _func->GetIntegerArray(EXTRACT_IDS); }
+
+  void SetRemovedIDs(const Handle(TColStd_HArray1OfInteger)& theRemovedIDs)
+    { _func->SetIntegerArray(EXTRACT_REMOVED_IDS, theRemovedIDs); }
+
+  Handle(TColStd_HArray1OfInteger) GetRemovedIDs()
+    { return _func->GetIntegerArray(EXTRACT_REMOVED_IDS); }
+
+  void SetModifiedIDs(const Handle(TColStd_HArray1OfInteger)& theModifiedIDs)
+    { _func->SetIntegerArray(EXTRACT_MODIFIED_IDS, theModifiedIDs); }
+
+  Handle(TColStd_HArray1OfInteger) GetModifiedIDs()
+    { return _func->GetIntegerArray(EXTRACT_MODIFIED_IDS); }
+
+  void SetAddedIDs(const Handle(TColStd_HArray1OfInteger)& theAddedIDs)
+    { _func->SetIntegerArray(EXTRACT_ADDED_IDS, theAddedIDs); }
+
+  Handle(TColStd_HArray1OfInteger) GetAddedIDs()
+    { return _func->GetIntegerArray(EXTRACT_ADDED_IDS); }
+
+ private:
+
+  Handle(GEOM_Function) _func;
+};
index 65716670c9e393839fade61a8d9ac9b74a4c3655..c02c13f4d9aa161988aa3d65842f588ec1c79ff8 100644 (file)
@@ -36,6 +36,7 @@
 #include "GEOMImpl_GlueDriver.hxx"
 #include "GEOMImpl_FillingDriver.hxx"
 
+#include "GEOMImpl_IExtract.hxx"
 #include "GEOMImpl_IVector.hxx"
 #include "GEOMImpl_IShapes.hxx"
 #include "GEOMImpl_IShapeExtend.hxx"
@@ -3163,6 +3164,107 @@ Handle(TColStd_HSequenceOfTransient)
   return aSeq;
 }
 
+//=============================================================================
+/*!
+ *  MakeExtraction
+ */
+//=============================================================================
+Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeExtraction
+                     (const Handle(GEOM_Object)              &theShape,
+                      const Handle(TColStd_HArray1OfInteger) &theSubShapeIDs,
+                      std::list<ExtractionStat>              &theStats)
+{
+  SetErrorCode(KO);
+
+  if (theShape.IsNull()) {
+    return NULL;
+  }
+
+  //Add a new Result object
+  Handle(GEOM_Object) aResult =
+              GetEngine()->AddObject(GetDocID(), GEOM_EXTRACTION);
+
+  //Add a new Extraction function
+  Handle(GEOM_Function) aFunction =
+    aResult->AddFunction(GEOMImpl_ShapeDriver::GetID(), EXTRACTION);
+
+  //Check if the function is set correctly
+  if (aFunction->GetDriverGUID() != GEOMImpl_ShapeDriver::GetID()) {
+    return NULL;
+  }
+
+  Handle(GEOM_Function) aShape = theShape->GetLastFunction();
+
+  if (aShape.IsNull()) {
+    return NULL;
+  }
+
+  GEOMImpl_IExtract aCI (aFunction);
+
+  aCI.SetShape(aShape);
+  aCI.SetSubShapeIDs(theSubShapeIDs);
+
+  //Compute the Edge value
+  try {
+    OCC_CATCH_SIGNALS;
+    if (!GetSolver()->ComputeFunction(aFunction)) {
+      SetErrorCode("Shape driver failed");
+
+      return NULL;
+    }
+  }
+  catch (Standard_Failure) {
+    Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+    SetErrorCode(aFail->GetMessageString());
+
+    return NULL;
+  }
+
+  // Fill in statistics.
+  theStats.clear();
+
+  Handle(TColStd_HArray1OfInteger) aStatIDsArray[3] = 
+    { aCI.GetRemovedIDs(), aCI.GetModifiedIDs(), aCI.GetAddedIDs() };
+  int                              i;
+  int                              j;
+
+  for (j = 0; j < 3; ++j) {
+    if (!aStatIDsArray[j].IsNull()) {
+      const int      anUpperID = aStatIDsArray[j]->Upper();
+      ExtractionStat aStat;
+
+      for (i = aStatIDsArray[j]->Lower(); i <= anUpperID; ++i) {
+        aStat.indices.push_back(aStatIDsArray[j]->Value(i));
+      }
+
+      aStat.type = (ExtractionStatType) j;
+      theStats.push_back(aStat);
+    }
+  }
+
+  //Make a Python command
+  GEOM::TPythonDump pd(aFunction);
+
+  pd << aResult  << " = geompy.MakeExtraction(" << theShape << ", [";
+
+  if (!theSubShapeIDs.IsNull()) {
+    const int aNbIDs = theSubShapeIDs->Upper();
+
+    for (i = theSubShapeIDs->Lower(); i < aNbIDs; ++i) {
+      pd << theSubShapeIDs->Value(i) << ", ";
+    }
+
+    // Dump the last value without a comma.
+    pd << theSubShapeIDs->Value(i);
+  }
+
+  pd << "])";
+
+  SetErrorCode(OK);
+
+  return aResult;
+}
+
 //=======================================================================
 //function : getShapesOnSurfaceIDs
   /*!
index d8e4f9fb21606071fd9146a6282c088ddf210850..38b3750594980dde91772029809faad269ed9ba9 100644 (file)
@@ -59,6 +59,25 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations
     All       = Groups | Fields | SubShapes,
   };
 
+  /**
+   * This enumeration represents an extraction statistics type.
+   */
+  enum ExtractionStatType
+  {
+    EST_Removed,  ///< Removed sub-shapes
+    EST_Modified, ///< Modified sub-shapes
+    EST_Added     ///< Newly created sub-shapes
+  };
+
+  /*!
+   * This structure defines a format of extraction statistics.
+   */
+  struct ExtractionStat
+  {
+    ExtractionStatType          type;    ///< Type of extraction statistics.
+    std::list<Standard_Integer> indices; ///< Shape indices touched by this type of modification.
+  };
+
   Standard_EXPORT GEOMImpl_IShapesOperations(GEOM_Engine* theEngine, int theDocID);
   Standard_EXPORT ~GEOMImpl_IShapesOperations();
 
@@ -470,6 +489,21 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations
                       const GEOMUtils::ComparisonCondition  theCondition,
                       const Standard_Real                   theTolerance);
 
+  /*!
+   * \brief Return the shape that is constructed from theShape without
+   * extracted sub-shapes from the input list.
+   *
+   * \param theShape the original shape.
+   * \param theSubShapeIDs the list of sub-shape IDs to be extracted from
+   *        the original shape.
+   * \param theStats the operation statistics. Output parameter.
+   * \return the shape without extracted sub-shapes.
+   */
+  Handle(GEOM_Object) MakeExtraction
+                     (const Handle(GEOM_Object)              &theShape,
+                      const Handle(TColStd_HArray1OfInteger) &theSubShapeIDs,
+                      std::list<ExtractionStat>              &theStats);
+
  private:
   Handle(GEOM_Object) MakeShape (std::list<Handle(GEOM_Object)>      theShapes,
                                  const Standard_Integer         theObjectType,
index 46bcd193eb05c6f17811afd69e9513c49eccac6d..471fd679bd74ab4c90939498cbe0348670f611b8 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <GEOMImpl_ShapeDriver.hxx>
 
+#include <GEOMImpl_IExtract.hxx>
 #include <GEOMImpl_IIsoline.hxx>
 #include <GEOMImpl_IShapes.hxx>
 #include <GEOMImpl_IShapeExtend.hxx>
@@ -32,6 +33,7 @@
 #include <GEOM_Function.hxx>
 #include <GEOMUtils_Hatcher.hxx>
 #include <GEOMAlgo_State.hxx>
+#include <GEOMAlgo_Extractor.hxx>
 
 // OCCT Includes
 #include <ShapeFix_Wire.hxx>
 
 #include <list>
 
+/**
+ * \brief This static function converts the list of shapes into an array
+ *  of their IDs. If the input list is empty, null handle will be returned.
+ *  this method doesn't check if a shape presents in theIndices map.
+ *
+ * \param theListOfShapes the list of shapes.
+ * \param theIndices the indexed map of shapes.
+ * \return the array of shape IDs.
+ */
+static Handle(TColStd_HArray1OfInteger) GetShapeIDs
+                  (const TopTools_ListOfShape       &theListOfShapes,
+                   const TopTools_IndexedMapOfShape &theIndices)
+{
+  Handle(TColStd_HArray1OfInteger) aResult;
+
+  if (!theListOfShapes.IsEmpty()) {
+    const Standard_Integer             aNbShapes = theListOfShapes.Extent();
+    TopTools_ListIteratorOfListOfShape anIter(theListOfShapes);
+    Standard_Integer                   i;
+
+    aResult = new TColStd_HArray1OfInteger(1, aNbShapes);
+
+    for (i = 1; anIter.More(); anIter.Next(), ++i) {
+      const TopoDS_Shape     &aShape  = anIter.Value();
+      const Standard_Integer  anIndex = theIndices.FindIndex(aShape);
+
+      aResult->SetValue(i, anIndex);
+    }
+  }
+
+  return aResult;
+}
+
 namespace
 {
   // check that compound includes only shapes of expected type
@@ -918,6 +953,97 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const
         }
       }
     }
+  } else if (aType == EXTRACTION) {
+    allowCompound = true;
+
+    GEOMImpl_IExtract     aCI(aFunction);
+    Handle(GEOM_Function) aRefShape  = aCI.GetShape();
+    TopoDS_Shape          aShapeBase = aRefShape->GetValue();
+
+    if (aShapeBase.IsNull()) {
+      Standard_NullObject::Raise("Argument Shape is null");
+      return 0;
+    }
+
+    Handle(TColStd_HArray1OfInteger) anIDs = aCI.GetSubShapeIDs();
+    TopTools_ListOfShape             aListSubShapes;
+    TopTools_IndexedMapOfShape       anIndices;
+    int                              i;
+
+    TopExp::MapShapes(aShapeBase, anIndices);
+
+    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);
+
+        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);
+      }
+    }
+
+    // Compute extraction.
+    GEOMAlgo_Extractor anExtractor;
+
+    anExtractor.SetShape(aShapeBase);
+    anExtractor.SetShapesToRemove(aListSubShapes);
+
+    anExtractor.Perform();
+
+    // Interprete results
+    Standard_Integer iErr = anExtractor.ErrorStatus();
+
+    // The detailed description of error codes is in GEOMAlgo_Extractor.cxx
+    if (iErr) {
+      TCollection_AsciiString aMsg(" iErr : ");
+
+      aMsg += TCollection_AsciiString(iErr);
+      StdFail_NotDone::Raise(aMsg.ToCString());
+      return 0;
+    }
+
+    aShape = anExtractor.GetResult();
+
+    // Get statistics.
+    const TopTools_ListOfShape       &aRemoved    = anExtractor.GetRemoved();
+    const TopTools_ListOfShape       &aModified   = anExtractor.GetModified();
+    const TopTools_ListOfShape       &aNew        = anExtractor.GetNew();
+    Handle(TColStd_HArray1OfInteger) aRemovedIDs  =
+                          GetShapeIDs(aRemoved, anIndices);
+    Handle(TColStd_HArray1OfInteger) aModifiedIDs =
+                          GetShapeIDs(aModified, anIndices);
+    Handle(TColStd_HArray1OfInteger) aNewIDs;
+
+    if (!aShape.IsNull()) {
+      // Get newly created sub-shapes
+      TopTools_IndexedMapOfShape aNewIndices;
+
+      TopExp::MapShapes(aShape, aNewIndices);
+      aNewIDs = GetShapeIDs(aNew, aNewIndices);
+    }
+
+    if (!aRemovedIDs.IsNull()) {
+      aCI.SetRemovedIDs(aRemovedIDs);
+    }
+
+    if (!aModifiedIDs.IsNull()) {
+      aCI.SetModifiedIDs(aModifiedIDs);
+    }
+
+    if (!aNewIDs.IsNull()) {
+      aCI.SetAddedIDs(aNewIDs);
+    }
   }
   else {
   }
@@ -1880,6 +2006,15 @@ GetCreationInformation(std::string&             theOperationName,
     AddParam(theParams, "Face", aSE.GetShape());
     break;
   }
+  case EXTRACTION:
+  {
+    GEOMImpl_IExtract aCI (function);
+
+    theOperationName = "EXTRACTION";
+    AddParam(theParams, "Main Shape", aCI.GetShape());
+    AddParam(theParams, "Sub-shape IDs", aCI.GetSubShapeIDs());
+    break;
+  }
   default:
     return false;
   }
index 393b4303c76d34b7eb1aa70f57244f68571b216c..2e58443acb57d616604de6dedc946d3d9a28debc 100644 (file)
 
 #define GEOM_TRANSFER_DATA 57
 
+#define GEOM_EXTRACTION 58
+
 //GEOM_Function types
 
 #define COPY_WITH_REF    1
 #define FACE_UV             17
 #define SURFACE_FROM_FACE   18
 #define SOLID_FACES         19
+#define EXTRACTION          20
 
 #define ARCHIMEDE_TYPE 1
 
index 7561d9a168461e0fe90191c2214a5d216ddc28d9..c6c30b2285da4df041ebe563849f2a38b14b5d95 100644 (file)
@@ -2230,3 +2230,98 @@ GEOM::ListOfGO* GEOM_IShapesOperations_i::GetSubShapesWithTolerance
 
   return aSeq._retn();
 }
+
+//=============================================================================
+/*!
+ *  MakeExtraction
+ */
+//=============================================================================
+GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeExtraction
+         (GEOM::GEOM_Object_ptr                              theShape,
+          const GEOM::ListOfLong                            &theSubShapeIDs,
+          GEOM::GEOM_IShapesOperations::ExtractionStats_out  theStats)
+{
+  GEOM::GEOM_Object_var aGEOMObject;
+
+  //Set a not done flag
+  theStats = new GEOM::GEOM_IShapesOperations::ExtractionStats;
+  GetOperations()->SetNotDone();
+
+  //Get the reference object
+  Handle(GEOM_Object) aShape = GetObjectImpl(theShape);
+
+  if (aShape.IsNull()) {
+    return aGEOMObject._retn();
+  }
+
+  const int aNbIDs = theSubShapeIDs.length();
+
+  if (aNbIDs == 0) {
+    return aGEOMObject._retn();
+  }
+
+  int                              i;
+  Handle(TColStd_HArray1OfInteger) anArray =
+    new TColStd_HArray1OfInteger (1, aNbIDs);
+
+  for (i = 0; i < aNbIDs; i++) {
+    anArray->SetValue(i + 1, theSubShapeIDs[i]);
+  }
+
+  //Get Shapes in place of aShapeWhat
+  std::list<GEOMImpl_IShapesOperations::ExtractionStat> aStats;
+  Handle(GEOM_Object)                                   aResult =
+          GetOperations()->MakeExtraction(aShape, anArray, aStats);
+
+  if (!GetOperations()->IsDone() || aResult.IsNull()) {
+    return aGEOMObject._retn();
+  }
+
+  // Convert statistics.
+  const int aNbStats = aStats.size();
+
+  theStats->length(aNbStats);
+
+  // fill the local CORBA array with values from lists
+  std::list<GEOMImpl_IShapesOperations::ExtractionStat>::const_iterator
+    anIt = aStats.begin();
+
+  for (i = 0; anIt != aStats.end(); i++, anIt++) {
+    GEOM::GEOM_IShapesOperations::ExtractionStat_var aResStat =
+      new GEOM::GEOM_IShapesOperations::ExtractionStat;
+
+    // Copy type
+    switch (anIt->type) {
+    case GEOMImpl_IShapesOperations::EST_Removed:
+      aResStat->type = GEOM::GEOM_IShapesOperations::EST_Removed;
+      break;
+    case GEOMImpl_IShapesOperations::EST_Modified:
+      aResStat->type = GEOM::GEOM_IShapesOperations::EST_Modified;
+      break;
+    case GEOMImpl_IShapesOperations::EST_Added:
+      aResStat->type = GEOM::GEOM_IShapesOperations::EST_Added;
+      break;
+    default:
+      break;
+    }
+
+    // Copy the list of IDs
+    std::list<Standard_Integer> aIDList    = anIt->indices;
+    GEOM::ListOfLong_var        aResIDList = new GEOM::ListOfLong;
+
+    aResIDList->length(aIDList.size());
+
+    std::list<Standard_Integer>::iterator anIDIt = aIDList.begin();
+    int j = 0;
+
+    for (; anIDIt != aIDList.end(); j++, anIDIt++) {
+      aResIDList[j] = *anIDIt;
+    }
+
+    aResStat->indices = aResIDList;
+
+    theStats[i] = aResStat;
+  }
+
+  return GetObject(aResult);
+}
index 0f36a38c3934aea05221cb243be714a0b59c1fd2..ff9e417f00c0582750f675fd19dcbacdd6c1360e 100644 (file)
@@ -306,6 +306,11 @@ class GEOM_I_EXPORT GEOM_IShapesOperations_i :
                       GEOM::comparison_condition theCondition,
                       CORBA::Double              theTolerance);
 
+  GEOM::GEOM_Object_ptr MakeExtraction
+         (GEOM::GEOM_Object_ptr                              theShape,
+          const GEOM::ListOfLong                            &theSubShapeIDs,
+          GEOM::GEOM_IShapesOperations::ExtractionStats_out  theStats);
+
   ::GEOMImpl_IShapesOperations* GetOperations()
   { return (::GEOMImpl_IShapesOperations*)GetImpl(); }
 };
index ea862293f2ab957bf8dfbef186691895e3e96ed7..a500a67d4e257bf86613af38932bf916c87aff9c 100644 (file)
@@ -590,5 +590,10 @@ def TestAll (geompy, math):
   geompy.GetSubShapesWithTolerance(Box, GEOM.FACE, GEOM.CC_LT, 2.e-7, "lt")
   geompy.GetSubShapesWithTolerance(Box, GEOM.FACE, GEOM.CC_LE, 1.e-7, "le")
 
+  # MakeExtraction
+  geompy.MakeExtraction(Box, [13], "Ext_no_face")
+  geompy.MakeExtraction(Box, [18], "Ext_no_edge")
+  geompy.MakeExtraction(Box, [16], "Ext_no_vertex")
+
 
   print "DONE"
index 379105b72a48a6dcf43e508f4921e63a3a4b22dc..5b74cabdd7309f315ff810cb4c7410d3b6960bf4 100644 (file)
@@ -6661,6 +6661,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 swig_MakeExtraction "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 2ff65aed2194b684f3392abbd47e9a2425513238..7f949c31c394fff759fede98d46e6b17bafae541 100755 (executable)
@@ -73,6 +73,7 @@ SET(OperationGUI_HEADERS
   OperationGUI_ChamferDlg.h
   OperationGUI_GetShapesOnShapeDlg.h
   OperationGUI_GetSharedShapesDlg.h
+  OperationGUI_ExtractionDlg.h
   OperationGUI_ExtrudedFeatureDlg.h
   OperationGUI_ClippingDlg.h
   OperationGUI_TransferDataDlg.h
@@ -87,6 +88,7 @@ SET(_moc_HEADERS
   OperationGUI_ChamferDlg.h
   OperationGUI_GetShapesOnShapeDlg.h
   OperationGUI_GetSharedShapesDlg.h
+  OperationGUI_ExtractionDlg.h
   OperationGUI_ExtrudedFeatureDlg.h
   OperationGUI_ClippingDlg.h
   OperationGUI_TransferDataDlg.h
@@ -109,6 +111,7 @@ SET(OperationGUI_SOURCES
   OperationGUI_FilletDlg.cxx
   OperationGUI_Fillet1d2dDlg.cxx
   OperationGUI_ChamferDlg.cxx
+  OperationGUI_ExtractionDlg.cxx
   OperationGUI_ExtrudedFeatureDlg.cxx
   OperationGUI_ClippingDlg.cxx
   OperationGUI_TransferDataDlg.cxx
index 3288921ab0614df4ad1bad908021825c36de5197..96e5fc57a617dffb237887c9db28bbc3f1bf2082 100644 (file)
@@ -40,6 +40,7 @@
 #include "OperationGUI_GetSharedShapesDlg.h"
 #include "OperationGUI_ExtrudedFeatureDlg.h" // Methods EXTRUDED BOSS / CUT
 #include "OperationGUI_TransferDataDlg.h"
+#include "OperationGUI_ExtractionDlg.h"
 
 //=======================================================================
 // function : OperationGUI()
@@ -83,6 +84,7 @@ bool OperationGUI::OnGUIEvent (int theCommandID, SUIT_Desktop* parent)
   case GEOMOp::OpFillet1d:      (new OperationGUI_Fillet1d2dDlg      (getGeometryGUI(), parent, true))->show(); break;
   case GEOMOp::OpFillet2d:      (new OperationGUI_Fillet1d2dDlg      (getGeometryGUI(), parent, false))->show(); break;
   case GEOMOp::OpTransferData:  (new OperationGUI_TransferDataDlg    (getGeometryGUI(), parent))->show(); break;
+  case GEOMOp::OpExtraction:    (new OperationGUI_ExtractionDlg      (getGeometryGUI(), parent))->show(); break;
   default:
     app->putInfo(tr("GEOM_PRP_COMMAND").arg(theCommandID));
   }
diff --git a/src/OperationGUI/OperationGUI_ExtractionDlg.cxx b/src/OperationGUI/OperationGUI_ExtractionDlg.cxx
new file mode 100644 (file)
index 0000000..47f2e72
--- /dev/null
@@ -0,0 +1,1324 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "OperationGUI_ExtractionDlg.h"
+
+#include <GEOMBase.h>
+#include <GeometryGUI.h>
+
+#include <LightApp_SelectionMgr.h>
+#include <SalomeApp_Application.h>
+#include <SalomeApp_Tools.h>
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
+
+#include <TColStd_MapIteratorOfMapOfInteger.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Iterator.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
+
+#include <QComboBox>
+#include <QGridLayout>
+#include <QGroupBox>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QListWidget>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QTreeWidget>
+#include <QVBoxLayout>
+#include <QtGlobal>
+
+#if QT_VERSION >= 0x050300
+  #include <QSignalBlocker>
+#else
+  /**
+   * This class is named as QT class as it is introduced since Qt 5.3.
+   * It should not be compiled when Salome is ported on Qt 5.3.
+   */
+  class QSignalBlocker
+  {
+  public:
+    QSignalBlocker(QObject *object)
+      : myObject    (object),
+        myIsBlocked (object && object->signalsBlocked()) {
+      if (myObject) {
+        myObject->blockSignals(true);
+      }
+    }
+
+    ~QSignalBlocker() {
+      if (myObject) {
+        myObject->blockSignals(myIsBlocked);
+      }
+    }
+
+  private:
+    QObject *myObject;    ///< Blocked object.
+    bool     myIsBlocked; ///< Initial blocked state.
+  };
+#endif
+
+
+#define ID_ROLE   Qt::DisplayRole
+#define TYPE_ROLE Qt::UserRole
+
+static const char* const TMP_STR = "TEMP";
+
+static const char* const SINGLE_SHAPE_TYPE_TR_CODES [] = {
+  "GEOM_COMPOUND",
+  "GEOM_COMPOUNDSOLID",
+  "GEOM_SOLID",
+  "GEOM_SHELL",
+  "GEOM_FACE",
+  "GEOM_WIRE",
+  "GEOM_EDGE",
+  "GEOM_VERTEX"
+};
+
+static const char* const PLURAL_SHAPE_TYPE_TR_CODES [] = {
+  "GEOM_COMPOUND",   // Not used
+  "GEOM_COMPSOLIDS",
+  "GEOM_SOLIDS",
+  "GEOM_SHELLS",
+  "GEOM_FACES",
+  "GEOM_WIREZ",
+  "GEOM_EDGES",
+  "GEOM_VERTEXES"
+};
+
+
+/**
+ * This static function creates a new list widget item with given ID and
+ * returns it.
+ *
+ * \param theID the item ID.
+ * \param theListWidget the list widget.
+ * \return the created list widget item.
+ */
+static QListWidgetItem *addNewItem(const int    theID,
+                                   QListWidget *theListWidget)
+{
+  QListWidgetItem *aResult = new QListWidgetItem;
+
+  aResult->setData(ID_ROLE, theID);
+  theListWidget->addItem(aResult);
+
+  return aResult;
+}
+
+/**
+ * This static function creates a new tree widget item as a child of the input
+ * one with given ID and returns it.
+ *
+ * \param theID the item ID.
+ * \param theParentItem the parent item.
+ * \return the created tree widget item.
+ */
+static QTreeWidgetItem *addChildItem(const int        theID,
+                                     QTreeWidgetItem *theParentItem)
+{
+  QTreeWidgetItem *aResult = new QTreeWidgetItem;
+
+  aResult->setData(0, ID_ROLE, theID);
+  theParentItem->addChild(aResult);
+
+  return aResult;
+}
+
+/**
+ * This static function returns the maximal shape type of sub-shapes stored in
+ * the input compound. If it is not a compound, it returns TopAbs_SHAPE.
+ *
+ * \param theCompound the compound.
+ * \return the maximal shape type of sub-shapes stored in the input compound.
+ */
+static TopAbs_ShapeEnum GetMaxShapeTypeInComp(const TopoDS_Shape &theCompound)
+{
+  TopAbs_ShapeEnum aResult = TopAbs_SHAPE;
+
+  if (theCompound.IsNull() || theCompound.ShapeType() != TopAbs_COMPOUND) {
+    return aResult;
+  }
+
+  TopoDS_Iterator anIt(theCompound, Standard_False, Standard_False);
+
+  for (; anIt.More(); anIt.Next()) {
+    const TopoDS_Shape &aSubShape = anIt.Value();
+
+    if (aSubShape.IsNull()) {
+      continue;
+    }
+
+    // Get the sub-shape type.
+    TopAbs_ShapeEnum aSubType = aSubShape.ShapeType();
+
+    if (aSubType == TopAbs_COMPOUND) {
+      aSubType = GetMaxShapeTypeInComp(aSubShape);
+    }
+
+    if (aSubType == TopAbs_SHAPE) {
+      continue;
+    }
+
+    if (aResult == TopAbs_SHAPE) {
+      // This is an initialization.
+      aResult = aSubType;
+    } else if (aResult > aSubType) {
+      aResult = aSubType;
+    }
+  }
+
+  return aResult;
+}
+
+//=================================================================================
+// class    : OperationGUI_ExtractionDlg()
+// purpose  : 
+//=================================================================================
+OperationGUI_ExtractionDlg::OperationGUI_ExtractionDlg
+                        (GeometryGUI* GUI, QWidget* parent)
+  : GEOMBase_Skeleton (GUI, parent, false),
+    mySelBtn          (0),
+    myMainShapeEdit   (0),
+    mySubShTypeCompo  (0),
+    myFilteredList    (0),
+    myExtractedTree   (0),
+    myRemovedList     (0),
+    myModifiedList    (0),
+    myAddedList       (0),
+    myRebuildBtn      (0),
+    myIsHiddenMain    (false)
+{
+  QPixmap image0(SUIT_Session::session()->resourceMgr()->loadPixmap(
+    "GEOM", tr("ICON_DLG_EXTRACTION")));
+  QPixmap image1(SUIT_Session::session()->resourceMgr()->loadPixmap(
+    "GEOM", tr("ICON_SELECT")));
+
+  setWindowTitle(tr("GEOM_EXTRACT_TITLE"));
+
+  /***************************************************************/
+
+  mainFrame()->GroupConstructors->setTitle(tr("GEOM_EXTRACT_TYPE"));
+  mainFrame()->RadioButton1->setIcon( image0 );
+  mainFrame()->RadioButton2->setAttribute(Qt::WA_DeleteOnClose);
+  mainFrame()->RadioButton2->close();
+  mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose);
+  mainFrame()->RadioButton3->close();
+
+  // Create an input group.
+  QGroupBox   *anInputGrp      = new QGroupBox(tr("GEOM_EXTRACT_INPUT_PARAMS"), centralWidget());
+  QGridLayout *anInputLayout   = new QGridLayout(anInputGrp);
+  QHBoxLayout *aShapeLayout    = new QHBoxLayout(anInputGrp);
+  QVBoxLayout *aViewBtnsLayout = new QVBoxLayout(anInputGrp);
+  QVBoxLayout *aMoveBtnsLayout = new QVBoxLayout(anInputGrp);
+  QLabel      *aMainObjLbl     = new QLabel(tr("GEOM_MAIN_OBJECT"), anInputGrp);
+  QLabel      *aSubShTypeLbl   = new QLabel(tr("GEOM_EXTRACT_SUB_SHAPE_TYPE"), anInputGrp);
+  QLabel      *aFilteredLbl    = new QLabel(tr("GEOM_EXTRACT_FILTERED_SHAPES"), anInputGrp);
+  QLabel      *anExtractedLbl  = new QLabel(tr("GEOM_EXTRACT_SHAPES_TO_EXTRACT"), anInputGrp);
+  QPushButton *aShowOnlySelBtn = new QPushButton(tr("SHOW_ONLY_SELECTED"), anInputGrp);
+  QPushButton *aHideSelBtn     = new QPushButton(tr("HIDE_SELECTED"), anInputGrp);
+  QPushButton *aShowAllBtn     = new QPushButton(tr("SHOW_ALL_SUB_SHAPES"), anInputGrp);
+  QPushButton *anAddBtn        = new QPushButton(">>", anInputGrp);
+  QPushButton *aRemoveBtn      = new QPushButton("<<", anInputGrp);
+
+  myRebuildBtn     = new QPushButton(tr("GEOM_EXTRACT_REBUILD"), anInputGrp);
+  mySelBtn         = new QPushButton(anInputGrp);
+  myMainShapeEdit  = new QLineEdit(anInputGrp);
+  mySubShTypeCompo = new QComboBox(anInputGrp);
+  myFilteredList   = new QListWidget(anInputGrp);
+  myExtractedTree  = new QTreeWidget(anInputGrp);
+  mySelBtn->setIcon(image1);
+  myMainShapeEdit->setReadOnly(true);
+
+  aShapeLayout->addWidget(mySelBtn);
+  aShapeLayout->addWidget(myMainShapeEdit);
+
+  aViewBtnsLayout->addStretch();
+  aViewBtnsLayout->addWidget(aShowOnlySelBtn);
+  aViewBtnsLayout->addWidget(aHideSelBtn);
+  aViewBtnsLayout->addWidget(aShowAllBtn);
+  aViewBtnsLayout->addStretch();
+
+  aMoveBtnsLayout->addStretch();
+  aMoveBtnsLayout->addWidget(anAddBtn);
+  aMoveBtnsLayout->addWidget(aRemoveBtn);
+  aMoveBtnsLayout->addStretch();
+
+  anInputLayout->setSpacing(6);
+  anInputLayout->setContentsMargins(9, 9, 9, 9);
+  anInputLayout->addWidget(aMainObjLbl,      0, 0);
+  anInputLayout->addLayout(aShapeLayout,     0, 1, 1, 3);
+  anInputLayout->addWidget(aSubShTypeLbl,    1, 0);
+  anInputLayout->addWidget(mySubShTypeCompo, 1, 1, 1, 3);
+  anInputLayout->addWidget(aFilteredLbl,     2, 1);
+  anInputLayout->addWidget(anExtractedLbl,   2, 3);
+  anInputLayout->addLayout(aViewBtnsLayout,  3, 0);
+  anInputLayout->addWidget(myFilteredList,   3, 1);
+  anInputLayout->addLayout(aMoveBtnsLayout,  3, 2);
+  anInputLayout->addWidget(myExtractedTree,  3, 3);
+  anInputLayout->addWidget(myRebuildBtn,     4, 0, 1, 4);
+
+  // Create a statistics group.
+  QGroupBox   *aStatGrp     = new QGroupBox(tr("GEOM_EXTRACT_STATISTICS"), centralWidget());
+  QGridLayout *aStatLayout  = new QGridLayout(aStatGrp);
+  QLabel      *aRemovedLbl  = new QLabel(tr("GEOM_EXTRACT_REMOVED"), aStatGrp);
+  QLabel      *aModifiedLbl = new QLabel(tr("GEOM_EXTRACT_MODIFIED"), aStatGrp);
+  QLabel      *anAddedLbl   = new QLabel(tr("GEOM_EXTRACT_ADDED"), aStatGrp);
+
+  myRemovedList  = new QListWidget(aStatGrp);
+  myModifiedList = new QListWidget(aStatGrp);
+  myAddedList    = new QListWidget(aStatGrp);
+
+  aStatLayout->setSpacing(6);
+  aStatLayout->setContentsMargins(9, 9, 9, 9);
+  aStatLayout->addWidget(aRemovedLbl,    0, 0);
+  aStatLayout->addWidget(aModifiedLbl,   0, 1);
+  aStatLayout->addWidget(anAddedLbl,     0, 2);
+  aStatLayout->addWidget(myRemovedList,  1, 0);
+  aStatLayout->addWidget(myModifiedList, 1, 1);
+  aStatLayout->addWidget(myAddedList,    1, 2);
+
+  // Create a main layout.
+  QVBoxLayout* aLayout = new QVBoxLayout(centralWidget());
+
+  aLayout->setMargin(0);
+  aLayout->setSpacing(6);
+  aLayout->addWidget(anInputGrp);
+  aLayout->addWidget(aStatGrp);
+
+  // signals and slots connections
+  connect(anAddBtn,        SIGNAL(clicked()), this, SLOT(onAddExtracted()));
+  connect(aRemoveBtn,      SIGNAL(clicked()), this, SLOT(onRemoveExtracted()));
+  connect(aShowOnlySelBtn, SIGNAL(clicked()), this, SLOT(showOnlySelected()));
+  connect(aHideSelBtn,     SIGNAL(clicked()), this, SLOT(hideSelected()));
+  connect(aShowAllBtn,     SIGNAL(clicked()), this, SLOT(showAllSelected()));
+
+  /***************************************************************/
+  myHelpFileName = "extract_and_rebuild_page.html";
+
+  resize(525, 600);
+
+  /* Initialisation */
+  Init();
+}
+
+//=================================================================================
+// function : ~OperationGUI_ExtractionDlg()
+// purpose  : Destroys the object and frees any allocated resources
+//=================================================================================
+OperationGUI_ExtractionDlg::~OperationGUI_ExtractionDlg()
+{
+  restoreViewer();
+}
+
+//=================================================================================
+// function : Init()
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::Init()
+{
+  mySelBtn->setCheckable(true);
+  mySelBtn->setChecked(true);
+  myFilteredList->setSelectionMode(QAbstractItemView::ExtendedSelection);
+  myFilteredList->setSortingEnabled(true);
+  myExtractedTree->setHeaderHidden(true);
+  myExtractedTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
+  myExtractedTree->setColumnCount(1);
+  myRebuildBtn->setEnabled(false);
+  myRemovedList->setSelectionMode(QAbstractItemView::NoSelection);
+  myModifiedList->setSelectionMode(QAbstractItemView::NoSelection);
+  myAddedList->setSelectionMode(QAbstractItemView::NoSelection);
+
+  // Fill in the extracted tree with initial elements.
+  myTopItems[0] = 0; // No need to create a item for compound.
+
+  int i;
+
+  for (i = 1; i < 8; i++) {
+    myTopItems[i] = new QTreeWidgetItem;
+    myTopItems[i]->setText(0, tr(PLURAL_SHAPE_TYPE_TR_CODES[i]));
+    myTopItems[i]->setData(0, TYPE_ROLE, i);
+  
+    myExtractedTree->addTopLevelItem(myTopItems[i]);
+    myTopItems[i]->setHidden(true);
+  }
+
+  // signals and slots connections
+  connect(mySelBtn,         SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
+  connect(buttonOk(),       SIGNAL(clicked()), this, SLOT(ClickOnOk()));
+  connect(buttonApply(),    SIGNAL(clicked()), this, SLOT(ClickOnApply()));
+  connect(mySubShTypeCompo, SIGNAL(currentIndexChanged(int)),
+          this,             SLOT(onShapeTypeChanged()));
+  connect(myRebuildBtn,     SIGNAL(clicked()), this, SLOT(onRebuild()));
+  connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
+          this, SLOT(SelectionIntoArgument()));
+  connect(myFilteredList,   SIGNAL(itemSelectionChanged()),
+          this,             SLOT(onListSelectionChanged()));
+  connect(myExtractedTree,  SIGNAL(itemSelectionChanged()),
+          this,             SLOT(onListSelectionChanged()));
+
+  initName(tr("GEOM_EXTRACT_NAME"));
+
+  activateSelection();
+  SelectionIntoArgument();
+}
+
+//=================================================================================
+// function : updateSubShTypeCompo()
+// purpose  :
+//=================================================================================
+bool OperationGUI_ExtractionDlg::updateSubShTypeCompo()
+{
+  bool         isValid  = true;
+  int          anIStart = TopAbs_COMPOUND;
+  const int    anIEnd   = TopAbs_VERTEX;
+  TopoDS_Shape aShape;
+
+  if (GEOMBase::GetShape(myObj, aShape)) {
+    const TopAbs_ShapeEnum aType = aShape.ShapeType();
+
+    if (aType == TopAbs_COMPOUND) {
+      anIStart = GetMaxShapeTypeInComp(aShape);
+      isValid  = anIStart != TopAbs_SHAPE;
+    } else {
+      anIStart = aType + 1;
+    }
+  }
+
+  QSignalBlocker aBlocker(mySubShTypeCompo);
+  mySubShTypeCompo->clear();
+
+  if (isValid) {
+    int i;
+
+    for (i = anIStart; i <= anIEnd; i++) {
+      mySubShTypeCompo->addItem(tr(SINGLE_SHAPE_TYPE_TR_CODES[i]), i);
+    }
+
+    updateFilteredList();
+  }
+
+  return isValid;
+}
+
+//=================================================================================
+// function : updateFilteredList()
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::updateFilteredList()
+{
+  TopoDS_Shape   aShape;
+  QSignalBlocker aBlocker(myFilteredList);
+
+  myFilteredList->clear();
+
+  if (GEOMBase::GetShape(myObj, aShape)) {
+    const TopAbs_ShapeEnum aType = (TopAbs_ShapeEnum)
+      mySubShTypeCompo->itemData(mySubShTypeCompo->currentIndex()).toInt();
+    TopExp_Explorer        anExp(aShape, aType);
+
+    if (anExp.More()) {
+      TopTools_MapOfShape aMapFence;
+
+      for (; anExp.More(); anExp.Next()) {
+        const TopoDS_Shape &aSubShape = anExp.Current();
+
+        if (!aSubShape.IsNull() && aMapFence.Add(aSubShape)) {
+          int anIndex = myIndices.FindIndex(aSubShape);
+
+          if (!myMapExtractedIDs.Contains(anIndex)) {
+            addNewItem(anIndex, myFilteredList);
+          }
+        }
+      }
+    }
+  }
+}
+
+//=================================================================================
+// function : resetBuildData()
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::resetBuildData(const bool isEnableBuild)
+{
+  // Clear result data.
+  myRemovedList->clear();
+  myModifiedList->clear();
+  myAddedList->clear();
+  myRebuildBtn->setEnabled(isEnableBuild);
+}
+
+//=================================================================================
+// function : isEmptyExtracted()
+// purpose  :
+//=================================================================================
+bool OperationGUI_ExtractionDlg::isEmptyExtracted()
+{
+  bool isEmpty = true;
+  int  i;
+
+  // Check if there are sub-shapes to be extracted.
+  for (i = 1; i < 8; i++) {
+    if (!myTopItems[i]->isHidden()) {
+      isEmpty = false;
+
+      break;
+    }
+  }
+
+  return isEmpty;
+}
+
+//=================================================================================
+// function : selectMainShape
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::selectMainShape()
+{
+  LightApp_SelectionMgr *aSelMgr = myGeomGUI->getApp()->selectionMgr();
+  SALOME_ListIO          aSelList;
+
+  aSelMgr->selectedObjects(aSelList);
+
+  if (aSelList.Extent() == 1) {
+    GEOM::GEOM_Object_var aSelObject =
+      GEOMBase::ConvertIOinGEOMObject(aSelList.First());
+    TopoDS_Shape          aSelShape;
+
+    if (GEOMBase::GetShape(aSelObject, aSelShape)) {
+      const TopAbs_ShapeEnum aType = aSelShape.ShapeType();
+
+      // Skip verices.
+      if (aType != TopAbs_VERTEX) {
+        myObj = aSelObject;
+
+        // Initialize map of indices. Note that myIndices should be empty.
+        TopExp::MapShapes(aSelShape, myIndices);
+      }
+    }
+  }
+
+  if (!updateSubShTypeCompo()) {
+    // Invalid selected object.
+    myObj = GEOM::GEOM_Object::_nil();
+  }
+
+  if (!CORBA::is_nil(myObj)) {
+    mySelBtn->setChecked(false);
+    myMainShapeEdit->setEnabled(false);
+    myMainShapeEdit->setText(GEOMBase::GetName(myObj));
+
+    // Hide the main object from the viewer.
+    SALOME_View* aView = GEOM_Displayer::GetActiveView();
+
+    if (aView) {
+      CORBA::String_var                aMainEntry = myObj->GetStudyEntry();
+      Handle(SALOME_InteractiveObject) anIO       = createIO(aMainEntry.in());
+
+      if (aView->isVisible(anIO)) {
+        GEOM_Displayer *aDisplayer = getDisplayer();
+
+        aDisplayer->Erase(myObj, false, true);
+        myIsHiddenMain = true;
+      }
+    }
+  }
+}
+
+//=================================================================================
+// function : selectSubShapes
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::selectSubShapes()
+{
+  QSignalBlocker aBlocker(myFilteredList);
+
+  // Clear current selection.
+  myFilteredList->clearSelection();
+
+  LightApp_SelectionMgr *aSelMgr  = myGeomGUI->getApp()->selectionMgr();
+  SALOME_ListIO          aSelList;
+  const int              aCurType =
+      mySubShTypeCompo->itemData(mySubShTypeCompo->currentIndex()).toInt();
+
+  aSelMgr->selectedObjects(aSelList);
+
+  // try to find out and process the global selection
+  // (of not published objects and of published sub-shapes)
+  SALOME_ListIteratorOfListIO anIter(aSelList);
+
+  for (; anIter.More(); anIter.Next()) {
+    Handle(SALOME_InteractiveObject) anIObj      = anIter.Value();
+    QString                          anEntry     = anIObj->getEntry();
+    QStringList                      aParts      = anEntry.split("_");
+    int                              aSubShapeId = -1;
+
+    if (!aParts.isEmpty()) {
+      if (aParts.first() == TMP_STR) {
+        bool      isOk    = false;
+        const int anIndex = aParts.last().toInt(&isOk);
+
+        if (isOk && anIndex > 0) {
+          // This is a sub-shape.
+          aSubShapeId = anIndex;
+        }
+      }
+    }
+
+    if (aSubShapeId < 0) {
+      // This is a published shape.
+      GEOM::GEOM_Object_var aSelObject =
+                    GEOMBase::ConvertIOinGEOMObject(anIObj);
+      TopoDS_Shape          aSelShape;
+
+      if (GEOMBase::GetShape(aSelObject, aSelShape)) {
+
+        if (aSelShape.ShapeType() == aCurType) {
+          const int anIndex = myIndices.FindIndex(aSelShape);
+
+          if (anIndex > 0) {
+            // This is a sub-shape. Select it in the filtered list.
+            aSubShapeId = anIndex;
+          }
+        }
+      }
+    }
+
+    // Select a list widget item by Id.
+    if (aSubShapeId > 0) {
+      QString                  anIdText = QString("%1").arg(aSubShapeId);
+      QList<QListWidgetItem *> aFound   =
+                    myFilteredList->findItems(anIdText, Qt::MatchExactly);
+
+      foreach (QListWidgetItem *anItem, aFound) {
+        anItem->setSelected(true);
+      }
+    }
+  }
+}
+
+//=================================================================================
+// function : ClickOnOk()
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::ClickOnOk()
+{
+  if (ClickOnApply()) {
+    ClickOnCancel();
+  }
+}
+
+//=================================================================================
+// function : ClickOnApply()
+// purpose  :
+//=================================================================================
+bool OperationGUI_ExtractionDlg::ClickOnApply()
+{
+  if (!onAccept()) {
+    return false;
+  }
+
+  initName();
+
+  return true;
+}
+
+//=================================================================================
+// function : onShapeTypeChanged
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::onShapeTypeChanged()
+{
+  updateFilteredList();
+  eraseAll();
+}
+
+//=================================================================================
+// function : onAddExtracted
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::onAddExtracted()
+{
+  QList<QListWidgetItem *> aListSelected = myFilteredList->selectedItems();
+
+  if (aListSelected.empty()) {
+    return;
+  }
+
+  const int aShapeType =
+      mySubShTypeCompo->itemData(mySubShTypeCompo->currentIndex()).toInt();
+  bool  isTreeUpdated  = false;
+
+  foreach (QListWidgetItem *anItem, aListSelected) {
+    const int anIndex = anItem->data(ID_ROLE).toInt();
+
+    if (myMapExtractedIDs.Add(anIndex)) {
+      addChildItem(anIndex, myTopItems[aShapeType]);
+      isTreeUpdated = true;
+    }
+
+    // Remove anItem from the list.
+    myFilteredList->removeItemWidget(anItem);
+    delete anItem;
+  }
+
+  if (isTreeUpdated) {
+    myTopItems[aShapeType]->sortChildren(0, Qt::AscendingOrder);
+
+    // Reset build data
+    resetBuildData(true);
+  }
+
+  myFilteredList->clearSelection();
+  myTopItems[aShapeType]->setHidden(false);
+}
+
+//=================================================================================
+// function : onRemoveExtracted
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::onRemoveExtracted()
+{
+  QList<QTreeWidgetItem *> aListSelected = myExtractedTree->selectedItems();
+
+  if (aListSelected.empty()) {
+    return;
+  }
+
+  const int               aShapeType =
+      mySubShTypeCompo->itemData(mySubShTypeCompo->currentIndex()).toInt();
+  QSet<QTreeWidgetItem *> aSetFence;
+  bool                    isTreeUpdated = false;
+
+  foreach (QTreeWidgetItem *anItem, aListSelected) {
+    if (!aSetFence.contains(anItem)) {
+      aSetFence.insert(anItem);
+
+      QTreeWidgetItem *aParent = anItem->parent();
+
+      if (aParent) {
+        const int anIndex = anItem->data(0, ID_ROLE).toInt();
+        // This is a ID item. Remove the ID from myMapExtractedIDs.
+        if (myMapExtractedIDs.Remove(anIndex)) {
+          // The item is not removed yet. Get parent index.
+          const int aParentIndex = aParent->data(0, TYPE_ROLE).toInt();
+
+          if (aShapeType == aParentIndex) {
+            // Create an item in the filtered list.
+            addNewItem(anIndex, myFilteredList);
+          }
+
+          aParent->removeChild(anItem);
+          delete anItem;
+          isTreeUpdated = true;
+
+          // Hilde an empty parent item.
+          if (aParent->childCount() == 0) {
+            aParent->setHidden(true);
+          }
+        }
+      } else {
+        // This is a top level item. Remove all its children.
+        QList<QTreeWidgetItem *> aChildItems = anItem->takeChildren();
+        const int                anIndex     = anItem->data(0, TYPE_ROLE).toInt();
+
+        // Remove IDs from myMapExtractedIDs.
+        foreach (QTreeWidgetItem *aChild, aChildItems) {
+          if (!aSetFence.contains(aChild)) {
+            aSetFence.insert(aChild);
+
+            const int aChildIndex = aChild->data(0, ID_ROLE).toInt();
+
+            if (myMapExtractedIDs.Remove(aChildIndex)) {
+              if (aShapeType == anIndex) {
+                // Create items in the filtered list.
+                addNewItem(aChildIndex, myFilteredList);
+              }
+
+              delete aChild;
+              isTreeUpdated = true;
+            }
+          }
+        }
+
+        // Hilde an empty item.
+        anItem->setHidden(true);
+      }
+    }
+  }
+
+  myExtractedTree->clearSelection();
+
+  if (isTreeUpdated) {
+    // Reset build data
+    const bool isEnableRebuild = !isEmptyExtracted();
+
+    resetBuildData(isEnableRebuild);
+  }
+}
+
+//=================================================================================
+// function : onListSelectionChanged
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::onListSelectionChanged()
+{
+  SALOME_ListIO            anIOList;
+  QList<QListWidgetItem *> aListSel = myFilteredList->selectedItems();
+  QList<QTreeWidgetItem *> aTreeSel = myExtractedTree->selectedItems();
+
+  // Collect selected items from myFilteredList
+  foreach (QListWidgetItem *anItem, aListSel) {
+    const int anIndex = anItem->data(ID_ROLE).toInt();
+
+    if (myMapDisplayedIDs.Contains(anIndex)) {
+      // Collect only displayed sub-shapes for selection in the viewer.
+      QString                          anEntry = getSubShapeEntry(anIndex);
+      Handle(SALOME_InteractiveObject) anIO    =
+                                      createIO(anEntry.toLatin1().data());
+
+      anIOList.Append(anIO);
+    }
+  }
+
+  // Collect selected items from myExtractedTree
+  foreach (QTreeWidgetItem *anItem, aTreeSel) {
+    if (anItem->parent()) {
+      // This is a ID item.
+      const int anIndex = anItem->data(0, ID_ROLE).toInt();
+
+      if (myMapDisplayedIDs.Contains(anIndex)) {
+        // Collect only displayed sub-shapes for selection in the viewer.
+        QString                          anEntry = getSubShapeEntry(anIndex);
+        Handle(SALOME_InteractiveObject) anIO    =
+                                    createIO(anEntry.toLatin1().data());
+
+        anIOList.Append(anIO);
+      }
+    }
+  }
+
+  // Select object in viewer.
+  LightApp_SelectionMgr *aSelMgr = myGeomGUI->getApp()->selectionMgr();
+
+  aSelMgr->setSelectedObjects(anIOList);
+}
+
+//=================================================================================
+// function : showOnlySelected
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::showOnlySelected()
+{
+  TColStd_MapOfInteger aMapIDsSelected;
+  TColStd_MapOfInteger aMapIDsToDisplay;
+  const int            aNbItems = myFilteredList->count();
+  int                  i;
+  QSet<QString>        aSelEntry;
+
+  // Get sub-shape IDs to be displayed.
+  for (i = 0; i < aNbItems; ++i) {
+    QListWidgetItem *anItem = myFilteredList->item(i);
+    const int       anIndex = anItem->data(ID_ROLE).toInt();
+
+    if (anItem->isSelected()) {
+      aMapIDsSelected.Add(anIndex);
+      aSelEntry.insert(getSubShapeEntry(anIndex));
+
+      if (!myMapDisplayedIDs.Contains(anIndex)) {
+        aMapIDsToDisplay.Add(anIndex);
+      }
+    }
+  }
+
+  // Get sub-shape IDs to be erased.
+  TColStd_MapOfInteger              aMapIDsToHide;
+  TColStd_MapIteratorOfMapOfInteger anIter(myMapDisplayedIDs);
+
+  for (; anIter.More(); anIter.Next()) {
+    const int anIndex = anIter.Key();
+
+    if (!aMapIDsSelected.Contains(anIndex)) {
+      aMapIDsToHide.Add(anIndex);
+    }
+  }
+
+  // Display sub-shapes.
+  for (anIter.Initialize(aMapIDsToDisplay); anIter.More(); anIter.Next()) {
+    displaySubShape(anIter.Key());
+  }
+
+  // Hide sub-shapes.
+  for (anIter.Initialize(aMapIDsToHide); anIter.More(); anIter.Next()) {
+    eraseSubShape(anIter.Key());
+  }
+
+  // Hide all objects except already displayed sub-shapes.
+  SALOME_ListIO  aDisplayed;
+  SALOME_View   *aView = GEOM_Displayer::GetActiveView();
+
+  if (aView) {
+    aView->GetVisible(aDisplayed);
+  }
+
+  SALOME_ListIteratorOfListIO  aDispIt(aDisplayed);
+  GEOM_Displayer              *aDisplayer = getDisplayer();
+
+  for (; aDispIt.More(); aDispIt.Next()) {
+    Handle(SALOME_InteractiveObject) anIO = aDispIt.Value();
+
+    if (!aSelEntry.contains(anIO->getEntry())) {
+      aDisplayer->Erase(anIO, false, false);
+    }
+  }
+
+  onListSelectionChanged();
+  aDisplayer->UpdateViewer();
+}
+
+//=================================================================================
+// function : hideSelected
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::hideSelected()
+{
+  QList<QListWidgetItem *> aListSelected = myFilteredList->selectedItems();
+
+  foreach (QListWidgetItem *anItem, aListSelected) {
+    const int anIndex = anItem->data(ID_ROLE).toInt();
+
+    eraseSubShape(anIndex);
+  }
+
+  getDisplayer()->UpdateViewer();
+}
+
+//=================================================================================
+// function : showAllSelected
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::showAllSelected()
+{
+  const int aNbItems = myFilteredList->count();
+  int       i;
+
+  for (i = 0; i < aNbItems; ++i) {
+    QListWidgetItem *anItem = myFilteredList->item(i);
+    const int anIndex = anItem->data(ID_ROLE).toInt();
+
+    displaySubShape(anIndex);
+  }
+
+  onListSelectionChanged();
+  getDisplayer()->UpdateViewer();
+}
+
+//=================================================================================
+// function : onRebuild
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::onRebuild()
+{
+  GEOM::GEOM_Object_var                         aResShape;
+  GEOM::GEOM_IShapesOperations::ExtractionStats aStats;
+
+  if (!getResult(aResShape.out(), aStats)) {
+    resetBuildData(false);
+    return;
+  }
+
+  TopoDS_Shape               anOldShape;
+  TopoDS_Shape               aNewShape;
+  TopTools_IndexedMapOfShape aNewIndices;
+
+  if (!GEOMBase::GetShape(aResShape, aNewShape)) {
+    resetBuildData(false);
+    return;
+  }
+
+  TopExp::MapShapes(aNewShape, aNewIndices);
+
+  const int aNbStat = aStats.length();
+  int       i;
+
+  for (i = 0; i < aNbStat; ++i) {
+    // Compute number of sub-shapes of each type.
+    const int aNbSubShapes = aStats[i].indices.length();
+    int       aNbShapes [] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+    int       j;
+
+    TopTools_IndexedMapOfShape *aMapShapes =
+      (aStats[i].type == GEOM::GEOM_IShapesOperations::EST_Added) ?
+            &aNewIndices : &myIndices;
+
+    for (j = 0; j < aNbSubShapes; ++j) {
+      const int anIndex = aStats[i].indices[j];
+
+      if (anIndex < 1 || anIndex > aMapShapes->Extent()) {
+        resetBuildData(false);
+        return;
+      }
+
+      const TopoDS_Shape &aSubShape = aMapShapes->FindKey(anIndex);
+
+      aNbShapes[aSubShape.ShapeType()]++;
+    }
+
+    // Fill the statistics.
+    QListWidget *aListWidget = 0;
+
+    switch (aStats[i].type) {
+      case GEOM::GEOM_IShapesOperations::EST_Removed:
+        aListWidget = myRemovedList;
+        break;
+      case GEOM::GEOM_IShapesOperations::EST_Modified:
+        aListWidget = myModifiedList;
+        break;
+      case GEOM::GEOM_IShapesOperations::EST_Added:
+        aListWidget = myAddedList;
+        break;
+      default:
+        resetBuildData(false);
+        return;
+    }
+
+    QStringList aStrList;
+
+    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];
+
+        aStrList.append(QString("%1 %2").arg(aNbShapes[j]).arg(tr(aShapeType)));
+      }
+    }
+
+    aListWidget->addItems(aStrList);
+  }
+
+  myRebuildBtn->setEnabled(false);
+}
+
+//=================================================================================
+// function : SelectionIntoArgument
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::SelectionIntoArgument()
+{
+  if (myMainShapeEdit->isEnabled()) {
+    // Selection of main object
+    selectMainShape();
+  } else {
+    // Selection of filtered shapes
+    selectSubShapes();
+  }
+}
+
+//=================================================================================
+// function : SetEditCurrentArgument
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::SetEditCurrentArgument()
+{
+  QSignalBlocker aBlockerList(myFilteredList);
+  QSignalBlocker aBlockerTree(myExtractedTree);
+
+  restoreViewer();
+  myObj = GEOM::GEOM_Object::_nil();
+  myMainShapeEdit->setEnabled(true);
+  myMainShapeEdit->setText("");
+  myMainShapeEdit->setFocus();
+
+  updateSubShTypeCompo();
+
+  myFilteredList->clear();
+  myRemovedList->clear();
+  myModifiedList->clear();
+  myAddedList->clear();
+  myIndices.Clear();
+
+  // Clear myExtractedTree.
+  int i;
+
+  for (i = 1; i < 8; i++) {
+    QList<QTreeWidgetItem *> aListItems = myTopItems[i]->takeChildren();
+
+    foreach (QTreeWidgetItem *anItem, aListItems) {
+      delete anItem;
+    }
+
+    myTopItems[i]->setHidden(true);
+  }
+
+  myExtractedTree->clearSelection();
+
+  myMapExtractedIDs.Clear();
+
+  // Update viewer
+  eraseAll();
+}
+
+//=================================================================================
+// function : ActivateThisDialog()
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::ActivateThisDialog()
+{
+  GEOMBase_Skeleton::ActivateThisDialog();
+
+  LightApp_SelectionMgr* aSel = myGeomGUI->getApp()->selectionMgr();
+
+  if (aSel) {
+    connect(aSel, SIGNAL(currentSelectionChanged()),
+            this, SLOT(SelectionIntoArgument()));
+  }
+
+  activateSelection();
+}
+
+//=================================================================================
+// function : activateSelection
+// purpose  : activate selection of all shapes
+//=================================================================================
+void OperationGUI_ExtractionDlg::activateSelection()
+{
+  globalSelection(GEOM_ALLSHAPES);
+}
+
+//=================================================================================
+// function : enterEvent()
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::enterEvent(QEvent *)
+{
+  if (!mainFrame()->GroupConstructors->isEnabled()) {
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : getResult
+// purpose  :
+//=================================================================================
+bool OperationGUI_ExtractionDlg::getResult
+             (GEOM::GEOM_Object_ptr                         &theResult,
+              GEOM::GEOM_IShapesOperations::ExtractionStats &theStats)
+{
+  if (myObj->_is_nil()) {
+    return false;
+  }
+
+  // Get IDs of extracted shapes.
+  int i;
+  int aNbShapes = 0;
+
+  for (i = 1; i < 8; i++) {
+    aNbShapes += myTopItems[i]->childCount();
+  }
+
+  if (aNbShapes == 0) {
+    return false;
+  }
+
+  GEOM::ListOfLong_var aSubShapeIDs = new GEOM::ListOfLong;
+  int                  j;
+  int                  jCur;
+
+  aSubShapeIDs->length(aNbShapes);
+
+  for (jCur = 0, i = 1; i < 8; ++i) {
+    aNbShapes = myTopItems[i]->childCount();
+    
+    for (j = 0; j < aNbShapes; ++j, ++jCur) {
+      aSubShapeIDs[jCur] = myTopItems[i]->child(j)->data(0, ID_ROLE).toInt();
+    }
+  }
+
+  GEOM::GEOM_IShapesOperations_var anOper =
+    GEOM::GEOM_IShapesOperations::_narrow(getOperation());
+
+  try {
+    GEOM::GEOM_Object_var                             anObj;
+    GEOM::GEOM_IShapesOperations::ExtractionStats_var aStats;
+
+    anObj = anOper->MakeExtraction(myObj, aSubShapeIDs, aStats);
+
+    if (anOper->IsDone() && aStats->length() > 0) {
+      theStats = aStats;
+    }
+
+    if (!CORBA::is_nil(anObj)) {
+      theResult = anObj._retn();
+    }
+  }
+  catch (const SALOME::SALOME_Exception& e) {
+    SalomeApp_Tools::QtCatchCorbaException(e);
+    return false;
+  }
+
+  return anOper->IsDone();
+}
+
+//=================================================================================
+// function : isValid
+// purpose  :
+//=================================================================================
+bool OperationGUI_ExtractionDlg::isValid(QString &)
+{
+  bool isOk = !myObj->_is_nil() && !isEmptyExtracted();
+
+  return isOk;
+}
+
+//=================================================================================
+// function : createOperation
+// purpose  :
+//=================================================================================
+GEOM::GEOM_IOperations_ptr OperationGUI_ExtractionDlg::createOperation()
+{
+  return getGeomEngine()->GetIShapesOperations(getStudyId());
+}
+
+//=================================================================================
+// function : execute
+// purpose  :
+//=================================================================================
+bool OperationGUI_ExtractionDlg::execute(ObjectList &objects)
+{
+  GEOM::GEOM_Object_var                         aResShape;
+  GEOM::GEOM_IShapesOperations::ExtractionStats aStats;
+
+  if (!getResult(aResShape.out(), aStats)) {
+    return false;
+  }
+
+  if (!aResShape->_is_nil()) {
+    objects.push_back(aResShape._retn());
+  }
+
+  return true;
+}
+
+//=================================================================================
+// function : getSubShapeEntry
+// purpose  :
+//=================================================================================
+QString OperationGUI_ExtractionDlg::getSubShapeEntry(const int theId)
+{
+  CORBA::String_var aMainEntry = myObj->GetStudyEntry();
+  QString           anEntry    = QString("%1_").arg(TMP_STR) +
+                                 aMainEntry.in() + QString("_%1").arg(theId);
+
+  return anEntry;
+}
+
+//=================================================================================
+// function : createIO
+// purpose  :
+//=================================================================================
+Handle_SALOME_InteractiveObject OperationGUI_ExtractionDlg::createIO
+                                                      (const char *theEntry)
+{
+  Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject
+                              (theEntry, "GEOM", "TEMP_IO");
+
+  return anIO;
+}
+
+//=================================================================================
+// function : displaySubShape
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::displaySubShape(const int theId)
+{
+  if (theId < 1 || theId > myIndices.Extent()) {
+    return;
+  }
+
+  // Create a presentation
+  const TopoDS_Shape &aSubShape  = myIndices.FindKey(theId);
+  QString             anEntry    = getSubShapeEntry(theId);
+  SALOME_View        *aView      = GEOM_Displayer::GetActiveView();
+  GEOM_Displayer     *aDisplayer = getDisplayer();
+  SALOME_Prs         *aPrs       = aDisplayer->buildSubshapePresentation
+                                  (aSubShape, anEntry, aView);
+
+  if (aPrs) {
+    if (aView) {
+      aView->Display(aDisplayer, aPrs);
+    }
+
+    delete aPrs;
+
+    myMapDisplayedIDs.Add(theId);
+  }
+}
+
+//=================================================================================
+// function : eraseSubShape
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::eraseSubShape(const int theId)
+{
+  QString                          anEntry = getSubShapeEntry(theId);
+  Handle(SALOME_InteractiveObject) anIO    =
+                                      createIO(anEntry.toLatin1().data());
+
+  getDisplayer()->Erase(anIO, false, false);
+  myMapDisplayedIDs.Remove(theId);
+}
+
+//=================================================================================
+// function : eraseAll
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::eraseAll()
+{
+  TColStd_MapIteratorOfMapOfInteger anIter(myMapDisplayedIDs);
+
+  for (; anIter.More(); anIter.Next()) {
+    eraseSubShape(anIter.Key());
+  }
+
+  myMapDisplayedIDs.Clear();
+  getDisplayer()->UpdateViewer();
+}
+
+//=================================================================================
+// function : restoreViewer
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::restoreViewer()
+{
+  if (!CORBA::is_nil(myObj)) {
+    if (myIsHiddenMain) {
+      getDisplayer()->Display(myObj, false);
+      myIsHiddenMain = false;
+    }
+
+    eraseAll();
+  }
+}
diff --git a/src/OperationGUI/OperationGUI_ExtractionDlg.h b/src/OperationGUI/OperationGUI_ExtractionDlg.h
new file mode 100644 (file)
index 0000000..f10592a
--- /dev/null
@@ -0,0 +1,115 @@
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef OPERATIONGUI_EXTRACTIONDLG_H
+#define OPERATIONGUI_EXTRACTIONDLG_H
+
+#include <GEOMBase_Skeleton.h>
+
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TColStd_MapOfInteger.hxx>
+
+class QComboBox;
+class QListWidget;
+class QTreeWidget;
+class QTreeWidgetItem;
+
+
+//=================================================================================
+// class    : OperationGUI_ExtractionDlg
+// purpose  :
+//=================================================================================
+class OperationGUI_ExtractionDlg : public GEOMBase_Skeleton
+{
+
+  Q_OBJECT
+
+public:
+
+  OperationGUI_ExtractionDlg( GeometryGUI*, QWidget* );
+  ~OperationGUI_ExtractionDlg();
+
+protected:
+
+  // redefined from GEOMBase_Helper and MeasureGUI_Skeleton
+  virtual GEOM::GEOM_IOperations_ptr  createOperation();
+  virtual bool                        execute(ObjectList &);
+  virtual void                        activateSelection();
+  virtual bool                        isValid( QString& );
+
+private slots:
+
+  void                                SelectionIntoArgument();
+  void                                ClickOnOk();
+  bool                                ClickOnApply();
+  void                                onShapeTypeChanged();
+  void                                onAddExtracted();
+  void                                onRemoveExtracted();
+  void                                onListSelectionChanged();
+  void                                showOnlySelected();
+  void                                hideSelected();
+  void                                showAllSelected();
+  void                                onRebuild();
+  void                                ActivateThisDialog();
+  void                                SetEditCurrentArgument();
+
+private:
+
+  void                                Init();
+  bool                                updateSubShTypeCompo();
+  void                                updateFilteredList();
+  void                                resetBuildData(const bool isEnableBuild);
+  bool                                isEmptyExtracted();
+  void                                selectMainShape();
+  void                                selectSubShapes();
+  void                                enterEvent(QEvent *);
+  bool                                getResult
+             (GEOM::GEOM_Object_ptr                         &theResult,
+              GEOM::GEOM_IShapesOperations::ExtractionStats &theStats);
+  QString                             getSubShapeEntry(const int theId);
+  Handle_SALOME_InteractiveObject     createIO(const char *theEntry);
+  void                                displaySubShape(const int theId);
+  void                                eraseSubShape(const int theId);
+  void                                eraseAll();
+  void                                restoreViewer();
+
+private:
+
+  GEOM::GEOM_Object_var       myObj;
+  QPushButton                *mySelBtn;
+  QLineEdit                  *myMainShapeEdit;
+  QComboBox                  *mySubShTypeCompo;
+  QListWidget                *myFilteredList;
+  QTreeWidget                *myExtractedTree;
+  QListWidget                *myRemovedList;
+  QListWidget                *myModifiedList;
+  QListWidget                *myAddedList;
+  QTreeWidgetItem            *myTopItems[8];
+  QPushButton                *myRebuildBtn;
+  TColStd_MapOfInteger        myMapExtractedIDs;
+  bool                        myIsHiddenMain;
+  TColStd_MapOfInteger        myMapDisplayedIDs;
+  TopTools_IndexedMapOfShape  myIndices;
+
+};
+
+#endif // OPERATIONGUI_EXTRACTIONDLG_H