X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FFeaturesPlugin%2FFeaturesPlugin_BooleanFuse.cpp;h=1214bb2147d2c0ffdf712727fb27c44dc5e20313;hb=744aa075cb2f3e7033c82ec28538c6e868878b37;hp=2eb87085dc165d7e1a546ac460e6ab615f3139ca;hpb=50a8df0c6a66da8067b16155e5ae39f8f26a7ebc;p=modules%2Fshaper.git diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp b/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp index 2eb87085d..1214bb214 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2020 CEA/DEN, EDF R&D +// Copyright (C) 2014-2021 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 @@ -41,6 +41,22 @@ #include #include +static void explodeCompound(const GeomShapePtr& theShape, ListOfShape& theResult) +{ + if (theShape->shapeType() == GeomAPI_Shape::COMPOUND) { + GeomAPI_ShapeIterator it(theShape); + for (; it.more(); it.next()) + theResult.push_back(it.current()); + } else + theResult.push_back(theShape); +} + +static void collectSolids(const ListOfShape& theShapes, ListOfShape& theResult) +{ + for (ListOfShape::const_iterator it = theShapes.begin(); it != theShapes.end(); ++it) + explodeCompound(*it, theResult); +} + //================================================================================================== FeaturesPlugin_BooleanFuse::FeaturesPlugin_BooleanFuse() : FeaturesPlugin_Boolean(FeaturesPlugin_Boolean::BOOL_FUSE) @@ -105,14 +121,20 @@ void FeaturesPlugin_BooleanFuse::execute() const std::string aFuseVersion = data()->version(); // Collecting all solids which will be fused. + // We explode the top-level compounds here because of issue #19931. It performs Fuse operation + // on a set of compounds, one of which is treated as self-intersected. + // But this problem is eliminated after the exploding, because in this case, + // the shapes are intersected, but not self-intersected. ListOfShape aSolidsToFuse; - aSolidsToFuse.insert(aSolidsToFuse.end(), anObjects.begin(), anObjects.end()); - aSolidsToFuse.insert(aSolidsToFuse.end(), aTools.begin(), aTools.end()); + collectSolids(anObjects, aSolidsToFuse); + collectSolids(aTools, aSolidsToFuse); // Collecting solids from compsolids which will not be modified // in boolean operation and will be added to result. bool isProcessCompsolid = !isSimpleCreation || !aFuseVersion.empty(); ListOfShape aShapesToAdd; + int aNbCompsolids = 0; // number of compsolids, which subs is taken into operation + bool hasSeparateSolids = false; // are solids or full results exist for (GeomAPI_ShapeHierarchy::iterator anObjectsIt = anObjectsHierarchy.begin(); isProcessCompsolid && anObjectsIt != anObjectsHierarchy.end(); ++anObjectsIt) { @@ -120,6 +142,7 @@ void FeaturesPlugin_BooleanFuse::execute() GeomShapePtr aParent = anObjectsHierarchy.parent(anObject, false); if (aParent && aParent->shapeType() == GeomAPI_Shape::COMPSOLID) { + ++aNbCompsolids; // mark all subs of this parent as precessed to avoid handling twice aParent = anObjectsHierarchy.parent(anObject); @@ -127,7 +150,10 @@ void FeaturesPlugin_BooleanFuse::execute() anObjectsHierarchy.splitCompound(aParent, aUsed, aNotUsed); aShapesToAdd.insert(aShapesToAdd.end(), aNotUsed.begin(), aNotUsed.end()); } + else + hasSeparateSolids = true; } + bool isSingleCompsolid = aNbCompsolids == 1 && !hasSeparateSolids; ListOfShape anOriginalShapes = aSolidsToFuse; anOriginalShapes.insert(anOriginalShapes.end(), aShapesToAdd.begin(), aShapesToAdd.end()); @@ -150,7 +176,7 @@ void FeaturesPlugin_BooleanFuse::execute() } // If we have compsolids then cut with not used solids all others. - if (!aShapesToAdd.empty()) { + if (!aShapesToAdd.empty() && !isSingleCompsolid) { aSolidsToFuse.clear(); for (ListOfShape::iterator anIt = anOriginalShapes.begin(); anIt != anOriginalShapes.end(); anIt++) { @@ -159,7 +185,7 @@ void FeaturesPlugin_BooleanFuse::execute() std::shared_ptr aCutAlgo( new GeomAlgoAPI_Boolean(aOneObjectList, aShapesToAdd, GeomAlgoAPI_Tools::BOOL_CUT)); - if (GeomAlgoAPI_ShapeTools::volume(aCutAlgo->shape()) > 1.e-27) { + if (GeomAlgoAPI_ShapeTools::area(aCutAlgo->shape()) > 1.e-27) { aSolidsToFuse.push_back(aCutAlgo->shape()); aMakeShapeList->appendAlgo(aCutAlgo); }