0029481: Implementation of the Feature Removal algorithm
authoremv <emv@opencascade.com>
Tue, 6 Feb 2018 05:48:27 +0000 (08:48 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 16 Mar 2018 11:56:36 +0000 (14:56 +0300)
Implementation of the 3D model De-featuring algorithm intended for the removal of the unwanted parts (or features) from the model consisting of solids. The features can be the holes, protrusions, gaps, chamfers, fillets etc.
The algorithm removes all possible requested features from the shape and builds the new shape as a result. The input model is not modified.

On the API level the algorithm is implemented in the class *BRepAlgoAPI_Defeaturing*. The actual features removal is performed by the low-level algorithm *BOPAlgo_RemoveFeatures*.

Documentation of the new classes.
Implementation of the DRAW commands for working with new algorithm.
Test cases for the new functionality.

Changes in other algorithms used by De-featuring algorithm:
- Provide history support for the solids in *ShapeUpgrade_UnifySameDomain* algorithm;
- Implementation of the mechanism to merge History of any Algorithm with standard history methods such as IsDeleted(), Modified() and Generated() into *BRepTools_History*.

112 files changed:
dox/user_guides/draw_test_harness/draw_test_harness.md
dox/user_guides/modeling_algos/images/modeling_algos_rf_im001.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im002.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im003.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im004.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im005.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im006.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im007.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im008.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im009.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im010.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im011.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im012.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im013.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im014.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im015.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im016.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im017.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im018.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im019.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im020.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im021.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im022.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im023.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im024.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im025.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im026.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im027.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im028.png [new file with mode: 0644]
dox/user_guides/modeling_algos/images/modeling_algos_rf_im029.png [new file with mode: 0644]
dox/user_guides/modeling_algos/modeling_algos.md
src/BOPAlgo/BOPAlgo.msg
src/BOPAlgo/BOPAlgo_Alerts.hxx
src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx
src/BOPAlgo/BOPAlgo_RemoveFeatures.cxx [new file with mode: 0644]
src/BOPAlgo/BOPAlgo_RemoveFeatures.hxx [new file with mode: 0644]
src/BOPAlgo/FILES
src/BOPTest/BOPTest.cxx
src/BOPTest/BOPTest.hxx
src/BOPTest/BOPTest_BOPCommands.cxx
src/BOPTest/BOPTest_CellsCommands.cxx
src/BOPTest/BOPTest_CheckCommands.cxx
src/BOPTest/BOPTest_DebugCommands.cxx
src/BOPTest/BOPTest_PartitionCommands.cxx
src/BOPTest/BOPTest_RemoveFeaturesCommands.cxx [new file with mode: 0644]
src/BOPTest/FILES
src/BRepAlgoAPI/BRepAlgoAPI_Defeaturing.cxx [new file with mode: 0644]
src/BRepAlgoAPI/BRepAlgoAPI_Defeaturing.hxx [new file with mode: 0644]
src/BRepAlgoAPI/FILES
src/BRepLib/BRepLib.cxx
src/BRepLib/BRepLib.hxx
src/BRepTools/BRepTools_History.cxx
src/BRepTools/BRepTools_History.hxx
src/ShapeUpgrade/ShapeUpgrade_UnifySameDomain.cxx
tests/boolean/grids.list
tests/boolean/removefeatures/A1 [new file with mode: 0644]
tests/boolean/removefeatures/A2 [new file with mode: 0644]
tests/boolean/removefeatures/A3 [new file with mode: 0644]
tests/boolean/removefeatures/A4 [new file with mode: 0644]
tests/boolean/removefeatures/A5 [new file with mode: 0644]
tests/boolean/removefeatures/A6 [new file with mode: 0644]
tests/boolean/removefeatures/A7 [new file with mode: 0644]
tests/boolean/removefeatures/A8 [new file with mode: 0644]
tests/boolean/removefeatures/A9 [new file with mode: 0644]
tests/boolean/removefeatures/B1 [new file with mode: 0644]
tests/boolean/removefeatures/B2 [new file with mode: 0644]
tests/boolean/removefeatures/B3 [new file with mode: 0644]
tests/boolean/removefeatures/B4 [new file with mode: 0644]
tests/boolean/removefeatures/B5 [new file with mode: 0644]
tests/boolean/removefeatures/B6 [new file with mode: 0644]
tests/boolean/removefeatures/B7 [new file with mode: 0644]
tests/boolean/removefeatures/B8 [new file with mode: 0644]
tests/boolean/removefeatures/B9 [new file with mode: 0644]
tests/boolean/removefeatures/C1 [new file with mode: 0644]
tests/boolean/removefeatures/C2 [new file with mode: 0644]
tests/boolean/removefeatures/C3 [new file with mode: 0644]
tests/boolean/removefeatures/C4 [new file with mode: 0644]
tests/boolean/removefeatures/C5 [new file with mode: 0644]
tests/boolean/removefeatures/C6 [new file with mode: 0644]
tests/boolean/removefeatures/C7 [new file with mode: 0644]
tests/boolean/removefeatures/C8 [new file with mode: 0644]
tests/boolean/removefeatures/C9 [new file with mode: 0644]
tests/boolean/removefeatures/D1 [new file with mode: 0644]
tests/boolean/removefeatures/D2 [new file with mode: 0644]
tests/boolean/removefeatures/D3 [new file with mode: 0644]
tests/boolean/removefeatures/D4 [new file with mode: 0644]
tests/boolean/removefeatures/D5 [new file with mode: 0644]
tests/boolean/removefeatures/D6 [new file with mode: 0644]
tests/boolean/removefeatures/D7 [new file with mode: 0644]
tests/boolean/removefeatures/D8 [new file with mode: 0644]
tests/boolean/removefeatures/D9 [new file with mode: 0644]
tests/boolean/removefeatures/E1 [new file with mode: 0644]
tests/boolean/removefeatures/E2 [new file with mode: 0644]
tests/boolean/removefeatures/E3 [new file with mode: 0644]
tests/boolean/removefeatures/E4 [new file with mode: 0644]
tests/boolean/removefeatures/E5 [new file with mode: 0644]
tests/boolean/removefeatures/E6 [new file with mode: 0644]
tests/boolean/removefeatures/E7 [new file with mode: 0644]
tests/boolean/removefeatures/E8 [new file with mode: 0644]
tests/boolean/removefeatures/E9 [new file with mode: 0644]
tests/boolean/removefeatures/F1 [new file with mode: 0644]
tests/boolean/removefeatures/F2 [new file with mode: 0644]
tests/boolean/removefeatures/F3 [new file with mode: 0644]
tests/boolean/removefeatures/F4 [new file with mode: 0644]
tests/boolean/removefeatures/F5 [new file with mode: 0644]
tests/boolean/removefeatures/F6 [new file with mode: 0644]
tests/boolean/removefeatures/F7 [new file with mode: 0644]
tests/boolean/removefeatures/F8 [new file with mode: 0644]
tests/boolean/removefeatures/F9 [new file with mode: 0644]
tests/boolean/removefeatures/G1 [new file with mode: 0644]
tests/boolean/removefeatures/G2 [new file with mode: 0644]
tests/boolean/removefeatures/begin [new file with mode: 0644]

index d4be9c0..c6dd982 100644 (file)
@@ -5844,6 +5844,7 @@ The following topics are covered in the eight sections of this chapter:
   * Transformations of shapes: translation, copy, etc.
   * Topological operations, or booleans.
   * Drafting and blending.
+  * Defeaturing.
   * Analysis of shapes.
 
 
@@ -7322,6 +7323,43 @@ buildevol
 ~~~~~
 
 
+@subsection occt_draw_defeaturing Defeaturing
+
+Draw module for @ref occt_modalg_defeaturing "3D Model Defeaturing" includes the command to perform the operation and the commands to access the history of shapes modifications.
+
+@subsubsection occt_draw_defeaturing_op removefeatures
+
+*removefeatures* command performs the removal of the requested features from the shape.
+
+Syntax:
+~~~~
+removefeatures result shape f1 f2 ... [-nohist] [-parallel]
+
+Where:
+result   - result of the operation;
+shape    - the shape to remove the features from;
+f1, f2   - features to remove from the shape;
+
+Options:
+nohist   - disables the history collection;
+parallel - enables the parallel processing mode.
+~~~~
+
+@subsubsection occt_draw_defeaturing_hist rfmodified, rfgenerated, rfisdeleted
+
+To track the history of a shape modification during Defeaturing the following commands can be used:
+* <b>rfmodified</b> Shows the shapes modified from the input shape during Defeaturing.
+* <b>rfgenerated</b> Shows the shapes generated from the input shape during Defeaturing.
+* <b>rfisdeleted</b> Checks if the shape has been deleted during Defeaturing (i.e. has no trace in the result shape).
+
+Syntax:
+~~~~
+rfmodified      : rfmodified c_modified shape
+rfgenerated     : rfgenerated c_generated shape
+rfisdeleted     : rfisdeleted shape
+~~~~
+
+
 @subsection occt_draw_7_9  Analysis of topology and geometry
 
 Analysis of shapes includes commands to compute length, area, volumes and inertial properties, as well as to compute some aspects impacting shape validity.
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im001.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im001.png
new file mode 100644 (file)
index 0000000..0d9110e
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im001.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im002.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im002.png
new file mode 100644 (file)
index 0000000..c0caebc
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im002.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im003.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im003.png
new file mode 100644 (file)
index 0000000..d74c877
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im003.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im004.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im004.png
new file mode 100644 (file)
index 0000000..0fefb30
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im004.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im005.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im005.png
new file mode 100644 (file)
index 0000000..956fcee
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im005.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im006.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im006.png
new file mode 100644 (file)
index 0000000..bdbb16f
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im006.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im007.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im007.png
new file mode 100644 (file)
index 0000000..5746300
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im007.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im008.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im008.png
new file mode 100644 (file)
index 0000000..f45bee8
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im008.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im009.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im009.png
new file mode 100644 (file)
index 0000000..a6b41ac
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im009.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im010.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im010.png
new file mode 100644 (file)
index 0000000..dcc64f1
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im010.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im011.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im011.png
new file mode 100644 (file)
index 0000000..965e3ba
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im011.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im012.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im012.png
new file mode 100644 (file)
index 0000000..e8c4c35
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im012.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im013.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im013.png
new file mode 100644 (file)
index 0000000..7e50f88
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im013.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im014.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im014.png
new file mode 100644 (file)
index 0000000..3e6c0da
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im014.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im015.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im015.png
new file mode 100644 (file)
index 0000000..5834c16
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im015.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im016.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im016.png
new file mode 100644 (file)
index 0000000..27d3957
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im016.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im017.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im017.png
new file mode 100644 (file)
index 0000000..af80cc9
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im017.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im018.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im018.png
new file mode 100644 (file)
index 0000000..26f4a00
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im018.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im019.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im019.png
new file mode 100644 (file)
index 0000000..173fdd1
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im019.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im020.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im020.png
new file mode 100644 (file)
index 0000000..6b96a1e
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im020.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im021.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im021.png
new file mode 100644 (file)
index 0000000..e23a0db
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im021.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im022.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im022.png
new file mode 100644 (file)
index 0000000..d6769a5
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im022.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im023.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im023.png
new file mode 100644 (file)
index 0000000..77a0922
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im023.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im024.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im024.png
new file mode 100644 (file)
index 0000000..f0fe205
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im024.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im025.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im025.png
new file mode 100644 (file)
index 0000000..ec2c795
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im025.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im026.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im026.png
new file mode 100644 (file)
index 0000000..b97074b
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im026.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im027.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im027.png
new file mode 100644 (file)
index 0000000..ccf93b4
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im027.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im028.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im028.png
new file mode 100644 (file)
index 0000000..e3b3241
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im028.png differ
diff --git a/dox/user_guides/modeling_algos/images/modeling_algos_rf_im029.png b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im029.png
new file mode 100644 (file)
index 0000000..1a7d248
Binary files /dev/null and b/dox/user_guides/modeling_algos/images/modeling_algos_rf_im029.png differ
index de47550..5ed722b 100644 (file)
@@ -3035,3 +3035,185 @@ Meshing covers a shape with a triangular mesh. Other than hidden line removal, y
 
 You can obtain information on the shape by first exploring it. To access triangulation of a face in the shape later, use *BRepTool::Triangulation*. To access a polygon, which is the approximation of an edge of the face, use *BRepTool::PolygonOnTriangulation*.
 
+
+@section occt_modalg_defeaturing 3D Model Defeaturing
+
+The Open CASCADE Technology Defeaturing algorithm is intended for removal of the unwanted parts or features from the model. These parts could be the holes, protrusions, gaps, chamfers, fillets etc.
+
+Feature detection is not performed, and all features desired for removal should be defined by the user. The input shape is not modified during Defeaturing, the new shape is built in the result.
+
+On the API level the Defeaturing algorithm is implemented in the *BRepAlgoAPI_Defeaturing* class. On the input the algorithm accepts the shape to remove the features from and the features (one or many) to remove from the shape.
+Currently, the input shape should either be SOLID, or COMPSOLID, or COMPOUND of SOLIDs.
+The features to remove are the sets of faces forming the features. It does not matter how the feature faces are given. It could be the separate faces or the collections of them. The faces should belong to the initial shape, and those that do not belong will be ignored.
+
+The actual features removal is performed by the low-level *BOPAlgo_RemoveFeatures* algorithm. On the API level, all the inputs are passed into the tool and the method *BOPAlgo_RemoveFeatures::Perform()* is called.
+
+Before starting Features removal all the faces requested for removal from the shape are sorted on the connected blocks - each block represents single feature to remove.
+The features will be removed from the shape one by one, which will allow removing all possible features even if there were some problems with the removal of some of them (due to e.g. incorrect input data).
+
+The removed feature is filled by the extension of the faces adjacent to the feature. In general, the algorithm of removing of the single feature from the shape looks as follows:
+* Find the faces adjacent to the feature;
+* Extend the adjacent faces to cover the feature;
+* Trim the extended faces by the bounds of original face (except for bounds common with the feature), so it will cover the feature only;
+* Rebuild the solids with reconstructed adjacent faces avoiding the feature faces.
+
+If the single feature removal was successful, the result shape is overwritten with the new shape, otherwise the results are not kept, and the warning is given.
+Either way the process continues with the next feature.
+
+The Defeaturing algorithm has the following options:
+* History support;
+
+and the options available from base class (*BOPAlgo_Options*):
+* Error/Warning reporting system;
+* Parallel processing mode.
+
+Please note that the other options of the base class are not supported here and will have no effect.
+
+<b>History support</b> allows tracking modification of the input shape in terms of Modified, IsDeleted and Generated. By default, the history is collected, but it is possible to disable it using the method *TrackHistory(false)*.
+On the low-level the history information is collected by the history tool *BRepTools_History*, which can be accessed through the method *BOPAlgo_RemoveFeatures::History()*. 
+
+<b>Error/Warning reporting system</b> - allows obtaining the extended overview of the Errors/Warnings occurred during the operation. As soon as any error appears the algorithm stops working. The warnings allow continuing the job, informing the user that something went wrong. The algorithm returns the following errors/warnings:
+* BOPAlgo_AlertUnsupportedType - the alert will be given as an error if the input shape does not contain any solids, and as a warning if the input shape contains not only solids, but also other shapes;
+* BOPAlgo_AlertNoFacesToRemove - the error alert is given in case there are no faces to remove from the shape (nothing to do);
+* BOPAlgo_AlertUnableToRemoveTheFeature - the warning alert is given to inform the user the removal of the feature is not possible. The algorithm will still try to remove the other features;
+* BOPAlgo_AlertRemoveFeaturesFailed - the error alert is given in case if the operation was aborted by the unknown reason.
+
+For more information on the error/warning reporting system please see the chapter @ref occt_algorithms_ers "Errors and warnings reporting system" of Boolean operations user guide.
+
+<b>Parallel processing mode</b> - allows running the algorithm in parallel mode obtaining the result faster.
+
+The algorithm has certain limitations:
+* Intersection of the surfaces of the connected faces adjacent to the feature should not be empty. It means, that such faces should not be tangent to each other.
+If the intersection of the adjacent faces will be empty, the algorithm will be unable to trim the faces correctly and, most likely, the feature will not be removed.
+* The algorithm does not process the INTERNAL parts of the solids, they are simply removed during reconstruction.
+
+Note, that for successful removal of the feature, the extended faces adjacent to the feature should cover the feature completely, otherwise the solids will not be rebuild.
+Take a look at the simple shape on the image below:
+@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im001.png,"",220}
+
+Removal of all three faces of the gap is not going to work, because there will be no face to fill the transverse part of the step.
+Although, removal of only two faces, keeping one of the transverse faces, will fill the gap with the kept face:
+<table align="center">
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im002.png,"Keeping the right transverse face",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im003.png,"Keeping the left transverse face",220}</td>
+</tr>
+</table>
+
+@subsection occt_modalg_defeaturing_usage Usage
+
+Here is the example of usage of the *BRepAlgoAPI_Defeaturing* algorithm on the C++ level:
+~~~~
+TopoDS_Shape aSolid = ...;               // Input shape to remove the features from
+TopTools_ListOfShape aFeatures = ...;    // Features to remove from the shape
+Standard_Boolean bRunParallel = ...;     // Parallel processing mode
+Standard_Boolean isHistoryNeeded = ...;  // History support
+
+BRepAlgoAPI_Defeaturing aDF;             // Defeaturing algorithm
+aDF.SetShape(aSolid);                    // Set the shape
+aDF.AddFacesToRemove(aFaces);            // Add faces to remove
+aDF.SetRunParallel(bRunParallel);        // Define the processing mode (parallel or single)
+aDF.TrackHistory(isHistoryNeeded);       // Define whether to track the shapes modifications
+aDF.Build();                             // Perform the operation
+if (!aDF.IsDone())                       // Check for the errors
+{
+  // error treatment
+  Standard_SStream aSStream;
+  aDF.DumpErrors(aSStream);
+  return;
+}
+if (aDF.HasWarnings())                   // Check for the warnings
+{
+  // warnings treatment
+  Standard_SStream aSStream;
+  aDF.DumpWarnings(aSStream);
+}
+const TopoDS_Shape& aResult = aDF.Shape(); // Result shape
+~~~~
+
+To track the history of a shape use the API history methods:
+~~~~
+// Obtain modification of the shape
+const TopTools_ListOfShape& BRepAlgoAPI_Defeaturing::Modified(const TopoDS_Shape& theS);
+
+// Obtain shapes generated from the shape
+const TopTools_ListOfShape& BRepAlgoAPI_Defeaturing::Generated(const TopoDS_Shape& theS);
+
+// Check if the shape is removed or not
+Standard_Boolean BRepAlgoAPI_Defeaturing::IsDeleted(const TopoDS_Shape& theS);
+~~~~
+
+For the usage of the Defeaturing algorithm on the Draw level the command <b>removefeatures</b> has been implemented.
+
+To track the history of a shape modification during Defeaturing the following commands can be used:
+* <b>rfmodified</b> Shows the shapes modified from the input shape during Defeaturing.
+* <b>rfgenerated</b> Shows the shapes generated from the input shape during Defeaturing.
+* <b>rfisdeleted</b> Checks if the shape has been deleted during Defeaturing.
+
+For more details on commands above please refer the @ref occt_draw_defeaturing "Defeaturing commands" of the Draw test harness user guide.
+
+To have possibility to access the error/warning shapes of the operation use the *bdrawwarnshapes* command before running the algorithm (see command usage in the @ref occt_algorithms_ers "Errors and warnings reporting system" of Boolean operations user guide).
+
+@subsection occt_modalg_defeaturing_examples Examples
+
+Here are the few examples of defeaturing of the ANC101 model:
+
+@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im004.png,"ANC101 model",220}</td>
+
+<table align="center">
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im005.png,"Removing the cylindrical protrusion",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im006.png,"Result",220}</td></td>
+</tr>
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im007.png,"Removing the cylindrical holes",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im008.png,"Result",220}</td></td>
+</tr>
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im009.png,"Removing the cylindrical holes",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im010.png,"Result",220}</td></td>
+</tr>
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im011.png,"Removing the small gaps in the front",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im012.png,"Result",220}</td></td>
+</tr>
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im013.png,"Removing the gaps in the front completely",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im014.png,"Result",220}</td></td>
+</tr>
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im015.png,"Removing the cylindrical protrusion",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im016.png,"Result",220}</td></td>
+</tr>
+</table>
+
+Here are the few examples of defeaturing of the model containing boxes with blends:
+
+@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im017.png,"Box blend model",220}</td>
+
+<table align="center">
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im018.png,"Removing the blend",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im019.png,"Result",220}</td></td>
+</tr>
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im020.png,"Removing the blend",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im021.png,"Result",220}</td></td>
+</tr>
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im022.png,"Removing the blend",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im023.png,"Result",220}</td></td>
+</tr>
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im024.png,"Removing the blend",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im025.png,"Result",220}</td></td>
+</tr>
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im026.png,"Removing the blend",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im027.png,"Result",220}</td></td>
+</tr>
+<tr>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im028.png,"Removing the blend",220}</td>
+  <td>@figure{/user_guides/modeling_algos/images/modeling_algos_rf_im029.png,"Result",220}</td></td>
+</tr>
+</table>
index 673a39e..e6c22a3 100644 (file)
@@ -76,3 +76,15 @@ Warning: Building 2D curve of edge on face has failed
 
 .BOPAlgo_AlertAcquiredSelfIntersection
 Warning: Some sub-shapes of some of the argument become connected through other shapes and the argument became self-interfered
+
+.BOPAlgo_AlertUnsupportedType
+Warning: Unsupported type of input shape
+
+.BOPAlgo_AlertUnableToRemoveTheFeature
+Warning: Unable to remove the feature
+
+.BOPAlgo_AlertNoFacesToRemove
+Error: No faces have been found for removal
+
+.BOPAlgo_AlertRemoveFeaturesFailed
+Error: The Feature Removal algorithm has failed
index 04ce9c7..806184d 100644 (file)
@@ -88,4 +88,16 @@ DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertBuildingPCurveFailed)
 //! other shapes and the argument became self-interfered
 DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertAcquiredSelfIntersection)
 
+//! Unsupported type of input shape
+DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnsupportedType)
+
+//! No faces have been found for removal
+DEFINE_SIMPLE_ALERT(BOPAlgo_AlertNoFacesToRemove)
+
+//! Unable to remove the feature
+DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToRemoveTheFeature)
+
+//! The Feature Removal algorithm has failed
+DEFINE_SIMPLE_ALERT(BOPAlgo_AlertRemoveFeaturesFailed)
+
 #endif // _BOPAlgo_Alerts_HeaderFile
index feec778..6d3ff38 100644 (file)
@@ -78,4 +78,16 @@ static const char BOPAlgo_BOPAlgo_msg[] =
   "Warning: Building 2D curve of edge on face has failed\n"
   "\n"
   ".BOPAlgo_AlertAcquiredSelfIntersection\n"
-  "Warning: Some sub-shapes of some of the argument become connected through other shapes and the argument became self-interfered\n";
+  "Warning: Some sub-shapes of some of the argument become connected through other shapes and the argument became self-interfered\n"
+  "\n"
+  ".BOPAlgo_AlertUnsupportedType\n"
+  "Warning: Unsupported type of input shape\n"
+  "\n"
+  ".BOPAlgo_AlertUnableToRemoveTheFeature\n"
+  "Warning: Unable to remove the feature\n"
+  "\n"
+  ".BOPAlgo_AlertNoFacesToRemove\n"
+  "Error: No faces have been found for removal\n"
+  "\n"
+  ".BOPAlgo_AlertRemoveFeaturesFailed\n"
+  "Error: The Feature Removal algorithm has failed\n";
diff --git a/src/BOPAlgo/BOPAlgo_RemoveFeatures.cxx b/src/BOPAlgo/BOPAlgo_RemoveFeatures.cxx
new file mode 100644 (file)
index 0000000..7ca9aef
--- /dev/null
@@ -0,0 +1,1671 @@
+// Created by: Eugeny MALTCHIKOV
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BOPAlgo_RemoveFeatures.hxx>
+
+#include <BOPAlgo_Alerts.hxx>
+#include <BOPAlgo_BOP.hxx>
+#include <BOPAlgo_Builder.hxx>
+#include <BOPAlgo_BuilderSolid.hxx>
+#include <BOPAlgo_MakerVolume.hxx>
+#include <BOPAlgo_Tools.hxx>
+
+#include <BOPTools_AlgoTools.hxx>
+#include <BOPTools_Parallel.hxx>
+#include <BOPTools_Set.hxx>
+
+#include <Bnd_Box.hxx>
+
+#include <BRep_Builder.hxx>
+
+#include <BRepBndLib.hxx>
+
+#include <BRepLib.hxx>
+
+#include <NCollection_Vector.hxx>
+
+#include <ShapeUpgrade_UnifySameDomain.hxx>
+
+#include <TopAbs_ShapeEnum.hxx>
+
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+
+#include <TopoDS.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+
+#include <TopTools_IndexedDataMapOfShapeShape.hxx>
+
+
+//=======================================================================
+// static methods declaration
+//=======================================================================
+
+static void MakeRemoved(const TopTools_ListOfShape& theShapes,
+                        BRepTools_History& theHistory,
+                        const TopTools_IndexedMapOfShape& theKeepShapes = TopTools_IndexedMapOfShape());
+
+static void FindInternals(const TopoDS_Shape& theS,
+                          TopTools_ListOfShape& theLInt);
+
+static void RemoveInternalWires(const TopTools_ListOfShape& theShapes,
+                                TopTools_ListOfShape* theRemoved = NULL);
+
+static void GetOriginalFaces(const TopoDS_Shape& theShape,
+                             const TopTools_IndexedMapOfShape& theSolids,
+                             const TopTools_MapOfShape& theFeatureFacesMap,
+                             const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
+                             const Handle(BRepTools_History)& theHistory,
+                             TopTools_IndexedMapOfShape& theFacesToBeKept,
+                             TopTools_ListOfShape& theInternalShapes,
+                             TopTools_MapOfShape& theFacesToCheckOri,
+                             TopTools_IndexedMapOfShape& theSolidsToRebuild,
+                             TopTools_ListOfShape& theSharedFaces,
+                             TopTools_ListOfShape& theUnTouchedSolids);
+
+static void FindShape(const TopoDS_Shape& theSWhat,
+                      const TopoDS_Shape& theSWhere,
+                      TopoDS_Shape& theSFound);
+
+static void GetValidSolids(BOPAlgo_MakerVolume& theMV,
+                           const TopTools_MapOfShape& theFacesToCheckOri,
+                           const TopTools_ListOfShape& aSharedFaces,
+                           const TopoDS_Shape& theOrigFaces,
+                           const Standard_Integer theNbSol,
+                           TopTools_ListOfShape& theLSRes,
+                           TopTools_ListOfShape& theRemovedShapes);
+
+static void FindExtraShapes(const TopTools_IndexedDataMapOfShapeListOfShape& theConnectionMap,
+                            const TopTools_MapOfShape& theShapesToCheckOri,
+                            BOPAlgo_Builder& theBuilder,
+                            TopTools_MapOfShape& theShapesToAvoid,
+                            TopTools_MapOfShape* theValidShapes = NULL);
+
+static void AvoidExtraSharedFaces(TopTools_ListOfShape& theLSolids,
+                                  const TopTools_ListOfShape& theLFSharedToAvoid,
+                                  BOPAlgo_Builder& theBuilder,
+                                  TopTools_ListOfShape& theExtraFaces);
+
+static void FillSolidsHistory(const TopTools_IndexedMapOfShape& theSolIn,
+                              TopTools_ListOfShape& theSolidsRes,
+                              const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
+                              BOPAlgo_Builder& theBuilder,
+                              BRepTools_History& theSolidsHistory);
+
+static void TakeModified(const TopoDS_Shape& theS,
+                         BOPAlgo_Builder& theBuilder,
+                         TopTools_ListOfShape& theList);
+
+static void TakeModified(const TopoDS_Shape& theS,
+                         BOPAlgo_Builder& theBuilder,
+                         TopTools_MapOfShape& theMap);
+
+static void FindSolid(const TopoDS_Shape& theSolIn,
+                      const TopTools_ListOfShape& theSolidsRes,
+                      const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
+                      BOPAlgo_Builder& theBuilder,
+                      TopoDS_Shape& theSolOut);
+
+
+//=======================================================================
+// function: Perform
+// purpose: Performs the removal of the requested faces from the input shape
+//=======================================================================
+void BOPAlgo_RemoveFeatures::Perform()
+{
+  try
+  {
+    OCC_CATCH_SIGNALS
+
+    if (myTrackHistory)
+      myHistory = new BRepTools_History();
+
+    // Check the input data
+    CheckData();
+    if (HasErrors())
+      return;
+
+    // Prepare the faces to remove.
+    PrepareFeatures();
+    if (HasErrors())
+      return;
+
+    // Remove the features and fill the created gaps
+    RemoveFeatures();
+
+    // Update history with the removed features
+    UpdateHistory();
+
+    // Simplify the result
+    SimplifyResult();
+
+    // Post treatment
+    PostTreat();
+  }
+  catch (Standard_Failure)
+  {
+    AddError(new BOPAlgo_AlertRemoveFeaturesFailed());
+  }
+}
+
+//=======================================================================
+// function: CheckData
+// purpose: Checks the input data on validity for the algorithm
+//=======================================================================
+void BOPAlgo_RemoveFeatures::CheckData()
+{
+  // Prepare the shape to work with
+  myShape = myInputShape;
+
+  // Check the type of input shape
+  const TopAbs_ShapeEnum aType = myInputShape.ShapeType();
+
+  if (aType == TopAbs_SOLID || aType == TopAbs_COMPSOLID)
+    return; // OK
+
+  if (aType == TopAbs_COMPOUND)
+  {
+    TopTools_ListOfShape aShapes;
+    TopTools_MapOfShape aMFence;
+    // Extract all shapes from the compound
+    BOPAlgo_Tools::TreatCompound(myInputShape, aMFence, aShapes);
+    if (aShapes.IsEmpty())
+    {
+      // Add error of empty input shape
+      AddError(new BOPAlgo_AlertEmptyShape(myInputShape));
+      return;
+    }
+
+    // Find all solids in the list of shapes
+    TopTools_ListOfShape aSolids;
+    TopTools_ListOfShape anOtherShapes;
+    TopTools_ListIteratorOfListOfShape aIt(aShapes);
+    for (; aIt.More(); aIt.Next())
+    {
+      const TopoDS_Shape& aS = aIt.Value();
+      if (aS.ShapeType() == TopAbs_SOLID || aS.ShapeType() == TopAbs_COMPSOLID)
+        aSolids.Append(aS);
+      else
+        anOtherShapes.Append(aS);
+    }
+
+    if (aSolids.IsEmpty())
+    {
+      // No solids have been found for processing.
+      // Add error of unsupported type of input shape
+      AddError(new BOPAlgo_AlertTooFewArguments());
+    }
+    else if (anOtherShapes.Extent() > 0)
+    {
+      // Add warning of unsupported type of input shape for all
+      // non-solid shapes, contained in the input shape
+      for (aIt.Initialize(anOtherShapes); aIt.More(); aIt.Next())
+      {
+        AddWarning(new BOPAlgo_AlertUnsupportedType(aIt.Value()));
+      }
+
+      // Collect all solids into compound and overwrite the shape to rebuild
+      TopoDS_Compound aCS;
+      BRep_Builder().MakeCompound(aCS);
+      for (aIt.Initialize(aSolids); aIt.More(); aIt.Next())
+        BRep_Builder().Add(aCS, aIt.Value());
+
+      myShape = aCS;
+
+      if (myTrackHistory)
+      {
+        // Make non solid shapes removed in the history
+        MakeRemoved(anOtherShapes, *myHistory.get());
+      }
+    }
+  }
+  else
+  {
+    // Add error of unsupported type of input shape
+    AddError(new BOPAlgo_AlertTooFewArguments());
+  }
+}
+
+//=======================================================================
+// function: PrepareFeatures
+// purpose: Prepares the features to remove
+//=======================================================================
+void BOPAlgo_RemoveFeatures::PrepareFeatures()
+{
+  // Map all sub-shapes of the input solids
+  TopExp::MapShapes(myInputShape, myInputsMap);
+
+  // Collect all faces of the input shape requested for removal
+  TopTools_ListOfShape aFacesToRemove;
+  TopTools_ListIteratorOfListOfShape aIt(myFacesToRemove);
+  for (; aIt.More(); aIt.Next())
+  {
+    const TopoDS_Shape& aS = aIt.Value();
+    TopExp_Explorer anExpF(aS, TopAbs_FACE);
+    for (; anExpF.More(); anExpF.Next())
+    {
+      const TopoDS_Shape& aF = anExpF.Current();
+      if (myInputsMap.Contains(aF))
+        aFacesToRemove.Append(aF);
+    }
+  }
+
+  if (aFacesToRemove.IsEmpty())
+  {
+    // Add error, that no features to remove have been found
+    AddError(new BOPAlgo_AlertNoFacesToRemove());
+    return;
+  }
+
+  // Build connexity blocks of the faces to remove
+  TopoDS_Compound aCFToRemove;
+  BRep_Builder().MakeCompound(aCFToRemove);
+  for (aIt.Initialize(aFacesToRemove); aIt.More(); aIt.Next())
+    BRep_Builder().Add(aCFToRemove, aIt.Value());
+
+  // Fill the list of features with connexity blocks of faces
+  BOPTools_AlgoTools::MakeConnexityBlocks(aCFToRemove, TopAbs_EDGE, TopAbs_FACE, myFeatures);
+}
+
+//=======================================================================
+// Adjacent faces extension block
+
+//=======================================================================
+// class: FillGaps
+// purpose: Auxiliary class for creation of the faces for filling the gap
+//          created by removal of the single feature
+//=======================================================================
+class FillGap
+{
+public: //! @name Constructors
+
+  //! Empty constructor
+  FillGap() :
+    myRunParallel(Standard_False),
+    myHasAdjacentFaces(Standard_False)
+  {}
+
+public: //! @name Setters/Getters
+
+  //! Sets the feature to remove
+  void SetFeature(const TopoDS_Shape& theFeature) { myFeature = theFeature; }
+
+  //! Returns the feature
+  const TopoDS_Shape& Feature() const { return myFeature; }
+
+  //! Sets the EF connection map
+  void SetEFConnectionMap(const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap)
+  {
+    myEFMap = (TopTools_IndexedDataMapOfShapeListOfShape*)&theEFMap;
+  }
+
+  //! Sets the FS connection map
+  void SetFSConnectionMap(const TopTools_IndexedDataMapOfShapeListOfShape& theFSMap)
+  {
+    myFSMap = (TopTools_IndexedDataMapOfShapeListOfShape*)&theFSMap;
+  }
+
+  //! Defines the parallel processing mode
+  void SetRunParallel(const Standard_Boolean bRunParallel) { myRunParallel = bRunParallel; }
+
+  //! Gets the History object
+  const Handle(BRepTools_History)& History()
+  {
+    return myHistory;
+  }
+
+public: //! @name Perform the operation
+
+  //! Performs the extension of the adjacent faces and
+  //! then trims the extended faces to fill the gaps
+  void Perform()
+  {
+    OCC_CATCH_SIGNALS
+
+    try
+    {
+      myHistory = new BRepTools_History();
+
+      // Find the faces adjacent to the faces of the feature
+      TopTools_IndexedMapOfShape aMFAdjacent;
+      FindAdjacentFaces(aMFAdjacent);
+
+      myHasAdjacentFaces = (aMFAdjacent.Extent() > 0);
+      if (!myHasAdjacentFaces)
+        return;
+
+      // Extend the adjacent faces keeping the connection to the original faces
+      TopTools_IndexedDataMapOfShapeShape aFaceExtFaceMap;
+      ExtendAdjacentFaces(aMFAdjacent, aFaceExtFaceMap);
+
+      // Trim the extended faces
+      TrimExtendedFaces(aFaceExtFaceMap);
+    }
+    catch (Standard_Failure)
+    {
+      // Make sure the warning will be given on the higher level
+      myHasAdjacentFaces = Standard_True;
+      myFaces.Clear();
+    }
+  }
+
+public: //! @name Obtain the result
+
+  //! Returns the map of faces of the feature
+  const TopTools_MapOfShape& FeatureFacesMap() const { return myFeatureFacesMap; }
+
+  //! Shows whether the adjacent faces have been found for the feature
+  Standard_Boolean HasAdjacentFaces() const { return myHasAdjacentFaces; }
+
+  //! Returns the Images map of the adjacent faces
+  const TopTools_IndexedDataMapOfShapeListOfShape& Faces() const { return myFaces; }
+
+  //! Returns the initial solids participating in the feature removal
+  const TopTools_IndexedMapOfShape& Solids() const { return mySolids; }
+
+
+private: //! @name Private methods performing the operation
+
+  //! Finds the faces adjacent to the feature and stores them into outgoing map.
+  void FindAdjacentFaces(TopTools_IndexedMapOfShape& theMFAdjacent)
+  {
+    // Map the faces of the feature to avoid them in the map of adjacent faces
+    TopoDS_Iterator aIt(myFeature);
+    for (; aIt.More(); aIt.Next())
+      myFeatureFacesMap.Add(aIt.Value());
+
+    // Find faces adjacent to the feature using the connection map
+    aIt.Initialize(myFeature);
+    for (; aIt.More(); aIt.Next())
+    {
+      const TopoDS_Shape& aF = aIt.Value();
+      TopExp_Explorer anExpE(aF, TopAbs_EDGE);
+      for (; anExpE.More(); anExpE.Next())
+      {
+        const TopoDS_Shape& aE = anExpE.Current();
+        const TopTools_ListOfShape* pAdjacentFaces = myEFMap->Seek(aE);
+        if (pAdjacentFaces)
+        {
+          TopTools_ListIteratorOfListOfShape itLFA(*pAdjacentFaces);
+          for (; itLFA.More(); itLFA.Next())
+          {
+            const TopoDS_Shape& anAF = itLFA.Value();
+            if (!myFeatureFacesMap.Contains(anAF))
+              theMFAdjacent.Add(anAF);
+          }
+        }
+      }
+      // Find solids containing the feature face
+      const TopTools_ListOfShape* pLS = myFSMap->Seek(aF);
+      if (pLS)
+      {
+        TopTools_ListIteratorOfListOfShape itLS(*pLS);
+        for (; itLS.More(); itLS.Next())
+          mySolids.Add(itLS.Value());
+      }
+    }
+
+    // Find solids containing the edges of adjacent faces
+    const Standard_Integer aNbFA = theMFAdjacent.Extent();
+    for (Standard_Integer i = 1; i <= aNbFA; ++i)
+    {
+      TopExp_Explorer anExpEA(theMFAdjacent(i), TopAbs_EDGE);
+      for (; anExpEA.More(); anExpEA.Next())
+      {
+        // Faces adjacent to the face adjacent to the feature
+        const TopTools_ListOfShape* pLFAA = myEFMap->Seek(anExpEA.Current());
+        if (pLFAA)
+        {
+          TopTools_ListIteratorOfListOfShape itLFAA(*pLFAA);
+          for (; itLFAA.More(); itLFAA.Next())
+          {
+            // Solids containing the faces
+            const TopTools_ListOfShape* pLS = myFSMap->Seek(itLFAA.Value());
+            if (pLS)
+            {
+              TopTools_ListIteratorOfListOfShape itLS(*pLS);
+              for (; itLS.More(); itLS.Next())
+                mySolids.Add(itLS.Value());
+            }
+          }
+        }
+      }
+    }
+  }
+
+  //! Extends the found adjacent faces and binds them to the original faces.
+  void ExtendAdjacentFaces(const TopTools_IndexedMapOfShape& theMFAdjacent,
+                           TopTools_IndexedDataMapOfShapeShape& theFaceExtFaceMap)
+  {
+    // Get the extension value for the faces - half of the diagonal of bounding box of the feature
+    Bnd_Box aFeatureBox;
+    BRepBndLib::Add(myFeature, aFeatureBox);
+
+    const Standard_Real anExtLength = sqrt(aFeatureBox.SquareExtent());
+
+    const Standard_Integer aNbFA = theMFAdjacent.Extent();
+    for (Standard_Integer i = 1; i <= aNbFA; ++i)
+    {
+      const TopoDS_Face& aF = TopoDS::Face(theMFAdjacent(i));
+      // Extend the face
+      TopoDS_Face aFExt;
+      BRepLib::ExtendFace(aF, anExtLength,
+                          Standard_True, Standard_True,
+                          Standard_True, Standard_True,
+                          aFExt);
+      theFaceExtFaceMap.Add(aF, aFExt);
+      myHistory->AddModified(aF, aFExt);
+    }
+  }
+
+  //! Trims the extended adjacent faces by intersection with each other
+  //! and following intersection with the bounds of original faces.
+  void TrimExtendedFaces(const TopTools_IndexedDataMapOfShapeShape& theFaceExtFaceMap)
+  {
+    // Intersect the extended faces first
+    BOPAlgo_Builder aGFInter;
+    // Add faces for intersection
+    const Standard_Integer aNbF = theFaceExtFaceMap.Extent();
+    for (Standard_Integer i = 1; i <= aNbF; ++i)
+      aGFInter.AddArgument(theFaceExtFaceMap(i));
+
+    aGFInter.SetRunParallel(myRunParallel);
+
+    // Intersection result
+    TopoDS_Shape anIntResult;
+    if (aGFInter.Arguments().Extent() > 1)
+    {
+      aGFInter.Perform();
+      if (aGFInter.HasErrors())
+        return;
+
+      anIntResult = aGFInter.Shape();
+
+      myHistory->Merge<BOPAlgo_Builder>(aGFInter.Arguments(), aGFInter);
+    }
+    else
+      anIntResult = aGFInter.Arguments().First();
+
+    // Prepare the EF map of the extended faces after intersection
+    // to select from them only boundary edges
+    TopTools_IndexedDataMapOfShapeListOfShape anEFExtMap;
+    TopExp::MapShapesAndAncestors(anIntResult, TopAbs_EDGE, TopAbs_FACE, anEFExtMap);
+
+    // Get the splits of the extended faces after intersection
+    // and trim them by the edges of the original faces
+
+    // Map the edges of the Feature to avoid them during the trim
+    TopTools_IndexedMapOfShape aFeatureEdgesMap;
+    TopExp::MapShapes(myFeature, TopAbs_EDGE, aFeatureEdgesMap);
+
+    for (Standard_Integer i = 1; i <= aNbF; ++i)
+    {
+      const TopoDS_Face& aFOriginal = TopoDS::Face(theFaceExtFaceMap.FindKey(i));
+      const TopoDS_Face& aFExt = TopoDS::Face(theFaceExtFaceMap(i));
+      TrimFace(aFExt, aFOriginal, aFeatureEdgesMap, anEFExtMap, aGFInter);
+    }
+  }
+
+  //! Trim the extended faces by the bounds of the original face,
+  //! except those contained in the feature to remove.
+  void TrimFace(const TopoDS_Face& theFExt,
+                const TopoDS_Face& theFOriginal,
+                const TopTools_IndexedMapOfShape& theFeatureEdgesMap,
+                const TopTools_IndexedDataMapOfShapeListOfShape& theEFExtMap,
+                BOPAlgo_Builder& theGFInter)
+  {
+    // Map all edges of the extended face, to filter the result of trim
+    // from the faces containing these edges
+    TopTools_MapOfShape aMExtEdges;
+    TopExp_Explorer anExpE(theFExt, TopAbs_EDGE);
+    for (; anExpE.More(); anExpE.Next())
+    {
+      const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current());
+      // skip degenerated and seam edges
+      if (BRep_Tool::Degenerated(aE) || BRep_Tool::IsClosed(aE, theFExt))
+        continue;
+      TopTools_ListOfShape aLEIm;
+      TakeModified(aE, theGFInter, aLEIm);
+      TopTools_ListIteratorOfListOfShape itLEIm(aLEIm);
+      for (; itLEIm.More(); itLEIm.Next())
+      {
+        const TopoDS_Shape& aEIm = itLEIm.Value();
+        if (theEFExtMap.FindFromKey(aEIm).Extent() == 1)
+          aMExtEdges.Add(aEIm);
+      }
+    }
+
+    // Trimming tool
+    BOPAlgo_Builder aGFTrim;
+
+    // Get the splits of the face and add them for trimming
+    TopTools_ListOfShape anExtSplits;
+    TakeModified(theFExt, theGFInter, anExtSplits);
+    aGFTrim.SetArguments(anExtSplits);
+
+    // Add edges of the original faces
+    TopTools_MapOfShape aMEdgesToCheckOri;
+    anExpE.Init(theFOriginal, TopAbs_EDGE);
+    for (; anExpE.More(); anExpE.Next())
+    {
+      const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current());
+      if (!theFeatureEdgesMap.Contains(aE))
+      {
+        aGFTrim.AddArgument(aE);
+        if (!BRep_Tool::Degenerated(aE) &&
+            !BRep_Tool::IsClosed(aE, theFOriginal))
+        {
+          if (!aMEdgesToCheckOri.Add(aE))
+            aMEdgesToCheckOri.Remove(aE);
+        }
+      }
+    }
+
+    // Avoid faces intersection
+    aGFTrim.SetGlue(BOPAlgo_GlueShift);
+    aGFTrim.SetRunParallel(myRunParallel);
+    aGFTrim.SetNonDestructive(Standard_True);
+
+    aGFTrim.Perform();
+    if (aGFTrim.HasErrors())
+      return;
+
+    // Get all splits
+    const TopoDS_Shape& aSplits = aGFTrim.Shape();
+    // Filter the trimmed faces and save the valid ones into result map
+    TopTools_ListOfShape aLFTrimmed;
+
+    TopExp_Explorer anExpF(aSplits, TopAbs_FACE);
+    for (; anExpF.More(); anExpF.Next())
+    {
+      const TopoDS_Shape& aSp = anExpF.Current();
+      anExpE.Init(aSp, TopAbs_EDGE);
+      for (; anExpE.More(); anExpE.Next())
+      {
+        if (aMExtEdges.Contains(anExpE.Current()))
+          break;
+      }
+      if (!anExpE.More())
+        aLFTrimmed.Append(aSp);
+    }
+
+    if (aLFTrimmed.Extent() > 1)
+    {
+      // Chose the correct faces - the ones that contains edges with proper
+      // bi-normal direction
+      TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
+      TopTools_ListIteratorOfListOfShape itLF(aLFTrimmed);
+      for (; itLF.More(); itLF.Next())
+        TopExp::MapShapesAndAncestors(itLF.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap);
+
+      // Check edges orientations
+      TopTools_MapOfShape aFacesToAvoid, aValidFaces;
+      FindExtraShapes(anEFMap, aMEdgesToCheckOri, aGFTrim, aFacesToAvoid, &aValidFaces);
+
+      if (aLFTrimmed.Extent() - aFacesToAvoid.Extent() > 1)
+      {
+        // It is possible that the splits are forming the different blocks.
+        // Take only those containing the valid faces.
+        TopoDS_Compound aCF;
+        BRep_Builder().MakeCompound(aCF);
+        itLF.Initialize(aLFTrimmed);
+        for (; itLF.More(); itLF.Next())
+        {
+          if (!aFacesToAvoid.Contains(itLF.Value()))
+            BRep_Builder().Add(aCF, itLF.Value());
+        }
+
+        TopTools_ListOfShape aLCB;
+        BOPTools_AlgoTools::MakeConnexityBlocks(aCF, TopAbs_EDGE, TopAbs_FACE, aLCB);
+        if (aLCB.Extent() > 1)
+        {
+          TopTools_ListIteratorOfListOfShape itLCB(aLCB);
+          for (; itLCB.More(); itLCB.Next())
+          {
+            // Check if the block contains any valid faces
+            const TopoDS_Shape& aCB = itLCB.Value();
+            TopoDS_Iterator itF(aCB);
+            for (; itF.More(); itF.Next())
+            {
+              if (aValidFaces.Contains(itF.Value()))
+                break;
+            }
+            if (!itF.More())
+            {
+              // Invalid block
+              for (itF.Initialize(aCB); itF.More(); itF.Next())
+                aFacesToAvoid.Add(itF.Value());
+            }
+          }
+        }
+      }
+
+      itLF.Initialize(aLFTrimmed);
+      for (; itLF.More();)
+      {
+        if (aFacesToAvoid.Contains(itLF.Value()))
+          aLFTrimmed.Remove(itLF);
+        else
+          itLF.Next();
+      }
+    }
+    else if (aLFTrimmed.IsEmpty())
+    {
+      // Use all splits, including those having the bounds of extended face
+      anExpF.ReInit();
+      for (; anExpF.More(); anExpF.Next())
+        aLFTrimmed.Append(anExpF.Current());
+    }
+
+    if (aLFTrimmed.Extent())
+    {
+      // Remove the internal edges and vertices from the faces
+      RemoveInternalWires(aLFTrimmed);
+
+      myFaces.Add(theFOriginal, aLFTrimmed);
+    }
+
+    // Update history after intersection of the extended face with bounds
+    myHistory->Merge<BOPAlgo_Builder>(aGFTrim.Arguments(), aGFTrim);
+
+    // Update history with all removed shapes
+    BRepTools_History aHistRem;
+
+    // Map of the result splits
+    TopTools_IndexedMapOfShape aResMap;
+    TopTools_ListIteratorOfListOfShape itLF(aLFTrimmed);
+    for (; itLF.More(); itLF.Next())
+      TopExp::MapShapes(itLF.Value(), aResMap);
+
+    TopTools_ListOfShape aLSplits;
+    aLSplits.Append(aSplits);
+
+    // Update the history with removed shapes
+    MakeRemoved(aLSplits, aHistRem, aResMap);
+    myHistory->Merge(aHistRem);
+  }
+
+private: //! @name Fields
+
+  // Inputs
+  Standard_Boolean myRunParallel;                     //!< Defines the mode of processing of the single feature
+  TopoDS_Shape myFeature;                             //!< Feature to remove
+  TopTools_IndexedDataMapOfShapeListOfShape* myEFMap; //!< EF Connection map to find adjacent faces
+  TopTools_IndexedDataMapOfShapeListOfShape* myFSMap; //!< FS Connection map to find solids participating in the feature removal
+
+  // Results
+  TopTools_MapOfShape myFeatureFacesMap;              //!< Faces of the feature
+  Standard_Boolean myHasAdjacentFaces;                //!< Flag to show whether the adjacent faces have been found or not
+  TopTools_IndexedMapOfShape mySolids;                //!< Solids participating in the feature removal
+  TopTools_IndexedDataMapOfShapeListOfShape myFaces;  //!< Reconstructed adjacent faces
+  Handle(BRepTools_History) myHistory;                //!< History of the adjacent faces reconstruction
+};
+
+typedef NCollection_Vector<FillGap> VectorOfFillGap;
+
+typedef BOPTools_Functor <FillGap, VectorOfFillGap> FillGapFunctor;
+
+typedef BOPTools_Cnt <FillGapFunctor, VectorOfFillGap> FillGapCnt;
+
+//=======================================================================
+
+//=======================================================================
+// function: RemoveFeatures
+// purpose: Remove features by filling the gaps by extension of the
+//          adjacent faces
+//=======================================================================
+void BOPAlgo_RemoveFeatures::RemoveFeatures()
+{
+  // For each feature:
+  // - Find the faces adjacent to the feature;
+  // - Extend the adjacent faces;
+  // - Trim the extended faces to fill the gap;
+  // - Rebuild the solids with reconstructed adjacent faces
+  //   and avoiding the feature faces.
+
+  // Make Edge-Face connection map of the input
+  // shape to find faces adjacent to the feature
+  TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
+  TopExp::MapShapesAndAncestors(myInputShape, TopAbs_EDGE, TopAbs_FACE, anEFMap);
+
+  // Make Face-Solid connection map to find the solids
+  // participating in the removal of each feature
+  TopTools_IndexedDataMapOfShapeListOfShape anFSMap;
+  TopExp::MapShapesAndAncestors(myInputShape, TopAbs_FACE, TopAbs_SOLID, anFSMap);
+
+  // Tool for reconstruction of the faces adjacent to the feature
+  // in parallel threads if necessary.
+  VectorOfFillGap aVFG;
+  // Fill the vector
+  TopTools_ListIteratorOfListOfShape itF(myFeatures);
+  for (; itF.More(); itF.Next())
+  {
+    const TopoDS_Shape& aFeature = itF.Value();
+    FillGap& aFG = aVFG.Appended();
+    aFG.SetFeature(aFeature);
+    aFG.SetEFConnectionMap(anEFMap);
+    aFG.SetFSConnectionMap(anFSMap);
+    aFG.SetRunParallel(myRunParallel);
+  }
+
+  // Perform the reconstruction of the adjacent faces
+  FillGapCnt::Perform(myRunParallel, aVFG);
+
+  // Even if the history is not requested, it is necessary to track:
+  // - The solids modification after each feature removal to find
+  //   the necessary solids to rebuild on the next step.
+  // - The faces modification after each feature removal to find the
+  //   splits of the adjacent and feature faces for the next steps.
+  if (myHistory.IsNull())
+    myHistory = new BRepTools_History();
+
+  // Remove the features one by one.
+  // It will allow removing the features even if there were
+  // some problems with removal of the previous features.
+  const Standard_Integer aNbF = aVFG.Length();
+  for (Standard_Integer i = 0; i < aNbF; ++i)
+  {
+    FillGap& aFG = aVFG(i);
+
+    // No need to fill the history for solids if the history is not
+    // requested and the current feature is the last one.
+    Standard_Boolean isSolidsHistoryNeeded = myTrackHistory || (i < (aNbF - 1));
+
+    // Perform removal of the single feature
+    RemoveFeature(aFG.Feature(), aFG.Solids(), aFG.FeatureFacesMap(),
+                  aFG.HasAdjacentFaces(), aFG.Faces(), aFG.History(),
+                  isSolidsHistoryNeeded);
+  }
+}
+
+//=======================================================================
+// function: RemoveFeature
+// purpose: Remove the single feature
+//=======================================================================
+void BOPAlgo_RemoveFeatures::RemoveFeature
+  (const TopoDS_Shape& theFeature,
+   const TopTools_IndexedMapOfShape& theSolids,
+   const TopTools_MapOfShape& theFeatureFacesMap,
+   const Standard_Boolean theHasAdjacentFaces,
+   const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
+   const Handle(BRepTools_History)& theAdjFacesHistory,
+   const Standard_Boolean theSolidsHistoryNeeded)
+{
+  Standard_Boolean bFuseShapes = Standard_True;
+  const Standard_Integer aNbAF = theAdjFaces.Extent();
+  if (aNbAF == 0)
+  {
+    if (theHasAdjacentFaces)
+    {
+      // The adjacent faces have been found for the feature,
+      // but something went wrong during their rebuilding.
+      // Add error
+      AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
+      return;
+    }
+
+    // No adjacent faces have been found for the feature.
+    // Most likely, the intention is to remove some internal part of the shape.
+    // We just have to rebuild the shape without the feature, no fuse is necessary.
+    bFuseShapes = Standard_False;
+  }
+
+  // Rebuild the shape using MakerVolume algorithm avoiding the faces of the
+  // feature and replacing the adjacent faces with their images
+
+  BRep_Builder aBB;
+
+  // From the faces of input shape build map of faces with which the result will be validated:
+  // - all non-internal faces of the input shape (except for adjacent and feature faces)
+  //   must have some trace in the result solids;
+  // - all adjacent faces (if any) must have some trace in the result solids.
+  TopTools_IndexedMapOfShape aFacesToBeKept;
+  // Build also the map of faces to compare orientation of the original and result faces
+  TopTools_MapOfShape aFacesToCheckOri;
+
+  // Collect list of internal entities of the input shape to be avoided in result
+  // and to make them removed in the history.
+  TopTools_ListOfShape anInternalShapes;
+
+  // In the feature removal will participate only the solids connected to the feature
+  // or the faces adjacent to the feature.
+
+  // Solids to be rebuilt  after the feature removal
+  TopTools_IndexedMapOfShape aSolidsToRebuild;
+  // Find faces shared between solids
+  TopTools_ListOfShape aSharedFaces;
+  // Solids to be avoided in the feature removal and added into result directly
+  TopTools_ListOfShape anUnTouchedSolids;
+
+  // Prepare to the feature removal - fill all necessary containers
+  GetOriginalFaces(myShape, theSolids, theFeatureFacesMap, theAdjFaces, myHistory,
+                   aFacesToBeKept, anInternalShapes, aFacesToCheckOri,
+                   aSolidsToRebuild, aSharedFaces, anUnTouchedSolids);
+
+  // To avoid excessive intersection of the faces collect the faces
+  // of the input shape into a compound
+  TopoDS_Compound anOrigF;
+  aBB.MakeCompound(anOrigF);
+  Standard_Integer aNbFK = aFacesToBeKept.Extent();
+  for (Standard_Integer i = 1; i <= aNbFK; ++i)
+    aBB.Add(anOrigF, aFacesToBeKept(i));
+
+  // Tool for solids reconstruction
+  BOPAlgo_MakerVolume aMV;
+  aMV.SetRunParallel(myRunParallel);
+  aMV.SetAvoidInternalShapes(Standard_True);
+  aMV.SetIntersect(bFuseShapes);
+  aMV.SetNonDestructive(Standard_True);
+  // Add faces of the input shape
+  aMV.AddArgument(anOrigF);
+
+  // Add reconstructed adjacent faces
+  for (Standard_Integer i = 1; i <= aNbAF; ++i)
+  {
+    const TopTools_ListOfShape& aLFA = theAdjFaces(i);
+    if (aLFA.Extent() == 1)
+    {
+      const TopoDS_Shape& aFA = aLFA.First();
+      aMV.AddArgument(aFA);
+      aFacesToBeKept.Add(aFA);
+    }
+    else
+    {
+      // To avoid intersection among the images, collect them into compound
+      TopoDS_Compound anAdjF;
+      aBB.MakeCompound(anAdjF);
+      TopTools_ListIteratorOfListOfShape itLFA(aLFA);
+      for (; itLFA.More(); itLFA.Next())
+        aBB.Add(anAdjF, itLFA.Value());
+
+      aMV.AddArgument(anAdjF);
+      aFacesToBeKept.Add(anAdjF);
+    }
+
+    if (myTrackHistory)
+    {
+      // Look for internal edges in the original adjacent faces
+      const TopoDS_Shape& aFOr = theAdjFaces.FindKey(i);
+      FindInternals(aFOr, anInternalShapes);
+    }
+  }
+
+  // Build solids
+  aMV.Perform();
+  if (aMV.HasErrors())
+  {
+    // Add warning for the feature
+    AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
+    return;
+  }
+
+  // Result of MV operation
+  const TopoDS_Shape& aSolids = aMV.Shape();
+  TopExp_Explorer anExpS(aSolids, TopAbs_SOLID);
+  if (!anExpS.More())
+  {
+    // No solids have been built - add warning for the feature
+    AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
+    return;
+  }
+
+  // Now, it is necessary to:
+  // - Validate the result by checking faces of the map <aFacesToBeKept>
+  //   to have some parts kept in the resulting solids;
+  // - Remove the solids possibly filling the holes in the original shapes;
+  // - Update history with the history of MakerVolume algorithm.
+
+  // Splits of adjacent faces from previous runs
+  TopTools_MapOfShape anAdjFacesSplits;
+  for (Standard_Integer i = 1; i <= aNbAF; ++i)
+  {
+    const TopoDS_Shape& aF = theAdjFaces.FindKey(i);
+    const TopTools_ListOfShape& aLFIm = myHistory->Modified(aF);
+    if (aLFIm.IsEmpty())
+      anAdjFacesSplits.Add(aF);
+    else
+    {
+      TopTools_ListIteratorOfListOfShape itLFIm(aLFIm);
+      for (; itLFIm.More(); itLFIm.Next())
+        anAdjFacesSplits.Add(itLFIm.Value());
+    }
+  }
+
+  // Validate the result
+  Standard_Boolean bValid = Standard_True;
+  aNbFK = aFacesToBeKept.Extent();
+  for (Standard_Integer i = 1; i <= aNbFK && bValid; ++i)
+  {
+    const TopoDS_Shape& aS = aFacesToBeKept(i);
+    if (anAdjFacesSplits.Contains(aS))
+      continue;
+    TopExp_Explorer anExpF(aS, TopAbs_FACE);
+    for (; anExpF.More(); anExpF.Next())
+    {
+      const TopoDS_Shape& aF = anExpF.Current();
+      if (!aMV.IsDeleted(aF))
+        break;
+    }
+    bValid = anExpF.More();
+  }
+
+  if (!bValid)
+  {
+    // Add warning for the feature
+    AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
+    return;
+  }
+
+  // It is possible that the result of MakerVolume operation contains
+  // some extra solids. Get only correct solids.
+  TopTools_ListOfShape aLSRes;
+  // Remember the removed shapes
+  TopTools_ListOfShape aRemovedShapes;
+  GetValidSolids(aMV, aFacesToCheckOri, aSharedFaces, anOrigF, theSolids.Extent(), aLSRes, aRemovedShapes);
+
+  if (aLSRes.Extent() != theSolids.Extent())
+  {
+    // Add warning for the feature
+    AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
+    return;
+  }
+
+  // Remove internal wires from the faces, possibly appeared after intersection
+  RemoveInternalWires(aLSRes, &anInternalShapes);
+
+  // Update history with:
+  // History of adjacent faces reconstruction
+  myHistory->Merge(theAdjFacesHistory);
+  // History of intersection
+  myHistory->Merge<BOPAlgo_MakerVolume>(aMV.Arguments(), aMV);
+
+  if (myTrackHistory)
+  {
+    // Map the result to check if the shape is removed
+    TopTools_IndexedMapOfShape aMSRes;
+    TopTools_ListIteratorOfListOfShape itLS(aLSRes);
+    for (; itLS.More(); itLS.Next())
+      TopExp::MapShapes(itLS.Value(), aMSRes);
+
+    // Remove internal shapes and extra faces
+    BRepTools_History aRemHist;
+    anInternalShapes.Append(aRemovedShapes);
+    MakeRemoved(anInternalShapes, aRemHist, aMSRes);
+    myHistory->Merge(aRemHist);
+  }
+
+  // Fill the history for the solids
+  if (theSolidsHistoryNeeded)
+  {
+    BRepTools_History aSolidsHistory;
+    FillSolidsHistory(aSolidsToRebuild, aLSRes, theAdjFaces, aMV, aSolidsHistory);
+    myHistory->Merge(aSolidsHistory);
+  }
+
+  TopoDS_Compound aCRes;
+  aBB.MakeCompound(aCRes);
+  // Add reconstructed solids
+  TopTools_ListIteratorOfListOfShape itLS(aLSRes);
+  for (; itLS.More(); itLS.Next())
+    aBB.Add(aCRes, itLS.Value());
+
+  // Add unmodified solids
+  itLS.Initialize(anUnTouchedSolids);
+  for (; itLS.More(); itLS.Next())
+    aBB.Add(aCRes, itLS.Value());
+
+  // Save the result
+  myShape = aCRes;
+}
+
+//=======================================================================
+// function: UpdateHistory
+// purpose: Update history with the removed features
+//=======================================================================
+void BOPAlgo_RemoveFeatures::UpdateHistory()
+{
+  if (!myTrackHistory)
+    return;
+
+  // Map the result
+  TopExp::MapShapes(myShape, myResultMap);
+
+  // Update the history
+  BRepTools_History aHistory;
+
+  const Standard_Integer aNbS = myInputsMap.Extent();
+  for (Standard_Integer i = 1; i <= aNbS; ++i)
+  {
+    const TopoDS_Shape& aS = myInputsMap(i);
+    if (!BRepTools_History::IsSupportedType(aS))
+      continue;
+
+    if (myHistory->IsRemoved(aS))
+      continue;
+
+    // Check if the shape has any trace in the result
+    const TopTools_ListOfShape& aLSIm = myHistory->Modified(aS);
+    if (aLSIm.IsEmpty())
+    {
+      if (!myResultMap.Contains(aS))
+        aHistory.Remove(aS);
+    }
+
+    TopTools_ListIteratorOfListOfShape itLSIm(aLSIm);
+    for (; itLSIm.More(); itLSIm.Next())
+    {
+      if (!myResultMap.Contains(itLSIm.Value()))
+        aHistory.Remove(itLSIm.Value());
+    }
+  }
+
+  myHistory->Merge(aHistory);
+}
+
+//=======================================================================
+// function: SimplifyResult
+// purpose: Simplifies the result by removing extra edges and vertices
+//          created during operation
+//=======================================================================
+void BOPAlgo_RemoveFeatures::SimplifyResult()
+{
+  if (myShape.IsSame(myInputShape))
+    return;
+  ShapeUpgrade_UnifySameDomain aSDTool;
+  aSDTool.Initialize(myShape, Standard_True, Standard_True);
+  // Do not allow producing internal edges
+  aSDTool.AllowInternalEdges(Standard_False);
+  // Avoid removal of the input edges and vertices
+  if (myResultMap.IsEmpty())
+    TopExp::MapShapes(myShape, myResultMap);
+
+  const Standard_Integer aNbS = myInputsMap.Extent();
+  for (Standard_Integer i = 1; i <= aNbS; ++i)
+  {
+    if (myResultMap.Contains(myInputsMap(i)))
+      aSDTool.KeepShape(myInputsMap(i));
+  }
+
+  // Perform unification
+  aSDTool.Build();
+  myShape = aSDTool.Shape();
+  if (myTrackHistory)
+    myHistory->Merge(aSDTool.History());
+}
+
+//=======================================================================
+// function: PostTreat
+// purpose: Restore the type of the initial shape
+//=======================================================================
+void BOPAlgo_RemoveFeatures::PostTreat()
+{
+  const TopAbs_ShapeEnum anInputType = myInputShape.ShapeType();
+  const TopAbs_ShapeEnum aResType = myShape.ShapeType();
+  if (aResType == anInputType)
+    return;
+
+  TopExp_Explorer anExpS(myShape, TopAbs_SOLID);
+
+  if (anInputType == TopAbs_SOLID)
+  {
+    myShape = anExpS.Current();
+    return;
+  }
+
+  TopoDS_Shape aRes;
+  if (anInputType == TopAbs_COMPOUND)
+    BRep_Builder().MakeCompound(TopoDS::Compound(aRes));
+  else
+    BRep_Builder().MakeCompSolid(TopoDS::CompSolid(aRes));
+
+  for (; anExpS.More(); anExpS.Next())
+    BRep_Builder().Add(aRes, anExpS.Current());
+
+  myShape = aRes;
+}
+
+//=======================================================================
+// static methods definition
+//=======================================================================
+
+//=======================================================================
+// function: MakeRemoved
+// purpose: Makes the shapes in the list removed in the history.
+//          Keeps the shapes contained in the map.
+//=======================================================================
+void MakeRemoved(const TopTools_ListOfShape& theShapes,
+                 BRepTools_History& theHistory,
+                 const TopTools_IndexedMapOfShape& theKeepShapes)
+{
+  TopTools_IndexedMapOfShape aShapesMap;
+  TopTools_ListIteratorOfListOfShape it(theShapes);
+  for (; it.More(); it.Next())
+    TopExp::MapShapes(it.Value(), aShapesMap);
+
+  const Standard_Integer aNbS = aShapesMap.Extent();
+  for (Standard_Integer i = 1; i <= aNbS; ++i)
+  {
+    const TopoDS_Shape& aS = aShapesMap(i);
+    if (!theKeepShapes.Contains(aS) &&
+        BRepTools_History::IsSupportedType(aS))
+    {
+      theHistory.Remove(aS);
+    }
+  }
+}
+
+//=======================================================================
+// function: FindInternals
+// purpose: Looks for internal shapes inside the face or solid
+//=======================================================================
+void FindInternals(const TopoDS_Shape& theS,
+                   TopTools_ListOfShape& theLInt)
+{
+  TopoDS_Iterator itS(theS);
+  for (; itS.More(); itS.Next())
+  {
+    const TopoDS_Shape& aSS = itS.Value();
+    if (aSS.Orientation() == TopAbs_INTERNAL)
+      theLInt.Append(aSS);
+    else
+    {
+      TopoDS_Iterator itSS(aSS);
+      for (; itSS.More(); itSS.Next())
+      {
+        if (itSS.Value().Orientation() == TopAbs_INTERNAL)
+        {
+          theLInt.Append(aSS);
+          break;
+        }
+      }
+    }
+  }
+}
+
+//=======================================================================
+// function: RemoveInternalWires
+// purpose: Removes internal wires from the faces
+//=======================================================================
+void RemoveInternalWires(const TopTools_ListOfShape& theShapes,
+                         TopTools_ListOfShape *theRemoved)
+{
+  TopTools_ListIteratorOfListOfShape itLS(theShapes);
+  for (; itLS.More(); itLS.Next())
+  {
+    const TopoDS_Shape& aShape = itLS.Value();
+    TopExp_Explorer anExpF(aShape, TopAbs_FACE);
+    for (; anExpF.More(); anExpF.Next())
+    {
+      TopoDS_Face& aF = *(TopoDS_Face*)&anExpF.Current();
+      TopTools_ListOfShape aLWToRemove;
+      FindInternals(aF, aLWToRemove);
+      if (aLWToRemove.Extent())
+      {
+        aF.Free(Standard_True);
+        TopTools_ListIteratorOfListOfShape itR(aLWToRemove);
+        for (; itR.More(); itR.Next())
+        {
+          if (theRemoved)
+            theRemoved->Append(itR.Value());
+          BRep_Builder().Remove(aF, itR.Value());
+        }
+        aF.Free(Standard_False);
+      }
+    }
+  }
+}
+
+//=======================================================================
+// function: GetOriginalFaces
+// purpose: Get original faces from my face
+//=======================================================================
+void GetOriginalFaces(const TopoDS_Shape& theShape,
+                      const TopTools_IndexedMapOfShape& theSolids,
+                      const TopTools_MapOfShape& theFeatureFacesMap,
+                      const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
+                      const Handle(BRepTools_History)& theHistory,
+                      TopTools_IndexedMapOfShape& theFacesToBeKept,
+                      TopTools_ListOfShape& theInternalShapes,
+                      TopTools_MapOfShape& theFacesToCheckOri,
+                      TopTools_IndexedMapOfShape& theSolidsToRebuild,
+                      TopTools_ListOfShape& theSharedFaces,
+                      TopTools_ListOfShape& theUnTouchedSolids)
+{
+  // Use only solids which has to be reconstructed by the feature.
+  // All other solids should be avoided in the feature removal and added
+  // into result directly.
+
+  // Update solids after removal of previous features
+  const Standard_Integer aNbSols = theSolids.Extent();
+  for (Standard_Integer i = 1; i <= aNbSols; ++i)
+  {
+    const TopoDS_Shape& aSol = theSolids(i);
+    const TopTools_ListOfShape& aLFIm = theHistory->Modified(aSol);
+    if (aLFIm.IsEmpty())
+      theSolidsToRebuild.Add(aSol);
+    else
+      theSolidsToRebuild.Add(aLFIm.First());
+  }
+
+  // Splits of the feature faces
+  TopTools_MapOfShape aFeatureFacesSplits;
+  TopTools_MapIteratorOfMapOfShape itM(theFeatureFacesMap);
+  for (; itM.More(); itM.Next())
+  {
+    const TopoDS_Shape& aF = itM.Value();
+    const TopTools_ListOfShape& aLFIm = theHistory->Modified(aF);
+    if (aLFIm.IsEmpty())
+      aFeatureFacesSplits.Add(aF);
+    else
+    {
+      TopTools_ListIteratorOfListOfShape itLFIm(aLFIm);
+      for (; itLFIm.More(); itLFIm.Next())
+        aFeatureFacesSplits.Add(itLFIm.Value());
+    }
+  }
+
+  TopExp_Explorer anExpS(theShape, TopAbs_SOLID);
+  for (; anExpS.More(); anExpS.Next())
+  {
+    const TopoDS_Shape& aSol = anExpS.Current();
+
+    // Check if the solid has to be reconstructed
+    if (!theSolidsToRebuild.Contains(aSol))
+    {
+      // untouched solid
+      theUnTouchedSolids.Append(aSol);
+      continue;
+    }
+
+    TopoDS_Iterator itSh(aSol);
+    for (; itSh.More(); itSh.Next())
+    {
+      const TopoDS_Shape& aSh = itSh.Value();
+      if (aSh.ShapeType() != TopAbs_SHELL)
+      {
+        theInternalShapes.Append(aSh);
+        continue;
+      }
+
+      TopoDS_Iterator itF(aSh);
+      for (; itF.More(); itF.Next())
+      {
+        const TopoDS_Shape& aF = itF.Value();
+        // Avoid the feature faces
+        if (aFeatureFacesSplits.Contains(aF))
+          continue;
+
+        // Avoid the adjacent faces
+        if (theAdjFaces.Contains(aF))
+          continue;
+
+        if (aF.Orientation() != TopAbs_INTERNAL)
+        {
+          theFacesToBeKept.Add(aF);
+
+          if (!theFacesToCheckOri.Add(aF))
+          {
+            theFacesToCheckOri.Remove(aF);
+            theSharedFaces.Append(aF);
+          }
+        }
+        else
+          theInternalShapes.Append(aSh);
+      }
+    }
+  }
+}
+
+//=======================================================================
+// function: FindShape
+// purpose: Find the shape in the other shape
+//=======================================================================
+void FindShape(const TopoDS_Shape& theSWhat,
+               const TopoDS_Shape& theSWhere,
+               TopoDS_Shape& theSFound)
+{
+  TopExp_Explorer anExp(theSWhere, theSWhat.ShapeType());
+  for (; anExp.More(); anExp.Next())
+  {
+    const TopoDS_Shape& aS = anExp.Current();
+    if (aS.IsSame(theSWhat))
+    {
+      theSFound = aS;
+      break;
+    }
+  }
+}
+
+//=======================================================================
+// function: GetValidSolids
+// purpose: Checks the validity of the solids and keeps only valid ones
+//=======================================================================
+void GetValidSolids(BOPAlgo_MakerVolume& theMV,
+                    const TopTools_MapOfShape& theFacesToCheckOri,
+                    const TopTools_ListOfShape& aSharedFaces,
+                    const TopoDS_Shape& theOrigFaces,
+                    const Standard_Integer theNbSol,
+                    TopTools_ListOfShape& theLSRes,
+                    TopTools_ListOfShape& theRemovedShapes)
+{
+  TopExp_Explorer anExpS(theMV.Shape(), TopAbs_SOLID);
+  for (; anExpS.More(); anExpS.Next())
+    theLSRes.Append(anExpS.Current());
+
+  if (theLSRes.Extent() > theNbSol)
+  {
+    // Find Solids filling the holes in the initial shape
+    TopTools_MapOfShape aSolidsToAvoid;
+    TopTools_IndexedDataMapOfShapeListOfShape aFSMap;
+    TopExp::MapShapesAndAncestors(theMV.Shape(), TopAbs_FACE, TopAbs_SOLID, aFSMap);
+    FindExtraShapes(aFSMap, theFacesToCheckOri, theMV, aSolidsToAvoid);
+
+    TopTools_ListIteratorOfListOfShape itLS(theLSRes);
+    for (; itLS.More(); )
+    {
+      if (aSolidsToAvoid.Contains(itLS.Value()))
+        theLSRes.Remove(itLS);
+      else
+        itLS.Next();
+    }
+  }
+
+  if (theLSRes.Extent() > theNbSol)
+  {
+    // Check if the splits of the adjacent faces split the solids
+    AvoidExtraSharedFaces(theLSRes, aSharedFaces, theMV, theRemovedShapes);
+  }
+
+  if (theLSRes.Extent() > theNbSol)
+  {
+    // Remove solids containing only the adjacent faces
+    TopTools_MapOfShape anOrigFacesRes;
+    TopExp_Explorer anExpF(theOrigFaces, TopAbs_FACE);
+    for (; anExpF.More(); anExpF.Next())
+      TakeModified(anExpF.Current(), theMV, anOrigFacesRes);
+
+    TopTools_ListIteratorOfListOfShape itLS(theLSRes);
+    for (; itLS.More(); )
+    {
+      anExpF.Init(itLS.Value(), TopAbs_FACE);
+      for (; anExpF.More(); anExpF.Next())
+      {
+        if (anOrigFacesRes.Contains(anExpF.Current()))
+          break;
+      }
+      if (!anExpF.More())
+      {
+        theRemovedShapes.Append(itLS.Value());
+        theLSRes.Remove(itLS);
+      }
+      else
+        itLS.Next();
+    }
+  }
+}
+
+//=======================================================================
+// function: FindExtraShape
+// purpose: Find shapes possibly filling the holes in the original shape
+//=======================================================================
+void FindExtraShapes(const TopTools_IndexedDataMapOfShapeListOfShape& theConnectionMap,
+                     const TopTools_MapOfShape& theShapesToCheckOri,
+                     BOPAlgo_Builder& theBuilder,
+                     TopTools_MapOfShape& theShapesToAvoid,
+                     TopTools_MapOfShape* theValidShapes)
+{
+  Handle(IntTools_Context) aCtx = theBuilder.Context();
+  TopTools_MapOfShape aValidShapes;
+  TopTools_MapOfShape* pValidShapes = theValidShapes ? theValidShapes : &aValidShapes;
+  TopTools_MapIteratorOfMapOfShape itM(theShapesToCheckOri);
+  for (; itM.More(); itM.Next())
+  {
+    const TopoDS_Shape& aSToCheckOri = itM.Value();
+    // Check modification of the shape during intersection
+    TopTools_ListOfShape aLSIm;
+    TakeModified(aSToCheckOri, theBuilder, aLSIm);
+
+    TopTools_ListIteratorOfListOfShape itLSIm(aLSIm);
+    for (; itLSIm.More(); itLSIm.Next())
+    {
+      const TopoDS_Shape& aSIm = itLSIm.Value();
+
+      const TopTools_ListOfShape* pShapesToValidate = theConnectionMap.Seek(aSIm);
+      if (!pShapesToValidate)
+        continue;
+
+      TopTools_ListIteratorOfListOfShape itSV(*pShapesToValidate);
+      for (; itSV.More(); itSV.Next())
+      {
+        const TopoDS_Shape& aShapeToValidate = itSV.Value();
+        if (pValidShapes->Contains(aShapeToValidate))
+          continue;
+
+        TopoDS_Face aSInShape;
+        FindShape(aSIm, aShapeToValidate, aSInShape);
+
+        Standard_Boolean bSameOri =
+          !BOPTools_AlgoTools::IsSplitToReverse(aSInShape, aSToCheckOri, aCtx);
+
+        if (bSameOri)
+          pValidShapes->Add(aShapeToValidate);
+        else
+          theShapesToAvoid.Add(aShapeToValidate);
+      }
+    }
+  }
+
+  itM.Initialize(*pValidShapes);
+  for (; itM.More(); itM.Next())
+    theShapesToAvoid.Remove(itM.Value());
+}
+
+//=======================================================================
+// function: AvoidExtraSharedFaces
+// purpose: Looks for the extra faces splitting the solids
+//=======================================================================
+void AvoidExtraSharedFaces(TopTools_ListOfShape& theLSolids,
+                           const TopTools_ListOfShape& theLFSharedToAvoid,
+                           BOPAlgo_Builder& theBuilder,
+                           TopTools_ListOfShape& theExtraFaces)
+{
+  // Get all splits of shared faces to avoid in the check
+  TopTools_MapOfShape aMFSharedSp;
+  {
+    TopTools_ListOfShape aLFSharedSp;
+    TopTools_ListIteratorOfListOfShape itLFS(theLFSharedToAvoid);
+    for (; itLFS.More(); itLFS.Next())
+      TakeModified(itLFS.Value(), theBuilder, aMFSharedSp);
+  }
+
+  TopTools_IndexedDataMapOfShapeListOfShape aFSMap;
+  TopTools_ListIteratorOfListOfShape itLS(theLSolids);
+  for (; itLS.More(); itLS.Next())
+    TopExp::MapShapesAndAncestors(itLS.Value(), TopAbs_FACE, TopAbs_SOLID, aFSMap);
+
+  TopTools_ListOfShape anExtraFaces;
+  TopTools_ListOfShape aLFArguments;
+  itLS.Initialize(theLSolids);
+  for (; itLS.More(); itLS.Next())
+  {
+    const TopoDS_Shape& aSol = itLS.Value();
+    TopExp_Explorer anExpF(aSol, TopAbs_FACE);
+    for (; anExpF.More(); anExpF.Next())
+    {
+      const TopoDS_Shape& aF = anExpF.Current();
+      const TopTools_ListOfShape& aLSol = aFSMap.FindFromKey(aF);
+      if (aLSol.Extent() != 2 || aMFSharedSp.Contains(aF))
+        aLFArguments.Append(aF);
+      else
+        anExtraFaces.Append(aF);
+    }
+  }
+
+  if (anExtraFaces.IsEmpty())
+    return;
+
+  // Rebuild the solids avoiding the extra faces
+  BOPAlgo_BuilderSolid aBS;
+  aBS.SetAvoidInternalShapes(Standard_True);
+  aBS.SetShapes(aLFArguments);
+  aBS.Perform();
+  if (aBS.HasErrors())
+    return;
+
+  theLSolids = aBS.Areas();
+  theExtraFaces.Append(anExtraFaces);
+}
+
+//=======================================================================
+// function: FillSolidsHistory
+// purpose: Fills the history of solids modifications
+//=======================================================================
+void FillSolidsHistory(const TopTools_IndexedMapOfShape& theSolIn,
+                       TopTools_ListOfShape& theSolidsOut,
+                       const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
+                       BOPAlgo_Builder& theBuilder,
+                       BRepTools_History& theSolidsHistory)
+{
+  const Standard_Integer aNbS = theSolIn.Extent();
+  for (Standard_Integer i = 1; i <= aNbS; ++i)
+  {
+    const TopoDS_Shape& aSolIn = theSolIn(i);
+
+    TopoDS_Shape aSolOut;
+    FindSolid(aSolIn, theSolidsOut, theAdjFaces, theBuilder, aSolOut);
+
+    if (aSolOut.IsNull())
+    {
+      theSolidsHistory.Remove(aSolIn);
+      continue;
+    }
+
+    // Check if the solid has really been modified
+    BOPTools_Set aSTIn, aSTOut;
+    aSTIn.Add(aSolIn, TopAbs_FACE);
+    aSTOut.Add(aSolOut, TopAbs_FACE);
+    if (aSTIn.IsEqual(aSTOut))
+    {
+      // The solids are the same. Replace the resulting solid in the result list
+      // with the initial solid.
+      TopTools_ListIteratorOfListOfShape itLS(theSolidsOut);
+      for (; itLS.More(); itLS.Next())
+      {
+        if (itLS.Value().IsSame(aSolOut))
+        {
+          theSolidsOut.InsertBefore(aSolIn, itLS);
+          theSolidsOut.Remove(itLS);
+          break;
+        }
+      }
+    }
+    else
+    {
+      theSolidsHistory.AddModified(aSolIn, aSolOut);
+    }
+  }
+}
+
+//=======================================================================
+// function: TakeModified
+// purpose: Stores the modified object into the list
+//=======================================================================
+void TakeModified(const TopoDS_Shape& theS,
+                  BOPAlgo_Builder& theBuilder,
+                  TopTools_ListOfShape& theList)
+{
+  const TopTools_ListOfShape& aModified = theBuilder.Modified(theS);
+  if (aModified.IsEmpty() && !theBuilder.IsDeleted(theS))
+    theList.Append(theS);
+  else
+  {
+    TopTools_ListIteratorOfListOfShape itM(aModified);
+    for (; itM.More(); itM.Next())
+      theList.Append(itM.Value());
+  }
+}
+//=======================================================================
+// function: TakeModified
+// purpose: Stores the modified object into the map
+//=======================================================================
+void TakeModified(const TopoDS_Shape& theS,
+                  BOPAlgo_Builder& theBuilder,
+                  TopTools_MapOfShape& theMap)
+{
+  const TopTools_ListOfShape& aModified = theBuilder.Modified(theS);
+  if (aModified.IsEmpty() && !theBuilder.IsDeleted(theS))
+    theMap.Add(theS);
+  else
+  {
+    TopTools_ListIteratorOfListOfShape itM(aModified);
+    for (; itM.More(); itM.Next())
+      theMap.Add(itM.Value());
+  }
+}
+
+//=======================================================================
+// function: FindSolid
+// purpose: Looks for the image of the solid in the list of resulting solids
+//=======================================================================
+void FindSolid(const TopoDS_Shape& theSolIn,
+               const TopTools_ListOfShape& theSolidsRes,
+               const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
+               BOPAlgo_Builder& theBuilder,
+               TopoDS_Shape& theSolOut)
+{
+  Handle(IntTools_Context) aCtx = theBuilder.Context();
+
+  // Take the face in the IN solid, and find it in the OUT list
+  TopExp_Explorer anExpF(theSolIn, TopAbs_FACE);
+  for (; anExpF.More(); anExpF.Next())
+  {
+    const TopoDS_Shape& aFS = anExpF.Current();
+    // Images of the face
+    TopTools_MapOfShape aMFSIm;
+    const TopTools_ListOfShape* pLFA = theAdjFaces.Seek(aFS);
+    if (pLFA)
+    {
+      TopTools_ListIteratorOfListOfShape itLFA(*pLFA);
+      for (; itLFA.More(); itLFA.Next())
+        TakeModified(itLFA.Value(), theBuilder, aMFSIm);
+    }
+    else
+    {
+      TakeModified(aFS, theBuilder, aMFSIm);
+    }
+
+    // Find any of these faces in the list of solids
+    TopTools_ListIteratorOfListOfShape itLS(theSolidsRes);
+    for (; itLS.More(); itLS.Next())
+    {
+      const TopoDS_Shape& aSol = itLS.Value();
+      TopExp_Explorer anExpFOut(aSol, TopAbs_FACE);
+      for (; anExpFOut.More(); anExpFOut.Next())
+      {
+        const TopoDS_Shape& aF = anExpFOut.Current();
+        if (aMFSIm.Contains(aF))
+        {
+          // check orientations
+          if (!BOPTools_AlgoTools::IsSplitToReverse(aF, aFS, aCtx))
+          {
+            theSolOut = aSol;
+            return;
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/BOPAlgo/BOPAlgo_RemoveFeatures.hxx b/src/BOPAlgo/BOPAlgo_RemoveFeatures.hxx
new file mode 100644 (file)
index 0000000..365488e
--- /dev/null
@@ -0,0 +1,315 @@
+// Created by: Eugeny MALTCHIKOV
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BOPAlgo_RemoveFeatures_HeaderFile
+#define _BOPAlgo_RemoveFeatures_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <BOPAlgo_Options.hxx>
+#include <BRepTools_History.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
+
+//! The RemoveFeatures algorithm is intended for reconstruction of
+//! the shape by removal of the unwanted parts from it. These parts can
+//! be holes, protrusions, spikes, fillets etc.
+//! The shape itself is not modified, the new shape is built in
+//! the result.
+//!
+//! Currently, only the shapes of type SOLID, COMPSOLID, and
+//! COMPOUND of Solids are supported. And only the FACEs can be
+//! removed from the shape.
+//!
+//! On the input the algorithm accepts the shape itself and the
+//! faces which have to be removed. It does not matter how the faces
+//! are given. It could be the separate faces or the collections of faces.
+//! The faces should belong to the initial shape, and those that
+//! do not belong will be ignored.
+//! Before reconstructing the shape, the algorithm will sort all
+//! the given faces on the connected blocks (features).
+//!
+//! The features will be removed from the shape one by one.
+//! It will allow removing all possible features even if there
+//! were problems with the removal of some of them.
+//!
+//! The removed feature is filled by the extension of the faces adjacent
+//! to the feature. In general, the algorithm of removing of the single
+//! feature from the shape looks as follows:
+//! - Find the faces adjacent to the feature;
+//! - Extend the adjacent faces to cover the feature;
+//! - Trim the extended faces by the bounds of original face
+//!   (except for bounds common with the feature), so it will cover
+//!   the feature only;
+//! - Rebuild the solids with reconstructed adjacent faces
+//!   avoiding the faces from the feature.
+//!
+//! If the removal is successful, the result is overwritten with the
+//! new shape and the next feature is treated. Otherwise, the warning
+//! will be given.
+//!
+//! The algorithm has the following options:
+//! - History support;
+//!
+//! and the options available from base class:
+//! - Error/Warning reporting system;
+//! - Parallel processing mode.
+//!
+//! Please note that the other options of the base class are not supported
+//! here and will have no effect.
+//!
+//! <b>History support</b> allows tracking modification of the input shape
+//! in terms of Modified, IsDeleted and Generated. The history is
+//! available through the methods of the history tool *BRepTools_History*,
+//! which can be accessed here through the method *History()*.
+//! By default, the history is collected, but it is possible to disable it
+//! using the method *TrackHistory(false)*;
+//!
+//! <b>Error/Warning reporting system</b> - allows obtaining the extended overview
+//! of the Errors/Warnings occurred during the operation. As soon as any error
+//! appears the algorithm stops working. The warnings allow continuing the job,
+//! informing the user that something went wrong.
+//! The algorithm returns the following errors/warnings:
+//! - *BOPAlgo_AlertTooFewArguments* - the error alert is given if the input
+//!     shape does not contain any solids;
+//! - *BOPAlgo_AlertUnsupportedType* - the warning alert is given if the input
+//!     shape contains not only solids, but also other shapes;
+//! - *BOPAlgo_AlertNoFacesToRemove* - the error alert is given in case
+//!     there are no faces to remove from the shape (nothing to do);
+//! - *BOPAlgo_AlertUnableToRemoveTheFeature* - the warning alert is given to
+//!     inform the user the removal of the feature is not possible. The algorithm
+//!     will still try to remove the other features;
+//! - *BOPAlgo_AlertRemoveFeaturesFailed* - the error alert is given in case if
+//!     the operation was aborted by the unknown reason.
+//!
+//! <b>Parallel processing mode</b> - allows running the algorithm in parallel mode
+//! obtaining the result faster.
+//!
+//! The algorithm has certain limitations:
+//! - Intersection of the connected faces adjacent to the feature should not be empty.
+//!   It means, that such faces should not be tangent to each other.
+//!   If the intersection of the adjacent faces will be empty, the algorithm will
+//!   be unable to trim the faces correctly and, most likely, the feature will not be removed.
+//! - The algorithm does not process the INTERNAL parts of the solids, they are simply
+//!   removed during reconstruction.
+//!
+//! Note that for successful removal of the feature, the extended faces adjacent
+//! to the feature should cover the feature completely, otherwise the solids will
+//! not be rebuild.
+//!
+//! Here is the example of usage of the algorithm:
+//! ~~~~
+//! TopoDS_Shape aSolid = ...;              // Input shape to remove the features from
+//! TopTools_ListOfShape aFaces = ...;      // Faces to remove from the shape
+//! Standard_Boolean bRunParallel = ...;    // Parallel processing mode
+//! Standard_Boolean isHistoryNeeded = ...; // History support
+//!
+//! BOPAlgo_RemoveFeatures aRF;             // Feature removal algorithm
+//! aRF.SetShape(aSolid);                   // Set the shape
+//! aRF.AddFacesToRemove(aFaces);           // Add faces to remove
+//! aRF.SetRunParallel(bRunParallel);       // Define the processing mode (parallel or single)
+//! aRF.TrackHistory(isHistoryNeeded);      // Define whether to track the shapes modifications
+//! aRF.Perform();                          // Perform the operation
+//! if (aRF.HasErrors())                    // Check for the errors
+//! {
+//!   // error treatment
+//!   return;
+//! }
+//! if (aRF.HasWarnings())                  // Check for the warnings
+//! {
+//!   // warnings treatment
+//! }
+//! const TopoDS_Shape& aResult = aRF.Shape(); // Result shape
+//! ~~~~
+//!
+//! The algorithm preserves the type of the input shape in the result shape. Thus,
+//! if the input shape is a COMPSOLID, the resulting solids will also be put into a COMPSOLID.
+//!
+//! When all possible features are removed, the shape is simplified by
+//! removing extra edges and vertices, created during operation, from the result shape.
+//!
+class BOPAlgo_RemoveFeatures: public BOPAlgo_Options
+{
+public:
+  DEFINE_STANDARD_ALLOC
+
+public: //! @name Constructors
+
+  //! Empty constructor
+  BOPAlgo_RemoveFeatures()
+  :
+    BOPAlgo_Options(),
+    myTrackHistory(Standard_True)
+  {
+  }
+
+
+public: //! @name Setting input data for the algorithm
+
+  //! Sets the shape for processing.
+  //! @param theShape [in] The shape to remove the faces from.
+  //!                      It should either be the SOLID, COMPSOLID or COMPOUND of Solids.
+  void SetShape(const TopoDS_Shape& theShape)
+  {
+    myInputShape = theShape;
+  }
+
+  //! Returns the input shape
+  const TopoDS_Shape& InputShape() const
+  {
+    return myInputShape;
+  }
+
+  //! Adds the face to remove from the input shape.
+  //! @param theFace [in] The shape to extract the faces for removal.
+  void AddFaceToRemove(const TopoDS_Shape& theFace)
+  {
+    myFacesToRemove.Append(theFace);
+  }
+
+  //! Adds the faces to remove from the input shape.
+  //! @param theFaces [in] The list of shapes to extract the faces for removal.
+  void AddFacesToRemove(const TopTools_ListOfShape& theFaces)
+  {
+    TopTools_ListIteratorOfListOfShape it(theFaces);
+    for (; it.More(); it.Next())
+      myFacesToRemove.Append(it.Value());
+  }
+
+  //! Returns the list of faces which have been requested for removal
+  //! from the input shape.
+  const TopTools_ListOfShape& FacesToRemove() const
+  {
+    return myFacesToRemove;
+  }
+
+
+public: //! @name Performing the operation
+
+  //! Performs the operation
+  Standard_EXPORT void Perform();
+
+
+public: //! @name Clearing the contents of the algorithm
+
+  //! Clears the contents of the algorithm from previous run,
+  //! allowing reusing it for following removals.
+  void Clear()
+  {
+    BOPAlgo_Options::Clear();
+    myHistory.Nullify();
+    myInputShape.Nullify();
+    myShape.Nullify();
+    myFacesToRemove.Clear();
+    myFeatures.Clear();
+    myInputsMap.Clear();
+    myResultMap.Clear();
+  }
+
+
+public: //! @name History support
+
+  //! Defines whether to track the modification of the shapes or not
+  void TrackHistory(const Standard_Boolean theFlag)
+  {
+    myTrackHistory = theFlag;
+  }
+
+  //! Gets the History object
+  Handle(BRepTools_History) History()
+  {
+    return (myTrackHistory ? myHistory : NULL);
+  }
+
+
+public: //! @name Obtaining the results
+
+  //! Returns the resulting shape
+  const TopoDS_Shape& Shape() const
+  {
+    return myShape;
+  }
+
+
+protected: //! @name Protected methods performing the removal
+
+  //! Checks the input data on validity for the algorithm:
+  //! - The input shape must be either a SOLID, COMPSOLID or COMPOUND of Solids.
+  //! If the input shape is not a solid, the method looks for the solids
+  //! in <myInputShape> and uses only them. All other shapes are simply removed.
+  //! If no solids were found, the Error of unsupported type is returned.
+  Standard_EXPORT void CheckData();
+
+  //! Prepares the faces to remove:
+  //! - Gets only faces contained in the input solids;
+  //! - Builds connected blocks of faces creating separate features to remove.
+  Standard_EXPORT void PrepareFeatures();
+
+  //! Removes the features and fills the created gaps by extension of the adjacent faces.
+  //! Processes each feature separately.
+  Standard_EXPORT void RemoveFeatures();
+
+  //! Remove the single feature from the shape.
+  //! @param theFeature [in] The feature to remove;
+  //! @param theSolids [in] The solids to be reconstructed after feature removal;
+  //! @param theFeatureFacesMap [in] The map of feature faces;
+  //! @param theHasAdjacentFaces [in] Shows whether the adjacent faces have been
+  //!                                 found for the feature or not;
+  //! @param theAdjFaces [in] The reconstructed adjacent faces covering the feature;
+  //! @param theAdjFacesHistory [in] The history of the adjacent faces reconstruction;
+  //! @param theSolidsHistoryNeeded [in] Defines whether the history of solids
+  //!                                    modifications should be tracked or not.
+  Standard_EXPORT void RemoveFeature(const TopoDS_Shape& theFeature,
+                                     const TopTools_IndexedMapOfShape& theSolids,
+                                     const TopTools_MapOfShape& theFeatureFacesMap,
+                                     const Standard_Boolean theHasAdjacentFaces,
+                                     const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
+                                     const Handle(BRepTools_History)& theAdjFacesHistory,
+                                     const Standard_Boolean theSolidsHistoryNeeded);
+
+  //! Updates history with the removed features
+  Standard_EXPORT void UpdateHistory();
+
+  //! Simplifies the result by removing extra edges and vertices created
+  //! during removal of the features.
+  Standard_EXPORT void SimplifyResult();
+
+  //! Post treatment - restore the type of the initial shape
+  Standard_EXPORT void PostTreat();
+
+protected: //! @name Fields
+
+  // Inputs
+  TopoDS_Shape myInputShape;              //!< Input shape
+  TopTools_ListOfShape myFacesToRemove;   //!< Faces to remove
+  Standard_Boolean myTrackHistory;        //!< Defines whether to track the history of shapes
+                                          //! modifications or not (true by default)
+
+  // Intermediate
+  TopTools_ListOfShape myFeatures;        //!< List of not connected features to remove
+                                          //! (each feature is a compound of faces)
+  TopTools_IndexedMapOfShape myInputsMap; //!< Map of all sub-shapes of the input shape
+  TopTools_MapOfShape myResultMap;        //!< Map of all sub-shapes of the result shape
+
+  // Results
+  TopoDS_Shape myShape;                   //!< Result shape
+  Handle(BRepTools_History) myHistory;    //!< History tool
+};
+
+#endif // _BOPAlgo_RemoveFeatures_HeaderFile
index 37036eb..deaff6e 100644 (file)
@@ -53,6 +53,8 @@ BOPAlgo_PBuilder.hxx
 BOPAlgo_PPaveFiller.hxx
 BOPAlgo_PSection.hxx
 BOPAlgo_PWireEdgeSet.hxx
+BOPAlgo_RemoveFeatures.cxx
+BOPAlgo_RemoveFeatures.hxx
 BOPAlgo_Section.cxx
 BOPAlgo_Section.hxx
 BOPAlgo_SectionAttribute.hxx
index edd9c37..d4736b5 100644 (file)
 #include <NCollection_Map.hxx>
 #include <MeshTest.hxx>
 #include <Message.hxx>
+#include <Message_Alert.hxx>
 #include <Message_Msg.hxx>
 #include <Message_Messenger.hxx>
+#include <Message_Report.hxx>
 #include <SWDRAW.hxx>
 #include <TopoDS_AlertWithShape.hxx>
 
-#include <BOPAlgo_Algo.hxx>
+#include <BOPAlgo_Alerts.hxx>
 #include <BOPTest_Objects.hxx>
 
 //=======================================================================
@@ -55,6 +57,7 @@ void  BOPTest::AllCommands(Draw_Interpretor& theCommands)
   BOPTest::DebugCommands     (theCommands);
   BOPTest::CellsCommands     (theCommands);
   BOPTest::UtilityCommands   (theCommands);
+  BOPTest::RemoveFeaturesCommands(theCommands);
 }
 //=======================================================================
 //function : Factory
@@ -84,7 +87,7 @@ DPLUGIN(BOPTest)
 //purpose  : 
 //=======================================================================
 
-void BOPTest::ReportAlerts (const BOPAlgo_Algo& theAlgorithm)
+void BOPTest::ReportAlerts(const Handle(Message_Report)& theReport)
 {
   // first report warnings, then errors
   Message_Gravity anAlertTypes[2] = { Message_Warning, Message_Fail };
@@ -92,11 +95,12 @@ void BOPTest::ReportAlerts (const BOPAlgo_Algo& theAlgorithm)
   {
     // report shapes for the same type of alert together
     NCollection_Map<Handle(Standard_Transient)> aPassedTypes;
-    const Message_ListOfAlert& aList = theAlgorithm.GetReport()->GetAlerts (anAlertTypes[iGravity]);
+    const Message_ListOfAlert& aList = theReport->GetAlerts (anAlertTypes[iGravity]);
     for (Message_ListOfAlert::Iterator aIt (aList); aIt.More(); aIt.Next())
     {
       // check that this type of warnings has not yet been processed
-      if (! aPassedTypes.Add (aIt.Value()->DynamicType()))
+      const Handle(Standard_Type)& aType = aIt.Value()->DynamicType();
+      if (!aPassedTypes.Add(aType))
         continue;
 
       // get alert message
@@ -112,7 +116,9 @@ void BOPTest::ReportAlerts (const BOPAlgo_Algo& theAlgorithm)
         {
           Handle(TopoDS_AlertWithShape) aShapeAlert = Handle(TopoDS_AlertWithShape)::DownCast (aIt2.Value());
 
-          if (! aShapeAlert.IsNull() && ! aShapeAlert->GetShape().IsNull()) 
+          if (!aShapeAlert.IsNull() &&
+              (aType == aShapeAlert->DynamicType()) &&
+              !aShapeAlert->GetShape().IsNull())
           {
             //
             char aName[80];
index 774ffb0..2787703 100644 (file)
@@ -23,7 +23,7 @@
 #include <Draw_Interpretor.hxx>
 class BOPTest_Objects;
 class BOPTest_DrawableShape;
-class BOPAlgo_Algo;
+class Message_Report;
 
 class BOPTest 
 {
@@ -60,9 +60,11 @@ public:
   
   Standard_EXPORT static void UtilityCommands (Draw_Interpretor& aDI);
 
+  Standard_EXPORT static void RemoveFeaturesCommands (Draw_Interpretor& aDI);
+
   //! Prints errors and warnings if any and draws attached shapes 
   //! if flag BOPTest_Objects::DrawWarnShapes() is set
-  Standard_EXPORT static void ReportAlerts (const BOPAlgo_Algo& theAlgorithm);
+  Standard_EXPORT static void ReportAlerts (const Handle(Message_Report)& theReport);
 
 protected:
 
index 26a5be4..7d333de 100644 (file)
@@ -164,7 +164,7 @@ Standard_Integer bop(Draw_Interpretor& di,
   pPF->SetUseOBB(BOPTest_Objects::UseOBB());
   //
   pPF->Perform();
-  BOPTest::ReportAlerts(*pPF);
+  BOPTest::ReportAlerts(pPF->GetReport());
   //
   return 0;
 }
@@ -257,7 +257,7 @@ Standard_Integer bopsmt(Draw_Interpretor& di,
   aBOP.SetCheckInverted(BOPTest_Objects::CheckInverted());
   //
   aBOP.PerformWithFiller(*pPF);
-  BOPTest::ReportAlerts(aBOP);
+  BOPTest::ReportAlerts(aBOP.GetReport());
   if (aBOP.HasErrors()) {
     return 0;
   }
@@ -318,7 +318,7 @@ Standard_Integer bopsection(Draw_Interpretor& di,
   aBOP.SetCheckInverted(BOPTest_Objects::CheckInverted());
   //
   aBOP.PerformWithFiller(*pPF);
-  BOPTest::ReportAlerts(aBOP);
+  BOPTest::ReportAlerts(aBOP.GetReport());
   if (aBOP.HasErrors()) {
     return 0;
   }
@@ -504,7 +504,7 @@ Standard_Integer bsmt (Draw_Interpretor& di,
   aPF.SetUseOBB(BOPTest_Objects::UseOBB());
   //
   aPF.Perform();
-  BOPTest::ReportAlerts(aPF);
+  BOPTest::ReportAlerts(aPF.GetReport());
   if (aPF.HasErrors()) {
     return 0;
   }
@@ -519,7 +519,7 @@ Standard_Integer bsmt (Draw_Interpretor& di,
   aBOP.SetCheckInverted(BOPTest_Objects::CheckInverted());
   // 
   aBOP.PerformWithFiller(aPF);
-  BOPTest::ReportAlerts(aBOP);
+  BOPTest::ReportAlerts(aBOP.GetReport());
   if (aBOP.HasErrors()) {
     return 0;
   }
@@ -827,7 +827,7 @@ Standard_Integer mkvolume(Draw_Interpretor& di, Standard_Integer n, const char**
   aMV.SetUseOBB(BOPTest_Objects::UseOBB());
   //
   aMV.Perform();
-  BOPTest::ReportAlerts(aMV);
+  BOPTest::ReportAlerts(aMV.GetReport());
   if (aMV.HasErrors()) {
     return 0;
   }
index 0a4924f..5c8814c 100644 (file)
@@ -115,7 +115,7 @@ Standard_Integer bcbuild(Draw_Interpretor& di,
   aCBuilder.SetUseOBB(BOPTest_Objects::UseOBB());
   //
   aCBuilder.PerformWithFiller(aPF); 
-  BOPTest::ReportAlerts(aCBuilder);
+  BOPTest::ReportAlerts(aCBuilder.GetReport());
   if (aCBuilder.HasErrors()) {
     return 0;
   }
@@ -162,7 +162,7 @@ Standard_Integer bcaddall(Draw_Interpretor& di,
   //
   aCBuilder.ClearWarnings();
   aCBuilder.AddAllToResult(iMaterial, bUpdate);
-  BOPTest::ReportAlerts(aCBuilder);
+  BOPTest::ReportAlerts(aCBuilder.GetReport());
   //
   const TopoDS_Shape& aR = aCBuilder.Shape();
   //
@@ -246,7 +246,7 @@ Standard_Integer bcadd(Draw_Interpretor& di,
   //
   aCBuilder.ClearWarnings();
   aCBuilder.AddToResult(aLSToTake, aLSToAvoid, iMaterial, bUpdate);
-  BOPTest::ReportAlerts(aCBuilder);
+  BOPTest::ReportAlerts(aCBuilder.GetReport());
   //
   const TopoDS_Shape& aR = aCBuilder.Shape();
   //
@@ -317,7 +317,7 @@ Standard_Integer bcremoveint(Draw_Interpretor& di,
   //
   aCBuilder.ClearWarnings();
   aCBuilder.RemoveInternalBoundaries();
-  BOPTest::ReportAlerts(aCBuilder);
+  BOPTest::ReportAlerts(aCBuilder.GetReport());
   //
   const TopoDS_Shape& aR = aCBuilder.Shape();
   //
index 9b5c305..a1da966 100644 (file)
@@ -247,7 +247,7 @@ Standard_Integer bopcheck (Draw_Interpretor& di,
   //
   aTimer.Stop();
   //
-  BOPTest::ReportAlerts(aChecker);
+  BOPTest::ReportAlerts(aChecker.GetReport());
   //
   iErr=aChecker.HasErrors();
   //
index 991cf0d..7c87dad 100644 (file)
@@ -1350,7 +1350,7 @@ Standard_Integer bopbface (Draw_Interpretor& di,
   aBF.SetFace(aF);
   aBF.SetShapes(aLE);
   aBF.Perform();
-  BOPTest::ReportAlerts(aBF);
+  BOPTest::ReportAlerts(aBF.GetReport());
   if (aBF.HasErrors()) {
     return 0;
   }
@@ -1410,7 +1410,7 @@ Standard_Integer bopbsolid (Draw_Interpretor& di,
   BOPAlgo_BuilderSolid aBS;
   aBS.SetShapes(aLF);
   aBS.Perform();
-  BOPTest::ReportAlerts(aBS);
+  BOPTest::ReportAlerts(aBS.GetReport());
   if (aBS.HasErrors()) {
     return 0;
   }
index 5cf77bd..960ab2d 100644 (file)
@@ -121,7 +121,7 @@ Standard_Integer bfillds(Draw_Interpretor& di,
   aTimer.Start();
   //
   aPF.Perform();
-  BOPTest::ReportAlerts(aPF);
+  BOPTest::ReportAlerts(aPF.GetReport());
   if (aPF.HasErrors()) {
     return 0;
   }
@@ -196,7 +196,7 @@ Standard_Integer bbuild(Draw_Interpretor& di,
   aTimer.Start();
   //
   aBuilder.PerformWithFiller(aPF); 
-  BOPTest::ReportAlerts(aBuilder);
+  BOPTest::ReportAlerts(aBuilder.GetReport());
   if (aBuilder.HasErrors()) {
     return 0;
   }
@@ -306,7 +306,7 @@ Standard_Integer bbop(Draw_Interpretor& di,
   aTimer.Start();
   //
   pBuilder->PerformWithFiller(aPF);
-  BOPTest::ReportAlerts(*pBuilder);
+  BOPTest::ReportAlerts(pBuilder->GetReport());
   if (pBuilder->HasErrors()) {
     return 0;
   }
@@ -376,7 +376,7 @@ Standard_Integer bsplit(Draw_Interpretor& di,
   pSplitter->PerformWithFiller(aPF);
   //
   aTimer.Stop();
-  BOPTest::ReportAlerts(*pSplitter);
+  BOPTest::ReportAlerts(pSplitter->GetReport());
   if (pSplitter->HasErrors()) {
     return 0;
   }
diff --git a/src/BOPTest/BOPTest_RemoveFeaturesCommands.cxx b/src/BOPTest/BOPTest_RemoveFeaturesCommands.cxx
new file mode 100644 (file)
index 0000000..80c95fb
--- /dev/null
@@ -0,0 +1,269 @@
+// Created by: Eugeny MALTCHIKOV
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <BOPTest.hxx>
+
+#include <BOPTest_DrawableShape.hxx>
+#include <BOPTest_Objects.hxx>
+
+#include <BRep_Builder.hxx>
+
+#include <BRepAlgoAPI_Defeaturing.hxx>
+
+#include <DBRep.hxx>
+#include <Draw.hxx>
+
+#include <TopoDS.hxx>
+#include <TopoDS_Compound.hxx>
+
+static Standard_Integer RemoveFeatures (Draw_Interpretor&, Standard_Integer, const char**);
+// History commands
+static Standard_Integer rfModified  (Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer rfGenerated (Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer rfIsDeleted (Draw_Interpretor&, Standard_Integer, const char**);
+
+namespace
+{
+  static BRepAlgoAPI_Defeaturing TheDefeaturingTool;
+}
+
+//=======================================================================
+//function : RemoveFeaturesCommands
+//purpose  : 
+//=======================================================================
+void BOPTest::RemoveFeaturesCommands(Draw_Interpretor& theCommands)
+{
+  static Standard_Boolean done = Standard_False;
+  if (done) return;
+  done = Standard_True;
+  // Chapter's name
+  const char* group = "BOPTest commands";
+  // Commands
+  theCommands.Add("removefeatures", "removefeatures result shape f1 f2 ... [-nohist] [-parallel]\n"
+                  "\t\tRemoves user-defined features (faces) from the shape.\n"
+                  "\t\tresult   - result of the operation;\n"
+                  "\t\tshape    - the shape to remove the features from;\n"
+                  "\t\tf1, f2   - features to remove from the shape;\n"
+                  "\t\tnohist   - disables the history collection;\n"
+                  "\t\tparallel - enables the parallel processing mode.",
+                  __FILE__, RemoveFeatures, group);
+
+  theCommands.Add("rfmodified", "rfmodified c_modified shape\n"
+                  "\t\tShows the shapes <c_modified> modified from the shape <shape> during Defeaturing.",
+                  __FILE__, rfModified, group);
+  theCommands.Add("rfgenerated", "rfgenerated c_generated shape\n"
+                  "\t\tShows the shapes <c_generated> generated from the shape <shape> during Defeaturing.",
+                  __FILE__, rfGenerated, group);
+  theCommands.Add("rfisdeleted", "rfisdeleted shape\n"
+                  "\t\tChecks if the shape has been deleted during Defeaturing.",
+                  __FILE__, rfIsDeleted, group);
+}
+
+//=======================================================================
+//function : RemoveFeatures
+//purpose  : 
+//=======================================================================
+Standard_Integer RemoveFeatures(Draw_Interpretor& theDI,
+                                Standard_Integer  theArgc,
+                                const char ** theArgv)
+{
+  if (theArgc < 4)
+  {
+    theDI.PrintHelp(theArgv[0]);
+    return 1;
+  }
+
+  // Get the shape to remove the features from
+  TopoDS_Shape aShape = DBRep::Get(theArgv[2]);
+  if (aShape.IsNull())
+  {
+    theDI << "Error: " << theArgv[2] << " is a null shape.\n";
+    return 1;
+  }
+
+  BRepAlgoAPI_Defeaturing aRF;
+  aRF.SetShape(aShape);
+
+  // Add faces to remove
+  for (Standard_Integer i = 3; i < theArgc; ++i)
+  {
+    TopoDS_Shape aF = DBRep::Get(theArgv[i]);
+    if (aF.IsNull())
+    {
+      // Check for the options
+      if (!strcmp(theArgv[i], "-nohist"))
+      {
+        // disable the history collection
+        aRF.TrackHistory(Standard_False);
+      }
+      else if (!strcmp(theArgv[i], "-parallel"))
+      {
+        // enable the parallel processing mode
+        aRF.SetRunParallel(Standard_True);
+      }
+      else
+        theDI << "Warning: " << theArgv[i] << " is a null shape. Skip it.\n";
+
+      continue;
+    }
+
+    aRF.AddFaceToRemove(aF);
+  }
+
+  // Perform the removal
+  aRF.Build();
+
+  // Check for the errors/warnings
+  BOPTest::ReportAlerts(aRF.GetReport());
+
+  if (aRF.HasErrors())
+    return 0;
+
+  const TopoDS_Shape& aResult = aRF.Shape();
+  DBRep::Set(theArgv[1], aResult);
+
+  TheDefeaturingTool = aRF;
+
+  return 0;
+}
+
+//=======================================================================
+//function : CheckHistory
+//purpose  : Checks if the history available for the shape
+//=======================================================================
+Standard_Boolean IsHistoryAvailable(const TopoDS_Shape& theS,
+                                    Draw_Interpretor& theDI)
+{
+  if (theS.IsNull())
+  {
+    theDI << "Null shape.\n";
+    return Standard_False;
+  }
+
+  if (!BRepTools_History::IsSupportedType(theS))
+  {
+    theDI << "The history is not supported for this kind of shape.\n";
+    return Standard_False;
+  }
+
+  if (!TheDefeaturingTool.HasHistory())
+  {
+    theDI << "The history has not been prepared.\n";
+    return Standard_False;
+  }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : rfModified
+//purpose  : 
+//=======================================================================
+Standard_Integer rfModified(Draw_Interpretor& theDI,
+                            Standard_Integer  theArgc,
+                            const char ** theArgv)
+{
+  if (theArgc != 3)
+  {
+    theDI.PrintHelp(theArgv[0]);
+    return 1;
+  }
+
+  const TopoDS_Shape& aS = DBRep::Get(theArgv[2]);
+  if (!IsHistoryAvailable(aS, theDI))
+    return 0;
+
+  const TopTools_ListOfShape& aLSIm = TheDefeaturingTool.Modified(aS);
+  if (aLSIm.IsEmpty())
+  {
+    theDI << "The shape has not been modified.\n";
+    return 0;
+  }
+
+  TopoDS_Shape aCModified;
+  if (aLSIm.Extent() == 1)
+    aCModified = aLSIm.First();
+  else
+  {
+    BRep_Builder().MakeCompound(TopoDS::Compound(aCModified));
+    TopTools_ListIteratorOfListOfShape itLS(aLSIm);
+    for (; itLS.More(); itLS.Next())
+      BRep_Builder().Add(aCModified, itLS.Value());
+  }
+
+  DBRep::Set(theArgv[1], aCModified);
+
+  return 0;
+}
+//=======================================================================
+//function : rfGenerated
+//purpose  : 
+//=======================================================================
+Standard_Integer rfGenerated(Draw_Interpretor& theDI,
+                             Standard_Integer  theArgc,
+                             const char ** theArgv)
+{
+  if (theArgc != 3)
+  {
+    theDI.PrintHelp(theArgv[0]);
+    return 1;
+  }
+
+  const TopoDS_Shape& aS = DBRep::Get(theArgv[2]);
+  if (!IsHistoryAvailable(aS, theDI))
+    return 0;
+
+  const TopTools_ListOfShape& aLSGen = TheDefeaturingTool.Generated(aS);
+  if (aLSGen.IsEmpty())
+  {
+    theDI << "No shapes were generated from the shape.\n";
+    return 0;
+  }
+
+  TopoDS_Shape aCGenerated;
+  if (aLSGen.Extent() == 1)
+    aCGenerated = aLSGen.First();
+  else
+  {
+    BRep_Builder().MakeCompound(TopoDS::Compound(aCGenerated));
+    TopTools_ListIteratorOfListOfShape itLS(aLSGen);
+    for (; itLS.More(); itLS.Next())
+      BRep_Builder().Add(aCGenerated, itLS.Value());
+  }
+
+  DBRep::Set(theArgv[1], aCGenerated);
+
+  return 0;
+}
+//=======================================================================
+//function : rfIsDeleted
+//purpose  : 
+//=======================================================================
+Standard_Integer rfIsDeleted(Draw_Interpretor& theDI,
+                             Standard_Integer  theArgc,
+                             const char ** theArgv)
+{
+  if (theArgc != 2)
+  {
+    theDI.PrintHelp(theArgv[0]);
+    return 1;
+  }
+
+  const TopoDS_Shape& aS = DBRep::Get(theArgv[1]);
+  if (!IsHistoryAvailable(aS, theDI))
+    return 0;
+
+  theDI << (TheDefeaturingTool.IsDeleted(aS) ? "Deleted" : "Not deleted") << "\n";
+
+  return 0;
+}
index 4895c62..bfc64ed 100755 (executable)
@@ -15,4 +15,5 @@ BOPTest_TolerCommands.cxx
 BOPTest_HistoryCommands.cxx
 BOPTest_DebugCommands.cxx
 BOPTest_CellsCommands.cxx
+BOPTest_RemoveFeaturesCommands.cxx
 BOPTest_UtilityCommands.cxx
\ No newline at end of file
diff --git a/src/BRepAlgoAPI/BRepAlgoAPI_Defeaturing.cxx b/src/BRepAlgoAPI/BRepAlgoAPI_Defeaturing.cxx
new file mode 100644 (file)
index 0000000..e3fc8fa
--- /dev/null
@@ -0,0 +1,86 @@
+// Created by: Eugeny MALTCHIKOV
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+
+#include <BRepAlgoAPI_Defeaturing.hxx>
+
+#include <BRepTools_History.hxx>
+
+//=======================================================================
+//function : Build
+//purpose  : 
+//=======================================================================
+void BRepAlgoAPI_Defeaturing::Build()
+{
+  // Set not done state for the operation
+  NotDone();
+
+  // Clear the tools performing the operation
+  Clear();
+
+  // Set the inputs to BOPAlgo_RemoveFeatures algorithm
+  myFeatureRemovalTool.SetShape(myInputShape);
+  myFeatureRemovalTool.AddFacesToRemove(myFacesToRemove);
+  myFeatureRemovalTool.TrackHistory(myTrackHistory);
+  myFeatureRemovalTool.SetRunParallel(myRunParallel);
+
+  // Perform the features removal
+  myFeatureRemovalTool.Perform();
+
+  // Merge the Errors/Warnings from the features removal tool
+  GetReport()->Merge(myFeatureRemovalTool.GetReport());
+
+  if (HasErrors())
+    return;
+
+  // Set done state
+  Done();
+
+  // Get the result shape
+  myShape = myFeatureRemovalTool.Shape();
+}
+
+//=======================================================================
+//function : Modified
+//purpose  : 
+//=======================================================================
+const TopTools_ListOfShape& BRepAlgoAPI_Defeaturing::Modified(const TopoDS_Shape& theS)
+{
+  myGenerated.Clear();
+  if (!myFeatureRemovalTool.History().IsNull())
+    myGenerated = myFeatureRemovalTool.History()->Modified(theS);
+  return myGenerated;
+}
+
+//=======================================================================
+//function : Generated
+//purpose  : 
+//=======================================================================
+const TopTools_ListOfShape& BRepAlgoAPI_Defeaturing::Generated(const TopoDS_Shape& theS)
+{
+  myGenerated.Clear();
+  if (!myFeatureRemovalTool.History().IsNull())
+    myGenerated = myFeatureRemovalTool.History()->Generated(theS);
+  return myGenerated;
+}
+
+//=======================================================================
+//function : IsDeleted
+//purpose  : 
+//=======================================================================
+Standard_Boolean BRepAlgoAPI_Defeaturing::IsDeleted(const TopoDS_Shape& theS)
+{
+  return (!myFeatureRemovalTool.History().IsNull() ?
+    myFeatureRemovalTool.History()->IsRemoved(theS) : Standard_False);
+}
diff --git a/src/BRepAlgoAPI/BRepAlgoAPI_Defeaturing.hxx b/src/BRepAlgoAPI/BRepAlgoAPI_Defeaturing.hxx
new file mode 100644 (file)
index 0000000..8165092
--- /dev/null
@@ -0,0 +1,205 @@
+// Created by: Eugeny MALTCHIKOV
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _BRepAlgoAPI_Defeaturing_HeaderFile
+#define _BRepAlgoAPI_Defeaturing_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <BOPAlgo_RemoveFeatures.hxx>
+#include <BRepAlgoAPI_Algo.hxx>
+
+
+//! The BRepAlgoAPI_Defeaturing algorithm is the API algorithm intended for
+//! removal of the unwanted parts from the shape. The unwanted parts 
+//! (or features) can be holes, protrusions, gaps, chamfers, fillets etc.
+//! The shape itself is not modified, the new shape is built as the result.
+//!
+//! The actual removal of the features from the shape is performed by
+//! the low-level *BOPAlgo_RemoveFeatures* tool. So the defeaturing algorithm
+//! has the same options, input data requirements, limitations as the
+//! low-level algorithm.
+//!
+//! <b>Input data</b>
+//!
+//! Currently, only the shapes of type SOLID, COMPSOLID, and COMPOUND of Solids
+//! are supported. And only the FACEs can be removed from the shape.
+//!
+//! On the input the algorithm accepts the shape itself and the
+//! features which have to be removed. It does not matter how the features
+//! are given. It could be the separate faces or the collections
+//! of faces. The faces should belong to the initial shape, and those that
+//! do not belong will be ignored.
+//!
+//! <b>Options</b>
+//!
+//! The algorithm has the following options:
+//! - History support;
+//!
+//! and the options available from base class:
+//! - Error/Warning reporting system;
+//! - Parallel processing mode.
+//!
+//! Please note that the other options of the base class are not supported
+//! here and will have no effect.
+//!
+//! For the details on the available options please refer to the description
+//! of *BOPAlgo_RemoveFeatures* algorithm.
+//!
+//! <b>Limitations</b>
+//!
+//! The defeaturing algorithm has the same limitations as *BOPAlgo_RemoveFeatures*
+//! algorithm.
+//!
+//! <b>Example</b>
+//!
+//! Here is the example of usage of the algorithm:
+//! ~~~~
+//! TopoDS_Shape aSolid = ...;               // Input shape to remove the features from
+//! TopTools_ListOfShape aFeatures = ...;    // Features to remove from the shape
+//! Standard_Boolean bRunParallel = ...;     // Parallel processing mode
+//! Standard_Boolean isHistoryNeeded = ...;  // History support
+//!
+//! BRepAlgoAPI_Defeaturing aDF;             // De-Featuring algorithm
+//! aDF.SetShape(aSolid);                    // Set the shape
+//! aDF.AddFacesToRemove(aFaces);            // Add faces to remove
+//! aDF.SetRunParallel(bRunParallel);        // Define the processing mode (parallel or single)
+//! aDF.TrackHistory(isHistoryNeeded);       // Define whether to track the shapes modifications
+//! aDF.Build();                             // Perform the operation
+//! if (!aDF.IsDone())                       // Check for the errors
+//! {
+//!   // error treatment
+//!   Standard_SStream aSStream;
+//!   aDF.DumpErrors(aSStream);
+//!   return;
+//! }
+//! if (aDF.HasWarnings())                   // Check for the warnings
+//! {
+//!   // warnings treatment
+//!   Standard_SStream aSStream;
+//!   aDF.DumpWarnings(aSStream);
+//! }
+//! const TopoDS_Shape& aResult = aDF.Shape(); // Result shape
+//! ~~~~
+//!
+//! The algorithm preserves the type of the input shape in the result shape. Thus,
+//! if the input shape is a COMPSOLID, the resulting solids will also be put into a COMPSOLID.
+//!
+class BRepAlgoAPI_Defeaturing: public BRepAlgoAPI_Algo
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+public: //! @name Constructors
+
+  //! Empty constructor
+  BRepAlgoAPI_Defeaturing()
+  :
+    BRepAlgoAPI_Algo(),
+    myTrackHistory(Standard_True)
+  {}
+
+
+public: //! @name Setting input data for the algorithm
+
+  //! Sets the shape for processing.
+  //! @param theShape [in] The shape to remove the features from.
+  //!                      It should either be the SOLID, COMPSOLID or COMPOUND of Solids.
+  void SetShape(const TopoDS_Shape& theShape)
+  {
+    myInputShape = theShape;
+  }
+
+  //! Returns the input shape
+  const TopoDS_Shape& InputShape() const
+  {
+    return myInputShape;
+  }
+
+  //! Adds the features to remove from the input shape.
+  //! @param theFace [in] The shape to extract the faces for removal.
+  void AddFaceToRemove(const TopoDS_Shape& theFace)
+  {
+    myFacesToRemove.Append(theFace);
+  }
+
+  //! Adds the faces to remove from the input shape.
+  //! @param theFaces [in] The list of shapes to extract the faces for removal.
+  void AddFacesToRemove(const TopTools_ListOfShape& theFaces)
+  {
+    TopTools_ListIteratorOfListOfShape it(theFaces);
+    for (; it.More(); it.Next())
+      myFacesToRemove.Append(it.Value());
+  }
+
+  //! Returns the list of faces which have been requested for removal
+  //! from the input shape.
+  const TopTools_ListOfShape& FacesToRemove() const
+  {
+    return myFacesToRemove;
+  }
+
+
+public: //! @name Performing the operation
+
+  //! Performs the operation
+  Standard_EXPORT virtual void Build() Standard_OVERRIDE;
+
+
+public: //! @name History Methods
+
+  //! Defines whether to track the modification of the shapes or not.
+  void TrackHistory(const Standard_Boolean theFlag)
+  {
+    myTrackHistory = theFlag;
+  }
+
+  //! Returns whether the history was requested or not.
+  Standard_Boolean HasHistory() const { return myTrackHistory; }
+
+  //! Returns the list of shapes modified from the shape <theS> during the operation.
+  Standard_EXPORT virtual const TopTools_ListOfShape& Modified(const TopoDS_Shape& theS) Standard_OVERRIDE;
+
+  //! Returns the list of shapes generated from the shape <theS> during the operation.
+  Standard_EXPORT virtual const TopTools_ListOfShape& Generated(const TopoDS_Shape& theS) Standard_OVERRIDE;
+
+  //! Returns true if the shape <theS> has been deleted during the operation.
+  //! It means that the shape has no any trace in the result.
+  //! Otherwise it returns false.
+  Standard_EXPORT virtual Standard_Boolean IsDeleted(const TopoDS_Shape& theS) Standard_OVERRIDE;
+
+
+protected: //! @name Setting the algorithm into default state
+
+  virtual void Clear() Standard_OVERRIDE
+  {
+    BRepAlgoAPI_Algo::Clear();
+    myFeatureRemovalTool.Clear();
+  }
+
+
+protected: //! @name Fields
+
+  TopoDS_Shape myInputShape;                   //!< Input shape to remove the features from
+  TopTools_ListOfShape myFacesToRemove;        //!< Features to remove from the shape
+  Standard_Boolean myTrackHistory;             //!< Defines whether to track the history of
+                                               //! shapes modifications or not (true by default)
+  BOPAlgo_RemoveFeatures myFeatureRemovalTool; //!< Tool for the features removal
+
+};
+
+#endif // _BRepAlgoAPI_Defeaturing_HeaderFile
index 9a12d65..ac68df7 100644 (file)
@@ -10,6 +10,8 @@ BRepAlgoAPI_Common.cxx
 BRepAlgoAPI_Common.hxx
 BRepAlgoAPI_Cut.cxx
 BRepAlgoAPI_Cut.hxx
+BRepAlgoAPI_Defeaturing.cxx
+BRepAlgoAPI_Defeaturing.hxx
 BRepAlgoAPI_Fuse.cxx
 BRepAlgoAPI_Fuse.hxx
 BRepAlgoAPI_Section.cxx
index 7ac087c..60d0bbc 100644 (file)
@@ -40,6 +40,7 @@
 #include <BRepBndLib.hxx>
 #include <BRepClass3d_SolidClassifier.hxx>
 #include <BRepLib.hxx>
+#include <BRepLib_MakeFace.hxx>
 #include <BSplCLib.hxx>
 #include <ElSLib.hxx>
 #include <Extrema_LocateExtPC.hxx>
@@ -2665,3 +2666,133 @@ void BRepLib::BoundingVertex(const NCollection_List<TopoDS_Shape>& theLV,
     theNewTol = aDmax;
   }
 }
+
+//=======================================================================
+//function : ExtendFace
+//purpose  :
+//=======================================================================
+void BRepLib::ExtendFace(const TopoDS_Face& theF,
+                         const Standard_Real theExtVal,
+                         const Standard_Boolean theExtUMin,
+                         const Standard_Boolean theExtUMax,
+                         const Standard_Boolean theExtVMin,
+                         const Standard_Boolean theExtVMax,
+                         TopoDS_Face& theFExtended)
+{
+  // Get face bounds
+  BRepAdaptor_Surface aBAS(theF);
+  Standard_Real aFUMin = aBAS.FirstUParameter(),
+                aFUMax = aBAS.LastUParameter(),
+                aFVMin = aBAS.FirstVParameter(),
+                aFVMax = aBAS.LastVParameter();
+  const Standard_Real aTol = BRep_Tool::Tolerance(theF);
+
+  // Surface to build the face
+  Handle(Geom_Surface) aS;
+
+  const GeomAbs_SurfaceType aType = aBAS.GetType();
+  // treat analytical surfaces first
+  if (aType == GeomAbs_Plane ||
+      aType == GeomAbs_Sphere ||
+      aType == GeomAbs_Cylinder ||
+      aType == GeomAbs_Torus ||
+      aType == GeomAbs_Cone)
+  {
+    // Get basis transformed basis surface
+    Handle(Geom_Surface) aSurf = Handle(Geom_Surface)::
+      DownCast(aBAS.Surface().Surface()->Transformed(aBAS.Trsf()));
+
+    // Get bounds of the basis surface
+    Standard_Real aSUMin, aSUMax, aSVMin, aSVMax;
+    aSurf->Bounds(aSUMin, aSUMax, aSVMin, aSVMax);
+
+    if (aBAS.IsUPeriodic())
+    {
+      // Adjust face bounds to first period
+      Standard_Real aDelta = aFUMax - aFUMin;
+      aFUMin = Max(aSUMin, aFUMin + aBAS.UPeriod()*Ceiling((aSUMin - aFUMin)/aBAS.UPeriod()));
+      aFUMax = aFUMin + aDelta;
+    }
+    if (aBAS.IsVPeriodic())
+    {
+      // Adjust face bounds to first period
+      Standard_Real aDelta = aFVMax - aFVMin;
+      aFVMin = Max(aSVMin, aFVMin + aBAS.VPeriod()*Ceiling((aSVMin - aFVMin)/aBAS.VPeriod()));
+      aFVMax = aFVMin + aDelta;
+    }
+
+    // Enlarge the face
+    Standard_Real anURes = 0., aVRes = 0.;
+    if (theExtUMin || theExtUMax)
+      anURes = aBAS.UResolution(theExtVal);
+    if (theExtVMin || theExtVMax)
+      aVRes = aBAS.VResolution(theExtVal);
+
+    if (theExtUMin) aFUMin = Max(aSUMin, aFUMin - anURes);
+    if (theExtUMax) aFUMax = Min(aSUMax, aFUMax + anURes);
+    if (theExtVMin) aFVMin = Max(aSVMin, aFVMin - aVRes);
+    if (theExtVMax) aFVMax = Min(aSVMax, aFVMax + aVRes);
+
+    aS = aSurf;
+  }
+  else
+  {
+    // General case
+
+    Handle(Geom_BoundedSurface) aSB =
+      Handle(Geom_BoundedSurface)::DownCast(BRep_Tool::Surface(theF));
+    if (aSB.IsNull())
+    {
+      theFExtended = theF;
+      return;
+    }
+
+    // Get surfaces bounds
+    Standard_Real aSUMin, aSUMax, aSVMin, aSVMax;
+    aSB->Bounds(aSUMin, aSUMax, aSVMin, aSVMax);
+
+    Standard_Boolean isUClosed = aSB->IsUClosed();
+    Standard_Boolean isVClosed = aSB->IsVClosed();
+
+    // Check if the extension in necessary directions is done
+    Standard_Boolean isExtUMin = Standard_False,
+                     isExtUMax = Standard_False,
+                     isExtVMin = Standard_False,
+                     isExtVMax = Standard_False;
+
+    // UMin
+    if (theExtUMin && !isUClosed && !Precision::IsInfinite(aSUMin)) {
+      GeomLib::ExtendSurfByLength(aSB, theExtVal, 1, Standard_True, Standard_False);
+      isExtUMin = Standard_True;
+    }
+    // UMax
+    if (theExtUMax && !isUClosed && !Precision::IsInfinite(aSUMax)) {
+      GeomLib::ExtendSurfByLength(aSB, theExtVal, 1, Standard_True, Standard_True);
+      isExtUMax = Standard_True;
+    }
+    // VMin
+    if (theExtVMin && !isVClosed && !Precision::IsInfinite(aSVMax)) {
+      GeomLib::ExtendSurfByLength(aSB, theExtVal, 1, Standard_False, Standard_False);
+      isExtVMin = Standard_True;
+    }
+    // VMax
+    if (theExtVMax && !isVClosed && !Precision::IsInfinite(aSVMax)) {
+      GeomLib::ExtendSurfByLength(aSB, theExtVal, 1, Standard_False, Standard_True);
+      isExtVMax = Standard_True;
+    }
+
+    aS = aSB;
+
+    // Get new bounds
+    aS->Bounds(aSUMin, aSUMax, aSVMin, aSVMax);
+    if (isExtUMin) aFUMin = aSUMin;
+    if (isExtUMax) aFUMax = aSUMax;
+    if (isExtVMin) aFVMin = aSVMin;
+    if (isExtVMax) aFVMax = aSVMax;
+  }
+
+  BRepLib_MakeFace aMF(aS, aFUMin, aFUMax, aFVMin, aFVMax, aTol);
+  theFExtended = *(TopoDS_Face*)&aMF.Shape();
+  if (theF.Orientation() == TopAbs_REVERSED)
+    theFExtended.Reverse();
+}
index 5f034bb..5bd8823 100644 (file)
@@ -274,6 +274,24 @@ public:
   Standard_EXPORT static Standard_Boolean FindValidRange
     (const TopoDS_Edge& theEdge, Standard_Real& theFirst, Standard_Real& theLast);
 
+
+  //! Enlarges the face on the given value.
+  //! @param theF [in] The face to extend
+  //! @param theExtVal [in] The extension value
+  //! @param theExtUMin [in] Defines whether to extend the face in UMin direction
+  //! @param theExtUMax [in] Defines whether to extend the face in UMax direction
+  //! @param theExtVMin [in] Defines whether to extend the face in VMin direction
+  //! @param theExtVMax [in] Defines whether to extend the face in VMax direction
+  //! @param theFExtended [in] The extended face
+  Standard_EXPORT static void ExtendFace(const TopoDS_Face& theF,
+                                         const Standard_Real theExtVal,
+                                         const Standard_Boolean theExtUMin,
+                                         const Standard_Boolean theExtUMax,
+                                         const Standard_Boolean theExtVMin,
+                                         const Standard_Boolean theExtVMax,
+                                         TopoDS_Face& theFExtended);
+
+
 protected:
 
 
index 6f9ea8a..8ad7a59 100644 (file)
@@ -215,6 +215,14 @@ Standard_Boolean BRepTools_History::IsRemoved(
 //==============================================================================
 void BRepTools_History::Merge(const Handle(BRepTools_History)& theHistory23)
 {
+  Merge(*theHistory23.get());
+}
+//==============================================================================
+//function : Merge
+//purpose  :
+//==============================================================================
+void BRepTools_History::Merge(const BRepTools_History& theHistory23)
+{
   // Propagate R23 directly and M23 and G23 fully to M12 and G12.
   // Remember the propagated shapes.
   TopTools_DataMapOfShapeListOfShape* aS1ToGAndM[] =
@@ -234,22 +242,22 @@ void BRepTools_History::Merge(const Handle(BRepTools_History)& theHistory23)
         for (TopTools_ListOfShape::Iterator aSIt2(aL12); aSIt2.More();)
         {
           const TopoDS_Shape& aS2 = aSIt2.Value();
-          if (theHistory23->IsRemoved(aS2))
+          if (theHistory23.IsRemoved(aS2))
           {
-            aL12.Remove(aSIt2);
             aRPropagated.Add(aS2);
+            aL12.Remove(aSIt2);
           }
           else
           {
-            if (theHistory23->myShapeToGenerated.IsBound(aS2))
+            if (theHistory23.myShapeToGenerated.IsBound(aS2))
             {
-              add(aAdditions[0], theHistory23->myShapeToGenerated(aS2));
+              add(aAdditions[0], theHistory23.myShapeToGenerated(aS2));
               aMAndGPropagated.Add(aS2);
             }
 
-            if (theHistory23->myShapeToModified.IsBound(aS2))
+            if (theHistory23.myShapeToModified.IsBound(aS2))
             {
-              add(aAdditions[aI], theHistory23->myShapeToModified(aS2));
+              add(aAdditions[aI], theHistory23.myShapeToModified(aS2));
               aMAndGPropagated.Add(aS2);
 
               aL12.Remove(aSIt2);
@@ -278,7 +286,7 @@ void BRepTools_History::Merge(const Handle(BRepTools_History)& theHistory23)
 
     // Propagate M23 and G23 to M12 and G12 sequentially.
     const TopTools_DataMapOfShapeListOfShape* aS2ToGAndM[] =
-      {&theHistory23->myShapeToGenerated, &theHistory23->myShapeToModified};
+      {&theHistory23.myShapeToGenerated, &theHistory23.myShapeToModified};
     for (Standard_Integer aI = 0; aI < 2; ++aI)
     {
       for (TopTools_DataMapOfShapeListOfShape::Iterator aMIt2(*aS2ToGAndM[aI]);
@@ -310,13 +318,14 @@ void BRepTools_History::Merge(const Handle(BRepTools_History)& theHistory23)
       aMIt1.Next();
       if (aL12.IsEmpty())
       {
+        myRemoved.Add(aS1);
         aS1ToGAndM[aI]->UnBind(aS1);
       }
     }
   }
 
   // Propagate R23 to R12 sequentially.
-  for (TopTools_MapOfShape::Iterator aRIt23(theHistory23->myRemoved);
+  for (TopTools_MapOfShape::Iterator aRIt23(theHistory23.myRemoved);
     aRIt23.More(); aRIt23.Next())
   {
     const TopoDS_Shape& aS2 = aRIt23.Value();
index 63f416c..4a17091 100644 (file)
@@ -17,6 +17,7 @@
 #define _BRepTools_History_HeaderFile
 
 #include <NCollection_Handle.hxx>
+#include <TopExp.hxx>
 #include <TopTools_DataMapOfShapeListOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
 
@@ -82,6 +83,51 @@ DEFINE_STANDARD_HANDLE(BRepTools_History, Standard_Transient)
 //!   Tj <= M12(Si), Qk <= M23(Tj) ==> Qk <= M13(Si);
 class BRepTools_History: public Standard_Transient
 {
+public: //! @name Constructors for History creation
+
+  //! Empty constructor
+  BRepTools_History() {}
+
+  //! Template constructor for History creation from the algorithm having
+  //! standard history methods such as IsDeleted(), Modified() and Generated().
+  //! @param theArguments [in] Arguments of the algorithm;
+  //! @param theAlgo [in] The algorithm.
+  template <class TheAlgo>
+  BRepTools_History(const TopTools_ListOfShape& theArguments,
+                    TheAlgo& theAlgo)
+  {
+    // Map all argument shapes to save them in history
+    TopTools_IndexedMapOfShape anArgsMap;
+    TopTools_ListIteratorOfListOfShape aIt(theArguments);
+    for (; aIt.More(); aIt.Next())
+      TopExp::MapShapes(aIt.Value(), anArgsMap);
+
+    // Copy the history for all supported shapes from the algorithm
+    Standard_Integer i, aNb = anArgsMap.Extent();
+    for (i = 1; i <= aNb; ++i)
+    {
+      const TopoDS_Shape& aS = anArgsMap(i);
+      if (!IsSupportedType(aS))
+        continue;
+
+      if (theAlgo.IsDeleted(aS))
+      {
+        Remove(aS);
+        continue;
+      }
+
+      // Check Modified
+      const TopTools_ListOfShape& aModified = theAlgo.Modified(aS);
+      for (aIt.Initialize(aModified); aIt.More(); aIt.Next())
+        AddModified(aS, aIt.Value());
+
+      // Check Generated
+      const TopTools_ListOfShape& aGenerated = theAlgo.Generated(aS);
+      for (aIt.Initialize(aGenerated); aIt.More(); aIt.Next())
+        AddGenerated(aS, aIt.Value());
+    }
+  }
+
 public:
 
   //! The types of the historical relations.
@@ -150,6 +196,22 @@ public: //! A method to merge a next history to this history.
   //! Merges the next history to this history.
   Standard_EXPORT void Merge(const Handle(BRepTools_History)& theHistory23);
 
+  //! Merges the next history to this history.
+  Standard_EXPORT void Merge(const BRepTools_History& theHistory23);
+
+  //! Template method for merging history of the algorithm having standard
+  //! history methods such as IsDeleted(), Modified() and Generated()
+  //! into current history object.
+  //! @param theArguments [in] Arguments of the algorithm;
+  //! @param theAlgo [in] The algorithm.
+  template<class TheAlgo>
+  void Merge(const TopTools_ListOfShape& theArguments,
+             TheAlgo& theAlgo)
+  {
+    // Create new history object from the given algorithm and merge it into this.
+    Merge(BRepTools_History(theArguments, theAlgo));
+  }
+
 public:
 
   //! Define the OCCT RTTI for the type.
index 57d9f03..4a30612 100644 (file)
@@ -1791,17 +1791,19 @@ void ShapeUpgrade_UnifySameDomain::FillHistory()
   // the history of UnifySameDomain algorithm
   Handle(BRepTools_History) aUSDHistory = new BRepTools_History();
 
-  // Map all Vertices, Edges and Faces in the input shape
+  // Map all Vertices, Edges, Faces and Solids in the input shape
   TopTools_IndexedMapOfShape aMapInputShape;
   TopExp::MapShapes(myInitShape, TopAbs_VERTEX, aMapInputShape);
   TopExp::MapShapes(myInitShape, TopAbs_EDGE  , aMapInputShape);
   TopExp::MapShapes(myInitShape, TopAbs_FACE  , aMapInputShape);
+  TopExp::MapShapes(myInitShape, TopAbs_SOLID , aMapInputShape);
 
-  // Map all Vertices, Edges and Faces in the result shape
+  // Map all Vertices, Edges, Faces and Solids in the result shape
   TopTools_IndexedMapOfShape aMapResultShapes;
   TopExp::MapShapes(myShape, TopAbs_VERTEX, aMapResultShapes);
   TopExp::MapShapes(myShape, TopAbs_EDGE  , aMapResultShapes);
   TopExp::MapShapes(myShape, TopAbs_FACE  , aMapResultShapes);
+  TopExp::MapShapes(myShape, TopAbs_SOLID , aMapResultShapes);
 
   // Iterate on all input shapes and get their modifications
   Standard_Integer i, aNb = aMapInputShape.Extent();
@@ -1831,10 +1833,12 @@ void ShapeUpgrade_UnifySameDomain::FillHistory()
     TopTools_ListIteratorOfListOfShape aItLSIm(aLSImages);
     for (; aItLSIm.More(); aItLSIm.Next())
     {
-      if (aMapResultShapes.Contains(aItLSIm.Value()))
+      const TopoDS_Shape& aSIm = aItLSIm.Value();
+      if (aMapResultShapes.Contains(aSIm))
       {
-        // Image is found in the result, thus the shape has been modified
-        aUSDHistory->AddModified(aS, aItLSIm.Value());
+        if (!aSIm.IsSame(aS))
+          // Image is found in the result, thus the shape has been modified
+          aUSDHistory->AddModified(aS, aSIm);
         bRemoved = Standard_False;
       }
     }
index 5130780..7b689c6 100644 (file)
@@ -27,4 +27,5 @@
 027 gdml_private
 028 cells_test
 029 splitter
-030 history
\ No newline at end of file
+030 history
+031 removefeatures
\ No newline at end of file
diff --git a/tests/boolean/removefeatures/A1 b/tests/boolean/removefeatures/A1
new file mode 100644 (file)
index 0000000..a7c841c
--- /dev/null
@@ -0,0 +1,50 @@
+pload XDE
+
+stepread [locate_data_file bug29481_L3.step] s *
+
+copy s_1 s
+explode s f
+
+compound s_6 s_7 feature1
+compound s_2 s_25 s_1 s_4 feature2
+compound s_24 feature3
+compound s_8 feature4
+compound feature1 feature2 feature3 feature4 gap
+
+removefeatures res1 s feature1
+checkshape res1
+checkprops res1 -s 2387.42 -v 1060.96 -deps 1.e-7
+checknbshapes res1 -vertex 68 -edge 102 -wire 36 -face 36 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved feature1 {v e f}
+
+removefeatures res3 s feature1 feature2
+checkshape res3
+checkprops res3 -s 2391.09 -v 1064.4 -deps 1.e-7
+checknbshapes res3 -vertex 60 -edge 90 -wire 32 -face 32 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved feature1 {v e f}
+CheckIsFeatureRemoved feature2 {e f}
+
+removefeatures res4 s feature3
+checkshape res4
+checkprops res4 -s 2387.67 -v 1060.68 -deps 1.e-7
+checknbshapes res4 -vertex 70 -edge 105 -wire 37 -face 37 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved feature3 {v e f}
+
+removefeatures res5 s feature4
+checkshape res5
+checkprops res5 -s 2387.67 -v 1060.68 -deps 1.e-7
+checknbshapes res5 -vertex 70 -edge 105 -wire 37 -face 37 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved feature4 {v e f}
+
+removefeatures res6 s feature3 feature4
+checkshape res6
+checkprops res6 -s 2387.89 -v 1060.71 -deps 1.e-7
+checknbshapes res6 -vertex 68 -edge 102 -wire 36 -face 36 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved feature3 {v e f}
+CheckIsFeatureRemoved feature4 {v e f}
+
+removefeatures res7 s gap
+checkshape res7
+checkprops res7 -s 2392.9 -v 1065.7 -deps 1.e-7
+checknbshapes res7 -vertex 54 -edge 81 -wire 29 -face 29 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved gap {v e f}
diff --git a/tests/boolean/removefeatures/A2 b/tests/boolean/removefeatures/A2
new file mode 100644 (file)
index 0000000..8e8bfde
--- /dev/null
@@ -0,0 +1,28 @@
+pload XDE
+
+stepread [locate_data_file bug29481_L3.step] s *
+
+copy s_1 s
+explode s f
+
+compound s_32 s_31 s_33 s_30 s_38 feature1
+compound s_34 s_35 s_36 s_29 feature2
+compound feature1 feature2 gap
+
+removefeatures res1 s feature1
+checkshape res1
+checkprops res1 -s 2387.38 -v 1060.67 -deps 1.e-7
+checknbshapes res1 -vertex 62 -edge 93 -wire 33 -face 33 -shell 1 -solid 1
+CheckIsFeatureRemoved feature1 {v e f}
+
+removefeatures res2 s feature2
+checkshape res2
+checkprops res2 -s 2387.17 -v 1060.75 -deps 1.e-7
+checknbshapes res2 -vertex 62 -edge 93 -wire 35 -face 34 -shell 1 -solid 1
+CheckIsFeatureRemoved feature2 {v e f}
+
+removefeatures res3 s gap
+checkshape res3
+checkprops res3 -s 2386.99 -v 1060.79 -deps 1.e-7
+checknbshapes res3 -vertex 54 -edge 81 -wire 29 -face 29 -shell 1 -solid 1
+CheckIsFeatureRemoved gap {v e f}
diff --git a/tests/boolean/removefeatures/A3 b/tests/boolean/removefeatures/A3
new file mode 100644 (file)
index 0000000..f1dc6c1
--- /dev/null
@@ -0,0 +1,14 @@
+pload XDE
+
+stepread [locate_data_file bug29481_L3.step] s *
+
+copy s_1 s
+explode s f
+
+compound s_37 s_26 s_27 s_28 gap
+
+removefeatures res s gap
+checkshape res
+checkprops res -s 2387.07 -v 1060.76 -deps 1.e-7
+checknbshapes res -vertex 64 -edge 96 -wire 34 -face 34 -shell 1 -solid 1
+CheckIsFeatureRemoved gap {v e f}
diff --git a/tests/boolean/removefeatures/A4 b/tests/boolean/removefeatures/A4
new file mode 100644 (file)
index 0000000..f56406a
--- /dev/null
@@ -0,0 +1,30 @@
+pload XDE
+
+stepread [locate_data_file bug29481_L3.step] s *
+
+copy s_1 s
+explode s f
+
+compound s_20 feature1
+compound s_16 feature2
+compound s_17 s_18 s_19 feature3
+compound feature1 feature2 feature3 gap
+
+removefeatures res1 s feature1 feature2
+checkshape res1
+checkprops res1 -s 2387.88 -v 1060.71 -deps 1.e-7
+checknbshapes res1 -vertex 68 -edge 102 -wire 36 -face 36 -shell 1 -solid 1
+CheckIsFeatureRemoved feature1 {v e f}
+CheckIsFeatureRemoved feature2 {v e f}
+
+removefeatures res2 s feature3
+checkshape res2
+checkprops res2 -s 2391.13 -v 1064.08 -deps 1.e-7
+checknbshapes res2 -vertex 66 -edge 99 -wire 35 -face 35 -shell 1 -solid 1
+CheckIsFeatureRemoved feature3 {v e f}
+
+removefeatures res3 s gap
+checkshape res3
+checkprops res3 -s 2392.93 -v 1065.38 -deps 1.e-7
+checknbshapes res3 -vertex 60 -edge 90 -wire 32 -face 32 -shell 1 -solid 1
+CheckIsFeatureRemoved gap {v e f}
diff --git a/tests/boolean/removefeatures/A5 b/tests/boolean/removefeatures/A5
new file mode 100644 (file)
index 0000000..f4da7d9
--- /dev/null
@@ -0,0 +1,14 @@
+pload XDE
+
+stepread [locate_data_file bug29481_L3.step] s *
+
+copy s_1 s
+explode s f
+
+compound s_11 s_13 s_12 spike
+
+removefeatures res s spike
+checkshape res
+checkprops res -s 2323.49 -v 1037.57 -deps 1.e-7
+checknbshapes res -vertex 64 -edge 96 -wire 34 -face 34 -shell 1 -solid 1
+CheckIsFeatureRemoved spike {v e f}
diff --git a/tests/boolean/removefeatures/A6 b/tests/boolean/removefeatures/A6
new file mode 100644 (file)
index 0000000..a9ef3b2
--- /dev/null
@@ -0,0 +1,27 @@
+pload XDE
+
+stepread [locate_data_file bug29481_L3.step] s *
+
+copy s_1 s
+explode s f
+
+compound s_11 s_13 s_12 spike
+
+removefeatures res s spike
+checkshape res
+checkprops res -s 2323.49 -v 1037.57 -deps 1.e-7
+checknbshapes res -vertex 64 -edge 96 -wire 34 -face 34 -shell 1 -solid 1
+CheckIsFeatureRemoved spike {v e f}
+
+# check modification of the top face
+rfmodified m5 s_5
+checkprops m5 -s 1089.87
+checknbshapes m5 -vertex 31 -edge 31 -wire 1 -face 1
+
+# check modification of the side faces where the spike was located
+rfmodified m10 s_10
+rfmodified m14 s_14
+
+if {![regexp "same shapes" [compare m10 m14]]} {
+  puts "Error: incorrect spike removal"
+}
diff --git a/tests/boolean/removefeatures/A7 b/tests/boolean/removefeatures/A7
new file mode 100644 (file)
index 0000000..e41d7bd
--- /dev/null
@@ -0,0 +1,63 @@
+pload XDE
+
+stepread [locate_data_file bug29481_L3.step] s *
+
+copy s_1 s
+explode s f
+
+
+# Clear the shape from all features
+compound s_24 s_7 s_1 s_2 s_6 s_8 s_4 s_25 s_31 s_30 s_38 s_36 s_34 s_29 s_32 s_33 s_35 s_13 s_12 s_11 s_37 s_27 s_28 s_26 s_20 s_16 s_17 s_18 s_19 features
+
+removefeatures result s features
+checkshape result
+checkprops result -s 2333.55 -v 1047.62 -deps 1.e-7
+checknbshapes result -vertex 8 -edge 12 -wire 6 -face 6 -shell 1 -solid 1
+CheckIsFeatureRemoved features {v e f}
+
+# check modification of the top face
+rfmodified m5 s_5
+checkprops m5 -s 1102.76
+checknbshapes m5 -vertex 4 -edge 4 -wire 1 -face 1
+
+# check modification of the bottom face
+rfmodified m3 s_3
+checkprops m3 -equal m5
+checknbshapes m5 -vertex 4 -edge 4 -wire 1 -face 1
+
+# check modification of the side faces
+rfmodified m10 s_10
+rfmodified m14 s_14
+
+if {![regexp "same shapes" [compare m10 m14]]} {
+  puts "Error: incorrect feature removal"
+}
+
+checkprops m10 -s 37.43
+checknbshapes m10 -vertex 4 -edge 4 -wire 1 -face 1
+
+
+rfmodified m22 s_22
+checkprops m22 -equal s_22
+
+
+rfmodified m9 s_9
+rfmodified m23 s_23
+
+if {![regexp "same shapes" [compare m9 m23]]} {
+  puts "Error: incorrect feature removal"
+}
+
+checkprops m9 -s 26.5893
+checknbshapes m9 -vertex 4 -edge 4 -wire 1 -face 1
+
+
+rfmodified m15 s_15
+rfmodified m21 s_21
+
+if {![regexp "same shapes" [compare m15 m21]]} {
+  puts "Error: incorrect feature removal"
+}
+
+checkprops m15 -equal m9
+checknbshapes m15 -vertex 4 -edge 4 -wire 1 -face 1
diff --git a/tests/boolean/removefeatures/A8 b/tests/boolean/removefeatures/A8
new file mode 100644 (file)
index 0000000..cbd2440
--- /dev/null
@@ -0,0 +1,17 @@
+puts "TODO OCC29504 ALL: Faulty shapes in variables faulty_1 to"
+
+pload XDE
+
+stepread [locate_data_file bug29481_L3.step] s *
+
+copy s_1 s
+explode s f
+
+# remove the square protrusio keeping the spherical one
+compound s_2 s_25 s_1 s_4 feature
+
+removefeatures result s feature
+checkshape result
+checkprops result -s 2386.95 -v 1064.36 -deps 1.e-7
+checknbshapes result -vertex 62 -edge 93 -wire 35 -face 34 -shell 1 -solid 1
+CheckIsFeatureRemoved feature {e f}
diff --git a/tests/boolean/removefeatures/A9 b/tests/boolean/removefeatures/A9
new file mode 100644 (file)
index 0000000..32393f3
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_ex4.brep] s
+explode s f
+
+# remove the chamfer
+removefeatures result s s_2 s_3
+checkshape result
+checkprops result -s 334.248 -v 241.372 -deps 1.e-7
+checknbshapes result -vertex 10 -edge 15 -wire 9 -face 8 -shell 1 -solid 1
+CheckIsFeatureRemoved s_2 {v e f}
+CheckIsFeatureRemoved s_3 {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/B1 b/tests/boolean/removefeatures/B1
new file mode 100644 (file)
index 0000000..073307b
--- /dev/null
@@ -0,0 +1,37 @@
+restore [locate_data_file bug29481_ex1.brep] s
+explode s f
+
+# fillet removal
+removefeatures result s s_13
+checkshape result
+checkprops result -s 463.068 -v 194.214 -deps 1.e-7
+checknbshapes result -vertex 32 -edge 53 -wire 24 -face 21 -shell 1 -solid 1
+CheckIsFeatureRemoved s_13 {v e f}
+
+# check modification of the side faces
+rfmodified m2 s_2
+checkprops m2 -s 20
+checknbshapes m2 -vertex 4 -edge 4 -wire 1 -face 1
+
+rfmodified m12 s_12
+checkprops m12 -s 8
+checknbshapes m12 -vertex 4 -edge 4 -wire 1 -face 1
+
+rfmodified m17 s_17
+checkprops m17 -s 10
+checknbshapes m17 -vertex 4 -edge 4 -wire 1 -face 1
+
+rfgenerated g17 s_17
+checkprops g17 -l 12
+
+explode s_17 e
+rfmodified m17_1 s_17_1
+checkprops m17_1 -l 1
+rfmodified m17_3 s_17_3
+checkprops m17_3 -l 1
+
+# check modification of the top face
+rfmodified m1 s_1
+checkprops m1 -s 172.551
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/B2 b/tests/boolean/removefeatures/B2
new file mode 100644 (file)
index 0000000..42604ea
--- /dev/null
@@ -0,0 +1,29 @@
+restore [locate_data_file bug29481_ex1.brep] s
+explode s f
+
+# chamfer removal
+removefeatures result s s_14
+checkshape result
+checkprops result -s 462.33 -v 194.594 -deps 1.e-7
+checknbshapes result -vertex 34 -edge 54 -wire 24 -face 21 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_14 {e f}
+
+# check modification of the top face
+rfmodified m1 s_1
+checkprops m1 -s 171.478
+checknbshapes m1 -vertex 14 -edge 14 -wire 3 -face 1
+
+rfgenerated g1 s_1
+checknbshapes g1 -vertex 1 -edge 1
+checkprops g1 -l 6.28319
+
+# check modification of the cylindrical face
+rfmodified m20 s_20
+checkprops m20 -s 6.28319
+checknbshapes m20 -vertex 2 -edge 3 -wire 1 -face 1
+
+rfgenerated g20 s_20
+checknbshapes g20 -vertex 1 -edge 1
+checkprops g20 -equal g1
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/B3 b/tests/boolean/removefeatures/B3
new file mode 100644 (file)
index 0000000..acb40c4
--- /dev/null
@@ -0,0 +1,29 @@
+restore [locate_data_file bug29481_ex1.brep] s
+explode s f
+
+# blend removal
+removefeatures result s s_15
+checkshape result
+checkprops result -s 462.273 -v 193.127 -deps 1.e-7
+checknbshapes result -vertex 34 -edge 54 -wire 24 -face 21 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_15 {e f}
+
+# check modification of the top face
+rfmodified m1 s_1
+checkprops m1 -s 172.452
+checknbshapes m1 -vertex 14 -edge 14 -wire 3 -face 1
+
+rfgenerated g1 s_1
+checknbshapes g1 -vertex 1 -edge 1
+checkprops g1 -l 6.28319
+
+# check modification of the cylindrical face
+rfmodified m21 s_21
+checkprops m21 -s 12.5664
+checknbshapes m21 -vertex 2 -edge 3 -wire 1 -face 1
+
+rfgenerated g21 s_21
+checknbshapes g21 -vertex 1 -edge 1
+checkprops g21 -equal g1
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/B4 b/tests/boolean/removefeatures/B4
new file mode 100644 (file)
index 0000000..bf79f42
--- /dev/null
@@ -0,0 +1,37 @@
+restore [locate_data_file bug29481_ex1.brep] s
+explode s f
+
+removefeatures result s s_4
+checkshape result
+checkprops result -s 462.815 -v 195.248 -deps 1.e-7
+checknbshapes result -vertex 31 -edge 50 -wire 23 -face 20 -shell 1 -solid 1
+CheckIsFeatureRemoved s_4 {v e f}
+
+# check modification of the top face
+rfmodified m1 s_1
+checkprops m1 -s 169.122
+checknbshapes m1 -vertex 12 -edge 12 -wire 3 -face 1
+
+# check modification of the side faces
+rfmodified m3 s_3
+rfmodified m5 s_5
+
+if {![regexp "same shapes" [compare m3 m5]]} {
+  puts "Error: incorrect feature removal"
+}
+
+checkprops m3 -s 9.75
+checknbshapes m3 -vertex 6 -edge 6 -wire 1 -face 1
+
+explode s_3 e
+explode s_5 e
+rfmodified m3_4 s_3_4
+rfmodified m5_2 s_5_2
+
+if {![regexp "same shapes" [compare m3_4 m5_2]]} {
+  puts "Error: incorrect feature removal"
+}
+
+checkprops m3_4 -l 9.5
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/B5 b/tests/boolean/removefeatures/B5
new file mode 100644 (file)
index 0000000..0d18a48
--- /dev/null
@@ -0,0 +1,22 @@
+restore [locate_data_file bug29481_ex1.brep] s
+explode s f
+
+# removal of the step
+removefeatures result s s_6 s_18
+checkshape result
+checkprops result -s 461.315 -v 196.178 -deps 1.e-7
+checknbshapes result -vertex 30 -edge 50 -wire 23 -face 20 -shell 1 -solid 1
+CheckIsFeatureRemoved s_6 {v e f}
+CheckIsFeatureRemoved s_18 {v e f}
+
+# check modification of the top face
+rfmodified m1 s_1
+checkprops m1 -s 172.551
+checknbshapes m1 -vertex 14 -edge 14 -wire 3 -face 1
+
+# check modification of the side face
+rfmodified m19 s_19
+checkprops m19 -s 10
+checknbshapes m19 -vertex 4 -edge 4 -wire 1 -face 1
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/B6 b/tests/boolean/removefeatures/B6
new file mode 100644 (file)
index 0000000..24436f9
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_ex1.brep] s
+explode s f
+
+# removal of the sphere
+removefeatures result s s_8 s_9
+checkshape result
+checkprops result -s 460.84 -v 194.168 -deps 1.e-7
+checknbshapes result -vertex 31 -edge 49 -wire 23 -face 20 -shell 1 -solid 1
+CheckIsFeatureRemoved s_8 {v e f}
+CheckIsFeatureRemoved s_9 {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/B7 b/tests/boolean/removefeatures/B7
new file mode 100644 (file)
index 0000000..d4ffb57
--- /dev/null
@@ -0,0 +1,24 @@
+restore [locate_data_file bug29481_ex1.brep] s
+explode s f
+
+# removal of the square gap, keeping the sphere.
+
+removefeatures result s s_7 s_10
+checkshape result
+checkprops result -s 466.126 -v 197.014 -deps 1.e-7
+checknbshapes result -vertex 28 -edge 43 -wire 22 -face 18 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_7 {e f}
+CheckIsFeatureRemoved s_10 {e f}
+
+# check modification of the side faces
+rfmodified m12 s_12
+rfmodified m19 s_19
+
+if {![regexp "same shapes" [compare m12 m19]]} {
+  puts "Error: incorrect feature removal"
+}
+
+checkprops m12 -s 13.9463
+checknbshapes m12 -vertex 7 -edge 7 -wire 1 -face 1
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/B8 b/tests/boolean/removefeatures/B8
new file mode 100644 (file)
index 0000000..053b6fa
--- /dev/null
@@ -0,0 +1,31 @@
+restore [locate_data_file bug29481_ex1.brep] s
+explode s f
+
+# removal of the hole in the shape
+
+removefeatures result s s_14 s_20
+checkshape result
+checkprops result -s 462.33 -v 197.735 -deps 1.e-7
+checknbshapes result -vertex 32 -edge 51 -wire 21 -face 20 -shell 1 -solid 1
+CheckIsFeatureRemoved s_14 {v e f}
+CheckIsFeatureRemoved s_20 {v e f}
+
+# check modification of the top and bottom faces
+rfmodified m1 s_1
+checkprops m1 -s 174.62
+checknbshapes m1 -vertex 13 -edge 13 -wire 2 -face 1
+
+rfmodified m16 s_16
+checkprops m16 -s 194.429
+checknbshapes m16 -vertex 10 -edge 10 -wire 1 -face 1
+
+# check that no new intersections have been created
+if {![regexp "No shapes were generated" [rfgenerated g1 s_1]]} {
+  puts "Error: incorrect feature removal"
+}
+
+if {![regexp "No shapes were generated" [rfgenerated g16 s_16]]} {
+  puts "Error: incorrect feature removal"
+}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/B9 b/tests/boolean/removefeatures/B9
new file mode 100644 (file)
index 0000000..80ff23d
--- /dev/null
@@ -0,0 +1,24 @@
+restore [locate_data_file bug29481_ex1.brep] s
+explode s f
+
+# removal of the cylindrical spike on the shape
+
+removefeatures result s s_15 s_21 s_22
+checkshape result
+checkprops result -s 449.707 -v 186.844 -deps 1.e-7
+checknbshapes result -vertex 31 -edge 51 -wire 21 -face 19 -shell 1 -solid 1
+CheckIsFeatureRemoved s_15 {v e f}
+CheckIsFeatureRemoved s_21 {v e f}
+CheckIsFeatureRemoved s_22 {v e f}
+
+# check modification of the top face
+rfmodified m1 s_1
+checkprops m1 -s 175.593
+checknbshapes m1 -vertex 13 -edge 13 -wire 2 -face 1
+
+# check that no new intersections have been created
+if {![regexp "No shapes were generated" [rfgenerated g1 s_1]]} {
+  puts "Error: incorrect feature removal"
+}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/C1 b/tests/boolean/removefeatures/C1
new file mode 100644 (file)
index 0000000..00e49ea
--- /dev/null
@@ -0,0 +1,29 @@
+restore [locate_data_file bug29481_ex1.brep] s
+explode s f
+
+# remove all features from the shape
+
+# remove the step first
+compound s_6 s_18 step
+
+removefeatures res s step
+
+compound s_4 s_15 s_21 s_22 s_7 s_11 s_8 s_9 s_10 s_14 s_20 s_13 features
+
+# check modification of the features
+compound mf
+foreach f [explode features f] {
+  if { [regexp "The shape has not been modified" [rfmodified m $f]]} {
+    add $f mf
+  } else {
+    add m mf
+  }
+}
+
+removefeatures result res mf
+checkshape result
+checkprops result -s 460 -v 200
+checknbshapes result -vertex 8 -edge 12 -wire 6 -face 6 -shell 1 -solid 1
+CheckIsFeatureRemoved mf {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/C2 b/tests/boolean/removefeatures/C2
new file mode 100644 (file)
index 0000000..80625a3
--- /dev/null
@@ -0,0 +1,29 @@
+restore [locate_data_file bug29481_ex2.brep] s
+explode s f
+
+# remove the gap 
+compound s_7 s_8 s_9 s_10 gap
+removefeatures res1 s gap
+checkshape res1
+checkprops res1 -s 624 -v 992
+checknbshapes res1 -vertex 16 -edge 24 -wire 12 -face 12 -shell 2 -solid 1
+CheckIsFeatureRemoved gap {v e f}
+
+
+# remove hole
+explode s
+removefeatures res2 s s_2
+checkshape res2
+checkprops res2 -s 608 -v 992
+checknbshapes res2 -vertex 16 -edge 24 -wire 10 -face 10 -shell 1 -solid 1
+CheckIsFeatureRemoved s_2 {v e f}
+
+
+# remove both gap and hole
+removefeatures result s gap s_2
+checkshape result
+checkprops result -s 600 -v 1000
+checknbshapes result -vertex 8 -edge 12 -wire 6 -face 6 -shell 1 -solid 1
+CheckIsFeatureRemoved gap {v e f}
+CheckIsFeatureRemoved s_2 {v e f}
+
diff --git a/tests/boolean/removefeatures/C3 b/tests/boolean/removefeatures/C3
new file mode 100644 (file)
index 0000000..a9e8229
--- /dev/null
@@ -0,0 +1,21 @@
+restore [locate_data_file bug29481_ex3.brep] s
+explode s f
+
+# remove the gap in both solids
+compound s_7 s_8 s_9 s_11 s_12 s_17 gap
+removefeatures result s gap
+checkshape result
+checkprops result -s 1200 -v 2000
+checknbshapes result -vertex 12 -edge 20 -wire 11 -face 11 -shell 2 -solid 2
+CheckIsFeatureRemoved gap {v e f}
+
+# check that the common face is still shared
+if {![regexp "OK" [bopcheck result]]} {
+  puts "Error: sharing is lost after removal"
+}
+
+# check modification of the common face
+rfmodified m6 s_6
+checkprops m6 -s 100
+checknbshapes m6 -vertex 4 -edge 4 -wire 1 -face 1
+
diff --git a/tests/boolean/removefeatures/C4 b/tests/boolean/removefeatures/C4
new file mode 100644 (file)
index 0000000..6555c0b
--- /dev/null
@@ -0,0 +1,31 @@
+restore [locate_data_file bug29481_boxes.brep] s
+explode s f
+
+# remove the hole inside compsolid
+
+compound s_30 s_31 s_32 s_60 s_39 s_54 s_48 s_58 s_7 s_12 s_46 s_25 s_21 s_40 s_9 s_38 s_45 s_13 s_59 s_8 s_22 s_51 s_52 s_18 hole
+removefeatures result s hole
+checkshape result
+checkprops result -s 4800 -v 8000
+checknbshapes result -vertex 27 -edge 54 -wire 36 -face 36 -shell 8 -solid 8
+CheckIsFeatureRemoved hole {v e f}
+
+# check that the shape is still a compsolid
+if {![regexp "COMPSOLID" [whatis result]]} {
+  puts "Error: the type of input shape is lost during feature removal"
+}
+
+# check that the sharing is kept
+if {![regexp "OK" [bopcheck result]]} {
+  puts "Error: sharing is lost after feature removal"
+}
+
+# check modification of the solids
+foreach solid [explode s so] {
+  rfmodified msol $solid
+  checkprops msol -s 600 -v 1000
+  checknbshapes msol -vertex 8 -edge 12 -wire 6 -face 6 -shell 1 -solid 1 -t
+
+  bcommon com msol $solid
+  checkprops com -equal $solid
+}
diff --git a/tests/boolean/removefeatures/C5 b/tests/boolean/removefeatures/C5
new file mode 100644 (file)
index 0000000..0f185db
--- /dev/null
@@ -0,0 +1,47 @@
+restore [locate_data_file bug29481_ex3.brep] s
+explode s f
+
+# remove the gaps in each solid
+compound s_7 s_8 s_9 gap1
+compound s_11 s_12 s_17 gap2
+
+removefeatures res1 s gap1
+checkshape res1
+checkprops res1 -s 1200 -v 1875
+checknbshapes res1 -vertex 21 -edge 35 -wire 17 -face 17 -shell 2 -solid 2
+CheckIsFeatureRemoved gap1 {e f}
+
+# check that the common face is still shared
+if {![regexp "OK" [bopcheck res1]]} {
+  puts "Error: sharing is lost after removal"
+}
+
+# check modification of the common face
+rfmodified m6 s_6
+checkprops m6 -s 100
+
+# check modification of the solid 1
+explode s
+rfmodified m1 s_1
+checkprops m1 -s 600 -v 1000
+
+
+removefeatures res2 s gap2
+checkshape res2
+checkprops res2 -s 1200 -v 1875
+checknbshapes res2 -vertex 21 -edge 35 -wire 17 -face 17 -shell 2 -solid 2
+CheckIsFeatureRemoved gap2 {e f}
+
+# check that the common face is still shared
+if {![regexp "OK" [bopcheck res2]]} {
+  puts "Error: sharing is lost after removal"
+}
+
+# check modification of the common face
+rfmodified m6 s_6
+checkprops m6 -s 100
+
+# check modification of the solid 1
+explode s
+rfmodified m2 s_2
+checkprops m2 -s 600 -v 1000
diff --git a/tests/boolean/removefeatures/C6 b/tests/boolean/removefeatures/C6
new file mode 100644 (file)
index 0000000..4025f67
--- /dev/null
@@ -0,0 +1,11 @@
+restore [locate_data_file bug29481_ANC101.brep] s
+explode s f
+
+removefeatures result s s_22 s_24
+checkshape result
+checkprops result -s 441102 -v 8.18199e+006 -deps 1.e-7
+checknbshapes result -vertex 127 -edge 192 -wire 115 -face 85 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_22 {v e f}
+CheckIsFeatureRemoved s_24 {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/C7 b/tests/boolean/removefeatures/C7
new file mode 100644 (file)
index 0000000..5a50774
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_ANC101.brep] s
+explode s f
+
+compound s_52 s_23 s_22 s_54 s_24 s_53 cyl
+
+removefeatures result s cyl
+checkshape result
+checkprops result -s 439513 -v 8.11395e+006 -deps 1.e-7
+checknbshapes result -vertex 119 -edge 180 -wire 111 -face 81 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved cyl {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/C8 b/tests/boolean/removefeatures/C8
new file mode 100644 (file)
index 0000000..4ad7f0f
--- /dev/null
@@ -0,0 +1,10 @@
+restore [locate_data_file bug29481_ANC101.brep] s
+explode s f
+
+removefeatures result s s_83
+checkshape result
+checkprops result -s 441340 -v 8.18282e+006 -deps 1.e-7
+checknbshapes result -vertex 130 -edge 196 -wire 116 -face 86 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_83 {e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/C9 b/tests/boolean/removefeatures/C9
new file mode 100644 (file)
index 0000000..50fdc12
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_ANC101.brep] s
+explode s f
+
+compound s_51 s_17 s_14 s_15 s_16 cyls
+
+removefeatures result s cyls
+checkshape result
+checkprops result -s 422114 -v 8.34108e+006 -deps 1.e-7
+checknbshapes result -vertex 121 -edge 183 -wire 102 -face 82 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved cyls {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/D1 b/tests/boolean/removefeatures/D1
new file mode 100644 (file)
index 0000000..db66848
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_ANC101.brep] s
+explode s f
+
+compound s_66 s_60 s_63 s_77 s_76 s_62 s_68 s_67 s_65 s_75 s_61 s_78 s_64 s_73 s_79 s_81 s_80 s_74 cyls
+
+removefeatures result s cyls
+checkshape result
+checkprops result -s 415106 -v 8.28188e+006 -deps 1.e-7
+checknbshapes result -vertex 113 -edge 171 -wire 90 -face 69 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved cyls {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/D2 b/tests/boolean/removefeatures/D2
new file mode 100644 (file)
index 0000000..6943273
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_ANC101.brep] s
+explode s f
+
+compound s_45 s_57 s_32 s_59 s_43 s_31 s_33 s_47 gaps
+
+removefeatures result s gaps
+checkshape result
+checkprops result -s 440693 -v 8.18581e+006 -deps 1.e-7
+checknbshapes result -vertex 115 -edge 174 -wire 109 -face 79 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved gaps {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/D3 b/tests/boolean/removefeatures/D3
new file mode 100644 (file)
index 0000000..6a83f23
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_ANC101.brep] s
+explode s f
+
+compound s_28 s_26 s_32 s_35 s_47 s_57 s_12 s_31 s_58 s_48 s_34 s_33 s_39 s_44 s_29 s_43 s_41 s_56 s_11 s_46 s_59 s_40 s_38 s_27 s_45 s_30 s_37 s_42 s_36 s_4 s_10 s_5 s_3 s_13 gaps
+
+removefeatures result s gaps
+checkshape result
+checkprops result -s 433947 -v 8.26107e+006 -deps 1.e-7
+checknbshapes result -vertex 71 -edge 107 -wire 80 -face 53 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved gaps {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/D4 b/tests/boolean/removefeatures/D4
new file mode 100644 (file)
index 0000000..7aff411
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_ANC101.brep] s
+explode s f
+
+compound s_86 s_25 s_72 s_55 bottom
+
+removefeatures result s bottom
+checkshape result
+checkprops result -s 439076 -v 8.27381e+006 -deps 1.e-7
+checknbshapes result -vertex 127 -edge 192 -wire 111 -face 83 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved bottom {e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/D5 b/tests/boolean/removefeatures/D5
new file mode 100644 (file)
index 0000000..449ed5b
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_ANC101.brep] s
+explode s f
+
+compound s_87 s_69 s_82 cyl
+
+removefeatures result s cyl
+checkshape result
+checkprops result -s 410701 -v 8.98858e+006 -deps 1.e-7
+checknbshapes result -vertex 127 -edge 192 -wire 111 -face 84 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved cyl {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/D6 b/tests/boolean/removefeatures/D6
new file mode 100644 (file)
index 0000000..7afc8f6
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_ANC101.brep] s
+explode s f
+
+removefeatures result s s_83 s_70 s_85
+checkshape result
+checkprops result -s 427464 -v 8.0484e+006 -deps 1.e-7
+checknbshapes result -vertex 128 -edge 193 -wire 113 -face 84 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_83 {v e f}
+CheckIsFeatureRemoved s_70 {v e f}
+CheckIsFeatureRemoved s_85 {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/D7 b/tests/boolean/removefeatures/D7
new file mode 100644 (file)
index 0000000..8eeb0ce
--- /dev/null
@@ -0,0 +1,16 @@
+restore [locate_data_file bug28840_5.brep] s
+explode s f
+
+compound s_3 s_8 s_29 s_2 s_1 feature1
+compound s_15 s_10 s_6 s_18 s_9 s_13 s_11 feature2
+compound s_19 s_14 s_7 s_16 s_17 s_12 feature3
+
+removefeatures result s feature1 feature2 feature3
+checkshape result
+checkprops result -s 19692.7 -v 142463 -deps 1.e-7
+checknbshapes result -vertex 16 -edge 24 -wire 12 -face 11 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved feature1 {v e f}
+CheckIsFeatureRemoved feature2 {v e f}
+CheckIsFeatureRemoved feature3 {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/D8 b/tests/boolean/removefeatures/D8
new file mode 100644 (file)
index 0000000..e0b6c6a
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug28840_5.brep] s
+explode s f
+
+compound s_3 s_8 s_29 s_2 s_1 feature1
+
+removefeatures result s feature1
+checkshape result
+checkprops result -s 19165.2 -v 142408 -deps 1.e-7
+checknbshapes result -vertex 31 -edge 53 -wire 25 -face 24 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved feature1 {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/D9 b/tests/boolean/removefeatures/D9
new file mode 100644 (file)
index 0000000..d295603
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug28840_5.brep] s
+explode s f
+
+compound s_15 s_10 s_6 s_18 s_9 s_13 s_11 feature2
+
+removefeatures result s feature2
+checkshape result
+checkprops result -s 18606.8 -v 138974 -deps 1.e-7
+checknbshapes result -vertex 31 -edge 51 -wire 23 -face 22 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved feature2 {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/E1 b/tests/boolean/removefeatures/E1
new file mode 100644 (file)
index 0000000..e9eacf7
--- /dev/null
@@ -0,0 +1,50 @@
+restore [locate_data_file bug28840_5.brep] s
+explode s f
+
+compound s_3 s_8 s_29 s_2 s_1 feature1
+compound s_15 s_10 s_6 s_18 s_9 s_13 s_11 feature2
+compound s_19 s_14 s_7 s_16 s_17 s_12 feature3
+
+# remove first feature
+removefeatures res1 s feature1
+checkshape res1
+checkprops res1 -s 19165.2 -v 142408 -deps 1.e-7
+checknbshapes res1 -vertex 31 -edge 53 -wire 25 -face 24 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved feature1 {v e f}
+
+
+# prepare for removal of the second feature
+compound mfeature2
+foreach f [explode feature2 f] {
+  if {[regexp "has not been modified" [rfmodified fm $f]]} {
+    add $f mfeature2
+  } else {
+    add fm mfeature2
+  }
+}
+
+# remove second feature
+removefeatures res2 res1 mfeature2
+checkshape res2
+checkprops res2 -s 19396.1 -v 141748 -deps 1.e-7
+checknbshapes res2 -vertex 24 -edge 39 -wire 18 -face 17 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved mfeature2 {v e f}
+
+# prepare for removal of the third feature
+compound mfeature3
+foreach f [explode feature3 f] {
+  if {[regexp "has not been modified" [rfmodified fm $f]]} {
+    add $f mfeature3
+  } else {
+    add fm mfeature3
+  }
+}
+
+# remove the third feature
+removefeatures result res2 mfeature3
+checkshape result
+checkprops result -s 19692.7 -v 142463 -deps 1.e-7
+checknbshapes result -vertex 16 -edge 24 -wire 12 -face 11 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved mfeature3 {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/E2 b/tests/boolean/removefeatures/E2
new file mode 100644 (file)
index 0000000..2ded430
--- /dev/null
@@ -0,0 +1,11 @@
+restore [locate_data_file bug28840_5.brep] s
+explode s f
+
+removefeatures result s s_11 s_12
+checkshape result
+checkprops result -s 18419.9 -v 139777 -deps 1.e-7
+checknbshapes result -vertex 36 -edge 61 -wire 28 -face 27 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_11 {e f}
+CheckIsFeatureRemoved s_12 {e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/E3 b/tests/boolean/removefeatures/E3
new file mode 100644 (file)
index 0000000..192805f
--- /dev/null
@@ -0,0 +1,11 @@
+restore [locate_data_file bug28840_5.brep] s
+explode s f
+
+removefeatures result s s_15 s_17
+checkshape result
+checkprops result -s 18427.3 -v 139789 -deps 1.e-7
+checknbshapes result -vertex 35 -edge 60 -wire 28 -face 27 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_15 {e f}
+CheckIsFeatureRemoved s_17 {e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/E4 b/tests/boolean/removefeatures/E4
new file mode 100644 (file)
index 0000000..a0dddec
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug28840_5.brep] s
+explode s f
+
+removefeatures result s s_7 s_9 s_16
+checkshape result
+checkprops result -s 18421.8 -v 139780 -deps 1.e-7
+checknbshapes result -vertex 35 -edge 58 -wire 27 -face 26 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_7 {e f}
+CheckIsFeatureRemoved s_9 {e f}
+CheckIsFeatureRemoved s_16 {e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/E5 b/tests/boolean/removefeatures/E5
new file mode 100644 (file)
index 0000000..a066d90
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug28840_6.brep] s
+explode s f
+
+removefeatures result s s_6 s_7 s_9
+checkshape result
+checkprops result -s 19274.8 -v 140565 -deps 1.e-7
+checknbshapes result -vertex 18 -edge 27 -wire 13 -face 12 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_6 {v e f}
+CheckIsFeatureRemoved s_7 {v e f}
+CheckIsFeatureRemoved s_9 {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/E6 b/tests/boolean/removefeatures/E6
new file mode 100644 (file)
index 0000000..a10a956
--- /dev/null
@@ -0,0 +1,13 @@
+restore [locate_data_file bug28840_12.brep] s
+explode s f
+
+removefeatures result s s_7 s_6 s_8 s_10
+checkshape result
+checkprops result -s 19274.8 -v 140565 -deps 1.e-7
+checknbshapes result -vertex 18 -edge 27 -wire 13 -face 12 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_6 {v e f}
+CheckIsFeatureRemoved s_7 {v e f}
+CheckIsFeatureRemoved s_8 {v e f}
+CheckIsFeatureRemoved s_10 {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/E7 b/tests/boolean/removefeatures/E7
new file mode 100644 (file)
index 0000000..367d06b
--- /dev/null
@@ -0,0 +1,11 @@
+restore [locate_data_file bug28840_1.brep] s
+explode s f
+
+removefeatures result s s_3 s_7
+checkshape result
+checkprops result -s 33645 -v 270128 -deps 1.e-7
+checknbshapes result -vertex 4 -edge 6 -wire 6 -face 5 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_3 {e f}
+CheckIsFeatureRemoved s_7 {e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/E8 b/tests/boolean/removefeatures/E8
new file mode 100644 (file)
index 0000000..b8d8367
--- /dev/null
@@ -0,0 +1,15 @@
+pload XDE
+
+stepread [locate_data_file bug26689_nist_ctc_01_asme1_ap242.stp] s *
+copy s_1 s
+explode s f
+
+compound s_146 s_135 s_149 s_141 s_132 s_140 s_144 s_130 s_122 s_148 s_134 s_139 s_147 s_127 s_145 s_120 s_150 s_129 s_136 s_125 s_142 s_121 s_126 s_151 s_124 s_143 s_138 s_118 s_133 s_137 s_131 s_119 s_123 s_128 nist
+
+removefeatures result s nist
+checkshape result
+checkprops result -s 807081 -v 1.46448e+007 -deps 1.e-7
+checknbshapes result -vertex 206 -edge 322 -wire 140 -face 117 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved nist {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/E9 b/tests/boolean/removefeatures/E9
new file mode 100644 (file)
index 0000000..99ae4b8
--- /dev/null
@@ -0,0 +1,15 @@
+pload XDE
+
+stepread [locate_data_file bug26689_nist_ctc_01_asme1_ap242.stp] s *
+copy s_1 s
+explode s f
+
+compound s_71 s_93 s_74 s_92 s_75 s_72 s_90 s_91 s_73 s_2 s_1 s_76 s_89 s_94 s_95 s_96 holes
+
+removefeatures result s holes
+checkshape result
+checkprops result -s 759902 -v 1.51258e+007 -deps 1.e-7
+checknbshapes result -vertex 238 -edge 370 -wire 144 -face 135 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved holes {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/F1 b/tests/boolean/removefeatures/F1
new file mode 100644 (file)
index 0000000..7d16302
--- /dev/null
@@ -0,0 +1,17 @@
+pload XDE
+
+stepread [locate_data_file bug26689_nist_ctc_01_asme1_ap242.stp] s *
+copy s_1 s
+explode s f
+
+compound s_100 s_99 s_101 s_98 s_102 s_103 fillet
+compound s_115 s_112 s_116 s_114 s_111 s_113 blend
+
+removefeatures result s fillet blend
+checkshape result
+checkprops result -s 809750 -v 1.46451e+007 -deps 1.e-7
+checknbshapes result -vertex 258 -edge 394 -wire 164 -face 139 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved fillet {e f}
+CheckIsFeatureRemoved blend {e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/F2 b/tests/boolean/removefeatures/F2
new file mode 100644 (file)
index 0000000..eb173c7
--- /dev/null
@@ -0,0 +1,15 @@
+pload XDE
+
+stepread [locate_data_file bug26689_nist_ctc_01_asme1_ap242.stp] s *
+copy s_1 s
+explode s f
+
+compound s_34 s_12 s_32 s_40 s_37 s_16 s_18 s_17 s_39 s_41 s_31 s_14 s_35 s_13 s_38 s_33 gaps
+
+removefeatures result s gaps
+checkshape result
+checkprops result -s 813251 -v 1.49885e+007 -deps 1.e-7
+checknbshapes result -vertex 230 -edge 358 -wire 156 -face 131 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved gaps {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/F3 b/tests/boolean/removefeatures/F3
new file mode 100644 (file)
index 0000000..bfd8703
--- /dev/null
@@ -0,0 +1,15 @@
+pload XDE
+
+stepread [locate_data_file bug26689_nist_ctc_01_asme1_ap242.stp] s *
+copy s_1 s
+explode s f
+
+compound s_86 s_83 s_81 s_82 s_84 s_85 s_80 s_78 s_79 s_88 s_77 s_87 holes
+
+removefeatures result s holes
+checkshape result
+checkprops result -s 798285 -v 1.51114e+007 -deps 1.e-7
+checknbshapes result -vertex 246 -edge 382 -wire 160 -face 139 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved holes {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/F4 b/tests/boolean/removefeatures/F4
new file mode 100644 (file)
index 0000000..e7bc71d
--- /dev/null
@@ -0,0 +1,15 @@
+pload XDE
+
+stepread [locate_data_file bug26689_nist_ctc_01_asme1_ap242.stp] s *
+copy s_1 s
+explode s f
+
+compound s_10 s_66 s_43 s_65 s_63 s_64 s_69 s_29 s_68 s_70 s_20 s_67 fillets
+
+removefeatures result s fillets
+checkshape result
+checkprops result -s 811691 -v 1.46014e+007 -deps 1.e-7
+checknbshapes result -vertex 246 -edge 382 -wire 164 -face 139 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved fillets {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/F5 b/tests/boolean/removefeatures/F5
new file mode 100644 (file)
index 0000000..54bf298
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_window_slots.brep] s
+explode s f
+
+compound s_84 s_68 s_61 s_57 s_64 s_56 s_62 s_67 s_76 s_85 s_63 s_49 s_52 s_80 s_59 s_70 s_82 s_54 s_86 s_66 s_55 s_69 s_72 s_73 s_58 s_74 s_51 s_77 s_78 s_79 s_81 s_83 s_50 s_65 s_53 s_75 s_71 s_60 s_15 s_33 s_40 s_22 s_13 s_98 s_18 s_35 s_17 s_37 s_27 s_93 s_26 s_24 s_29 s_12 s_94 s_19 s_21 s_39 s_97 s_91 s_96 s_34 s_20 s_23 s_14 s_16 s_92 s_25 s_95 s_31 s_38 s_28 s_99 s_90 s_36 s_32 s_30 pockets
+
+removefeatures result s pockets
+checkshape result
+checkprops result -s 22976.2 -v 68900 -deps 1.e-7
+checknbshapes result -vertex 38 -edge 58 -wire 22 -face 21 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved pockets {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/F6 b/tests/boolean/removefeatures/F6
new file mode 100644 (file)
index 0000000..badc45e
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_window_slots.brep] s
+explode s f
+
+compound s_11 s_10 s_46 s_45 s_47 hole
+
+removefeatures result s hole
+checkshape result
+checkprops result -s 32410 -v 108650 -deps 1.e-7
+checknbshapes result -vertex 104 -edge 156 -wire 54 -face 54 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved hole {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/F7 b/tests/boolean/removefeatures/F7
new file mode 100644 (file)
index 0000000..0c827fa
--- /dev/null
@@ -0,0 +1,12 @@
+restore [locate_data_file bug29481_window_slots.brep] s
+explode s f
+
+compound s_8 s_9 s_89 s_88 s_7 gap
+
+removefeatures result s gap
+checkshape result
+checkprops result -s 23746.2 -v 69550 -deps 1.e-7
+checknbshapes result -vertex 184 -edge 276 -wire 94 -face 93 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved gap {e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/F8 b/tests/boolean/removefeatures/F8
new file mode 100644 (file)
index 0000000..754bde1
--- /dev/null
@@ -0,0 +1,11 @@
+restore [locate_data_file bug29481_window_slots.brep] s
+explode s f
+
+removefeatures result s s_10 s_46
+checkshape result
+checkprops result -s 24110 -v 66650 -deps 1.e-7
+checknbshapes result -vertex 190 -edge 286 -wire 98 -face 97 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_10 {v e f}
+CheckIsFeatureRemoved s_46 {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/F9 b/tests/boolean/removefeatures/F9
new file mode 100644 (file)
index 0000000..8c946b4
--- /dev/null
@@ -0,0 +1,11 @@
+restore [locate_data_file bug28840_5.brep] s
+explode s f
+
+removefeatures result s s_14 s_16
+checkshape result
+checkprops result -s 18428.1 -v 139749 -deps 1.e-7
+checknbshapes result -vertex 37 -edge 61 -wire 28 -face 27 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_14 {e f}
+CheckIsFeatureRemoved s_16 {e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/G1 b/tests/boolean/removefeatures/G1
new file mode 100644 (file)
index 0000000..4c8b3da
--- /dev/null
@@ -0,0 +1,27 @@
+# prepare model
+polyline p 0 0 0 10 0 0 10 0 5 5 0 5 0 0 0
+mkplane f p
+prism s f 0 5 0
+pcylinder c 2 3
+ttranslate c 7.5 2.5 2
+
+bclearobjects
+bcleartools
+baddobjects s
+baddtools c
+bfillds
+bbop model 2
+
+# find face to remove - top face of the model
+explode s f
+bmodified feature s_3
+
+# remove features
+removefeatures result model feature
+
+checkshape result
+checkprops result -s 334.621 -v 180.885 -deps 1.e-7
+checknbshapes result -vertex 8 -edge 12 -wire 8 -face 7 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved feature {e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/G2 b/tests/boolean/removefeatures/G2
new file mode 100644 (file)
index 0000000..476851a
--- /dev/null
@@ -0,0 +1,10 @@
+restore [locate_data_file bug29481_ANC101.brep] s
+explode s f
+
+removefeatures result s s_49
+checkshape result
+checkprops result -s 501833 -v 8.60751e+006 -deps 1.e-7
+checknbshapes result -vertex 129 -edge 195 -wire 116 -face 86 -shell 1 -solid 1 -t
+CheckIsFeatureRemoved s_49 {v e f}
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/boolean/removefeatures/begin b/tests/boolean/removefeatures/begin
new file mode 100644 (file)
index 0000000..aaf3edf
--- /dev/null
@@ -0,0 +1,12 @@
+proc CheckIsFeatureRemoved {theFeature types} {
+  upvar $theFeature TheFeature
+  compound TheFeature TheFeatureC
+  foreach t $types {
+    foreach s [explode TheFeatureC $t] {
+      set log [rfisdeleted $s]
+      if {$log != "Deleted\n"} {
+        puts "Error: Feature is not removed"
+      }
+    }
+  }
+}