X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FFeaturesPlugin%2FFeaturesPlugin_Union.cpp;h=ad7a638de10fa2e6effa1ff9bb2e8f63a78fbc58;hb=b392d5b4fb3f49a8258ec024cdf1729f80f5629a;hp=8daf2723ebffce8d911fc102d76ce377dbc04156;hpb=1ca6bc647dcecfbd22beb5c8991f06545bf7614e;p=modules%2Fshaper.git diff --git a/src/FeaturesPlugin/FeaturesPlugin_Union.cpp b/src/FeaturesPlugin/FeaturesPlugin_Union.cpp index 8daf2723e..ad7a638de 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Union.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Union.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 @@ -20,10 +20,11 @@ #include "FeaturesPlugin_Union.h" #include +#include #include #include +#include #include -#include #include #include @@ -41,124 +42,91 @@ FeaturesPlugin_Union::FeaturesPlugin_Union() void FeaturesPlugin_Union::initAttributes() { data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); + initVersion(BOP_VERSION_9_4(), selectionList(BASE_OBJECTS_ID())); } //================================================================================================= void FeaturesPlugin_Union::execute() { - ListOfShape anObjects; - std::map, ListOfShape> aCompSolidsObjects; + GeomAPI_ShapeHierarchy anObjects; + ListOfShape anEmptyList; // Getting objects. - AttributeSelectionListPtr anObjectsSelList = - selectionList(FeaturesPlugin_Union::BASE_OBJECTS_ID()); - for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) { - AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex); - std::shared_ptr anObject = anObjectAttr->value(); - if(!anObject.get()) { - return; - } - ResultPtr aContext = anObjectAttr->context(); - ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext); - if(aResCompSolidPtr.get()) { - std::shared_ptr aContextShape = aResCompSolidPtr->shape(); - std::map, ListOfShape>::iterator - anIt = aCompSolidsObjects.begin(); - for(; anIt != aCompSolidsObjects.end(); anIt++) { - if(anIt->first->isEqual(aContextShape)) { - aCompSolidsObjects[anIt->first].push_back(anObject); - break; - } - } - if(anIt == aCompSolidsObjects.end()) { - aCompSolidsObjects[aContextShape].push_back(anObject); - } - } else { - anObjects.push_back(anObject); - } - } - - // Collecting solids from compsolids which will not be modified in - // boolean operation and will be added to result. - ListOfShape aShapesToAdd; - for(std::map, ListOfShape>::iterator - anIt = aCompSolidsObjects.begin(); - anIt != aCompSolidsObjects.end(); anIt++) { - std::shared_ptr aCompSolid = anIt->first; - ListOfShape& aUsedInOperationSolids = anIt->second; - anObjects.insert(anObjects.end(), aUsedInOperationSolids.begin(), aUsedInOperationSolids.end()); - - // Collect solids from compsolid which will not be modified in boolean operation. - for(GeomAPI_ShapeIterator anExp(aCompSolid); anExp.more(); anExp.next()) { - std::shared_ptr aSolidInCompSolid = anExp.current(); - ListOfShape::iterator anIt = aUsedInOperationSolids.begin(); - for(; anIt != aUsedInOperationSolids.end(); anIt++) { - if(aSolidInCompSolid->isEqual(*anIt)) { - break; - } - } - if(anIt == aUsedInOperationSolids.end()) { - aShapesToAdd.push_back(aSolidInCompSolid); - } - } - } + if (!processAttribute(BASE_OBJECTS_ID(), anObjects, anEmptyList)) + return; - if(anObjects.size() < 2) { + if(anObjects.objects().size() < 2) { setError("Error: Not enough objects for operation. Should be at least 2."); return; } - // Fuse objects. std::string anError; - std::shared_ptr anAlgo; - ListOfShape aTools; - if (anObjects.front()->shapeType() == GeomAPI_Shape::SOLID) { - aTools.splice(aTools.begin(), anObjects, anObjects.begin()); - anAlgo.reset(new GeomAlgoAPI_Boolean(anObjects, - aTools, - GeomAlgoAPI_Tools::BOOL_FUSE)); - } else { - anAlgo.reset(new GeomAlgoAPI_UnifySameDomain(anObjects)); + int aResultIndex = 0; + std::vector aResultBaseAlgoList; + ListOfShape aResultShapesList; + + GeomShapePtr aResultCompound = GeomAlgoAPI_CompoundBuilder::compound(ListOfShape()); + + // Fuse objects. + bool isOk = true; + for (GeomAPI_ShapeHierarchy::iterator anObjectsIt = anObjects.begin(); + anObjectsIt != anObjects.end() && isOk; + ++anObjectsIt) { + GeomShapePtr anObject = *anObjectsIt; + GeomShapePtr aParent = anObjects.parent(anObject, false); + + if (aParent && aParent->shapeType() <= GeomAPI_Shape::COMPSOLID) { + // get parent once again to mark it and the subs as processed + aParent = anObjects.parent(anObject); + // compsolid handling + isOk = processCompsolid(GeomAlgoAPI_Tools::BOOL_FUSE, + anObjects, aParent, anEmptyList, anEmptyList, + aResultIndex, aResultBaseAlgoList, aResultShapesList, + aResultCompound); + } else { + // process object as is + isOk = processObject(GeomAlgoAPI_Tools::BOOL_FUSE, + anObject, anEmptyList, anEmptyList, + aResultIndex, aResultBaseAlgoList, aResultShapesList, + aResultCompound); + } } - // Checking that the algorithm worked properly. std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); - GeomAPI_DataMapOfShapeShape aMapOfShapes; - if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(anAlgo, getKind(), anError)) { - setError(anError); - return; + for (std::vector::iterator + aRBAIt = aResultBaseAlgoList.begin(); + aRBAIt != aResultBaseAlgoList.end(); ++aRBAIt) { + aMakeShapeList->appendAlgo(aRBAIt->makeShape); } - GeomShapePtr aShape = anAlgo->shape(); - aMakeShapeList->appendAlgo(anAlgo); - aMapOfShapes.merge(anAlgo->mapOfSubShapes()); - - // Store original shapes for naming. - anObjects.splice(anObjects.begin(), aTools); - anObjects.insert(anObjects.end(), aShapesToAdd.begin(), aShapesToAdd.end()); - - // Combine result with not used solids from compsolid. - if(aShapesToAdd.size() > 0) { - aShapesToAdd.push_back(aShape); - std::shared_ptr aFillerAlgo( - new GeomAlgoAPI_PaveFiller(aShapesToAdd, true)); - if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aFillerAlgo, getKind(), anError)) { - setError(anError); - return; + GeomShapePtr aShape; + GeomAPI_ShapeIterator aCIt(aResultCompound); + if (data()->version().empty()) { + // if the compound consists of a single sub-shape, take it, + // otherwise, take the full compound + aShape = aCIt.current(); + aCIt.next(); + if (aCIt.more()) + aShape = aResultCompound; + } + else { + // merge hierarchies of compounds containing objects and tools + aShape = keepUnusedSubsOfCompound(aCIt.current(), anObjects, GeomAPI_ShapeHierarchy(), + aMakeShapeList); + for (aCIt.next(); aCIt.more(); aCIt.next()) { + std::shared_ptr aBuilder(new GeomAlgoAPI_ShapeBuilder); + aBuilder->add(aShape, aCIt.current()); + aMakeShapeList->appendAlgo(aBuilder); } - - aShape = aFillerAlgo->shape(); - aMakeShapeList->appendAlgo(aFillerAlgo); - aMapOfShapes.merge(aFillerAlgo->mapOfSubShapes()); } - // workaround: make copy to name edges correctly // Store result and naming. - std::shared_ptr aResultBody = document()->createBody(data()); - aResultBody->storeModified(anObjects.front(), aShape); + ListOfShape anObjectsList = anObjects.objects(); + aResultBody->storeModified(anObjectsList.front(), aShape); - for(ListOfShape::const_iterator anIter = anObjects.begin(); anIter != anObjects.end(); ++anIter) { + for(ListOfShape::const_iterator anIter = anObjectsList.begin(); + anIter != anObjectsList.end(); ++anIter) { aResultBody->loadModifiedShapes(aMakeShapeList, *anIter, GeomAPI_Shape::EDGE); aResultBody->loadModifiedShapes(aMakeShapeList, *anIter, GeomAPI_Shape::FACE); //aResultBody->loadDeletedShapes(&aMakeShapeList, *anIter, GeomAPI_Shape::FACE, aDeletedTag);