diff --git a/doc/salome/gui/GEOM/CMakeLists.txt b/doc/salome/gui/GEOM/CMakeLists.txt
index f7877081b..b765fe7ae 100644
--- a/doc/salome/gui/GEOM/CMakeLists.txt
+++ b/doc/salome/gui/GEOM/CMakeLists.txt
@@ -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
index 000000000..d60855104
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
index 000000000..f553d263d
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
index 000000000..4148d0d97
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
index 000000000..88a90da3d
--- /dev/null
+++ b/doc/salome/gui/GEOM/input/extract_and_rebuild.doc
@@ -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 Operations -> Extract and Rebuild.
+The following dialog box appears:
+
+\image html extract_rebuild.png "Extract and Rebuild Dialog"
+
+In this dialog:
+
+
\b Name is a result object name.
+
Main Object 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.
+
Sub-shape type is the type filter for sub-shapes to be chosen
+for the extraction.
+
Filtered shapes is the list of filtered sub-shape IDs available
+for the extraction.
+
Shapes to extract is the list of sub-shape IDs to be extracted
+grouped by shape types.
+
\b >> is the button to copy object IDs from Filtered shapes to
+Shapes to extract.
+
\b << is the button to copy object IDs from Shapes to extract to
+Filtered shapes.
+
Show Only Selected is the button to show objects selected in the
+Filtered shapes list and hide all other objects.
+
Hide Selected is the button to hide objects selected in the
+Filtered shapes list.
+
Show all sub-shapes is the button to show all objects from the
+Filtered shapes list.
+
\b Rebuild is the button to perform extraction and show the operation
+statistics.
+
The block of \b Statistics shows how many shapes of a certain type
+are \b Removed, \b Modified and \b Added.
+
\b Apply is the button to create the result.
+
Apply and Close is the button to create the result and close
+the dialog.
+
\b Close is the button to close this dialog.
+
\b Help is the button to show this help page.
+
+
+TUI Command:geompy.MakeExtraction(theShape, theListOfID),
+ where \em theShape is the main shape, \em theListOfID is a list of
+sub-shape IDs to be extracted.
+
+Our TUI Scripts provide you with useful example of the use of
+\ref swig_MakeExtraction "Extract and Rebuild" functionality.
+
+More details
+
+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 this document for a detailed
+description of Extract and Rebuild operation.
+
+*/
diff --git a/doc/salome/gui/GEOM/input/related_docs.doc b/doc/salome/gui/GEOM/input/related_docs.doc
index fea4ba010..2f210676c 100644
--- a/doc/salome/gui/GEOM/input/related_docs.doc
+++ b/doc/salome/gui/GEOM/input/related_docs.doc
@@ -7,4 +7,6 @@ that can be useful for reading.
General Fuse Algorithm, Partition
Algorithm, Boolean Operations Algorithm. Backgrounds.
+Extract and Rebuild algorithm specification.
+
*/
diff --git a/doc/salome/gui/GEOM/input/transforming_geom_objs.doc b/doc/salome/gui/GEOM/input/transforming_geom_objs.doc
index 8ded8676a..3a1307360 100644
--- a/doc/salome/gui/GEOM/input/transforming_geom_objs.doc
+++ b/doc/salome/gui/GEOM/input/transforming_geom_objs.doc
@@ -27,6 +27,8 @@ special case of \b Explode operation.
special case of \b Explode operation.
\subpage transfer_data_page "Transfer Data" operation, which copies
non-topological data from one shape to another.
+
\subpage extract_and_rebuild_page "Extract and Rebuild" operation, which
+extracts sub-shapes from the main shape.
\subpage restore_presentation_parameters_page "Restore presentation parameters".
diff --git a/doc/salome/gui/GEOM/input/tui_test_all.doc b/doc/salome/gui/GEOM/input/tui_test_all.doc
index 5ed1334a0..7c2ddd136 100644
--- a/doc/salome/gui/GEOM/input/tui_test_all.doc
+++ b/doc/salome/gui/GEOM/input/tui_test_all.doc
@@ -105,6 +105,9 @@
\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
index 000000000..36e411057
Binary files /dev/null and b/doc/salome/gui/GEOM/static/ExtractAndRebuild.pdf differ
diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl
index be4adbbd0..777f3bcc3 100644
--- a/idl/GEOM_Gen.idl
+++ b/idl/GEOM_Gen.idl
@@ -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 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:
diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt
index b08b1d5b9..ed5809964 100755
--- a/resources/CMakeLists.txt
+++ b/resources/CMakeLists.txt
@@ -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
index 000000000..cdbe85a83
Binary files /dev/null and b/resources/extract.png differ
diff --git a/src/GEOMAlgo/CMakeLists.txt b/src/GEOMAlgo/CMakeLists.txt
index d2b6024ab..38126e94b 100755
--- a/src/GEOMAlgo/CMakeLists.txt
+++ b/src/GEOMAlgo/CMakeLists.txt
@@ -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
index 000000000..bdbadab69
--- /dev/null
+++ b/src/GEOMAlgo/GEOMAlgo_Extractor.cxx
@@ -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
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+//=======================================================================
+//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 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 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 &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::Iterator anIter(theListListEdges);
+
+ for (;anIter.More(); anIter.Next()) {
+ if (anIter.Value().IsEmpty()) {
+ theListListEdges.Remove(anIter);
+ break;
+ }
+ }
+ }
+ }
+
+ // Create wires.
+ NCollection_List::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 aGroupedSubShapes;
+ NCollection_Sequence 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
index 000000000..9e9215334
--- /dev/null
+++ b/src/GEOMAlgo/GEOMAlgo_Extractor.hxx
@@ -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
+
+#include
+#include
+#include
+#include
+#include
+
+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 &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
diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts
index cfcccd313..5ec53885f 100644
--- a/src/GEOMGUI/GEOM_images.ts
+++ b/src/GEOMGUI/GEOM_images.ts
@@ -1387,6 +1387,10 @@
transfer_data.png
+
+
+ extract.png
+ import.png
@@ -1407,6 +1411,10 @@
transfer_data.png
+
+
+ extract.png
+ scale_along_axes.png
diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts
index 7aef53a75..efb543e09 100644
--- a/src/GEOMGUI/GEOM_msg_en.ts
+++ b/src/GEOMGUI/GEOM_msg_en.ts
@@ -471,6 +471,10 @@ Please, select face, shell or solid and try again
CompSolid
+
+
+ CompSolids
+ Create A Compound
@@ -607,6 +611,10 @@ Please, select face, shell or solid and try again
Edge
+
+
+ Edges
+ Create An Edge
@@ -2024,6 +2032,10 @@ Please, select face, shell or solid and try again
Solid
+
+
+ Solids
+ Solid Construction
@@ -5236,6 +5248,18 @@ Please, select face, shell or solid and try again
Transfer Data
+
+
+ Extract and Rebuild
+
+
+
+ Extract and Rebuild
+
+
+
+ Extract and Rebuild
+ Extend Edge or Face
@@ -7629,4 +7653,55 @@ Do you want to create new material?
Rotation angle
+
+ OperationGUI_ExtractionDlg
+
+
+ Extract and Rebuild
+
+
+
+ Extraction type
+
+
+
+ Input parameters
+
+
+
+ Statistics
+
+
+
+ Sub-shape type
+
+
+
+ Filtered shapes
+
+
+
+ Shapes to extract
+
+
+
+ Rebuild
+
+
+
+ Removed
+
+
+
+ Modified
+
+
+
+ Added
+
+
+
+ Extraction
+
+
diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts
index a7111b94c..7db35f809 100644
--- a/src/GEOMGUI/GEOM_msg_fr.ts
+++ b/src/GEOMGUI/GEOM_msg_fr.ts
@@ -471,6 +471,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau
Assemblage solide
+
+
+ CompSolids
+ Créer un assemblage
@@ -607,6 +611,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau
Arête
+
+
+ Edges
+ Créer une arête
@@ -2016,6 +2024,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau
Solide
+
+
+ Solids
+ Construction d'un solide
@@ -5228,6 +5240,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau
Transfert de données
+
+
+ Extract and Rebuild
+
+
+
+ Extract and Rebuild
+
+
+
+ Extract and Rebuild
+ Extend Edge or Face
@@ -7605,4 +7629,55 @@ Voulez-vous en créer un nouveau ?
Longueur de l'angle
+
+ OperationGUI_ExtractionDlg
+
+
+ Extract and Rebuild
+
+
+
+ Extraction type
+
+
+
+ Input parameters
+
+
+
+ Statistics
+
+
+
+ Sub-shape type
+
+
+
+ Filtered shapes
+
+
+
+ Shapes to extract
+
+
+
+ Rebuild
+
+
+
+ Removed
+
+
+
+ Modified
+
+
+
+ Added
+
+
+
+ Extraction
+
+
diff --git a/src/GEOMGUI/GEOM_msg_ja.ts b/src/GEOMGUI/GEOM_msg_ja.ts
index 0e42dfe3d..667818994 100644
--- a/src/GEOMGUI/GEOM_msg_ja.ts
+++ b/src/GEOMGUI/GEOM_msg_ja.ts
@@ -467,6 +467,10 @@
固体のアセンブリ
+
+
+ CompSolids
+ コンパウンドの作成
@@ -603,6 +607,10 @@
Edge
+
+
+ Edges
+ エッジを作成
@@ -2019,6 +2027,10 @@
ソリッド
+
+
+ Solids
+ ソリッドの構築
@@ -5231,6 +5243,18 @@
データ転送
+
+
+ Extract and Rebuild
+
+
+
+ Extract and Rebuild
+
+
+
+ Extract and Rebuild
+ エッジまたは面の拡張
@@ -7598,4 +7622,55 @@
回転角度
+
+ OperationGUI_ExtractionDlg
+
+
+ Extract and Rebuild
+
+
+
+ Extraction type
+
+
+
+ Input parameters
+
+
+
+ Statistics
+
+
+
+ Sub-shape type
+
+
+
+ Filtered shapes
+
+
+
+ Shapes to extract
+
+
+
+ Rebuild
+
+
+
+ Removed
+
+
+
+ Modified
+
+
+
+ Added
+
+
+
+ Extraction
+
+
diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx
index 0d3f733a6..47aeffbf8 100644
--- a/src/GEOMGUI/GeometryGUI.cxx
+++ b/src/GEOMGUI/GeometryGUI.cxx
@@ -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 );
diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h
index 480b7d2fd..a80c3d093 100644
--- a/src/GEOMGUI/GeometryGUI_Operations.h
+++ b/src/GEOMGUI/GeometryGUI_Operations.h
@@ -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
diff --git a/src/GEOMImpl/CMakeLists.txt b/src/GEOMImpl/CMakeLists.txt
index 5c59b2e72..9bdce7d48 100755
--- a/src/GEOMImpl/CMakeLists.txt
+++ b/src/GEOMImpl/CMakeLists.txt
@@ -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
index 000000000..35a2799e4
--- /dev/null
+++ b/src/GEOMImpl/GEOMImpl_IExtract.hxx
@@ -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
+
+#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;
+};
diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
index 65716670c..c02c13f4d 100644
--- a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
+++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
@@ -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 &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
/*!
diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx
index d8e4f9fb2..38b375059 100644
--- a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx
+++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx
@@ -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 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 &theStats);
+
private:
Handle(GEOM_Object) MakeShape (std::list theShapes,
const Standard_Integer theObjectType,
diff --git a/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx b/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
index 46bcd193e..471fd679b 100644
--- a/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
+++ b/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
@@ -22,6 +22,7 @@
#include
+#include
#include
#include
#include
@@ -32,6 +33,7 @@
#include
#include
#include
+#include
// OCCT Includes
#include
@@ -109,6 +111,39 @@
#include
+/**
+ * \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;
}
diff --git a/src/GEOMImpl/GEOMImpl_Types.hxx b/src/GEOMImpl/GEOMImpl_Types.hxx
index 393b4303c..2e58443ac 100644
--- a/src/GEOMImpl/GEOMImpl_Types.hxx
+++ b/src/GEOMImpl/GEOMImpl_Types.hxx
@@ -119,6 +119,8 @@
#define GEOM_TRANSFER_DATA 57
+#define GEOM_EXTRACTION 58
+
//GEOM_Function types
#define COPY_WITH_REF 1
@@ -316,6 +318,7 @@
#define FACE_UV 17
#define SURFACE_FROM_FACE 18
#define SOLID_FACES 19
+#define EXTRACTION 20
#define ARCHIMEDE_TYPE 1
diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.cc b/src/GEOM_I/GEOM_IShapesOperations_i.cc
index 7561d9a16..c6c30b228 100644
--- a/src/GEOM_I/GEOM_IShapesOperations_i.cc
+++ b/src/GEOM_I/GEOM_IShapesOperations_i.cc
@@ -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 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::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 aIDList = anIt->indices;
+ GEOM::ListOfLong_var aResIDList = new GEOM::ListOfLong;
+
+ aResIDList->length(aIDList.size());
+
+ std::list::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);
+}
diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.hh b/src/GEOM_I/GEOM_IShapesOperations_i.hh
index 0f36a38c3..ff9e417f0 100644
--- a/src/GEOM_I/GEOM_IShapesOperations_i.hh
+++ b/src/GEOM_I/GEOM_IShapesOperations_i.hh
@@ -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(); }
};
diff --git a/src/GEOM_SWIG/GEOM_TestAll.py b/src/GEOM_SWIG/GEOM_TestAll.py
index ea862293f..a500a67d4 100644
--- a/src/GEOM_SWIG/GEOM_TestAll.py
+++ b/src/GEOM_SWIG/GEOM_TestAll.py
@@ -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"
diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py
index 379105b72..5b74cabdd 100644
--- a/src/GEOM_SWIG/geomBuilder.py
+++ b/src/GEOM_SWIG/geomBuilder.py
@@ -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
## @}
diff --git a/src/OperationGUI/CMakeLists.txt b/src/OperationGUI/CMakeLists.txt
index 2ff65aed2..7f949c31c 100755
--- a/src/OperationGUI/CMakeLists.txt
+++ b/src/OperationGUI/CMakeLists.txt
@@ -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
diff --git a/src/OperationGUI/OperationGUI.cxx b/src/OperationGUI/OperationGUI.cxx
index 3288921ab..96e5fc57a 100644
--- a/src/OperationGUI/OperationGUI.cxx
+++ b/src/OperationGUI/OperationGUI.cxx
@@ -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
index 000000000..47f2e722b
--- /dev/null
+++ b/src/OperationGUI/OperationGUI_ExtractionDlg.cxx
@@ -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
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if QT_VERSION >= 0x050300
+ #include
+#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 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 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 aListSelected = myExtractedTree->selectedItems();
+
+ if (aListSelected.empty()) {
+ return;
+ }
+
+ const int aShapeType =
+ mySubShTypeCompo->itemData(mySubShTypeCompo->currentIndex()).toInt();
+ QSet 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 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 aListSel = myFilteredList->selectedItems();
+ QList 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 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 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 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
index 000000000..f10592aa5
--- /dev/null
+++ b/src/OperationGUI/OperationGUI_ExtractionDlg.h
@@ -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
+
+#include
+#include
+
+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