X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FFeaturesPlugin%2FFeaturesPlugin_BooleanFuse.cpp;h=1214bb2147d2c0ffdf712727fb27c44dc5e20313;hb=744aa075cb2f3e7033c82ec28538c6e868878b37;hp=84df36d061a8ef547e4d8daed7d064d5ee205a78;hpb=1c211701f7bcc21ef86892d889d7c58e9b276adb;p=modules%2Fshaper.git diff --git a/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp b/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp index 84df36d06..1214bb214 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_BooleanFuse.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2019 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,7 +41,21 @@ #include #include -static const int THE_FUSE_VERSION_1 = 20190506; +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() @@ -62,23 +76,14 @@ void FeaturesPlugin_BooleanFuse::initAttributes() ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), OBJECT_LIST_ID()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID()); - AttributePtr aVerAttr = data()->addAttribute(VERSION_ID(), ModelAPI_AttributeInteger::typeId()); - aVerAttr->setIsArgument(false); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), VERSION_ID()); - if (!integer(VERSION_ID())->isInitialized() && - !selectionList(OBJECT_LIST_ID())->isInitialized() && - !selectionList(TOOL_LIST_ID())->isInitialized()) { - // this is a newly created feature (not read from file), - // so, initialize the latest version - integer(VERSION_ID())->setValue(THE_FUSE_VERSION_1); - } + initVersion(BOP_VERSION_9_4(), selectionList(OBJECT_LIST_ID()), selectionList(TOOL_LIST_ID())); } //================================================================================================== void FeaturesPlugin_BooleanFuse::execute() { std::string anError; - ObjectHierarchy anObjectsHierarchy, aToolsHierarchy; + GeomAPI_ShapeHierarchy anObjectsHierarchy, aToolsHierarchy; ListOfShape aPlanes; bool isSimpleCreation = false; @@ -101,9 +106,9 @@ void FeaturesPlugin_BooleanFuse::execute() ListOfShape anObjects, aTools, anEdgesAndFaces; // all objects except edges and faces - anObjectsHierarchy.ObjectsByType(anEdgesAndFaces, anObjects, + anObjectsHierarchy.objectsByType(anEdgesAndFaces, anObjects, GeomAPI_Shape::FACE, GeomAPI_Shape::EDGE); - aToolsHierarchy.ObjectsByType(anEdgesAndFaces, aTools, + aToolsHierarchy.objectsByType(anEdgesAndFaces, aTools, GeomAPI_Shape::FACE, GeomAPI_Shape::EDGE); if ((anObjects.size() + aTools.size() + anEdgesAndFaces.size()) < 2) { @@ -113,31 +118,42 @@ void FeaturesPlugin_BooleanFuse::execute() } // version of FUSE feature - int aFuseVersion = version(); + 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; - for (ObjectHierarchy::Iterator anObjectsIt = anObjectsHierarchy.Begin(); - !isSimpleCreation && anObjectsIt != anObjectsHierarchy.End(); + 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) { GeomShapePtr anObject = *anObjectsIt; - GeomShapePtr aParent = anObjectsHierarchy.Parent(anObject, false); + 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); + aParent = anObjectsHierarchy.parent(anObject); ListOfShape aUsed, aNotUsed; - anObjectsHierarchy.SplitCompound(aParent, aUsed, aNotUsed); + 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()); @@ -153,11 +169,14 @@ void FeaturesPlugin_BooleanFuse::execute() aMakeShapeList->appendAlgo(aCutAlgo); } } - anOriginalShapes.insert(anOriginalShapes.end(), anEdgesAndFaces.begin(), - anEdgesAndFaces.end()); + + if (aShapesToAdd.empty() || !aCuttedEdgesAndFaces) { + anOriginalShapes.insert(anOriginalShapes.end(), anEdgesAndFaces.begin(), + anEdgesAndFaces.end()); + } // 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++) { @@ -166,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); } @@ -241,7 +260,7 @@ void FeaturesPlugin_BooleanFuse::execute() aMakeShapeList->appendAlgo(aUnifyAlgo); } - if (aFuseVersion == THE_FUSE_VERSION_1) { + if (aFuseVersion == BOP_VERSION_9_4()) { // merge hierarchies of compounds containing objects and tools // and append the result of the FUSE operation aShape = keepUnusedSubsOfCompound(aShape, anObjectsHierarchy, aToolsHierarchy, aMakeShapeList);