+//=================================================================================================
+bool FeaturesPlugin_CompositeBoolean::cutRecursiveCompound(const GeomShapePtr theCompound,
+ const ListOfShape& theTools,
+ std::shared_ptr<GeomAlgoAPI_MakeShapeList>& theMakeShapeList,
+ GeomShapePtr& theResult)
+{
+ // I. If theCompound is among the selected objects,
+ // cut it by all tools and return result through theResult.
+ // It can be a SOLID, ?COMPOUND?, ?COMPSOLID?
+ AttributeSelectionListPtr anObjectsSelList = myFeature->selectionList(OBJECTS_ID());
+ for (int anObjIndex = 0; anObjIndex < anObjectsSelList->size(); anObjIndex++) {
+ AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjIndex);
+ GeomShapePtr anObject = anObjectAttr->value();
+ if (theCompound->isEqual(anObject)) {
+ // Cut theCompound itself
+ ListOfShape aListWithObject;
+ aListWithObject.push_back(anObject);
+ std::shared_ptr<GeomAlgoAPI_Boolean> aBoolAlgo
+ (new GeomAlgoAPI_Boolean(aListWithObject, theTools, GeomAlgoAPI_Tools::BOOL_CUT));
+
+ // Checking that the algorithm worked properly.
+ if (!aBoolAlgo->isDone() || aBoolAlgo->shape()->isNull() || !aBoolAlgo->isValid()) {
+ myFeature->setError("Error: Boolean algorithm failed.");
+ return false;
+ }
+
+ if (GeomAlgoAPI_ShapeTools::area(aBoolAlgo->shape()) > 1.e-27) {
+ theMakeShapeList->appendAlgo(aBoolAlgo);
+ theResult = aBoolAlgo->shape();
+ return true;
+ }
+ return false;
+ }
+ }
+
+ // II. Iterate the COMPOUND or COMPSOLID
+ // to find and cut Objects among its sub-shapes
+ if (theCompound->shapeType() == GeomAPI_Shape::COMPOUND ||
+ theCompound->shapeType() == GeomAPI_Shape::COMPSOLID) {
+
+ bool hasCut = false;
+ ListOfShape aShapesToAdd;
+ for (GeomAPI_ShapeIterator it (theCompound); it.more(); it.next()) {
+ GeomShapePtr aSubShape = it.current();
+ GeomShapePtr aResult;
+ if (cutRecursiveCompound(aSubShape, theTools, theMakeShapeList, aResult)) {
+ hasCut = true;
+ aShapesToAdd.push_back(aResult);
+ }
+ else {
+ aShapesToAdd.push_back(aSubShape);
+ }
+ }
+
+ if (hasCut) {
+ if (theCompound->shapeType() == GeomAPI_Shape::COMPSOLID) {
+ // Build COMPSOLID
+ std::shared_ptr<GeomAlgoAPI_PaveFiller> aFillerAlgo
+ (new GeomAlgoAPI_PaveFiller(aShapesToAdd, true));
+ if (!aFillerAlgo->isDone() || aFillerAlgo->shape()->isNull() || !aFillerAlgo->isValid()) {
+ myFeature->setError("Error: PaveFiller algorithm failed.");
+ return false;
+ }
+ theResult = aFillerAlgo->shape();
+ theMakeShapeList->appendAlgo(aFillerAlgo);
+ }
+ else {
+ // Build COMPOUND
+ theResult = GeomAlgoAPI_CompoundBuilder::compound(aShapesToAdd);
+ std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aCompMkr (new GeomAlgoAPI_MakeShapeCustom);
+ aCompMkr->setResult(theResult);
+ aCompMkr->addModified(theCompound, theResult); // ??
+ theMakeShapeList->appendAlgo(aCompMkr);
+ }
+ return true;
+ }
+ }
+
+ return false; // no cuts
+}
+
+//=================================================================================================
+void FeaturesPlugin_CompositeBoolean::addSubShapes (const GeomShapePtr theCompound,
+ const ListOfShape& theSubShapesToAvoid,
+ ListOfShape& theSubShapesToAdd) {
+ for (GeomAPI_ShapeIterator aCompoundIt (theCompound);
+ aCompoundIt.more();
+ aCompoundIt.next()) {
+ GeomShapePtr aCompoundSS = aCompoundIt.current();
+ ListOfShape::const_iterator aUseIt = theSubShapesToAvoid.cbegin();
+ for (; aUseIt != theSubShapesToAvoid.cend(); aUseIt++) {
+ if (aCompoundSS->isEqual(*aUseIt)) {
+ break;
+ }
+ }
+ if (aUseIt == theSubShapesToAvoid.cend()) {
+ if (aCompoundSS->shapeType() == GeomAPI_Shape::COMPSOLID ||
+ aCompoundSS->shapeType() == GeomAPI_Shape::COMPOUND) {
+ addSubShapes(aCompoundSS, theSubShapesToAvoid, theSubShapesToAdd);
+ }
+ else {
+ theSubShapesToAdd.push_back(aCompoundSS);
+ }
+ }
+ }
+}
+