TestExtrusionFuse_ByPlanesAndOffsets.py
TestExtrusion_ErrorMsg.py
TestExtrusion_ZeroOffsetError.py
+ TestExtrusion_ByFaces01.py
+ TestExtrusion_ByFaces02.py
+ TestExtrusion_ByFaces03.py
+ TestExtrusion_ByFaces04.py
+ TestExtrusion_ByFaces05.py
+ TestExtrusion_ByFaces06.py
+ TestExtrusion_ByFaces07.py
+ TestExtrusion_ByFaces08.py
+ TestExtrusion_ByFaces09.py
+ TestExtrusion_ByFaces10.py
+ TestExtrusion_ByFaces11.py
+ TestExtrusion_ByFaces12.py
+ TestExtrusion_ByFaces13.py
+ TestExtrusion_ByFaces14.py
+ TestExtrusion_ByFaces15.py
+ TestExtrusion_ByFaces16.py
+ TestExtrusion_ByFaces17.py
+ TestExtrusion_ByFaces18.py
+ TestExtrusion_ByFaces19.py
TestRevolution.py
TestRevolution_ByAngle.py
TestRevolutionOfPoint.py
//
#include <FeaturesPlugin_CompositeSketch.h>
+#include <FeaturesPlugin_Tools.h>
#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_AttributeReference.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
-#include <GeomAlgoAPI_CompoundBuilder.h>
#include <GeomAlgoAPI_Revolution.h>
-#include <GeomAlgoAPI_ShapeTools.h>
-#include <GeomAlgoAPI_SketchBuilder.h>
-#include <GeomAPI_PlanarEdges.h>
#include <GeomAPI_ShapeExplorer.h>
-#include <map>
-#include <sstream>
static void storeSubShape(const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
ResultBodyPtr theResultBody,
void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList,
const bool theIsMakeShells)
{
- theBaseShapesList.clear();
-
- ListOfShape aBaseFacesList;
- std::map<ResultConstructionPtr, ListOfShape> aSketchWiresMap;
AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
- if(!aBaseObjectsSelectionList.get()) {
- setError("Error: Could not get base objects selection list.");
- return;
- }
- if(aBaseObjectsSelectionList->size() == 0) {
- setError("Error: Base objects list is empty.");
- return;
- }
- for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) {
- AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex);
- if(!aBaseObjectSelection.get()) {
- setError("Error: Selected base object is empty.");
- return;
- }
- GeomShapePtr aBaseShape = aBaseObjectSelection->value();
- if(aBaseShape.get() && !aBaseShape->isNull()) {
- GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
- if(aST == GeomAPI_Shape::SOLID || aST == GeomAPI_Shape::COMPSOLID) {
- setError("Error: Selected shapes has unsupported type.");
- return;
- }
- ResultConstructionPtr aConstruction =
- std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
- if(aConstruction.get() && !aBaseShape->isEqual(aConstruction->shape()) &&
- aST == GeomAPI_Shape::WIRE) {
- // It is a wire on the sketch, store it to make face later.
- aSketchWiresMap[aConstruction].push_back(aBaseShape);
- continue;
- } else {
- aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
- theBaseShapesList.push_back(aBaseShape);
- }
- } else {
- // This may be the whole sketch result selected, check and get faces.
- ResultConstructionPtr aConstruction =
- std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
- if(!aConstruction.get()) {
- setError("Error: Selected sketches does not have results.");
- return;
- }
- int aFacesNum = aConstruction->facesNum();
- if(aFacesNum == 0) {
- // Probably it can be construction.
- aBaseShape = aConstruction->shape();
- if(aBaseShape.get() && !aBaseShape->isNull()) {
- GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
- if(aST != GeomAPI_Shape::VERTEX && aST != GeomAPI_Shape::EDGE &&
- aST != GeomAPI_Shape::WIRE &&
- aST != GeomAPI_Shape::FACE && aST != GeomAPI_Shape::SHELL) {
- setError("Error: Selected shapes has unsupported type.");
- return;
- }
- aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
- theBaseShapesList.push_back(aBaseShape);
- }
- } else {
- for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
- GeomShapePtr aBaseFace = aConstruction->face(aFaceIndex);
- if(!aBaseFace.get() || aBaseFace->isNull()) {
- setError("Error: One of the faces on selected sketch is null.");
- return;
- }
- aBaseFacesList.push_back(aBaseFace);
- }
- }
- }
- }
-
- // Make faces from sketch wires.
- for(std::map<ResultConstructionPtr, ListOfShape>::const_iterator anIt = aSketchWiresMap.cbegin();
- anIt != aSketchWiresMap.cend(); ++anIt) {
- const std::shared_ptr<GeomAPI_PlanarEdges> aSketchPlanarEdges =
- std::dynamic_pointer_cast<GeomAPI_PlanarEdges>((*anIt).first->shape());
- const ListOfShape& aWiresList = (*anIt).second;
- ListOfShape aFaces;
- GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
- aSketchPlanarEdges->norm(),
- aWiresList,
- aFaces);
- aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
- }
-
- // Searching faces with common edges.
- if(theIsMakeShells && aBaseFacesList.size() > 1) {
- GeomShapePtr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
- GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, theBaseShapesList);
- } else {
- theBaseShapesList.insert(theBaseShapesList.end(), aBaseFacesList.begin(),
- aBaseFacesList.end());
- }
+ std::string anError;
+ bool isOk = FeaturesPlugin_Tools::getShape(
+ aBaseObjectsSelectionList, theIsMakeShells, theBaseShapesList, anError);
+ if (!isOk)
+ setError(anError);
}
//=================================================================================================
//
#include "FeaturesPlugin_Extrusion.h"
+#include "FeaturesPlugin_Tools.h"
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_AttributeSelection.h>
//=================================================================================================
void FeaturesPlugin_Extrusion::execute()
{
- ListOfShape aBaseShapesList;
+ ListOfShape aBaseShapesList, aBoundaryShapes;
ListOfMakeShape aMakeShapesList;
// Make extrusions.
- if(!makeExtrusions(aBaseShapesList, aMakeShapesList)) {
+ if(!makeExtrusions(aBaseShapesList, aBoundaryShapes, aMakeShapesList)) {
return;
}
ListOfMakeShape::const_iterator anAlgoIt = aMakeShapesList.cbegin();
for(; aBaseIt != aBaseShapesList.cend() && anAlgoIt != aMakeShapesList.cend();
++aBaseIt, ++anAlgoIt) {
- storeResult(*aBaseIt, *anAlgoIt, aResultIndex++);
+ if (aBoundaryShapes.empty())
+ storeResult(*aBaseIt, *anAlgoIt, aResultIndex++);
+ else
+ storeResultWithBoundaries(*aBaseIt, aBoundaryShapes, *anAlgoIt, aResultIndex++);
}
removeResults(aResultIndex);
//=================================================================================================
bool FeaturesPlugin_Extrusion::makeExtrusions(ListOfShape& theBaseShapes,
+ ListOfShape& theBoundaryShapes,
ListOfMakeShape& theMakeShapes)
{
theMakeShapes.clear();
}
}
}
+ if (aToShape)
+ theBoundaryShapes.push_back(aToShape);
+ if (aFromShape)
+ theBoundaryShapes.push_back(aFromShape);
// Generating result for each base shape.
std::string anError;
return true;
}
+
+//=================================================================================================
+void FeaturesPlugin_Extrusion::storeResultWithBoundaries(
+ const GeomShapePtr theBaseShape,
+ const ListOfShape& theBoundaryShapes,
+ const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
+ const int theIndex)
+{
+ // Create result body.
+ ResultBodyPtr aResultBody = document()->createBody(data(), theIndex);
+
+ // Store modified shapes.
+ FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, theBoundaryShapes, ListOfShape(),
+ theMakeShape, theMakeShape->shape());
+
+ // Store generated edges/faces.
+ storeGenerationHistory(aResultBody, theBaseShape, theMakeShape);
+
+ setResult(aResultBody, theIndex);
+}
protected:
/// Generates extrusions.
/// \param[out] theBaseShapes list of base shapes.
+ /// \param[out] theBoundaryShapes list of faces limiting the extrusion
/// \param[out] theMakeShapes list of according algos.
/// \return false in case one of algo failed.
bool makeExtrusions(ListOfShape& theBaseShapes,
+ ListOfShape& theBoundaryShapes,
ListOfMakeShape& theMakeShapes);
+
+ /// Stores result of generation.
+ void storeResultWithBoundaries(const GeomShapePtr theBaseShape,
+ const ListOfShape& theBoundaryShapes,
+ const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
+ const int theIndex = 0);
};
#endif
bool FeaturesPlugin_ExtrusionBoolean::makeGeneration(ListOfShape& theBaseShapes,
ListOfMakeShape& theMakeShapes)
{
- return makeExtrusions(theBaseShapes, theMakeShapes);
+ ListOfShape aBoundaryShapes;
+ return makeExtrusions(theBaseShapes, aBoundaryShapes, theMakeShapes);
}
//=================================================================================================
new FeaturesPlugin_ValidatorPipeLocationsNumber);
aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionDir",
new FeaturesPlugin_ValidatorExtrusionDir);
+ aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionBoundary",
+ new FeaturesPlugin_ValidatorExtrusionBoundaryFace);
aFactory->registerValidator("FeaturesPlugin_ValidatorBooleanSelection",
new FeaturesPlugin_ValidatorBooleanSelection);
aFactory->registerValidator("FeaturesPlugin_ValidatorPartitionSelection",
#include "FeaturesPlugin_Tools.h"
+#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+#include <GeomAPI_PlanarEdges.h>
#include <GeomAPI_ShapeIterator.h>
//==================================================================================================
theResultShapesCompound);
}
}
+
+//==================================================================================================
+bool FeaturesPlugin_Tools::getShape(const AttributeSelectionListPtr theSelectionList,
+ const bool theShareTopology,
+ ListOfShape& theShapesList,
+ std::string& theError)
+{
+ theShapesList.clear();
+
+ ListOfShape aBaseFacesList;
+ std::map<ResultConstructionPtr, ListOfShape> aSketchWiresMap;
+ if(!theSelectionList.get()) {
+ theError = "Error: Could not get base objects selection list.";
+ return false;
+ }
+ if(theSelectionList->size() == 0) {
+ theError = "Error: Base objects list is empty.";
+ return false;
+ }
+ for(int anIndex = 0; anIndex < theSelectionList->size(); anIndex++) {
+ AttributeSelectionPtr aBaseObjectSelection = theSelectionList->value(anIndex);
+ if(!aBaseObjectSelection.get()) {
+ theError = "Error: Selected base object is empty.";
+ return false;
+ }
+ GeomShapePtr aBaseShape = aBaseObjectSelection->value();
+ if(aBaseShape.get() && !aBaseShape->isNull()) {
+ GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
+ if(aST == GeomAPI_Shape::SOLID || aST == GeomAPI_Shape::COMPSOLID) {
+ theError = "Error: Selected shapes has unsupported type.";
+ return false;
+ }
+ ResultConstructionPtr aConstruction =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
+ if(aConstruction.get() && !aBaseShape->isEqual(aConstruction->shape()) &&
+ aST == GeomAPI_Shape::WIRE) {
+ // It is a wire on the sketch, store it to make face later.
+ aSketchWiresMap[aConstruction].push_back(aBaseShape);
+ continue;
+ } else {
+ aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
+ theShapesList.push_back(aBaseShape);
+ }
+ } else {
+ // This may be the whole sketch result selected, check and get faces.
+ ResultConstructionPtr aConstruction =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
+ if(!aConstruction.get()) {
+ theError = "Error: Selected sketches does not have results.";
+ return false;
+ }
+ int aFacesNum = aConstruction->facesNum();
+ if(aFacesNum == 0) {
+ // Probably it can be construction.
+ aBaseShape = aConstruction->shape();
+ if(aBaseShape.get() && !aBaseShape->isNull()) {
+ GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
+ if(aST != GeomAPI_Shape::VERTEX && aST != GeomAPI_Shape::EDGE &&
+ aST != GeomAPI_Shape::WIRE &&
+ aST != GeomAPI_Shape::FACE && aST != GeomAPI_Shape::SHELL) {
+ theError = "Error: Selected shapes has unsupported type.";
+ return false;
+ }
+ aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
+ theShapesList.push_back(aBaseShape);
+ }
+ } else {
+ for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
+ GeomShapePtr aBaseFace = aConstruction->face(aFaceIndex);
+ if(!aBaseFace.get() || aBaseFace->isNull()) {
+ theError = "Error: One of the faces on selected sketch is null.";
+ return false;
+ }
+ aBaseFacesList.push_back(aBaseFace);
+ }
+ }
+ }
+ }
+
+ // Make faces from sketch wires.
+ for(std::map<ResultConstructionPtr, ListOfShape>::const_iterator anIt = aSketchWiresMap.cbegin();
+ anIt != aSketchWiresMap.cend(); ++anIt) {
+ const std::shared_ptr<GeomAPI_PlanarEdges> aSketchPlanarEdges =
+ std::dynamic_pointer_cast<GeomAPI_PlanarEdges>((*anIt).first->shape());
+ const ListOfShape& aWiresList = (*anIt).second;
+ ListOfShape aFaces;
+ GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
+ aSketchPlanarEdges->norm(),
+ aWiresList,
+ aFaces);
+ aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
+ }
+
+ // Searching faces with common edges.
+ if(theShareTopology && aBaseFacesList.size() > 1) {
+ GeomShapePtr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
+ GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, theShapesList);
+ } else {
+ theShapesList.insert(theShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end());
+ }
+ return true;
+}
const GeomShapePtr& theBaseShape,
const GeomMakeShapePtr& theMakeShape,
const std::string theName);
- /// Stores deleted shapes.
+ /// Stores deleted shapes.
static void loadDeletedShapes(ResultBodyPtr theResultBody,
const GeomShapePtr theBaseShape,
const ListOfShape& theTools,
static void loadDeletedShapes(std::vector<ResultBaseAlgo>& theResultBaseAlgoList,
const ListOfShape& theTools,
const GeomShapePtr theResultShapesCompound);
+
+ /// Obtain shapes from the selection list attribute.
+ static bool getShape(const std::shared_ptr<ModelAPI_AttributeSelectionList> theSelectionList,
+ const bool theShareTopology,
+ ListOfShape& theShapesList,
+ std::string& theError);
};
#endif /* FeaturesPlugin_Tools_H_ */
#include "FeaturesPlugin_BooleanFuse.h"
#include "FeaturesPlugin_BooleanCommon.h"
#include "FeaturesPlugin_BooleanSmash.h"
+#include "FeaturesPlugin_Extrusion.h"
#include "FeaturesPlugin_Pipe.h"
#include "FeaturesPlugin_Union.h"
#include <Events_InfoMessage.h>
#include <ModelAPI_Attribute.h>
+#include <ModelAPI_AttributeDouble.h>>
#include <ModelAPI_AttributeInteger.h>
#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_AttributeString.h>
#include <GeomAPI_ShapeIterator.h>
#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_Prism.h>
#include <GeomAlgoAPI_ShapeBuilder.h>
#include <GeomAlgoAPI_ShapeTools.h>
#include <GeomAlgoAPI_WireBuilder.h>
return true;
}
+//==================================================================================================
+bool FeaturesPlugin_ValidatorExtrusionBoundaryFace::isValid(
+ const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner());
+
+ // Collect all necessary attributes and try to build prism
+
+ // base face
+ AttributeSelectionListPtr aBaseShapeAttr =
+ aFeature->selectionList(FeaturesPlugin_Extrusion::BASE_OBJECTS_ID());
+ ListOfShape aBaseShapeList;
+ std::string anError;
+ if (!FeaturesPlugin_Tools::getShape(aBaseShapeAttr, true, aBaseShapeList, anError)) {
+ theError = anError;
+ return false;
+ }
+
+ // direction
+ AttributeSelectionPtr aSelection =
+ aFeature->selection(FeaturesPlugin_Extrusion::DIRECTION_OBJECT_ID());
+ GeomShapePtr aShape = aSelection->value();
+ if (!aShape.get() && aSelection->context().get())
+ aShape = aSelection->context()->shape();
+
+ GeomEdgePtr anEdge;
+ if (aShape.get()) {
+ if (aShape->isEdge())
+ anEdge = aShape->edge();
+ else if (aShape->isCompound()) {
+ GeomAPI_ShapeIterator anIt(aShape);
+ anEdge = anIt.current()->edge();
+ }
+ }
+
+ std::shared_ptr<GeomAPI_Dir> aDir;
+ if (anEdge.get() && anEdge->isLine())
+ aDir = anEdge->line()->direction();
+
+ // from/to shapes
+ GeomShapePtr aFromShape, aToShape;
+ aSelection = aFeature->selection(FeaturesPlugin_Extrusion::TO_OBJECT_ID());
+ if (aSelection.get()) {
+ aToShape = aSelection->value();
+ if (!aToShape.get() && aSelection->context().get())
+ aToShape = aSelection->context()->shape();
+ if (aToShape.get() && aToShape->isCompound()) {
+ GeomAPI_ShapeIterator anIt(aToShape);
+ aToShape = anIt.current();
+ }
+ if (aToShape.get() && !aToShape->isFace()) {
+ theError = "\"To\" shape is not a face";
+ return false;
+ }
+ }
+ aSelection = aFeature->selection(FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
+ if (aSelection.get()) {
+ aFromShape = aSelection->value();
+ if (!aFromShape.get() && aSelection->context().get())
+ aFromShape = aSelection->context()->shape();
+ if (aFromShape.get() && aFromShape->isCompound()) {
+ GeomAPI_ShapeIterator anIt(aFromShape);
+ aFromShape = anIt.current();
+ }
+ if (aFromShape.get() && !aFromShape->isFace()) {
+ theError = "\"From\" shape is not a face";
+ return false;
+ }
+ }
+
+ double aToSize = aFeature->real(FeaturesPlugin_Extrusion::TO_OFFSET_ID())->value();
+ double aFromSize = aFeature->real(FeaturesPlugin_Extrusion::FROM_OFFSET_ID())->value();
+
+ // check extrusion
+ for (ListOfShape::iterator anIt = aBaseShapeList.begin(); anIt != aBaseShapeList.end(); anIt++) {
+ std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIt;
+
+ std::shared_ptr<GeomAlgoAPI_Prism> aPrismAlgo(
+ new GeomAlgoAPI_Prism(aBaseShape, aDir, aToShape, aToSize, aFromShape, aFromSize));
+ bool isFailed = GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPrismAlgo,
+ FeaturesPlugin_Extrusion::ID(),
+ anError);
+ if (isFailed) {
+ theError = anError;
+ return false;
+ }
+ }
+
+ return true;
+}
+
//==================================================================================================
bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAttribute,
const std::list<std::string>& theArguments,
Events_InfoMessage& theError) const;
};
+/// \class FeaturesPlugin_ValidatorExtrusionBoundaryFace
+/// \ingroup Validators
+/// \brief A validator for extrusion from/to face attribute.
+class FeaturesPlugin_ValidatorExtrusionBoundaryFace: public ModelAPI_AttributeValidator
+{
+public:
+ //! \return true if attribute listed in the parameter arguments are planar.
+ //! \param[in] theFeature the checked feature.
+ //! \param[in] theArguments arguments of the attribute.
+ //! \param[out] theError error message.
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+};
+
/// \class FeaturesPlugin_ValidatorBooleanSelection
/// \ingroup Validators
/// \brief Validates selection for boolean operation.
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "R", 100, 180)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(20, 40, -30, 40)
+SketchLine_2 = Sketch_1.addLine(-30, 40, -30, 20)
+SketchLine_3 = Sketch_1.addLine(-30, 20, 20, 20)
+SketchLine_4 = Sketch_1.addLine(20, 20, 20, 40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), 50)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 20)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), model.selection("FACE", "Cylinder_1_1/Face_1"), "offsetTo", model.selection(), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [24])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [48])
+model.testResultsVolumes(Extrusion_1, [47540.6])
+
+# change radius of cylinder
+ParamR.setValue(10)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [12])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [24])
+model.testResultsVolumes(Extrusion_1, [3141.59265])
+
+# check the intersected boundaries are processed well
+ParamR.setValue(30)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [18])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [36])
+model.testResultsVolumes(Extrusion_1, [25176.8518])
+
+ParamR.setValue(40);
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testResultsVolumes(Extrusion_1, [36812.03])
+
+# change offsetting "To" face
+ParamTo.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [4])
+model.testResultsVolumes(Extrusion_1, [12566.37])
+
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testResultsVolumes(Extrusion_1, [57985.85])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testResultsVolumes(Extrusion_1, [37985.85])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [24])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [48])
+model.testResultsVolumes(Extrusion_1, [77985.85])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "R", 100, 180)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OY"), 50)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(20, 40, -30, 40)
+SketchLine_2 = Sketch_1.addLine(-30, 40, -30, 20)
+SketchLine_3 = Sketch_1.addLine(-30, 20, 20, 20)
+SketchLine_4 = Sketch_1.addLine(20, 20, 20, 40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), 50)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 20)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_1"), "offsetTo", model.selection(), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [24])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [48])
+model.testResultsVolumes(Extrusion_1, [97540.6])
+
+# change radius of cylinder and check failure
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure, check the intersected boundaries are processed well
+ParamR.setValue(30)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testResultsVolumes(Extrusion_1, [75176.8518])
+
+ParamR.setValue(40);
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testResultsVolumes(Extrusion_1, [86812.03])
+
+# change offsetting "To" face and check failure
+ParamTo.setValue(-20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testResultsVolumes(Extrusion_1, [107985.85])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testResultsVolumes(Extrusion_1, [87985.85])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [24])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [48])
+model.testResultsVolumes(Extrusion_1, [127985.85])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamSize = model.addParameter(Part_1_doc, "Size", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), "R")
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Sphere_1_1"), model.selection("FACE", "PartSet/XOZ")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), 10, False)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchLine_1 = Sketch_1.addLine(50, -50, -50, -50)
+SketchLine_2 = Sketch_1.addLine(-50, -50, -50, 50)
+SketchLine_3 = Sketch_1.addLine(-50, 50, 50, 50)
+SketchLine_4 = Sketch_1.addLine(50, 50, 50, -50)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.result(), "Size", True)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.result(), "Size", True)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result(), "Size", True)
+SketchConstraintDistance_4 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.result(), "Size", True)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")])
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_5 = Sketch_2.addLine(20, -15, 20, 20)
+SketchLine_6 = Sketch_2.addLine(20, 20, -15, 20)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_5.result())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_6.result())
+SketchArc_1 = Sketch_2.addArc(0, 0, -15, 20, 20, -15, False)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchArc_1.endPoint(), SketchLine_5.startPoint())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_5.result(), SketchLine_6.result())
+SketchConstraintDistance_5 = Sketch_2.setDistance(SketchArc_1.center(), SketchLine_5.result(), 20, True)
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchArc_1.center())
+SketchConstraintRadius_1 = Sketch_2.setRadius(SketchArc_1.results()[1], 25)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_5r-SketchLine_6f-SketchArc_1_2f")], model.selection(), model.selection("FACE", "Partition_1_1_2/Modified_Face&Sphere_1_1/Face_1"), "offsetTo", model.selection("FACE", "Face_1_1"), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [18])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [36])
+model.testResultsVolumes(Extrusion_1, [100878.6])
+
+# change radius of sphere and check failure
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure, check the intersected boundaries are processed well
+ParamR.setValue(30)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testResultsVolumes(Extrusion_1, [60964.23998])
+
+ParamR.setValue(40);
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testResultsVolumes(Extrusion_1, [81651.666])
+
+# change size of the face
+ParamSize.setValue(10)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testResultsVolumes(Extrusion_1, [81651.666])
+
+# change offsetting "To" face and check failure
+ParamTo.setValue(-20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [22])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [44])
+model.testResultsVolumes(Extrusion_1, [119535.04])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testResultsVolumes(Extrusion_1, [84126.377])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [22])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [44])
+model.testResultsVolumes(Extrusion_1, [154943.7])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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 GeomAPI import GeomAPI_Shape
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamSize = model.addParameter(Part_1_doc, "Size", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), "R")
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Sphere_1_1"), model.selection("FACE", "PartSet/XOZ")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), 30, False)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchLine_1 = Sketch_1.addLine(50, -50, -50, -50)
+SketchLine_2 = Sketch_1.addLine(-50, -50, -50, 50)
+SketchLine_3 = Sketch_1.addLine(-50, 50, 50, 50)
+SketchLine_4 = Sketch_1.addLine(50, 50, 50, -50)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.result(), "Size", True)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.result(), "Size", True)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result(), "Size", True)
+SketchConstraintDistance_4 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.result(), "Size", True)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")])
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_5 = Sketch_2.addLine(20, -40.3112887414928, 20, 20)
+SketchLine_6 = Sketch_2.addLine(20, 20, -40.31128874149281, 20.00000000000001)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_5.result())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_6.result())
+SketchArc_1 = Sketch_2.addArc(0, 0, -40.31128874149281, 20.00000000000001, 20, -40.3112887414928, False)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchArc_1.endPoint(), SketchLine_5.startPoint())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_5.result(), SketchLine_6.result())
+SketchConstraintDistance_5 = Sketch_2.setDistance(SketchArc_1.center(), SketchLine_5.result(), 20, True)
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchArc_1.center())
+SketchConstraintRadius_1 = Sketch_2.setRadius(SketchArc_1.results()[1], 45)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_5r-SketchLine_6f-SketchArc_1_2f")], model.selection(), model.selection("FACE", "Partition_1_1_1/Modified_Face&Sphere_1_1/Face_1"), "offsetTo", model.selection("FACE", "Face_1_1"), "offsetFrom")
+
+# extrusion have to fail because of several results with shared topology
+assert(Extrusion_1.feature().error() != "")
+
+# change radius of sphere and check failure
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+ParamR.setValue(45)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# change offsetting "To" face and check failure
+ParamTo.setValue(-20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [22])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [44])
+model.testResultsVolumes(Extrusion_1, [105008.93])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testResultsVolumes(Extrusion_1, [179594.5])
+
+# check failure
+ParamFrom.setValue(20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(0)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [21])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [42])
+model.testResultsVolumes(Extrusion_1, [62569.416])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamRSph = model.addParameter(Part_1_doc, "rSphere", "50")
+ParamRCyl = model.addParameter(Part_1_doc, "rCyl", "30")
+ParamRCir = model.addParameter(Part_1_doc, "rCircle", "10")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), "rSphere")
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "rCyl", 100)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchCircle_1 = Sketch_1.addCircle(15, 20, 10)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "rCircle")
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchCircle_1.center(), 15)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchCircle_1.center(), 20)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r")], model.selection(), model.selection("FACE", "Sphere_1_1/Face_1"), "offsetTo", model.selection("FACE", "Cylinder_1_1/Face_1"), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [12])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [24])
+model.testResultsVolumes(Extrusion_1, [10878.5462])
+
+# change radius of sketch circle
+ParamRCir.setValue(17)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [18])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [36])
+model.testResultsVolumes(Extrusion_1, [32102.718377])
+
+# change radius of sphere and check failure
+ParamRSph.setValue(10)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [18])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [36])
+model.testResultsVolumes(Extrusion_1, [42694.3277614])
+
+# change radius of sketch circle and check failure
+ParamRCir.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamRSph.setValue(45);
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [12])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [24])
+model.testResultsVolumes(Extrusion_1, [7083.567843])
+
+# change radius of cylinder
+ParamRCyl.setValue(10)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [12])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [24])
+model.testResultsVolumes(Extrusion_1, [22295.845141])
+
+ParamRCyl.setValue(50)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [12])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [24])
+model.testResultsVolumes(Extrusion_1, [6805.1007457])
+
+# change offsetting "To" face
+ParamTo.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [18])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [36])
+model.testResultsVolumes(Extrusion_1, [26158.63076])
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [16])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [32])
+model.testResultsVolumes(Extrusion_1, [7626.2279286])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [20])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [40])
+model.testResultsVolumes(Extrusion_1, [21514.8965])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [20])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [40])
+model.testResultsVolumes(Extrusion_1, [5427.194275658])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "R", "R/5", "R")
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Cone_1_1"), model.selection("FACE", "PartSet/XOZ")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), 20, False)
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Plane_1"), model.selection("EDGE", "PartSet/OZ"), 330)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(10, 8.819660112501044, 10, 30)
+SketchLine_2 = Sketch_1.addLine(10, 30, -11.18033988749895, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_2.result())
+SketchArc_1 = Sketch_1.addArc(0, 20, -11.18033988749895, 30, 10, 8.819660112501044, False)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.startPoint())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_1.center(), SketchLine_1.result(), 10, True)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 15)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_3 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_3.result())
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_3).startPoint(), SketchArc_1.center(), 20)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchArc_1_2f")], model.selection(), model.selection("FACE", "Partition_1_1_2/Modified_Face&Cone_1_1/Face_1"), "offsetTo", model.selection("FACE", "Plane_2"), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [20])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [40])
+model.testResultsVolumes(Extrusion_1, [31363.4963946])
+
+# change radius of sphere and check failure
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure, check the intersected boundaries are processed well
+ParamR.setValue(40)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testResultsVolumes(Extrusion_1, [25645.0102138])
+
+# change offsetting "To" face and check failure
+ParamTo.setValue(-20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(8)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [20])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [40])
+model.testResultsVolumes(Extrusion_1, [31501.9671234])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testResultsVolumes(Extrusion_1, [18737.752452])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
+model.testResultsVolumes(Extrusion_1, [44266.1817647])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "R", 100, 180)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(20, 40, -30, 40)
+SketchLine_2 = Sketch_1.addLine(-30, 40, -30, 20)
+SketchLine_3 = Sketch_1.addLine(-30, 20, 20, 20)
+SketchLine_4 = Sketch_1.addLine(20, 20, 20, 40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), 50)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 20)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+SketchLine_5 = Sketch_1.addLine(-10, 20, 5, 40)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.startPoint(), SketchLine_3.result())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_1.result())
+SketchConstraintDistanceHorizontal_2 = Sketch_1.setHorizontalDistance(SketchLine_2.endPoint(), SketchLine_5.startPoint(), 20)
+SketchConstraintDistanceHorizontal_3 = Sketch_1.setHorizontalDistance(SketchLine_5.endPoint(), SketchLine_1.startPoint(), 15)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), model.selection("FACE", "Cylinder_1_1/Face_1"), "offsetTo", model.selection(), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [48])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [96])
+model.testResultsVolumes(Extrusion_1, [47540.6])
+
+# change radius of cylinder
+ParamR.setValue(10)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [28])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [56])
+model.testResultsVolumes(Extrusion_1, [3141.59265])
+
+# check the intersected boundaries are processed well
+ParamR.setValue(30)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [11])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [42])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [84])
+model.testResultsVolumes(Extrusion_1, [25176.8518])
+
+ParamR.setValue(40);
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [48])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [96])
+model.testResultsVolumes(Extrusion_1, [36812.03])
+
+# change offsetting "To" face
+ParamTo.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [10])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [36])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [72])
+model.testResultsVolumes(Extrusion_1, [12566.37])
+
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [48])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [96])
+model.testResultsVolumes(Extrusion_1, [57985.85])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
+model.testResultsVolumes(Extrusion_1, [37985.85])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
+model.testResultsVolumes(Extrusion_1, [77985.85])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "R", 100, 180)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OY"), 50)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(20, 40, -30, 40)
+SketchLine_2 = Sketch_1.addLine(-30, 40, -30, 20)
+SketchLine_3 = Sketch_1.addLine(-30, 20, 20, 20)
+SketchLine_4 = Sketch_1.addLine(20, 20, 20, 40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), 50)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 20)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+SketchLine_5 = Sketch_1.addLine(-10, 20, 5, 40)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.startPoint(), SketchLine_3.result())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_1.result())
+SketchConstraintDistanceHorizontal_2 = Sketch_1.setHorizontalDistance(SketchLine_2.endPoint(), SketchLine_5.startPoint(), 20)
+SketchConstraintDistanceHorizontal_3 = Sketch_1.setHorizontalDistance(SketchLine_5.endPoint(), SketchLine_1.startPoint(), 15)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_5f"), model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_5r-SketchLine_3f-SketchLine_4f")], model.selection(), model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_1"), "offsetTo", model.selection(), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [48])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [96])
+model.testResultsVolumes(Extrusion_1, [97540.6])
+
+# change radius of cylinder and check failure
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure, check the intersected boundaries are processed well
+ParamR.setValue(30)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
+model.testResultsVolumes(Extrusion_1, [75176.8518])
+
+ParamR.setValue(40);
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
+model.testResultsVolumes(Extrusion_1, [86812.03])
+
+# change offsetting "To" face and check failure
+ParamTo.setValue(-25)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
+model.testResultsVolumes(Extrusion_1, [107985.85])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
+model.testResultsVolumes(Extrusion_1, [87985.85])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [48])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [96])
+model.testResultsVolumes(Extrusion_1, [127985.85])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamSize = model.addParameter(Part_1_doc, "Size", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), "R")
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Sphere_1_1"), model.selection("FACE", "PartSet/XOZ")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), 10, False)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchLine_1 = Sketch_1.addLine(50, -50, -50, -50)
+SketchLine_2 = Sketch_1.addLine(-50, -50, -50, 50)
+SketchLine_3 = Sketch_1.addLine(-50, 50, 50, 50)
+SketchLine_4 = Sketch_1.addLine(50, 50, 50, -50)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.result(), "Size", True)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.result(), "Size", True)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result(), "Size", True)
+SketchConstraintDistance_4 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.result(), "Size", True)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")])
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_5 = Sketch_2.addLine(20, -15, 20, 20)
+SketchLine_6 = Sketch_2.addLine(20, 20, -15, 20)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_5.result())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_6.result())
+SketchArc_1 = Sketch_2.addArc(0, 0, -15, 20, 20, -15, False)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchArc_1.endPoint(), SketchLine_5.startPoint())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_5.result(), SketchLine_6.result())
+SketchConstraintDistance_5 = Sketch_2.setDistance(SketchArc_1.center(), SketchLine_5.result(), 20, True)
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchArc_1.center())
+SketchConstraintRadius_1 = Sketch_2.setRadius(SketchArc_1.results()[1], 25)
+SketchLine_7 = Sketch_2.addLine(-15, 20, 20, -15)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_5.startPoint(), SketchLine_7.endPoint())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchArc_1_2f-SketchLine_7r"), model.selection("FACE", "Sketch_2/Face-SketchLine_5r-SketchLine_6f-SketchLine_7f")], model.selection(), model.selection("FACE", "Partition_1_1_2/Modified_Face&Sphere_1_1/Face_1"), "offsetTo", model.selection("FACE", "Face_1_1"), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [30])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [60])
+model.testResultsVolumes(Extrusion_1, [100878.6])
+
+# change radius of sphere and check failure
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure, check the intersected boundaries are processed well
+ParamR.setValue(30)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testResultsVolumes(Extrusion_1, [60964.23998])
+
+ParamR.setValue(40);
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testResultsVolumes(Extrusion_1, [81651.666])
+
+# change size of the face
+ParamSize.setValue(10)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testResultsVolumes(Extrusion_1, [81651.666])
+
+# change offsetting "To" face and check failure
+ParamTo.setValue(-20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [34])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [68])
+model.testResultsVolumes(Extrusion_1, [119535.04])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testResultsVolumes(Extrusion_1, [84126.377])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [34])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [68])
+model.testResultsVolumes(Extrusion_1, [154943.7])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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 GeomAPI import GeomAPI_Shape
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamSize = model.addParameter(Part_1_doc, "Size", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), "R")
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Sphere_1_1"), model.selection("FACE", "PartSet/XOZ")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), 30, False)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchLine_1 = Sketch_1.addLine(50, -50, -50, -50)
+SketchLine_2 = Sketch_1.addLine(-50, -50, -50, 50)
+SketchLine_3 = Sketch_1.addLine(-50, 50, 50, 50)
+SketchLine_4 = Sketch_1.addLine(50, 50, 50, -50)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.result(), "Size", True)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.result(), "Size", True)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result(), "Size", True)
+SketchConstraintDistance_4 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.result(), "Size", True)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")])
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_5 = Sketch_2.addLine(20, -40.3112887414928, 20, 20)
+SketchLine_6 = Sketch_2.addLine(20, 20, -40.31128874149281, 20.00000000000001)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_5.result())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_6.result())
+SketchArc_1 = Sketch_2.addArc(0, 0, -40.31128874149281, 20.00000000000001, 20, -40.3112887414928, False)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchArc_1.endPoint(), SketchLine_5.startPoint())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_5.result(), SketchLine_6.result())
+SketchConstraintDistance_5 = Sketch_2.setDistance(SketchArc_1.center(), SketchLine_5.result(), 20, True)
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchArc_1.center())
+SketchConstraintRadius_1 = Sketch_2.setRadius(SketchArc_1.results()[1], 45)
+SketchLine_7 = Sketch_2.addLine(20, 20, -31.81980515339464, -31.81980515339464)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchArc_1.results()[1])
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchArc_1.center(), SketchLine_7.result())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_2")], model.selection(), model.selection("FACE", "Partition_1_1_1/Modified_Face&Sphere_1_1/Face_1"), "offsetTo", model.selection("FACE", "Face_1_1"), "offsetFrom")
+
+# extrusion have to fail because of several results with shared topology
+assert(Extrusion_1.feature().error() != "")
+
+# change radius of sphere and check failure
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+ParamR.setValue(45)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# change offsetting "To" face and check failure
+ParamTo.setValue(-20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [10])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [40])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [80])
+model.testResultsVolumes(Extrusion_1, [105008.93])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [10])
+model.testResultsVolumes(Extrusion_1, [179594.5])
+
+# check failure
+ParamFrom.setValue(20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(0)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [10])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [39])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [78])
+model.testResultsVolumes(Extrusion_1, [62569.416])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamRSph = model.addParameter(Part_1_doc, "rSphere", "50")
+ParamRCyl = model.addParameter(Part_1_doc, "rCyl", "30")
+ParamRCir = model.addParameter(Part_1_doc, "rCircle", "10")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), "rSphere")
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "rCyl", 100)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchCircle_1 = Sketch_1.addCircle(15, 20, 10)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "rCircle")
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchCircle_1.center(), 15)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchCircle_1.center(), 20)
+SketchLine_1 = Sketch_1.addLine(6.339745962155468, 15, 23.66025403784453, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchCircle_1.results()[1])
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchCircle_1.results()[1])
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchCircle_1.center(), SketchLine_1.result(), "rCircle/2", True)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r-SketchCircle_1_2r-SketchLine_1r"), model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r-SketchLine_1f")], model.selection(), model.selection("FACE", "Sphere_1_1/Face_1"), "offsetTo", model.selection("FACE", "Cylinder_1_1/Face_1"), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [18])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [60])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [120])
+model.testResultsVolumes(Extrusion_1, [10878.5462])
+
+# change radius of sketch circle
+ParamRCir.setValue(17)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [3])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [3])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [17])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [66])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [132])
+model.testResultsVolumes(Extrusion_1, [32102.71838])
+
+# change radius of sphere and check failure
+ParamRSph.setValue(15)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [13])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [61])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [122])
+model.testResultsVolumes(Extrusion_1, [41289.10946])
+
+# change radius of sketch circle and check failure
+ParamRCir.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamRSph.setValue(45);
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [18])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [60])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [120])
+model.testResultsVolumes(Extrusion_1, [7083.567842])
+
+# change radius of cylinder
+ParamRCyl.setValue(10)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [13])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [54])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [108])
+model.testResultsVolumes(Extrusion_1, [22295.845141])
+
+ParamRCyl.setValue(50)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [18])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [60])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [120])
+model.testResultsVolumes(Extrusion_1, [6805.1007457])
+
+# change offsetting "To" face
+ParamTo.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [14])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [60])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [120])
+model.testResultsVolumes(Extrusion_1, [26158.63076])
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [18])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [64])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [128])
+model.testResultsVolumes(Extrusion_1, [7626.2279286])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [18])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [68])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [136])
+model.testResultsVolumes(Extrusion_1, [21514.8965])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [18])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [68])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [136])
+model.testResultsVolumes(Extrusion_1, [5427.194275658])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "R", "R/5", "R")
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Cone_1_1"), model.selection("FACE", "PartSet/XOZ")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), 20, False)
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Plane_1"), model.selection("EDGE", "PartSet/OZ"), 330)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(10, 8.819660112501044, 10, 30)
+SketchLine_2 = Sketch_1.addLine(10, 30, -11.18033988749895, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_2.result())
+SketchArc_1 = Sketch_1.addArc(0, 20, -11.18033988749895, 30, 10, 8.819660112501044, False)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.startPoint())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_1.center(), SketchLine_1.result(), 10, True)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 15)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_3 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_3.result())
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_3).startPoint(), SketchArc_1.center(), 20)
+SketchLine_4 = Sketch_1.addLine(-11.18033988749895, 30, 10, 8.819660112501044)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_4.endPoint())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), model.selection("FACE", "Partition_1_1_2/Modified_Face&Cone_1_1/Face_1"), "offsetTo", model.selection("FACE", "Plane_2"), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [32])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [64])
+model.testResultsVolumes(Extrusion_1, [31363.4963946])
+
+# change radius of sphere and check failure
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure, check the intersected boundaries are processed well
+ParamR.setValue(40)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [32])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [64])
+model.testResultsVolumes(Extrusion_1, [25645.0102138])
+
+# change offsetting "To" face and check failure
+ParamTo.setValue(-20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(8)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [32])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [64])
+model.testResultsVolumes(Extrusion_1, [31501.9671234])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testResultsVolumes(Extrusion_1, [18737.752452])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
+model.testResultsVolumes(Extrusion_1, [44266.1817647])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "R", 100, 180)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(20, 40, -30, 40)
+SketchLine_2 = Sketch_1.addLine(-30, 40, -30, 20)
+SketchLine_3 = Sketch_1.addLine(-30, 20, 20, 20)
+SketchLine_4 = Sketch_1.addLine(20, 20, 20, 40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), 50)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 20)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+model.do()
+Edge_1_objects = [model.selection("EDGE", "Sketch_1/SketchLine_1"), model.selection("EDGE", "Sketch_1/SketchLine_2"), model.selection("EDGE", "Sketch_1/SketchLine_3"), model.selection("EDGE", "Sketch_1/SketchLine_4")]
+Edge_1 = model.addEdge(Part_1_doc, Edge_1_objects)
+Extrusion_1_objects = [model.selection("EDGE", "Edge_1_1"), model.selection("EDGE", "Edge_1_2"), model.selection("EDGE", "Edge_1_3"), model.selection("EDGE", "Edge_1_4")]
+Extrusion_1 = model.addExtrusion(Part_1_doc, Extrusion_1_objects, model.selection("EDGE", "PartSet/OY"), model.selection("FACE", "Cylinder_1_1/Face_1"), "offsetTo", model.selection(), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 4)
+model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [2377.030013, 800, 2377.030013, 916.515139])
+
+# change radius of cylinder
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+ParamR.setValue(30)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure and check the intersected boundaries are processed well
+ParamR.setValue(40);
+model.do()
+model.testNbResults(Extrusion_1, 4)
+model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [1840.601542, 529.150262, 1840.601542, 692.820323])
+
+# change offsetting "To" face
+ParamTo.setValue(-20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 4)
+model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [2899.292521, 1039.2304845, 2899.292521, 1131.3708499])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 4)
+model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [3899.292521, 1439.2304845, 3899.292521, 1531.3708499])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 4)
+model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [1899.292521, 639.2304845, 1899.292521, 731.3708499])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "R", 100, 180)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], model.selection("EDGE", "PartSet/OY"), 50)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(20, 40, -30, 40)
+SketchLine_2 = Sketch_1.addLine(-30, 40, -30, 20)
+SketchLine_3 = Sketch_1.addLine(-30, 20, 20, 20)
+SketchLine_4 = Sketch_1.addLine(20, 20, 20, 40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), 50)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 20)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+model.do()
+Edge_1_objects = [model.selection("EDGE", "Sketch_1/SketchLine_1"), model.selection("EDGE", "Sketch_1/SketchLine_2"), model.selection("EDGE", "Sketch_1/SketchLine_3"), model.selection("EDGE", "Sketch_1/SketchLine_4")]
+Edge_1 = model.addEdge(Part_1_doc, Edge_1_objects)
+Extrusion_1_objects = [model.selection("EDGE", "Edge_1_1"), model.selection("EDGE", "Edge_1_2"), model.selection("EDGE", "Edge_1_3"), model.selection("EDGE", "Edge_1_4")]
+Extrusion_1 = model.addExtrusion(Part_1_doc, Extrusion_1_objects, model.selection("EDGE", "PartSet/OY"), model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_1"), "offsetTo", model.selection(), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 4)
+model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [4877.030013, 1800, 4877.030013, 1916.515139])
+
+# change radius of cylinder and check failure
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+ParamR.setValue(30)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure, check the intersected boundaries are processed well
+ParamR.setValue(40);
+model.do()
+model.testNbResults(Extrusion_1, 4)
+model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [4340.6015418, 1529.1502622, 4340.6015418, 1692.820323])
+
+# change offsetting "To" face and check failure
+ParamTo.setValue(-20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 4)
+model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [5399.2925211, 2039.2304845, 5399.2925212, 2131.37085])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 4)
+model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [6399.2925211, 2439.2304845, 6399.2925212, 2531.37085])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 4)
+model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [4399.2925211, 1639.2304845, 4399.2925212, 1731.37085])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamSize = model.addParameter(Part_1_doc, "Size", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), "R")
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Sphere_1_1"), model.selection("FACE", "PartSet/XOZ")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), 10, False)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchLine_1 = Sketch_1.addLine(50, -50, -50, -50)
+SketchLine_2 = Sketch_1.addLine(-50, -50, -50, 50)
+SketchLine_3 = Sketch_1.addLine(-50, 50, 50, 50)
+SketchLine_4 = Sketch_1.addLine(50, 50, 50, -50)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.result(), "Size", True)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.result(), "Size", True)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result(), "Size", True)
+SketchConstraintDistance_4 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.result(), "Size", True)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")])
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_5 = Sketch_2.addLine(20, -15, 20, 20)
+SketchLine_6 = Sketch_2.addLine(20, 20, -15, 20)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_5.result())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_6.result())
+SketchArc_1 = Sketch_2.addArc(0, 0, -15, 20, 20, -15, False)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchArc_1.endPoint(), SketchLine_5.startPoint())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_5.result(), SketchLine_6.result())
+SketchConstraintDistance_5 = Sketch_2.setDistance(SketchArc_1.center(), SketchLine_5.result(), 20, True)
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchArc_1.center())
+SketchConstraintRadius_1 = Sketch_2.setRadius(SketchArc_1.results()[1], 25)
+model.do()
+Edge_1_objects = [model.selection("EDGE", "Sketch_2/SketchLine_5"), model.selection("EDGE", "Sketch_2/SketchLine_6"), model.selection("EDGE", "Sketch_2/SketchArc_1_2")]
+Edge_1 = model.addEdge(Part_1_doc, Edge_1_objects)
+Extrusion_1_objects = [model.selection("EDGE", "Edge_1_1"), model.selection("EDGE", "Edge_1_2"), model.selection("EDGE", "Edge_1_3")]
+Extrusion_1 = model.addExtrusion(Part_1_doc, Extrusion_1_objects, model.selection("EDGE", "PartSet/OY"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Sphere_1_1/Face_1"), "offsetTo", model.selection("FACE", "Face_1_1"), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [1911.43203298, 1911.43203298, 4564.43663366])
+
+# change radius of sphere and check failure
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure, check the intersected boundaries are processed well
+ParamR.setValue(30)
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [1034.989222291, 1034.989222291, 2276.43702246])
+
+ParamR.setValue(40);
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [1505.0174, 1505.0174, 3530.28837537636])
+
+# change size of the face
+ParamSize.setValue(10)
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8])
+model.testResultsVolumes(Extrusion_1, [1505.0174, 1505.0174, 3530.28837537636])
+
+# change offsetting "To" face and check failure
+ParamTo.setValue(-20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 12])
+model.testResultsVolumes(Extrusion_1, [2295.81450653, 2295.81450653, 5527.16645028])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 12])
+model.testResultsVolumes(Extrusion_1, [1595.81450653, 1595.81450653, 3814.47306888])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 12])
+model.testResultsVolumes(Extrusion_1, [2995.81450653, 2995.81450653, 7239.85983168])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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 GeomAPI import GeomAPI_Shape
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamSize = model.addParameter(Part_1_doc, "Size", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), "R")
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Sphere_1_1"), model.selection("FACE", "PartSet/XOZ")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), 30, False)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchLine_1 = Sketch_1.addLine(50, -50, -50, -50)
+SketchLine_2 = Sketch_1.addLine(-50, -50, -50, 50)
+SketchLine_3 = Sketch_1.addLine(-50, 50, 50, 50)
+SketchLine_4 = Sketch_1.addLine(50, 50, 50, -50)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.result(), "Size", True)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.result(), "Size", True)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result(), "Size", True)
+SketchConstraintDistance_4 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.result(), "Size", True)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")])
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_5 = Sketch_2.addLine(20, -40.3112887414928, 20, 20)
+SketchLine_6 = Sketch_2.addLine(20, 20, -40.31128874149281, 20.00000000000001)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_5.result())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_6.result())
+SketchArc_1 = Sketch_2.addArc(0, 0, -40.31128874149281, 20.00000000000001, 20, -40.3112887414928, False)
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchArc_1.endPoint(), SketchLine_5.startPoint())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_5.result(), SketchLine_6.result())
+SketchConstraintDistance_5 = Sketch_2.setDistance(SketchArc_1.center(), SketchLine_5.result(), 20, True)
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchArc_1.center())
+SketchConstraintRadius_1 = Sketch_2.setRadius(SketchArc_1.results()[1], 45)
+model.do()
+Edge_1_objects = [model.selection("EDGE", "Sketch_2/SketchLine_5"), model.selection("EDGE", "Sketch_2/SketchLine_6"), model.selection("EDGE", "Sketch_2/SketchArc_1_2")]
+Edge_1 = model.addEdge(Part_1_doc, Edge_1_objects)
+Extrusion_1_objects = [model.selection("EDGE", "Edge_1_1"), model.selection("EDGE", "Edge_1_2"), model.selection("EDGE", "Edge_1_3")]
+Extrusion_1 = model.addExtrusion(Part_1_doc, Extrusion_1_objects, model.selection("EDGE", "PartSet/OY"), model.selection("FACE", "Partition_1_1_1/Modified_Face&Sphere_1_1/Face_1"), "offsetTo", model.selection("FACE", "Face_1_1"), "offsetFrom")
+
+# extrusion have to fail because of several results with shared topology
+assert(Extrusion_1.feature().error() != "")
+
+# change radius of sphere and check failure
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+ParamR.setValue(45)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# change offsetting "To" face and check failure
+ParamTo.setValue(-20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 12])
+model.testResultsVolumes(Extrusion_1, [1708.843326299, 1708.843325768, 1895.559443038])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 12])
+model.testResultsVolumes(Extrusion_1, [2915.069101129, 2915.069100598, 4138.27332218])
+
+# check failure
+ParamFrom.setValue(20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamFrom.setValue(10)
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 12])
+model.testResultsVolumes(Extrusion_1, [1105.7304388842, 1105.730438353, 774.2025034671])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamRSph = model.addParameter(Part_1_doc, "rSphere", "50")
+ParamRCyl = model.addParameter(Part_1_doc, "rCyl", "30")
+ParamRCir = model.addParameter(Part_1_doc, "rCircle", "10")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), "rSphere")
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "rCyl", 100)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchCircle_1 = Sketch_1.addCircle(15, 20, 10)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "rCircle")
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchCircle_1.center(), 15)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchCircle_1.center(), 20)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/SketchCircle_1_2")])
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], model.selection("EDGE", "PartSet/OY"), model.selection("FACE", "Sphere_1_1/Face_1"), "offsetTo", model.selection("FACE", "Cylinder_1_1/Face_1"), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [8])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [16])
+model.testResultsVolumes(Extrusion_1, [2178.8497332])
+
+# change radius of sketch circle
+ParamRCir.setValue(17)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [10])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [20])
+model.testResultsVolumes(Extrusion_1, [3960.00723])
+
+# change radius of sphere
+ParamRSph.setValue(10)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [10])
+model.testResultsVolumes(Extrusion_1, [3658.7714])
+
+# change radius of sketch circle and check failure
+ParamRCir.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamRSph.setValue(45);
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [8])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [16])
+model.testResultsVolumes(Extrusion_1, [1398.72992867])
+
+# change radius of cylinder
+ParamRCyl.setValue(10)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [6])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [12])
+model.testResultsVolumes(Extrusion_1, [4194.25709])
+
+ParamRCyl.setValue(50)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [8])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [16])
+model.testResultsVolumes(Extrusion_1, [1433.0518])
+
+# change offsetting "To" face
+ParamTo.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [10])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [20])
+model.testResultsVolumes(Extrusion_1, [5078.347278])
+
+# revert failure
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [10])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [20])
+model.testResultsVolumes(Extrusion_1, [1504.36096473])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [12])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [24])
+model.testResultsVolumes(Extrusion_1, [4336.142699])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [12])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [24])
+model.testResultsVolumes(Extrusion_1, [1118.8887326])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "R", "R/5", "R")
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Cone_1_1"), model.selection("FACE", "PartSet/XOZ")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), 20, False)
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Plane_1"), model.selection("EDGE", "PartSet/OZ"), 330)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(10, 8.819660112501044, 10, 30)
+SketchLine_2 = Sketch_1.addLine(10, 30, -11.18033988749895, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_2.result())
+SketchArc_1 = Sketch_1.addArc(0, 20, -11.18033988749895, 30, 10, 8.819660112501044, False)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.startPoint())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_1.center(), SketchLine_1.result(), 10, True)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 15)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+SketchLine_3 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_3.result())
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Line(SketchLine_3).startPoint(), SketchArc_1.center(), 20)
+model.do()
+Edge_1_objects = [model.selection("EDGE", "Sketch_1/SketchLine_1"), model.selection("EDGE", "Sketch_1/SketchLine_2"), model.selection("EDGE", "Sketch_1/SketchArc_1_2")]
+Edge_1 = model.addEdge(Part_1_doc, Edge_1_objects)
+Extrusion_1_objects = [model.selection("EDGE", "Edge_1_1"), model.selection("EDGE", "Edge_1_2"), model.selection("EDGE", "Edge_1_3")]
+Extrusion_1 = model.addExtrusion(Part_1_doc, Extrusion_1_objects, model.selection("EDGE", "PartSet/OY"), model.selection("FACE", "Partition_1_1_2/Modified_Face&Cone_1_1/Face_1"), "offsetTo", model.selection("FACE", "Plane_2"), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 10])
+model.testResultsVolumes(Extrusion_1, [1309.42058662, 1016.82520496, 2589.5946928])
+
+# change radius of sphere and check failure
+ParamR.setValue(10)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure, check the intersected boundaries are processed well
+ParamR.setValue(40)
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 10])
+model.testResultsVolumes(Extrusion_1, [1081.93830116, 793.80218227, 2095.8021933])
+
+# change offsetting "To" face and check failure
+ParamTo.setValue(-20)
+model.do()
+assert(Extrusion_1.feature().error() != "")
+
+# revert failure
+ParamTo.setValue(8)
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4, 4, 5])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 10])
+model.testResultsVolumes(Extrusion_1, [1314.8586588, 1022.169915122, 2601.32913399])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testResultsVolumes(Extrusion_1, [825.71966141, 533.030917699, 1551.6191757579])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 3)
+model.testNbSubResults(Extrusion_1, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0, 0, 0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testResultsVolumes(Extrusion_1, [1803.997656259, 1511.308912545, 3651.0390970659])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-2019 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()
+ParamR = model.addParameter(Part_1_doc, "R", "50")
+ParamFrom = model.addParameter(Part_1_doc, "offsetFrom", "0")
+ParamTo = model.addParameter(Part_1_doc, "offsetTo", "0")
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), "R", 100, 180)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_1.addLine(20, 40, -30, 40)
+SketchLine_2 = Sketch_1.addLine(-30, 40, -30, 20)
+SketchLine_3 = Sketch_1.addLine(-30, 20, 20, 20)
+SketchLine_4 = Sketch_1.addLine(20, 20, 20, 40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_3.result(), 50)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 20)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.endPoint(), 20)
+model.do()
+Wire_1_objects = [model.selection("EDGE", "Sketch_1/SketchLine_1"), model.selection("EDGE", "Sketch_1/SketchLine_2"), model.selection("EDGE", "Sketch_1/SketchLine_3"), model.selection("EDGE", "Sketch_1/SketchLine_4")]
+Wire_1 = model.addWire(Part_1_doc, Wire_1_objects)
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Wire_1_1")], model.selection("EDGE", "PartSet/OY"), model.selection("FACE", "Cylinder_1_1/Face_1"), "offsetTo", model.selection(), "offsetFrom")
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [16])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [32])
+model.testResultsVolumes(Extrusion_1, [6470.575165134267])
+
+# change radius of cylinder
+ParamR.setValue(10)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8])
+model.testResultsVolumes(Extrusion_1, [314.159265359])
+
+ParamR.setValue(30)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [3])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [10])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [20])
+model.testResultsVolumes(Extrusion_1, [2964.89877572])
+
+# check the intersected boundaries are processed well
+ParamR.setValue(40);
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [16])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [32])
+model.testResultsVolumes(Extrusion_1, [4903.173668915])
+
+# change offsetting "To" face
+ParamTo.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [2])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8])
+model.testResultsVolumes(Extrusion_1, [1256.637061267])
+
+ParamTo.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [16])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [32])
+model.testResultsVolumes(Extrusion_1, [7969.186376787])
+
+# offset "From" face
+ParamFrom.setValue(-20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [16])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [32])
+model.testResultsVolumes(Extrusion_1, [10769.186376787])
+
+ParamFrom.setValue(20)
+model.do()
+model.testNbResults(Extrusion_1, 1)
+model.testNbSubResults(Extrusion_1, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [4])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.EDGE, [16])
+model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [32])
+model.testResultsVolumes(Extrusion_1, [5169.186376787])
+
+model.testHaveNamingSubshapes(Extrusion_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
.. image:: images/extrusion_by_bounding_planes.png
:align: left
-**By Bounding Planes** extrudes objects by specifying bounding planes and offsets.
+**By Bounding Faces** extrudes objects by specifying bounding faces/planes and offsets.
By sizes
**See Also** a sample TUI Script of :ref:`tui_create_extrusion_by_sizes` operation.
-By bounding planes
+By bounding faces
------------------
.. image:: images/Extrusion2.png
:align: center
.. centered::
- Extrusion: definition by bounding planes
+ Extrusion: definition by bounding faces
- **Base objects** - contains a list of objects selected in the Object Browser or in the Viewer, which will be extruded.
- **Axis** if selected, it will be direction of extrusion, otherwise objects normals will be used.
-- **To plane** - a planar face can be selected to bound extrusion from one side.
+- **To face** - a face can be selected to bound extrusion from one side.
- **To offset** - offset for extrusion or for bounding plane, if selected.
-- **From plane** - a planar face can be selected to bound extrusion from the other side.
+- **From face** - a face can be selected to bound extrusion from the other side.
- **From offset** - offset for extrusion or for bounding plane, if selected.
+Planar face selected as a boundary of extrusion will be enlarged infinitely. As a result, extrusion bounded only by planar faces will be completed always.
+On the other hand, if the boundary face is not planar, extrusion may fail, for example, in case of the base object cannot be projected to this face along given direction.
+
**TUI Command**: *model.addExtrusion(part, objects, toObject, toOffset, fromObject, fromOffset);*
**Arguments**: Part + list of objects + to object + to offset + from object + from offset.
</groupbox>
</box>
<box id="ByPlanesAndOffsets"
- title="By bounding planes and offsets"
+ title="By bounding faces and offsets"
icon="icons/Features/plane_inverted_32x32.png">
<groupbox title="From">
<shape_selector id="from_object"
icon="icons/Features/plane.png"
- label="Plane face"
- tooltip="Bounding plane (select a planar face)"
+ label="From face"
+ tooltip="From face"
shape_types="face"
geometrical_selection="true"
default="<base sketch>">
- <validator id="GeomValidators_Face" parameters="plane"/>
+ <validator id="FeaturesPlugin_ValidatorExtrusionBoundary"/>
</shape_selector>
<doublevalue id="from_offset"
label="Offset"
<groupbox title="To">
<shape_selector id="to_object"
icon="icons/Features/plane_inverted.png"
- label="Plane face"
- tooltip="Bounding plane (select a planar face)"
+ label="To face"
+ tooltip="To face"
shape_types="face"
geometrical_selection="true"
default="<base sketch>">
- <validator id="GeomValidators_Face" parameters="plane"/>
+ <validator id="FeaturesPlugin_ValidatorExtrusionBoundary"/>
</shape_selector>
<doublevalue id="to_offset"
label="Offset"
GeomAlgoAPI_Filling.h
GeomAlgoAPI_CurveBuilder.h
GeomAlgoAPI_NExplode.h
+ GeomAlgoAPI_Offset.h
)
SET(PROJECT_SOURCES
GeomAlgoAPI_Filling.cpp
GeomAlgoAPI_CurveBuilder.cpp
GeomAlgoAPI_NExplode.cpp
+ GeomAlgoAPI_Offset.cpp
)
SET(PROJECT_LIBRARIES
--- /dev/null
+// Copyright (C) 2019-2019 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_Offset.h"
+
+#include <BRepOffsetAPI_MakeOffsetShape.hxx>
+
+
+GeomAlgoAPI_Offset::GeomAlgoAPI_Offset(const GeomShapePtr& theShape,
+ const double theOffsetValue)
+{
+ build(theShape, theOffsetValue);
+}
+
+void GeomAlgoAPI_Offset::build(const GeomShapePtr& theShape, const double theOffsetValue)
+{
+ BRepOffsetAPI_MakeOffsetShape* anOffsetAlgo = new BRepOffsetAPI_MakeOffsetShape;
+ anOffsetAlgo->PerformBySimple(theShape->impl<TopoDS_Shape>(), theOffsetValue);
+ setImpl(anOffsetAlgo);
+ setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
+
+ if (anOffsetAlgo->IsDone()) {
+ const TopoDS_Shape& aResult = anOffsetAlgo->Shape();
+ std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+ aShape->setImpl(new TopoDS_Shape(aResult));
+ setShape(aShape);
+ setDone(true);
+ }
+}
+
+void GeomAlgoAPI_Offset::generated(const GeomShapePtr theOldShape,
+ ListOfShape& theNewShapes)
+{
+ try {
+ GeomAlgoAPI_MakeShape::generated(theOldShape, theNewShapes);
+ } catch(...) {
+ // nothing is generated
+ }
+}
--- /dev/null
+// Copyright (C) 2019-2019 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_Offset_H_
+#define GeomAlgoAPI_Offset_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAlgoAPI_MakeShape.h>
+
+/// \class GeomAlgoAPI_Offset
+/// \ingroup DataAlgo
+/// \brief Perform 3D offset for the shape
+class GeomAlgoAPI_Offset : public GeomAlgoAPI_MakeShape
+{
+public:
+ /// \brief Construct offset.
+ GEOMALGOAPI_EXPORT GeomAlgoAPI_Offset(const GeomShapePtr& theShape,
+ const double theOffsetValue);
+
+ /// \return the list of shapes generated from the shape \a theShape.
+ /// \param[in] theOldShape base shape.
+ /// \param[out] theNewShapes shapes generated from \a theShape. Does not cleared!
+ GEOMALGOAPI_EXPORT virtual void generated(const GeomShapePtr theOldShape,
+ ListOfShape& theNewShapes);
+
+private:
+ /// \brief Perform offset operation
+ void build(const GeomShapePtr& theShape, const double theOffsetValue);
+};
+
+#endif
#include "GeomAlgoAPI_Prism.h"
+#include <GeomAPI_Ax1.h>
+#include <GeomAPI_Dir.h>
#include <GeomAPI_Face.h>
#include <GeomAPI_Pln.h>
#include <GeomAPI_Pnt.h>
#include <GeomAPI_ShapeExplorer.h>
#include <GeomAPI_XYZ.h>
+
+#include <GeomAlgoAPI_CompoundBuilder.h>
#include <GeomAlgoAPI_DFLoader.h>
#include <GeomAlgoAPI_FaceBuilder.h>
+#include <GeomAlgoAPI_Offset.h>
+#include <GeomAlgoAPI_Partition.h>
#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAlgoAPI_Translation.h>
#include <Bnd_Box.hxx>
#include <BRep_Builder.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
+/// Expand planar face to cover the bounding box if theOriginalShape is planar.
+/// Otherwise, return the same shape;
+static GeomShapePtr buildPlanarFace(const GeomShapePtr& theOriginalShape,
+ const Bnd_Box& theBaseShapeBB);
+
+/// Build offset for the given shape.
+/// If the offset algorithm failed, translate the shape along the direction.
+static GeomShapePtr buildOffset(const GeomShapePtr& theShape,
+ const double theOffset,
+ const GeomDirPtr theDirection,
+ GeomAlgoAPI_MakeShapeList& theMakeShapeList);
+
+/// Collect base faces of the prism.
+static void collectPrismBases(const TopoDS_Shape& theBaseShape,
+ BRepPrimAPI_MakePrism& thePrismAlgo,
+ ListOfShape& theBoundaries,
+ const GeomAPI_Shape::ShapeType theTypeToExp);
+
+/// Collect all solids which contain boundaries but do not contain bases of prism.
+static GeomShapePtr collectResults(const GeomMakeShapePtr& theOperation,
+ const ListOfShape& theBoundaries,
+ const ListOfShape& theShapesToExclude,
+ const GeomAPI_Shape::ShapeType theTypeToExp);
+
static void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
const TopoDS_Shape& theBase,
const TopAbs_ShapeEnum theType,
const TopoDS_Face& theToFace,
const TopoDS_Face& theFromFace);
-
-//==================================================================================================
-GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr theBaseShape,
- const std::shared_ptr<GeomAPI_Dir> theDirection,
- const GeomShapePtr theToShape,
- const double theToSize,
- const GeomShapePtr theFromShape,
- const double theFromSize)
+static GeomShapePtr toShape(const TopoDS_Shape& theShape)
{
- build(theBaseShape, theDirection, theToShape, theToSize, theFromShape, theFromSize);
+ GeomShapePtr aShape(new GeomAPI_Shape());
+ aShape->setImpl(new TopoDS_Shape(theShape));
+ return aShape;
}
+
//==================================================================================================
-void GeomAlgoAPI_Prism::build(const GeomShapePtr& theBaseShape,
- const std::shared_ptr<GeomAPI_Dir> theDirection,
- const GeomShapePtr& theToShape,
- const double theToSize,
- const GeomShapePtr& theFromShape,
- const double theFromSize)
+GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr theBaseShape,
+ const GeomDirPtr theDirection,
+ const GeomShapePtr theToShape,
+ const double theToSize,
+ const GeomShapePtr theFromShape,
+ const double theFromSize)
{
if(!theBaseShape.get() ||
(((!theFromShape.get() && !theToShape.get()) ||
// Getting base shape.
const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
- TopAbs_ShapeEnum aShapeTypeToExp;
+ GeomAPI_Shape::ShapeType aShapeTypeToExp;
switch(aBaseShape.ShapeType()) {
case TopAbs_VERTEX:
- aShapeTypeToExp = TopAbs_VERTEX;
+ aShapeTypeToExp = GeomAPI_Shape::VERTEX;
break;
case TopAbs_EDGE:
case TopAbs_WIRE:
- aShapeTypeToExp = TopAbs_EDGE;
+ aShapeTypeToExp = GeomAPI_Shape::EDGE;
break;
case TopAbs_FACE:
case TopAbs_SHELL:
- aShapeTypeToExp = TopAbs_FACE;
+ aShapeTypeToExp = GeomAPI_Shape::FACE;
break;
case TopAbs_COMPOUND:
- aShapeTypeToExp = TopAbs_COMPOUND;
+ aShapeTypeToExp = GeomAPI_Shape::COMPOUND;
break;
default:
return;
aBaseLoc.reset(new GeomAPI_Pnt(aLoc.X(), aLoc.Y(), aLoc.Z()));
}
- GeomShapePtr aBasePlane = GeomAlgoAPI_FaceBuilder::planarFace(aBaseLoc, aBaseDir);
-
gp_Vec anExtVec;
std::shared_ptr<GeomAPI_Dir> anExtDir;
if (theDirection.get())
TopoDS_Shape aResult;
const bool isBoundingShapesSet = theFromShape.get() || theToShape.get();
if(!isBoundingShapesSet) {
- // Moving base shape.
- gp_Trsf aTrsf;
- aTrsf.SetTranslation(anExtVec * -theFromSize);
- BRepBuilderAPI_Transform* aTransformBuilder =
- new BRepBuilderAPI_Transform(aBaseShape, aTrsf);
- if(!aTransformBuilder || !aTransformBuilder->IsDone()) {
- return;
- }
- this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
- new GeomAlgoAPI_MakeShape(aTransformBuilder)));
- TopoDS_Shape aMovedBase = aTransformBuilder->Shape();
-
- // Making prism.
- BRepPrimAPI_MakePrism* aPrismBuilder =
- new BRepPrimAPI_MakePrism(aMovedBase, anExtVec * (theFromSize + theToSize));
- if(!aPrismBuilder || !aPrismBuilder->IsDone()) {
- return;
- }
- this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
- new GeomAlgoAPI_MakeShape(aPrismBuilder)));
- aResult = aPrismBuilder->Shape();
-
- // Setting naming.
- if(aShapeTypeToExp == TopAbs_COMPOUND) {
- storeGenerationHistory(this, aMovedBase, TopAbs_EDGE, aPrismBuilder);
- storeGenerationHistory(this, aMovedBase, TopAbs_FACE, aPrismBuilder);
- } else {
- storeGenerationHistory(this, aMovedBase, aShapeTypeToExp, aPrismBuilder);
- }
+ buildBySizes(theBaseShape, anExtDir, theToSize, theFromSize, aShapeTypeToExp);
} else {
+ GeomShapePtr aBasePlane = GeomAlgoAPI_FaceBuilder::squareFace(aBaseLoc, aBaseDir, 100.0);
+
GeomShapePtr aBoundingFromShape = theFromShape ? theFromShape : aBasePlane;
GeomShapePtr aBoundingToShape = theToShape ? theToShape : aBasePlane;
- // Moving prism bounding faces according to "from" and "to" sizes.
- std::shared_ptr<GeomAPI_Pln> aFromPln = GeomAPI_Face(aBoundingFromShape).getPlane();
- std::shared_ptr<GeomAPI_Pnt> aFromLoc = aFromPln->location();
- std::shared_ptr<GeomAPI_Dir> aFromDir = aFromPln->direction();
-
- std::shared_ptr<GeomAPI_Pln> aToPln = GeomAPI_Face(aBoundingToShape).getPlane();
- std::shared_ptr<GeomAPI_Pnt> aToLoc = aToPln->location();
- std::shared_ptr<GeomAPI_Dir> aToDir = aToPln->direction();
-
- bool aSign = aFromLoc->xyz()->dot(anExtDir->xyz()) > aToLoc->xyz()->dot(anExtDir->xyz());
-
- std::shared_ptr<GeomAPI_Pnt> aFromPnt(
- new GeomAPI_Pnt(aFromLoc->xyz()->added(anExtDir->xyz()->multiplied(
- aSign ? theFromSize : -theFromSize))));
- aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
-
- std::shared_ptr<GeomAPI_Pnt> aToPnt(
- new GeomAPI_Pnt(aToLoc->xyz()->added(anExtDir->xyz()->multiplied(
- aSign ? -theToSize : theToSize))));
- aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
-
- // Getting bounding box for base shape.
- Bnd_Box aBndBox;
- BRepBndLib::Add(aBaseShape, aBndBox);
- Standard_Real aXArr[2] = {aBndBox.CornerMin().X(), aBndBox.CornerMax().X()};
- Standard_Real aYArr[2] = {aBndBox.CornerMin().Y(), aBndBox.CornerMax().Y()};
- Standard_Real aZArr[2] = {aBndBox.CornerMin().Z(), aBndBox.CornerMax().Z()};
- gp_Pnt aPoints[8];
- int aNum = 0;
- for(int i = 0; i < 2; i++) {
- for(int j = 0; j < 2; j++) {
- for(int k = 0; k < 2; k++) {
- aPoints[aNum] = gp_Pnt(aXArr[i], aYArr[j], aZArr[k]);
- aNum++;
- }
- }
+ bool isFromShapePlanar = aBoundingFromShape->isPlanar();
+ bool isToShapePlanar = aBoundingToShape->isPlanar();
+
+ // Set signs of offsets if both bounding shapes are planar
+ if (isFromShapePlanar && isToShapePlanar) {
+ std::shared_ptr<GeomAPI_Pln> aFromPln = GeomAPI_Face(aBoundingFromShape).getPlane();
+ std::shared_ptr<GeomAPI_Pln> aToPln = GeomAPI_Face(aBoundingToShape).getPlane();
+ buildByPlanes(theBaseShape, anExtDir,
+ aToPln, theToSize,
+ aFromPln, theFromSize,
+ aShapeTypeToExp);
}
-
- // Project points to bounding planes. Search max distance to them.
- IntAna_Quadric aBndToQuadric(gp_Pln(aToPnt->impl<gp_Pnt>(), aToDir->impl<gp_Dir>()));
- IntAna_Quadric aBndFromQuadric(gp_Pln(aFromPnt->impl<gp_Pnt>(), aFromDir->impl<gp_Dir>()));
- Standard_Real aMaxToDist = 0, aMaxFromDist = 0;
- for(int i = 0; i < 8; i++) {
- gp_Lin aLine(aPoints[i], anExtVec);
- IntAna_IntConicQuad aToIntAna(aLine, aBndToQuadric);
- IntAna_IntConicQuad aFromIntAna(aLine, aBndFromQuadric);
- if(aToIntAna.NbPoints() == 0 || aFromIntAna.NbPoints() == 0) {
- return;
- }
- const gp_Pnt& aPntOnToFace = aToIntAna.Point(1);
- const gp_Pnt& aPntOnFromFace = aFromIntAna.Point(1);
- if(aPoints[i].Distance(aPntOnToFace) > aMaxToDist) {
- aMaxToDist = aPoints[i].Distance(aPntOnToFace);
- }
- if(aPoints[i].Distance(aPntOnFromFace) > aMaxFromDist) {
- aMaxFromDist = aPoints[i].Distance(aPntOnFromFace);
- }
+ else {
+ buildByFaces(theBaseShape, anExtDir,
+ aBoundingToShape, theToSize, isToShapePlanar,
+ aBoundingFromShape, theFromSize, isFromShapePlanar,
+ aShapeTypeToExp);
}
+ }
+}
- // We added 1 just to be sure that prism is long enough for boolean operation.
- double aPrismLength = aMaxToDist + aMaxFromDist + 1;
+//==================================================================================================
+void GeomAlgoAPI_Prism::buildBySizes(const GeomShapePtr theBaseShape,
+ const GeomDirPtr theDirection,
+ const double theToSize,
+ const double theFromSize,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
+{
+ const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
+ gp_Vec anExtVec = theDirection->impl<gp_Dir>();
- // Moving base shape.
- gp_Trsf aTrsf;
- aTrsf.SetTranslation(anExtVec * -aPrismLength);
- BRepBuilderAPI_Transform* aTransformBuilder = new BRepBuilderAPI_Transform(aBaseShape, aTrsf);
- if(!aTransformBuilder || !aTransformBuilder->IsDone()) {
- return;
- }
- this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ // Moving base shape.
+ gp_Trsf aTrsf;
+ aTrsf.SetTranslation(anExtVec * -theFromSize);
+ BRepBuilderAPI_Transform* aTransformBuilder =
+ new BRepBuilderAPI_Transform(aBaseShape, aTrsf);
+ if (!aTransformBuilder || !aTransformBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
new GeomAlgoAPI_MakeShape(aTransformBuilder)));
- TopoDS_Shape aMovedBase = aTransformBuilder->Shape();
+ TopoDS_Shape aMovedBase = aTransformBuilder->Shape();
- // Making prism.
- BRepPrimAPI_MakePrism* aPrismBuilder =
- new BRepPrimAPI_MakePrism(aMovedBase, anExtVec * 2 * aPrismLength);
- if(!aPrismBuilder || !aPrismBuilder->IsDone()) {
- return;
- }
- this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ // Making prism.
+ BRepPrimAPI_MakePrism* aPrismBuilder =
+ new BRepPrimAPI_MakePrism(aMovedBase, anExtVec * (theFromSize + theToSize));
+ if (!aPrismBuilder || !aPrismBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
new GeomAlgoAPI_MakeShape(aPrismBuilder)));
- aResult = aPrismBuilder->Shape();
+ TopoDS_Shape aResult = aPrismBuilder->Shape();
- // Orienting bounding planes.
- std::shared_ptr<GeomAPI_Pnt> aCentreOfMass = GeomAlgoAPI_ShapeTools::centreOfMass(theBaseShape);
- const gp_Pnt& aCentrePnt = aCentreOfMass->impl<gp_Pnt>();
- gp_Lin aLine(aCentrePnt, anExtVec);
- IntAna_IntConicQuad aToIntAna(aLine, aBndToQuadric);
- IntAna_IntConicQuad aFromIntAna(aLine, aBndFromQuadric);
- Standard_Real aToParameter = aToIntAna.ParamOnConic(1);
- Standard_Real aFromParameter = aFromIntAna.ParamOnConic(1);
- if(aToParameter > aFromParameter) {
- gp_Vec aVec = aToDir->impl<gp_Dir>();
- if((aVec * anExtVec) > 0) {
- aToDir->setImpl(new gp_Dir(aVec.Reversed()));
- aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
- }
- aVec = aFromDir->impl<gp_Dir>();
- if((aVec * anExtVec) < 0) {
- aFromDir->setImpl(new gp_Dir(aVec.Reversed()));
- aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
- }
- } else {
- gp_Vec aVec = aToDir->impl<gp_Dir>();
- if((aVec * anExtVec) < 0) {
- aToDir->setImpl(new gp_Dir(aVec.Reversed()));
- aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
- }
- aVec = aFromDir->impl<gp_Dir>();
- if((aVec * anExtVec) > 0) {
- aFromDir->setImpl(new gp_Dir(aVec.Reversed()));
- aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
+ // Setting naming.
+ if(theTypeToExp == GeomAPI_Shape::COMPOUND) {
+ storeGenerationHistory(this, aMovedBase, TopAbs_EDGE, aPrismBuilder);
+ storeGenerationHistory(this, aMovedBase, TopAbs_FACE, aPrismBuilder);
+ } else {
+ storeGenerationHistory(this, aMovedBase, (TopAbs_ShapeEnum)theTypeToExp, aPrismBuilder);
+ }
+
+ // Setting result.
+ if (!aResult.IsNull()) {
+ aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+ this->setShape(toShape(aResult));
+ this->setDone(true);
+ }
+}
+
+//==================================================================================================
+void GeomAlgoAPI_Prism::buildByPlanes(const GeomShapePtr theBaseShape,
+ const GeomDirPtr theDirection,
+ const GeomPlanePtr theToPlane,
+ const double theToSize,
+ const GeomPlanePtr theFromPlane,
+ const double theFromSize,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
+{
+ const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
+ gp_Vec anExtVec = theDirection->impl<gp_Dir>();
+
+ // Moving prism bounding faces according to "from" and "to" sizes.
+ std::shared_ptr<GeomAPI_Pnt> aFromLoc = theFromPlane->location();
+ std::shared_ptr<GeomAPI_Dir> aFromDir = theFromPlane->direction();
+
+ std::shared_ptr<GeomAPI_Pnt> aToLoc = theToPlane->location();
+ std::shared_ptr<GeomAPI_Dir> aToDir = theToPlane->direction();
+
+ std::shared_ptr<GeomAPI_XYZ> anExtDir = theDirection->xyz();
+ bool aSign = aFromLoc->xyz()->dot(anExtDir) > aToLoc->xyz()->dot(anExtDir);
+
+ std::shared_ptr<GeomAPI_Pnt> aFromPnt(
+ new GeomAPI_Pnt(aFromLoc->xyz()->added(anExtDir->multiplied(
+ aSign ? theFromSize : -theFromSize))));
+ GeomShapePtr aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
+
+ std::shared_ptr<GeomAPI_Pnt> aToPnt(
+ new GeomAPI_Pnt(aToLoc->xyz()->added(anExtDir->multiplied(
+ aSign ? -theToSize : theToSize))));
+ GeomShapePtr aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
+
+ // Getting bounding box for base shape.
+ Bnd_Box aBndBox;
+ BRepBndLib::Add(aBaseShape, aBndBox);
+ Standard_Real aXArr[2] = {aBndBox.CornerMin().X(), aBndBox.CornerMax().X()};
+ Standard_Real aYArr[2] = {aBndBox.CornerMin().Y(), aBndBox.CornerMax().Y()};
+ Standard_Real aZArr[2] = {aBndBox.CornerMin().Z(), aBndBox.CornerMax().Z()};
+ gp_Pnt aPoints[8];
+ int aNum = 0;
+ for(int i = 0; i < 2; i++) {
+ for(int j = 0; j < 2; j++) {
+ for(int k = 0; k < 2; k++) {
+ aPoints[aNum] = gp_Pnt(aXArr[i], aYArr[j], aZArr[k]);
+ aNum++;
}
}
+ }
- // Making solids from bounding planes.
- TopoDS_Shell aToShell, aFromShell;
- TopoDS_Solid aToSolid, aFromSolid;
- const TopoDS_Shape& aToShape = aBoundingToShape->impl<TopoDS_Shape>();
- const TopoDS_Shape& aFromShape = aBoundingFromShape->impl<TopoDS_Shape>();
- TopoDS_Face aToFace = TopoDS::Face(aToShape);
- TopoDS_Face aFromFace = TopoDS::Face(aFromShape);
- BRep_Builder aBoundingBuilder;
- aBoundingBuilder.MakeShell(aToShell);
- aBoundingBuilder.Add(aToShell, aToShape);
- aBoundingBuilder.MakeShell(aFromShell);
- aBoundingBuilder.Add(aFromShell, aFromShape);
- aBoundingBuilder.MakeSolid(aToSolid);
- aBoundingBuilder.Add(aToSolid, aToShell);
- aBoundingBuilder.MakeSolid(aFromSolid);
- aBoundingBuilder.Add(aFromSolid, aFromShell);
-
- // Cutting with to plane.
- BRepAlgoAPI_Cut* aToCutBuilder = new BRepAlgoAPI_Cut(aResult, aToSolid);
- aToCutBuilder->Build();
- if(!aToCutBuilder->IsDone()) {
+ // Project points to bounding planes. Search max distance to them.
+ IntAna_Quadric aBndToQuadric(gp_Pln(aToPnt->impl<gp_Pnt>(), aToDir->impl<gp_Dir>()));
+ IntAna_Quadric aBndFromQuadric(gp_Pln(aFromPnt->impl<gp_Pnt>(), aFromDir->impl<gp_Dir>()));
+ Standard_Real aMaxToDist = 0, aMaxFromDist = 0;
+ for(int i = 0; i < 8; i++) {
+ gp_Lin aLine(aPoints[i], anExtVec);
+ IntAna_IntConicQuad aToIntAna(aLine, aBndToQuadric);
+ IntAna_IntConicQuad aFromIntAna(aLine, aBndFromQuadric);
+ if(aToIntAna.NbPoints() == 0 || aFromIntAna.NbPoints() == 0) {
return;
}
- this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
- new GeomAlgoAPI_MakeShape(aToCutBuilder)));
- aResult = aToCutBuilder->Shape();
- if(aResult.ShapeType() == TopAbs_COMPOUND) {
- aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+ const gp_Pnt& aPntOnToFace = aToIntAna.Point(1);
+ const gp_Pnt& aPntOnFromFace = aFromIntAna.Point(1);
+ if(aPoints[i].Distance(aPntOnToFace) > aMaxToDist) {
+ aMaxToDist = aPoints[i].Distance(aPntOnToFace);
}
- if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
- const TopTools_ListOfShape& aToShapes = aToCutBuilder->Modified(aToShape);
- for(TopTools_ListIteratorOfListOfShape anIt(aToShapes); anIt.More(); anIt.Next()) {
- GeomShapePtr aGeomSh(new GeomAPI_Shape());
- aGeomSh->setImpl(new TopoDS_Shape(anIt.Value()));
- fixOrientation(aGeomSh);
- this->addToShape(aGeomSh);
- }
+ if(aPoints[i].Distance(aPntOnFromFace) > aMaxFromDist) {
+ aMaxFromDist = aPoints[i].Distance(aPntOnFromFace);
}
+ }
- // Cutting with from plane.
- BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aResult, aFromSolid);
- aFromCutBuilder->Build();
- if(!aFromCutBuilder->IsDone()) {
- return;
+ // We added 1 just to be sure that prism is long enough for boolean operation.
+ double aPrismLength = aMaxToDist + aMaxFromDist + 1;
+
+ // Moving base shape.
+ gp_Trsf aTrsf;
+ aTrsf.SetTranslation(anExtVec * -aPrismLength);
+ BRepBuilderAPI_Transform* aTransformBuilder = new BRepBuilderAPI_Transform(aBaseShape, aTrsf);
+ if(!aTransformBuilder || !aTransformBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ new GeomAlgoAPI_MakeShape(aTransformBuilder)));
+ TopoDS_Shape aMovedBase = aTransformBuilder->Shape();
+
+ // Making prism.
+ BRepPrimAPI_MakePrism* aPrismBuilder =
+ new BRepPrimAPI_MakePrism(aMovedBase, anExtVec * 2 * aPrismLength);
+ if(!aPrismBuilder || !aPrismBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ new GeomAlgoAPI_MakeShape(aPrismBuilder)));
+ TopoDS_Shape aResult = aPrismBuilder->Shape();
+
+ // Orienting bounding planes.
+ std::shared_ptr<GeomAPI_Pnt> aCentreOfMass = GeomAlgoAPI_ShapeTools::centreOfMass(theBaseShape);
+ const gp_Pnt& aCentrePnt = aCentreOfMass->impl<gp_Pnt>();
+ gp_Lin aLine(aCentrePnt, anExtVec);
+ IntAna_IntConicQuad aToIntAna(aLine, aBndToQuadric);
+ IntAna_IntConicQuad aFromIntAna(aLine, aBndFromQuadric);
+ Standard_Real aToParameter = aToIntAna.ParamOnConic(1);
+ Standard_Real aFromParameter = aFromIntAna.ParamOnConic(1);
+ if(aToParameter > aFromParameter) {
+ gp_Vec aVec = aToDir->impl<gp_Dir>();
+ if((aVec * anExtVec) > 0) {
+ aToDir->setImpl(new gp_Dir(aVec.Reversed()));
+ aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
}
- this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
- new GeomAlgoAPI_MakeShape(aFromCutBuilder)));
- aResult = aFromCutBuilder->Shape();
- TopoDS_Iterator aCheckIt(aResult);
- if(!aCheckIt.More()) {
- return;
+ aVec = aFromDir->impl<gp_Dir>();
+ if((aVec * anExtVec) < 0) {
+ aFromDir->setImpl(new gp_Dir(aVec.Reversed()));
+ aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
}
- if(aResult.ShapeType() == TopAbs_COMPOUND) {
- aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+ } else {
+ gp_Vec aVec = aToDir->impl<gp_Dir>();
+ if((aVec * anExtVec) < 0) {
+ aToDir->setImpl(new gp_Dir(aVec.Reversed()));
+ aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
}
- if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
- const TopTools_ListOfShape& aFromShapes = aFromCutBuilder->Modified(aFromShape);
- for(TopTools_ListIteratorOfListOfShape anIt(aFromShapes); anIt.More(); anIt.Next()) {
- GeomShapePtr aGeomSh(new GeomAPI_Shape());
- aGeomSh->setImpl(new TopoDS_Shape(anIt.Value()));
- fixOrientation(aGeomSh);
- this->addFromShape(aGeomSh);
- }
+ aVec = aFromDir->impl<gp_Dir>();
+ if((aVec * anExtVec) > 0) {
+ aFromDir->setImpl(new gp_Dir(aVec.Reversed()));
+ aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
}
+ }
- // Naming for extrusion from vertex, edge.
- if(aShapeTypeToExp == TopAbs_COMPOUND) {
- storeGenerationHistory(this, aResult, TopAbs_EDGE, aToFace, aFromFace);
- storeGenerationHistory(this, aResult, TopAbs_FACE, aToFace, aFromFace);
- } else {
- storeGenerationHistory(this, aResult, aShapeTypeToExp, aToFace, aFromFace);
+ // Making solids from bounding planes.
+ TopoDS_Shell aToShell, aFromShell;
+ TopoDS_Solid aToSolid, aFromSolid;
+ const TopoDS_Shape& aToShape = aBoundingToShape->impl<TopoDS_Shape>();
+ const TopoDS_Shape& aFromShape = aBoundingFromShape->impl<TopoDS_Shape>();
+ TopoDS_Face aToFace = TopoDS::Face(aToShape);
+ TopoDS_Face aFromFace = TopoDS::Face(aFromShape);
+ BRep_Builder aBoundingBuilder;
+ aBoundingBuilder.MakeShell(aToShell);
+ aBoundingBuilder.Add(aToShell, aToShape);
+ aBoundingBuilder.MakeShell(aFromShell);
+ aBoundingBuilder.Add(aFromShell, aFromShape);
+ aBoundingBuilder.MakeSolid(aToSolid);
+ aBoundingBuilder.Add(aToSolid, aToShell);
+ aBoundingBuilder.MakeSolid(aFromSolid);
+ aBoundingBuilder.Add(aFromSolid, aFromShell);
+
+ // Cutting with to plane.
+ BRepAlgoAPI_Cut* aToCutBuilder = new BRepAlgoAPI_Cut(aResult, aToSolid);
+ aToCutBuilder->Build();
+ if(!aToCutBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ new GeomAlgoAPI_MakeShape(aToCutBuilder)));
+ aResult = aToCutBuilder->Shape();
+ if(aResult.ShapeType() == TopAbs_COMPOUND) {
+ aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+ }
+ if (theTypeToExp == GeomAPI_Shape::FACE || theTypeToExp == GeomAPI_Shape::COMPOUND) {
+ const TopTools_ListOfShape& aToShapes = aToCutBuilder->Modified(aToShape);
+ for(TopTools_ListIteratorOfListOfShape anIt(aToShapes); anIt.More(); anIt.Next()) {
+ GeomShapePtr aGeomSh = toShape(anIt.Value());
+ fixOrientation(aGeomSh);
+ this->addToShape(aGeomSh);
}
+ }
- if(aResult.ShapeType() == TopAbs_COMPOUND) {
- std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
- aGeomShape->setImpl(new TopoDS_Shape(aResult));
- ListOfShape aResults;
- aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
- GeomAPI_Shape::COMPSOLID,
- aResults);
- aResult = aGeomShape->impl<TopoDS_Shape>();
+ // Cutting with from plane.
+ BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aResult, aFromSolid);
+ aFromCutBuilder->Build();
+ if(!aFromCutBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ new GeomAlgoAPI_MakeShape(aFromCutBuilder)));
+ aResult = aFromCutBuilder->Shape();
+ TopoDS_Iterator aCheckIt(aResult);
+ if(!aCheckIt.More()) {
+ return;
+ }
+ if(aResult.ShapeType() == TopAbs_COMPOUND) {
+ aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+ }
+ if (theTypeToExp == GeomAPI_Shape::FACE || theTypeToExp == GeomAPI_Shape::COMPOUND) {
+ const TopTools_ListOfShape& aFromShapes = aFromCutBuilder->Modified(aFromShape);
+ for(TopTools_ListIteratorOfListOfShape anIt(aFromShapes); anIt.More(); anIt.Next()) {
+ GeomShapePtr aGeomSh = toShape(anIt.Value());
+ fixOrientation(aGeomSh);
+ this->addFromShape(aGeomSh);
}
}
+ // Naming for extrusion from vertex, edge.
+ if(theTypeToExp == GeomAPI_Shape::COMPOUND) {
+ storeGenerationHistory(this, aResult, TopAbs_EDGE, aToFace, aFromFace);
+ storeGenerationHistory(this, aResult, TopAbs_FACE, aToFace, aFromFace);
+ } else {
+ storeGenerationHistory(this, aResult, (TopAbs_ShapeEnum)theTypeToExp, aToFace, aFromFace);
+ }
+
+ if(aResult.ShapeType() == TopAbs_COMPOUND) {
+ GeomShapePtr aGeomShape = toShape(aResult);
+ ListOfShape aResults;
+ aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
+ GeomAPI_Shape::COMPSOLID,
+ aResults);
+ aResult = aGeomShape->impl<TopoDS_Shape>();
+ }
+
// Setting result.
if (!aResult.IsNull()) {
aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
- GeomShapePtr aGeomSh(new GeomAPI_Shape());
- aGeomSh->setImpl(new TopoDS_Shape(aResult));
- this->setShape(aGeomSh);
+ this->setShape(toShape(aResult));
this->setDone(true);
}
}
+//==================================================================================================
+void GeomAlgoAPI_Prism::buildByFaces(const GeomShapePtr theBaseShape,
+ const GeomDirPtr theDirection,
+ const GeomShapePtr theToShape,
+ const double theToSize,
+ const bool theToIsPlanar,
+ const GeomShapePtr theFromShape,
+ const double theFromSize,
+ const bool theFromIsPlanar,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
+{
+ const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
+ gp_Vec anExtVec = theDirection->impl<gp_Dir>();
+
+ // Moving prism bounding faces according to "from" and "to" sizes.
+ GeomShapePtr aBoundingFromShape = buildOffset(theFromShape, theFromSize, theDirection, *this);
+ GeomShapePtr aBoundingToShape = buildOffset(theToShape, theToSize, theDirection, *this);
+
+ // Bounding box for shapes used in prism building.
+ Bnd_Box aBndBox;
+ BRepBndLib::Add(aBaseShape, aBndBox);
+ BRepBndLib::Add(aBoundingFromShape->impl<TopoDS_Shape>(), aBndBox);
+ BRepBndLib::Add(aBoundingToShape->impl<TopoDS_Shape>(), aBndBox);
+ double aPrismLength = 2.0 * aBndBox.CornerMin().Distance(aBndBox.CornerMax());
+
+ // Prism building.
+ gp_Trsf aTrsf;
+ aTrsf.SetTranslation(anExtVec * -aPrismLength);
+ BRepBuilderAPI_Transform* aTransformBuilder = new BRepBuilderAPI_Transform(aBaseShape, aTrsf);
+ if (!aTransformBuilder || !aTransformBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ new GeomAlgoAPI_MakeShape(aTransformBuilder)));
+ TopoDS_Shape aMovedBase = aTransformBuilder->Shape();
+
+ // Making prism.
+ BRepPrimAPI_MakePrism* aPrismBuilder =
+ new BRepPrimAPI_MakePrism(aMovedBase, anExtVec * 2 * aPrismLength);
+ if (!aPrismBuilder || !aPrismBuilder->IsDone()) {
+ return;
+ }
+ this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
+ new GeomAlgoAPI_MakeShape(aPrismBuilder)));
+
+ GeomShapePtr aResult = toShape(aPrismBuilder->Shape());
+
+ // Prism generatrix
+ ListOfShape aPrismBaseFaces;
+ collectPrismBases(aMovedBase, *aPrismBuilder, aPrismBaseFaces, theTypeToExp);
+
+ // Build planar faces intersecting the prism fully.
+ BRepBndLib::Add(aResult->impl<TopoDS_Shape>(), aBndBox);
+ aBoundingFromShape = buildPlanarFace(aBoundingFromShape, aBndBox);
+ aBoundingToShape = buildPlanarFace(aBoundingToShape, aBndBox);
+
+ // Perform partition.
+ ListOfShape anObjects, aTools;
+ anObjects.push_back(aResult);
+ aTools.push_back(aBoundingFromShape);
+ aTools.push_back(aBoundingToShape);
+
+ GeomMakeShapePtr aPartition(new GeomAlgoAPI_Partition(anObjects, aTools));
+ if (!aPartition->isDone())
+ return;
+
+ this->appendAlgo(aPartition);
+
+ // Collect pieces of boundary shapes, split by Partition.
+ if (theFromIsPlanar) {
+ ListOfShape anImagesFrom;
+ aPartition->modified(aBoundingFromShape, anImagesFrom);
+ for (ListOfShape::iterator anIt = anImagesFrom.begin(); anIt != anImagesFrom.end(); ++anIt)
+ addFromShape(*anIt);
+ }
+
+ if (theToIsPlanar) {
+ ListOfShape anImagesTo;
+ aPartition->modified(aBoundingToShape, anImagesTo);
+ for (ListOfShape::iterator anIt = anImagesTo.begin(); anIt != anImagesTo.end(); ++anIt)
+ addToShape(*anIt);
+ }
+
+ // Collect results which have both boundaries, selected for extrusion,
+ // but which do not contain top and bottom faces of the prism
+ // (these faces are treated as infinitely distant).
+ aResult = collectResults(aPartition, aTools, aPrismBaseFaces, theTypeToExp);
+ if (aResult && aResult->shapeType() == GeomAPI_Shape::COMPOUND) {
+ ListOfShape aResults;
+ aResult = GeomAlgoAPI_ShapeTools::combineShapes(aResult,
+ theTypeToExp == GeomAPI_Shape::EDGE ? GeomAPI_Shape::SHELL : GeomAPI_Shape::COMPSOLID,
+ aResults);
+
+ if (aResults.size() > 1 &&
+ (GeomAlgoAPI_ShapeTools::hasSharedTopology(aResults, GeomAPI_Shape::EDGE) ||
+ GeomAlgoAPI_ShapeTools::hasSharedTopology(aResults, GeomAPI_Shape::VERTEX))) {
+ // results shuold not have shared topology
+ aResult = GeomShapePtr();
+ }
+ }
+
+ if (aResult) {
+ this->setShape(aResult);
+ this->setDone(true);
+ }
+}
+
+
// Auxilary functions:
+//==================================================================================================
+GeomShapePtr buildPlanarFace(const GeomShapePtr& theOriginalShape,
+ const Bnd_Box& theBaseShapeBB)
+{
+ GeomPlanePtr aPlane = GeomAPI_Face(theOriginalShape).getPlane();
+ if (!aPlane)
+ return theOriginalShape;
+
+ gp_Pnt aCornerMin = theBaseShapeBB.CornerMin();
+ gp_Pnt aCornerMax = theBaseShapeBB.CornerMax();
+ double aSize = aCornerMin.SquareDistance(aCornerMax);
+
+ gp_Pnt aLocation = aPlane->location()->impl<gp_Pnt>();
+
+ gp_Pnt aCurPnt;
+ for (int x = 0; x < 2; ++x) {
+ aCurPnt.SetX(x == 0 ? aCornerMin.X() : aCornerMax.X());
+ for (int y = 0; y < 2; ++y) {
+ aCurPnt.SetY(y == 0 ? aCornerMin.Y() : aCornerMax.Y());
+ for (int z = 0; z < 2; ++z) {
+ aCurPnt.SetZ(z == 0 ? aCornerMin.Z() : aCornerMax.Z());
+ double aDist = aCurPnt.SquareDistance(aLocation);
+ if (aDist > aSize)
+ aSize = aDist;
+ }
+ }
+ }
+
+ aSize = Sqrt(aSize);
+ return GeomAlgoAPI_FaceBuilder::squareFace(aPlane, 2.0 * aSize);
+}
+
+//==================================================================================================
+GeomShapePtr buildOffset(const GeomShapePtr& theShape,
+ const double theOffset,
+ const GeomDirPtr theDirection,
+ GeomAlgoAPI_MakeShapeList& theMakeShapeList)
+{
+ if (Abs(theOffset) < Precision::Confusion())
+ return theShape; // no need zero offset
+
+ GeomMakeShapePtr anAlgo(new GeomAlgoAPI_Offset(theShape, theOffset));
+ if (!anAlgo->isDone()) {
+ // offset not done, perform translation
+ std::shared_ptr<GeomAPI_Ax1> anAxis(new GeomAPI_Ax1());
+ anAxis->setDir(theDirection);
+ anAlgo.reset(new GeomAlgoAPI_Translation(theShape, anAxis, theOffset));
+ }
+
+ GeomShapePtr aResult = theShape;
+ if (anAlgo->isDone()) {
+ theMakeShapeList.appendAlgo(anAlgo);
+ aResult = anAlgo->shape();
+ }
+ return aResult;
+}
+
+//==================================================================================================
+void collectPrismBases(const TopoDS_Shape& theBaseShape,
+ BRepPrimAPI_MakePrism& thePrismAlgo,
+ ListOfShape& theBoundaries,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
+{
+ for (TopExp_Explorer anExp(theBaseShape, (TopAbs_ShapeEnum)theTypeToExp);
+ anExp.More(); anExp.Next()) {
+ theBoundaries.push_back(toShape(thePrismAlgo.FirstShape(anExp.Current())));
+ theBoundaries.push_back(toShape(thePrismAlgo.LastShape(anExp.Current())));
+ }
+}
+
+//==================================================================================================
+typedef std::set<GeomShapePtr, GeomAPI_Shape::Comparator> SetOfShape;
+
+bool isShapeApplicable(const GeomShapePtr& theSolid,
+ const std::list<ListOfShape>& theShapesToExist,
+ const SetOfShape& theShapesToExclude,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
+{
+ SetOfShape aFaces;
+ for (GeomAPI_ShapeExplorer aFExp(theSolid, theTypeToExp);
+ aFExp.more(); aFExp.next()) {
+ GeomShapePtr aCurrent = aFExp.current();
+ if (theShapesToExclude.find(aCurrent) != theShapesToExclude.end())
+ return false;
+ aFaces.insert(aCurrent);
+ }
+
+ // check all faces are in solid
+ bool isApplicable = true;
+ for (std::list<ListOfShape>::const_iterator it1 = theShapesToExist.begin();
+ it1 != theShapesToExist.end() && isApplicable; ++it1) {
+ ListOfShape::const_iterator it2 = it1->begin();
+ for (; it2 != it1->end(); ++it2)
+ if (aFaces.find(*it2) != aFaces.end())
+ break;
+ isApplicable = it2 != it1->end();
+ }
+ return isApplicable;
+}
+
+void collectModified(const GeomMakeShapePtr& theOperation,
+ const ListOfShape& theShapes,
+ std::list<ListOfShape>& theModified)
+{
+ for (ListOfShape::const_iterator anIt = theShapes.begin();
+ anIt != theShapes.end(); ++anIt) {
+ theModified.push_back(ListOfShape());
+ theOperation->modified(*anIt, theModified.back());
+ theOperation->generated(*anIt, theModified.back());
+ theModified.back().push_back(*anIt);
+ }
+}
+
+GeomShapePtr collectResults(const GeomMakeShapePtr& theOperation,
+ const ListOfShape& theBoundaries,
+ const ListOfShape& theShapesToExclude,
+ const GeomAPI_Shape::ShapeType theTypeToExp)
+{
+ ListOfShape aResults;
+
+ // collect modified shapes
+ std::list<ListOfShape> aModifiedBoundaries;
+ collectModified(theOperation, theBoundaries, aModifiedBoundaries);
+
+ std::list<ListOfShape> aModifiedExclude;
+ collectModified(theOperation, theShapesToExclude, aModifiedExclude);
+ SetOfShape aTabooShapes;
+ for (std::list<ListOfShape>::iterator anIt = aModifiedExclude.begin();
+ anIt != aModifiedExclude.end(); ++anIt)
+ aTabooShapes.insert(anIt->begin(), anIt->end());
+
+ // type of sub-shapes to explode
+ GeomAPI_Shape::ShapeType aSubshapeType;
+ switch (theTypeToExp) {
+ case GeomAPI_Shape::VERTEX:
+ aSubshapeType = GeomAPI_Shape::EDGE;
+ break;
+ case GeomAPI_Shape::EDGE:
+ aSubshapeType = GeomAPI_Shape::FACE;
+ break;
+ case GeomAPI_Shape::FACE:
+ aSubshapeType = GeomAPI_Shape::SOLID;
+ break;
+ default:
+ aSubshapeType = GeomAPI_Shape::COMPOUND;
+ }
+
+ // search applicable solids
+ GeomShapePtr anOperationResult = theOperation->shape();
+ for (GeomAPI_ShapeExplorer anExp(anOperationResult, aSubshapeType);
+ anExp.more(); anExp.next()) {
+ if (isShapeApplicable(anExp.current(), aModifiedBoundaries, aTabooShapes, theTypeToExp))
+ aResults.push_back(anExp.current());
+ }
+
+ GeomShapePtr aResult;
+ if (aResults.size() == 1)
+ aResult = aResults.front();
+ else if (!aResults.empty())
+ aResult = GeomAlgoAPI_CompoundBuilder::compound(aResults);
+ return aResult;
+}
+
//==================================================================================================
void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
const TopoDS_Shape& theBase,
#ifndef GeomAlgoAPI_Prism_H_
#define GeomAlgoAPI_Prism_H_
-#include "GeomAlgoAPI.h"
-
#include "GeomAlgoAPI_MakeSweep.h"
-#include <GeomAPI_Dir.h>
#include <GeomAPI_Shape.h>
#include <memory>
+class GeomAPI_Dir;
+class GeomAPI_Pln;
+
/// \class GeomAlgoAPI_Prism
/// \ingroup DataAlgo
/// \brief Allows to create the prism based on a given face and bounding planes.
const double theFromSize);
private:
- /// Builds resulting shape.
- void build(const GeomShapePtr& theBaseShape,
- const std::shared_ptr<GeomAPI_Dir> theDirection,
- const GeomShapePtr& theToShape,
- const double theToSize,
- const GeomShapePtr& theFromShape,
- const double theFromSize);
+ /// Build extrusion by distances from the base shape.
+ void buildBySizes(const GeomShapePtr theBaseShape,
+ const std::shared_ptr<GeomAPI_Dir> theDirection,
+ const double theToSize,
+ const double theFromSize,
+ const GeomAPI_Shape::ShapeType theTypeToExp);
+
+ /// Build extrusion from plane to plane.
+ void buildByPlanes(const GeomShapePtr theBaseShape,
+ const std::shared_ptr<GeomAPI_Dir> theDirection,
+ const std::shared_ptr<GeomAPI_Pln> theToPlane,
+ const double theToSize,
+ const std::shared_ptr<GeomAPI_Pln> theFromPlane,
+ const double theFromSize,
+ const GeomAPI_Shape::ShapeType theTypeToExp);
+
+ /// Build extrusion from face to face.
+ void buildByFaces(const GeomShapePtr theBaseShape,
+ const std::shared_ptr<GeomAPI_Dir> theDirection,
+ const GeomShapePtr theToShape,
+ const double theToSize,
+ const bool theToIsPlanar,
+ const GeomShapePtr theFromShape,
+ const double theFromSize,
+ const bool theFromIsPlanar,
+ const GeomAPI_Shape::ShapeType theTypeToExp);
};
#endif
return aResult;
}
+//==================================================================================================
+bool GeomAlgoAPI_ShapeTools::hasSharedTopology(const ListOfShape& theShapes,
+ const GeomAPI_Shape::ShapeType theShapeType)
+{
+ TopTools_IndexedMapOfShape aSubs;
+ for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt) {
+ TopTools_IndexedMapOfShape aCurSubs;
+ TopExp::MapShapes((*anIt)->impl<TopoDS_Shape>(), (TopAbs_ShapeEnum)theShapeType, aCurSubs);
+ for (TopTools_IndexedMapOfShape::Iterator aSubIt(aCurSubs); aSubIt.More(); aSubIt.Next()) {
+ if (aSubs.Contains(aSubIt.Value()))
+ return true;
+ else
+ aSubs.Add(aSubIt.Value());
+ }
+ }
+ return false;
+}
+
//==================================================================================================
std::list<std::shared_ptr<GeomAPI_Pnt> >
GeomAlgoAPI_ShapeTools::getBoundingBox(const ListOfShape& theShapes, const double theEnlarge)
GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Shape>
groupSharedTopology(const std::shared_ptr<GeomAPI_Shape> theCompound);
+ /// \brief Check group of shapes has shared sub-shapes of the given type
+ /// \param[in] theShapes list of shapes
+ /// \param[in] theShapeType type of sub-shapes to check
+ /// \return \c true if shared topology exists
+ GEOMALGOAPI_EXPORT static bool hasSharedTopology(const ListOfShape& theShapes,
+ const GeomAPI_Shape::ShapeType theShapeType);
+
/// \brief Calculates bounding box for theShapes
/// \return list of eight points.
/// \param[in] theShapes list of shapes.