FeaturesAPI_FusionFaces.h
FeaturesAPI_Copy.h
FeaturesAPI_ImportResult.h
+ FeaturesAPI_Defeaturing.h
)
SET(PROJECT_SOURCES
FeaturesAPI_FusionFaces.cpp
FeaturesAPI_Copy.cpp
FeaturesAPI_ImportResult.cpp
+ FeaturesAPI_Defeaturing.cpp
)
SET(PROJECT_LIBRARIES
%shared_ptr(FeaturesAPI_RemoveResults)
%shared_ptr(FeaturesAPI_Copy)
%shared_ptr(FeaturesAPI_ImportResult)
+%shared_ptr(FeaturesAPI_Defeaturing)
%typecheck(SWIG_TYPECHECK_POINTER) std::pair<std::list<ModelHighAPI_Selection>, bool>, const std::pair<std::list<ModelHighAPI_Selection>, bool> & {
%include "FeaturesAPI_BooleanSmash.h"
%include "FeaturesAPI_BooleanFill.h"
%include "FeaturesAPI_Chamfer.h"
+%include "FeaturesAPI_Defeaturing.h"
%include "FeaturesAPI_Extrusion.h"
%include "FeaturesAPI_ExtrusionBoolean.h"
%include "FeaturesAPI_Fillet.h"
--- /dev/null
+// Copyright (C) 2020 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "FeaturesAPI_Defeaturing.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+FeaturesAPI_Defeaturing::FeaturesAPI_Defeaturing(
+ const std::shared_ptr<ModelAPI_Feature>& theFeature)
+ : ModelHighAPI_Interface(theFeature)
+{
+ initialize();
+}
+
+FeaturesAPI_Defeaturing::FeaturesAPI_Defeaturing(
+ const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theFacesToRemove)
+ : ModelHighAPI_Interface(theFeature)
+{
+ if (initialize())
+ setFaces(theFacesToRemove);
+}
+
+FeaturesAPI_Defeaturing::~FeaturesAPI_Defeaturing()
+{
+}
+
+void FeaturesAPI_Defeaturing::setFaces(const std::list<ModelHighAPI_Selection>& theFacesToRemove)
+{
+ mybaseObjects->clear();
+ fillAttribute(theFacesToRemove, mybaseObjects);
+
+ execIfBaseNotEmpty();
+}
+
+void FeaturesAPI_Defeaturing::dump(ModelHighAPI_Dumper& theDumper) const
+{
+ FeaturePtr aBase = feature();
+ const std::string& aDocName = theDumper.name(aBase->document());
+
+ AttributeSelectionListPtr anAttrObjects =
+ aBase->selectionList(FeaturesPlugin_Defeaturing::OBJECT_LIST_ID());
+
+ theDumper << aBase << " = model.addDefeaturing(" << aDocName << ", "
+ << anAttrObjects << ")" << std::endl;
+}
+
+void FeaturesAPI_Defeaturing::execIfBaseNotEmpty()
+{
+ if (mybaseObjects->size() > 0)
+ execute();
+}
+
+
+//==================================================================================================
+
+DefeaturingPtr addDefeaturing(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theFaces)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(FeaturesAPI_Defeaturing::ID());
+ return DefeaturingPtr(new FeaturesAPI_Defeaturing(aFeature, theFaces));
+}
--- /dev/null
+// Copyright (C) 2020 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef FeaturesAPI_Defeaturing_H_
+#define FeaturesAPI_Defeaturing_H_
+
+#include "FeaturesAPI.h"
+
+#include <FeaturesPlugin_Defeaturing.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Selection;
+
+/// \class FeaturesAPI_Defeaturing
+/// \ingroup CPPHighAPI
+/// \brief Interface for the Defeaturing feature.
+class FeaturesAPI_Defeaturing: public ModelHighAPI_Interface
+{
+public:
+ /// Constructor without values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_Defeaturing(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+ /// Constructor with values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_Defeaturing(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theFacesToRemove);
+
+ /// Destructor.
+ FEATURESAPI_EXPORT
+ virtual ~FeaturesAPI_Defeaturing();
+
+ INTERFACE_1(FeaturesPlugin_Defeaturing::ID(),
+ baseObjects, FeaturesPlugin_Defeaturing::OBJECT_LIST_ID(),
+ ModelAPI_AttributeSelectionList, /** Base objects */)
+
+ /// Modify faces to be removed.
+ FEATURESAPI_EXPORT
+ void setFaces(const std::list<ModelHighAPI_Selection>& theFacesToRemove);
+
+ /// Dump wrapped feature
+ FEATURESAPI_EXPORT
+ virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+
+private:
+ void execIfBaseNotEmpty();
+};
+
+/// Pointer on the Defeaturing object.
+typedef std::shared_ptr<FeaturesAPI_Defeaturing> DefeaturingPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Defeaturing feature.
+FEATURESAPI_EXPORT
+DefeaturingPtr addDefeaturing(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theFaces);
+
+#endif // FeaturesAPI_Defeaturing_H_
#include "FeaturesAPI_BooleanSmash.h"
#include "FeaturesAPI_BooleanFill.h"
#include "FeaturesAPI_Chamfer.h"
+ #include "FeaturesAPI_Defeaturing.h"
#include "FeaturesAPI_Extrusion.h"
#include "FeaturesAPI_ExtrusionBoolean.h"
#include "FeaturesAPI_Fillet.h"
FeaturesPlugin_Chamfer.h
FeaturesPlugin_Copy.h
FeaturesPlugin_ImportResult.h
+ FeaturesPlugin_Defeaturing.h
)
SET(PROJECT_SOURCES
FeaturesPlugin_Chamfer.cpp
FeaturesPlugin_Copy.cpp
FeaturesPlugin_ImportResult.cpp
+ FeaturesPlugin_Defeaturing.cpp
)
SET(XML_RESOURCES
chamfer_widget.xml
copy_widget.xml
import_result_widget.xml
+ defeaturing_widget.xml
)
SET(TEXT_RESOURCES
TestCopySubShapes.py
TestCopyWholeFeature.py
TestImportResult.py
+ TestDefeaturing_ErrorMsg.py
+ TestDefeaturing_OnSolid1.py
+ TestDefeaturing_OnSolid2.py
+ TestDefeaturing_OnSolid3.py
+ TestDefeaturing_OnCompsolid1.py
+ TestDefeaturing_OnCompsolid2.py
+ TestDefeaturing_OnCompsolid3.py
+ TestDefeaturing_OnCompound.py
)
--- /dev/null
+// Copyright (C) 2020 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include <FeaturesPlugin_Defeaturing.h>
+#include <FeaturesPlugin_Tools.h>
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_Tools.h>
+
+#include <GeomAPI_ShapeExplorer.h>
+
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_Defeaturing.h>
+#include <GeomAlgoAPI_MakeShapeList.h>
+#include <GeomAlgoAPI_Tools.h>
+
+#include <unordered_map>
+
+
+FeaturesPlugin_Defeaturing::FeaturesPlugin_Defeaturing()
+{
+}
+
+void FeaturesPlugin_Defeaturing::initAttributes()
+{
+ data()->addAttribute(OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
+}
+
+
+void FeaturesPlugin_Defeaturing::execute()
+{
+ typedef std::unordered_map<GeomShapePtr, ListOfShape,
+ GeomAPI_Shape::Hash, GeomAPI_Shape::Equal> SolidFaces;
+ SolidFaces aBodiesAndFacesToRemove;
+
+ // getting objects and sort them according to parent solids
+ AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECT_LIST_ID());
+ for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); ++anObjectsIndex) {
+ AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
+ GeomShapePtr anObject = anObjectAttr->value();
+ if (!anObject)
+ return;
+
+ ResultPtr aContext = anObjectAttr->context();
+ if (!aContext.get())
+ return;
+
+ ResultBodyPtr aCtxOwner = ModelAPI_Tools::bodyOwner(aContext, true);
+ GeomShapePtr aParent = aCtxOwner ? aCtxOwner->shape() : aContext->shape();
+ aBodiesAndFacesToRemove[aParent].push_back(anObject);
+ }
+
+ // Perform Defeaturing algorithm
+ GeomAlgoAPI_MakeShapeList aMakeShapeList;
+ std::shared_ptr<GeomAlgoAPI_Defeaturing> anAlgo;
+ int aResultIndex = 0;
+ std::string anError;
+
+ std::vector<FeaturesPlugin_Tools::ResultBaseAlgo> aResultBaseAlgoList;
+ ListOfShape anOriginalShapesList, aResultShapesList;
+
+ for (SolidFaces::iterator anIt = aBodiesAndFacesToRemove.begin();
+ anIt != aBodiesAndFacesToRemove.end(); ++anIt) {
+ GeomShapePtr aParent = anIt->first;
+ anAlgo.reset(new GeomAlgoAPI_Defeaturing(aParent, anIt->second));
+ if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(anAlgo, getKind(), anError)) {
+ setError(anError);
+ return;
+ }
+
+ GeomShapePtr aResult = anAlgo->shape();
+ ListOfShape aBaseShapes;
+ for (GeomAPI_ShapeExplorer anExp(aParent, GeomAPI_Shape::SOLID); anExp.more(); anExp.next())
+ aBaseShapes.push_back(anExp.current());
+
+ std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
+ FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, aBaseShapes, ListOfShape(),
+ anAlgo, aResult, "Defeaturing");
+
+ setResult(aResultBody, aResultIndex);
+ aResultIndex++;
+
+ FeaturesPlugin_Tools::ResultBaseAlgo aRBA;
+ aRBA.resultBody = aResultBody;
+ aRBA.baseShape = aParent;
+ aRBA.makeShape = anAlgo;
+ aResultBaseAlgoList.push_back(aRBA);
+ aResultShapesList.push_back(aResult);
+ anOriginalShapesList.insert(anOriginalShapesList.end(), aBaseShapes.begin(), aBaseShapes.end());
+ }
+
+ // Store deleted shapes after all results has been proceeded. This is to avoid issue when in one
+ // result shape has been deleted, but in another it was modified or stayed.
+ GeomShapePtr aResultShapesCompound = GeomAlgoAPI_CompoundBuilder::compound(aResultShapesList);
+ FeaturesPlugin_Tools::loadDeletedShapes(aResultBaseAlgoList,
+ anOriginalShapesList, aResultShapesCompound);
+
+ removeResults(aResultIndex);
+}
--- /dev/null
+// Copyright (C) 2020 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef FeaturesPlugin_Defeaturing_H_
+#define FeaturesPlugin_Defeaturing_H_
+
+#include "FeaturesPlugin.h"
+
+#include <ModelAPI_Feature.h>
+
+class GeomAlgoAPI_MakeShape;
+class GeomAPI_Shape;
+
+/// \class FeaturesPlugin_Defeaturing
+/// \ingroup Plugins
+/// \brief Feature for the removal of the unwanted parts or features from the model.
+class FeaturesPlugin_Defeaturing : public ModelAPI_Feature
+{
+public:
+ /// Feature kind.
+ inline static const std::string& ID()
+ {
+ static const std::string MY_ID("Defeaturing");
+ return MY_ID;
+ }
+
+ /// \return the kind of a feature.
+ FEATURESPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = FeaturesPlugin_Defeaturing::ID();
+ return MY_KIND;
+ }
+
+ /// Attribute name of main objects.
+ inline static const std::string& OBJECT_LIST_ID()
+ {
+ static const std::string MY_OBJECT_LIST_ID("main_objects");
+ return MY_OBJECT_LIST_ID;
+ }
+
+ /// Performs the defeaturing algorithm and stores it in the data structure.
+ FEATURESPLUGIN_EXPORT virtual void execute();
+
+ /// Request for initialization of data model of the feature: adding all attributes.
+ FEATURESPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Use plugin manager for features creation.
+ FeaturesPlugin_Defeaturing();
+
+private:
+ /// Load Naming data structure of the feature to the document
+ void loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+ const std::shared_ptr<GeomAPI_Shape> theBaseShape,
+ const std::shared_ptr<GeomAPI_Shape> theResultShape,
+ const std::shared_ptr<GeomAlgoAPI_MakeShape>& theMakeShape);
+};
+
+#endif
#include <FeaturesPlugin_BooleanSmash.h>
#include <FeaturesPlugin_BooleanFill.h>
#include <FeaturesPlugin_Chamfer.h>
+#include <FeaturesPlugin_Defeaturing.h>
#include <FeaturesPlugin_Extrusion.h>
#include <FeaturesPlugin_ExtrusionCut.h>
#include <FeaturesPlugin_ExtrusionFuse.h>
new FeaturesPlugin_ValidatorBooleanCommonArguments);
aFactory->registerValidator("FeaturesPlugin_ValidatorImportResults",
new FeaturesPlugin_ValidatorImportResults);
+ aFactory->registerValidator("FeaturesPlugin_ValidatorDefeaturingSelection",
+ new FeaturesPlugin_ValidatorDefeaturingSelection);
// register this plugin
ModelAPI_Session::get()->registerPlugin(this);
return FeaturePtr(new FeaturesPlugin_Copy);
} else if (theFeatureID == FeaturesPlugin_ImportResult::ID()) {
return FeaturePtr(new FeaturesPlugin_ImportResult);
+ } else if (theFeatureID == FeaturesPlugin_Defeaturing::ID()) {
+ return FeaturePtr(new FeaturesPlugin_Defeaturing);
}
return false;
}
// LCOV_EXCL_STOP
+
+//==================================================================================================
+bool FeaturesPlugin_ValidatorDefeaturingSelection::isValid(
+ const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ AttributeSelectionListPtr anAttrSelectionList =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+ if (!anAttrSelectionList.get()) {
+ // LCOV_EXCL_START
+ theError = "Error: This validator can only work with selection list attributes.";
+ return false;
+ // LCOV_EXCL_STOP
+ }
+
+ // Check selected entities are sub-shapes of solid or compsolid
+ GeomShapePtr aBaseSolid;
+ for (int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
+ AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
+ if (!anAttrSelection.get()) {
+ theError = "Error: Empty attribute selection.";
+ return false;
+ }
+ ResultPtr aContext = anAttrSelection->context();
+ if (!aContext.get()) {
+ theError = "Error: Empty selection context.";
+ return false;
+ }
+
+ GeomShapePtr aContextShape = aContext->shape();
+ if (aContextShape->shapeType() != GeomAPI_Shape::SOLID) {
+ theError = "Error: Not all selected shapes are sub-shapes of solids.";
+ return false;
+ }
+ }
+
+ return true;
+}
virtual bool isNotObligatory(std::string theFeature, std::string theAttribute);
};
+/// \class FeaturesPlugin_ValidatorDefeaturingSelection
+/// \ingroup Validators
+/// \brief Validates selection for fillet operation.
+class FeaturesPlugin_ValidatorDefeaturingSelection : public ModelAPI_AttributeValidator
+{
+public:
+ /// \return True if the attribute is valid. It checks whether the selection
+ /// is acceptable for boolean operation.
+ /// \param[in] theAttribute an attribute to check.
+ /// \param[in] theArguments a filter parameters.
+ /// \param[out] theError error message.
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+};
+
#endif
--- /dev/null
+# Copyright (C) 2020 CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+
+Defeaturing_1 = model.addDefeaturing(Part_1_doc, [model.selection("FACE", "Box_1_1/Top")])
+assert(Defeaturing_1.feature().error() != "")
+
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_2 = model.addBox(Part_2_doc, 10, 10, 10)
+ExtrusionCut_1 = model.addExtrusionCut(Part_2_doc, [], model.selection(), [model.selection("SOLID", "Box_1_1")])
+Sketch_1 = model.addSketch(Part_2_doc, model.selection("FACE", "Box_1_1/Top"))
+SketchCircle_1 = Sketch_1.addCircle(4, 5.137343601256935, 3)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 3)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchCircle_1.center(), SketchLine_1.result(), 4, True)
+ExtrusionCut_1.setNestedSketch(Sketch_1)
+Plane_4 = model.addPlane(Part_2_doc, model.selection("FACE", "Box_1_1/Back"), model.selection("FACE", "Box_1_1/Front"))
+Partition_1 = model.addPartition(Part_2_doc, [model.selection("SOLID", "ExtrusionCut_1_1"), model.selection("FACE", "Plane_1")], keepSubResults = True)
+
+Defeaturing_2 = model.addDefeaturing(Part_2_doc, [model.selection("FACE", "Partition_1_1_1/Modified_Face&Sketch_1/SketchCircle_1_2")])
+assert(Defeaturing_2.feature().error() != "")
+
+model.end()
--- /dev/null
+# Copyright (C) 2020 CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 20, 20, 10)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], 10, 10, 0)
+Cylinder_2 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Cut_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Box_1_1")], [model.selection("SOLID", "Translation_1_1"), model.selection("SOLID", "Cylinder_2_1")], keepSubResults = True)
+LinearCopy_1 = model.addMultiTranslation(Part_1_doc, [model.selection("SOLID", "Cut_1_1")], model.selection("EDGE", "PartSet/OX"), 30, 2, model.selection("EDGE", "PartSet/OY"), 30, 2)
+Defeaturing_1_objects = [model.selection("FACE", "LinearCopy_1_1_1/MF:Translated&Cylinder_2_1/Face_1"), model.selection("FACE", "LinearCopy_1_1_4/MF:Translated&Cylinder_1_1/Face_1"), model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Cylinder_2_1/Face_1"), model.selection("FACE", "LinearCopy_1_1_3/MF:Translated&Cylinder_1_1/Face_1")]
+Defeaturing_1 = model.addDefeaturing(Part_1_doc, Defeaturing_1_objects)
+model.testHaveNamingSubshapes(Defeaturing_1, model, Part_1_doc)
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(Defeaturing_1, 1)
+model.testNbSubResults(Defeaturing_1, [4])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.SOLID, [4])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.FACE, [28])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.EDGE, [120])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.VERTEX, [240])
+model.testResultsVolumes(Defeaturing_1, [14036.50459153])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2020 CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Cut_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Box_1_1")], [model.selection("SOLID", "Cylinder_1_1")], keepSubResults = True)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Cut_1_1/Modified_Face&Box_1_1/Back"), model.selection("FACE", "Box_1_1/Front"))
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Cut_1_1"), model.selection("FACE", "Plane_1")], keepSubResults = True)
+Defeaturing_1 = model.addDefeaturing(Part_1_doc, [model.selection("FACE", "Cut_1_1/Modified_Face&Cylinder_1_1/Face_1")])
+model.testHaveNamingSubshapes(Defeaturing_1, model, Part_1_doc)
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(Defeaturing_1, 1)
+model.testNbSubResults(Defeaturing_1, [2])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.FACE, [12])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.EDGE, [48])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.VERTEX, [96])
+model.testResultsVolumes(Defeaturing_1, [1000])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2020 CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), [model.selection("SOLID", "Box_1_1")])
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Top"))
+SketchCircle_1 = Sketch_1.addCircle(4, 5.137343601256935, 3)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 3)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Top]"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchCircle_1.center(), SketchLine_1.result(), 4, True)
+ExtrusionCut_1.setNestedSketch(Sketch_1)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Back"), model.selection("FACE", "Box_1_1/Front"))
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "ExtrusionCut_1_1"), model.selection("FACE", "Plane_1")], keepSubResults = True)
+Defeaturing_1_objects = [model.selection("FACE", "Partition_1_1_2/Modified_Face&Sketch_1/SketchCircle_1_2&weak_name_2"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Sketch_1/SketchCircle_1_2&weak_name_1"), model.selection("FACE", "Partition_1_1_1/Modified_Face&Sketch_1/SketchCircle_1_2")]
+Defeaturing_1 = model.addDefeaturing(Part_1_doc, Defeaturing_1_objects)
+model.testHaveNamingSubshapes(Defeaturing_1, model, Part_1_doc)
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(Defeaturing_1, 1)
+model.testNbSubResults(Defeaturing_1, [2])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.FACE, [12])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.EDGE, [48])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.VERTEX, [96])
+model.testResultsVolumes(Defeaturing_1, [1000])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2020 CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(5, 1.355252715607035e-20, 20, -1.336382355046098e-51)
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(20, -1.336382355046098e-51, 20, 5.85786437626905)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(20, 5.85786437626905, 15.85786437626905, 10)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(15.85786437626905, 10, 20, 14.14213562373095)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(20, 14.14213562373095, 20, 20)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(20, 20, 0, 20)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_6.result())
+SketchLine_7 = Sketch_1.addLine(0, 20, 0, 5)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_7.result())
+SketchConstraintVertical_2.setName("SketchConstraintVertical_3")
+SketchArc_1 = Sketch_1.addArc(0, 0, 5, 1.355252715607035e-20, 0, 5, False)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchArc_1.endPoint())
+SketchConstraintCollinear_1 = Sketch_1.setCollinear(SketchLine_2.result(), SketchLine_5.result())
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_3.result(), SketchLine_4.result())
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_1.result())
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_7.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchArc_1.center(), SketchAPI_Point(SketchPoint_1).coordinates())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_1.center(), SketchLine_1.endPoint(), 20, True)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchArc_1.center(), SketchLine_7.startPoint(), 20, True)
+SketchLine_8 = Sketch_1.addLine(10, 0, 10, 20)
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_8.startPoint(), SketchLine_1.result())
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_6.result())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_8.result())
+SketchConstraintVertical_3.setName("SketchConstraintVertical_4")
+SketchConstraintMiddle_1 = Sketch_1.setMiddlePoint(SketchLine_8.endPoint(), SketchLine_6.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_2.result(), SketchLine_5.result())
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_3.result(), SketchLine_4.result())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 5)
+SketchConstraintEqual_3 = Sketch_1.setEqual(SketchLine_2.result(), SketchLine_3.result())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 10, 0)
+Defeaturing_1 = model.addDefeaturing(Part_1_doc, [model.selection("FACE", "Extrusion_1_1_2/Generated_Face&Sketch_1/SketchArc_1_2"), model.selection("FACE", "Extrusion_1_1_1/Generated_Face&Sketch_1/SketchLine_3")])
+model.testHaveNamingSubshapes(Defeaturing_1, model, Part_1_doc)
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(Defeaturing_1, 1)
+model.testNbSubResults(Defeaturing_1, [2])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.FACE, [14])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.EDGE, [60])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.VERTEX, [120])
+model.testResultsVolumes(Defeaturing_1, [4000])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2020 CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 5, 10)
+Cut_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Box_1_1")], [model.selection("SOLID", "Cylinder_1_1")], keepSubResults = True)
+Defeaturing_1 = model.addDefeaturing(Part_1_doc, [model.selection("FACE", "Cut_1_1/Modified_Face&Cylinder_1_1/Face_1")])
+model.testHaveNamingSubshapes(Defeaturing_1, model, Part_1_doc)
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(Defeaturing_1, 1)
+model.testNbSubResults(Defeaturing_1, [0])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.EDGE, [24])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.VERTEX, [48])
+model.testResultsVolumes(Defeaturing_1, [1000])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2020 CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(10.19197853506727, -21.07109716039953, 30.19197853506727, -21.07109716039953)
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(30.19197853506727, -21.07109716039953, 30.19197853506727, -6.071097160399531)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(30.19197853506727, -6.071097160399531, 20.19197853506727, -6.071097160399531)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchLine_4 = Sketch_1.addLine(20.19197853506727, -6.071097160399531, 20.19197853506727, 8.928902839600468)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchLine_5 = Sketch_1.addLine(20.19197853506727, 8.928902839600468, 30.19197853506727, 8.928902839600468)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchLine_6 = Sketch_1.addLine(30.19197853506727, 8.928902839600468, 30.19197853506727, 18.92890283960047)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_1.addLine(30.19197853506727, 18.92890283960047, 10.19197853506727, 18.92890283960047)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_7.result())
+SketchLine_8 = Sketch_1.addLine(10.19197853506727, 18.92890283960047, 10.19197853506727, -21.07109716039953)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_8.endPoint())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_8.result())
+SketchConstraintVertical_3.setName("SketchConstraintVertical_4")
+SketchConstraintCollinear_1 = Sketch_1.setCollinear(SketchLine_2.result(), SketchLine_6.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 20)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_8.result(), 40)
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_2.result(), 15)
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_6.result(), 10)
+SketchConstraintLength_5 = Sketch_1.setLength(SketchLine_3.result(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f-SketchLine_7f-SketchLine_8f")], model.selection(), 10, 0)
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3"), 0, model.selection(), 0, [model.selection("SOLID", "Extrusion_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_1"))
+SketchLine_9 = Sketch_2.addLine(30.19197853506727, 5, 25.19197853506727, 5)
+SketchLine_10 = Sketch_2.addLine(25.19197853506727, 5, 25.19197853506727, 10)
+SketchLine_11 = Sketch_2.addLine(25.19197853506727, 10, 30.19197853506727, 10)
+SketchLine_12 = Sketch_2.addLine(30.19197853506727, 10, 30.19197853506727, 5)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_12.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint())
+SketchConstraintHorizontal_5 = Sketch_2.setHorizontal(SketchLine_9.result())
+SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_10.result())
+SketchConstraintVertical_4.setName("SketchConstraintVertical_5")
+SketchConstraintHorizontal_6 = Sketch_2.setHorizontal(SketchLine_11.result())
+SketchConstraintVertical_5 = Sketch_2.setVertical(SketchLine_12.result())
+SketchConstraintVertical_5.setName("SketchConstraintVertical_6")
+SketchProjection_1 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_1][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2][Extrusion_1_1/To_Face]"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchPoint_1.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_12.result(), SketchLine_11.result())
+SketchConstraintLength_6 = Sketch_2.setLength(SketchLine_12.result(), 5)
+ExtrusionCut_1.setNestedSketch(Sketch_2)
+Defeaturing_1 = model.addDefeaturing(Part_1_doc, [model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_4"), model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_5")])
+model.testHaveNamingSubshapes(Defeaturing_1, model, Part_1_doc)
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(Defeaturing_1, 1)
+model.testNbSubResults(Defeaturing_1, [0])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.EDGE, [42])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.VERTEX, [84])
+model.testResultsVolumes(Defeaturing_1, [7625])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2020 CEA/DEN, EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(10.19197853506727, -21.07109716039953, 30.19197853506727, -21.07109716039953)
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(30.19197853506727, -21.07109716039953, 30.19197853506727, -6.071097160399531)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchLine_3 = Sketch_1.addLine(30.19197853506727, -6.071097160399531, 20.19197853506727, -6.071097160399531)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchLine_4 = Sketch_1.addLine(20.19197853506727, -6.071097160399531, 20.19197853506727, 8.928902839600468)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchLine_5 = Sketch_1.addLine(20.19197853506727, 8.928902839600468, 30.19197853506727, 8.928902839600468)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchLine_6 = Sketch_1.addLine(30.19197853506727, 8.928902839600468, 30.19197853506727, 18.92890283960047)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchLine_7 = Sketch_1.addLine(30.19197853506727, 18.92890283960047, 10.19197853506727, 18.92890283960047)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintHorizontal_4 = Sketch_1.setHorizontal(SketchLine_7.result())
+SketchLine_8 = Sketch_1.addLine(10.19197853506727, 18.92890283960047, 10.19197853506727, -21.07109716039953)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_8.endPoint())
+SketchConstraintVertical_3 = Sketch_1.setVertical(SketchLine_8.result())
+SketchConstraintVertical_3.setName("SketchConstraintVertical_4")
+SketchConstraintCollinear_1 = Sketch_1.setCollinear(SketchLine_2.result(), SketchLine_6.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 20)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_8.result(), 40)
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_2.result(), 15)
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_6.result(), 10)
+SketchConstraintLength_5 = Sketch_1.setLength(SketchLine_3.result(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f-SketchLine_5f-SketchLine_6f-SketchLine_7f-SketchLine_8f")], model.selection(), 10, 0)
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3"), 0, model.selection(), 0, [model.selection("SOLID", "Extrusion_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_1"))
+SketchLine_9 = Sketch_2.addLine(30.19197853506727, 5, 25.19197853506727, 5)
+SketchLine_10 = Sketch_2.addLine(25.19197853506727, 5, 25.19197853506727, 10)
+SketchLine_11 = Sketch_2.addLine(25.19197853506727, 10, 30.19197853506727, 10)
+SketchLine_12 = Sketch_2.addLine(30.19197853506727, 10, 30.19197853506727, 5)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_12.endPoint(), SketchLine_9.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_9.endPoint(), SketchLine_10.startPoint())
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchLine_12.startPoint())
+SketchConstraintHorizontal_5 = Sketch_2.setHorizontal(SketchLine_9.result())
+SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_10.result())
+SketchConstraintVertical_4.setName("SketchConstraintVertical_5")
+SketchConstraintHorizontal_6 = Sketch_2.setHorizontal(SketchLine_11.result())
+SketchConstraintVertical_5 = Sketch_2.setVertical(SketchLine_12.result())
+SketchConstraintVertical_5.setName("SketchConstraintVertical_6")
+SketchProjection_1 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_1][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2][Extrusion_1_1/To_Face]"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchLine_11.endPoint(), SketchPoint_1.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_12.result(), SketchLine_11.result())
+SketchConstraintLength_6 = Sketch_2.setLength(SketchLine_12.result(), 5)
+ExtrusionCut_1.setNestedSketch(Sketch_2)
+Defeaturing_1 = model.addDefeaturing(Part_1_doc, [model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_10"), model.selection("FACE", "ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchLine_9")])
+model.testHaveNamingSubshapes(Defeaturing_1, model, Part_1_doc)
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(Defeaturing_1, 1)
+model.testNbSubResults(Defeaturing_1, [0])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.FACE, [10])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.EDGE, [48])
+model.testNbSubShapes(Defeaturing_1, GeomAPI_Shape.VERTEX, [96])
+model.testResultsVolumes(Defeaturing_1, [6500])
+
+assert(model.checkPythonDump())
--- /dev/null
+<source>
+ <multi_selector id="main_objects"
+ label="Faces to remove"
+ icon=""
+ tooltip="Select faces"
+ shape_types="faces"
+ use_choice="false"
+ concealment="true">
+ <validator id="PartSet_DifferentObjects"/>
+ <validator id="FeaturesPlugin_ValidatorDefeaturingSelection"/>
+ </multi_selector>
+</source>
<multi_selector id="results" concealment="true"/>
</feature>
</group>
- <group id="Fillet">
+ <group id="Features">
<feature id="Fillet" title="Fillet" tooltip="Perform fillet on face or edge"
icon="icons/Features/fillet.png" auto_preview="true" helpfile="filletFeature.html">
<source path="fillet_widget.xml"/>
icon="icons/Features/fusion_faces.png" auto_preview="true" helpfile="FeaturesPlugin/fusionFacesFeature.html">
<source path="fusion_faces_widget.xml"/>
</feature>
+ <feature id="Defeaturing" title="Defeaturing" tooltip="Perform removing faces from solid"
+ icon="icons/Features/defeaturing.png" auto_preview="true" helpfile="defeaturingFeature.html">
+ <source path="defeaturing_widget.xml"/>
+ </feature>
</group>
</workbench>
<workbench id="Part">
}
return isLess;
}
+
+int GeomAPI_Shape::Hash::operator()(const std::shared_ptr<GeomAPI_Shape>& theShape) const
+{
+ const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
+ return aShape.HashCode(IntegerLast());
+}
+
+bool GeomAPI_Shape::Equal::operator()(const std::shared_ptr<GeomAPI_Shape>& theShape1,
+ const std::shared_ptr<GeomAPI_Shape>& theShape2) const
+{
+ const TopoDS_Shape& aShape1 = theShape1->impl<TopoDS_Shape>();
+ const TopoDS_Shape& aShape2 = theShape2->impl<TopoDS_Shape>();
+
+ Standard_Integer aHash1 = aShape1.Location().HashCode(IntegerLast());
+ Standard_Integer aHash2 = aShape2.Location().HashCode(IntegerLast());
+
+ return aShape1.TShape() == aShape2.TShape() && aHash1 == aHash2;
+}
bool operator ()(const std::shared_ptr<GeomAPI_Shape>& theShape1,
const std::shared_ptr<GeomAPI_Shape>& theShape2) const;
};
+
+ /// \brief Hash code for the shape
+ class Hash
+ {
+ public:
+ /// Return Hash value according to the address of the shape
+ GEOMAPI_EXPORT
+ int operator ()(const std::shared_ptr<GeomAPI_Shape>& theShape) const;
+ };
+
+ /// \brief Compare addresses of shapes
+ class Equal
+ {
+ public:
+ /// Return \c true if the address of the shapes are equal
+ GEOMAPI_EXPORT
+ bool operator ()(const std::shared_ptr<GeomAPI_Shape>& theShape1,
+ const std::shared_ptr<GeomAPI_Shape>& theShape2) const;
+ };
};
//! Pointer on list of shapes
GeomAlgoAPI_MapShapesAndAncestors.h
GeomAlgoAPI_Projection.h
GeomAlgoAPI_Chamfer.h
+ GeomAlgoAPI_Defeaturing.h
)
SET(PROJECT_SOURCES
GeomAlgoAPI_MapShapesAndAncestors.cpp
GeomAlgoAPI_Projection.cpp
GeomAlgoAPI_Chamfer.cpp
+ GeomAlgoAPI_Defeaturing.cpp
)
SET(PROJECT_LIBRARIES
--- /dev/null
+// Copyright (C) 2020 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include <GeomAlgoAPI_Defeaturing.h>
+#include <GeomAlgoAPI_DFLoader.h>
+
+#include <BRepAlgoAPI_Defeaturing.hxx>
+
+GeomAlgoAPI_Defeaturing::GeomAlgoAPI_Defeaturing(const GeomShapePtr& theBaseSolid,
+ const ListOfShape& theFacesToRemove)
+{
+ build(theBaseSolid, theFacesToRemove);
+}
+
+void GeomAlgoAPI_Defeaturing::build(const GeomShapePtr& theBaseSolid,
+ const ListOfShape& theFacesToRemove)
+{
+ if (!theBaseSolid || theFacesToRemove.empty())
+ return;
+
+ BRepAlgoAPI_Defeaturing* aDefeaturing = new BRepAlgoAPI_Defeaturing;
+ aDefeaturing->SetShape(theBaseSolid->impl<TopoDS_Shape>());
+ aDefeaturing->SetRunParallel(Standard_True);
+
+ // collect faces to remove
+ TopTools_ListOfShape aFaces;
+ for (ListOfShape::const_iterator anIt = theFacesToRemove.begin();
+ anIt != theFacesToRemove.end(); ++anIt)
+ aDefeaturing->AddFaceToRemove((*anIt)->impl<TopoDS_Shape>());
+
+ setImpl(aDefeaturing);
+ setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
+
+ // build and get result
+ aDefeaturing->Build();
+ if (!aDefeaturing->IsDone() || aDefeaturing->HasErrors() || aDefeaturing->HasWarnings()) {
+ std::ostringstream errors;
+ aDefeaturing->DumpErrors(errors);
+ aDefeaturing->DumpWarnings(errors);
+ myError = errors.str();
+ return;
+ }
+
+ TopoDS_Shape aResult = GeomAlgoAPI_DFLoader::refineResult(aDefeaturing->Shape());
+
+ std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+ aShape->setImpl(new TopoDS_Shape(aResult));
+ setShape(aShape);
+ setDone(true);
+}
--- /dev/null
+// Copyright (C) 2020 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef GeomAlgoAPI_Defeaturing_H_
+#define GeomAlgoAPI_Defeaturing_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAlgoAPI_MakeShape.h>
+
+#include <GeomAPI_Shape.h>
+
+/// \class GeomAlgoAPI_Defeaturing
+/// \ingroup DataAlgo
+/// \brief Perform Defeaturing algorithm
+class GeomAlgoAPI_Defeaturing : public GeomAlgoAPI_MakeShape
+{
+public:
+ /// Run Defeaturing operation on the solid for the given list of faces.
+ /// \param theBaseSolid a changing solid
+ /// \param theFacesToRemove list of faces to be removed
+ GEOMALGOAPI_EXPORT GeomAlgoAPI_Defeaturing(const GeomShapePtr& theBaseSolid,
+ const ListOfShape& theFacesToRemove);
+
+private:
+ /// Perform Defeaturing operation.
+ void build(const GeomShapePtr& theBaseSolid,
+ const ListOfShape& theFacesToRemove);
+};
+
+#endif
from FeaturesAPI import measureLength, measureDistance, measureRadius, measureAngle
from FeaturesAPI import addRemoveResults
from FeaturesAPI import addCopy, addImportResult
+from FeaturesAPI import addDefeaturing