X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FFeaturesPlugin%2FFeaturesPlugin_Partition.cpp;h=e1a257aefa37a8e17ae123e1620feb388c33dd10;hb=71e54dccdd7194a911151c626896ec7dc2942241;hp=43ae4130c0fa13b171c932b375b2cab4a6ec431b;hpb=d4b0a5cb916f4eccf4a0bce02e43a54c7a67cb93;p=modules%2Fshaper.git diff --git a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp old mode 100755 new mode 100644 index 43ae4130c..e1a257aef --- a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// Copyright (C) 2014-2020 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 @@ -12,10 +12,9 @@ // // 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 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include "FeaturesPlugin_Partition.h" @@ -37,6 +36,7 @@ #include #include #include +#include #include #include @@ -48,25 +48,6 @@ #include #include -typedef std::list > CompsolidSubs; - -static GeomShapePtr findBase(const GeomShapePtr theObjectShape, - const GeomShapePtr theResultShape, - const GeomAPI_Shape::ShapeType theShapeType, - const std::shared_ptr theMakeShape); - -static void pullObjectsAndPlanes(const AttributeSelectionListPtr& theSelectedList, - CompsolidSubs& theObjects, ListOfShape& thePlanes); - -static void resizePlanes(const CompsolidSubs& theObjects, ListOfShape& thePlanes, - std::shared_ptr& theMakeShapeList); - -static void unusedSubsOfComposolid(const CompsolidSubs& theObjects, CompsolidSubs& theNotUsed); - -static bool cutUnusedSubs(CompsolidSubs& theObjects, CompsolidSubs& theNotUsed, - std::shared_ptr& theMakeShapeList, - std::string& theError); - //================================================================================================= FeaturesPlugin_Partition::FeaturesPlugin_Partition() @@ -77,50 +58,42 @@ FeaturesPlugin_Partition::FeaturesPlugin_Partition() void FeaturesPlugin_Partition::initAttributes() { data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); + initVersion(BOP_VERSION_9_4(), selectionList(BASE_OBJECTS_ID())); } //================================================================================================= void FeaturesPlugin_Partition::execute() { - CompsolidSubs anObjects; + GeomAPI_ShapeHierarchy anObjects; ListOfShape aPlanes; // Getting objects. - pullObjectsAndPlanes(selectionList(BASE_OBJECTS_ID()), anObjects, aPlanes); + processAttribute(BASE_OBJECTS_ID(), anObjects, aPlanes); if(anObjects.empty()) { static const std::string aFeatureError = "Error: No objects for partition."; setError(aFeatureError); return; } - ListOfShape aBaseObjects; - for (CompsolidSubs::iterator anIt = anObjects.begin(); anIt != anObjects.end(); ++anIt) - aBaseObjects.insert(aBaseObjects.end(), anIt->second.begin(), anIt->second.end()); + ListOfShape aBaseObjects = anObjects.objects(); aBaseObjects.insert(aBaseObjects.end(), aPlanes.begin(), aPlanes.end()); // resize planes to the bounding box of operated shapes std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); - resizePlanes(anObjects, aPlanes, aMakeShapeList); + resizePlanes(anObjects.objects(), aPlanes, aMakeShapeList); // cut unused solids of composolids from the objects of partition - CompsolidSubs anUnusedSubs; - unusedSubsOfComposolid(anObjects, anUnusedSubs); - for (CompsolidSubs::iterator anIt = anUnusedSubs.begin(); anIt != anUnusedSubs.end(); ++anIt) - aBaseObjects.insert(aBaseObjects.end(), anIt->second.begin(), anIt->second.end()); - + ListOfShape aTargetObjects, anUnusedSubs; std::string aError; - if (!cutUnusedSubs(anObjects, anUnusedSubs, aMakeShapeList, aError)) { + if (!cutSubs(anObjects, aTargetObjects, anUnusedSubs, aMakeShapeList, aError)) { setError(aError); return; } + aBaseObjects.insert(aBaseObjects.end(), anUnusedSubs.begin(), anUnusedSubs.end()); - // perform partition first time to split target solids - ListOfShape aTargetObjects; - for (CompsolidSubs::iterator anIt = anObjects.begin(); anIt != anObjects.end(); ++anIt) - aTargetObjects.insert(aTargetObjects.end(), anIt->second.begin(), anIt->second.end()); - + // perform partition first time to split target solids by planes std::shared_ptr aPartitionAlgo( - new GeomAlgoAPI_Partition(aTargetObjects, aPlanes)); + new GeomAlgoAPI_Partition(aTargetObjects, aPlanes)); // Checking that the algorithm worked properly. if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), aError)) { @@ -135,8 +108,7 @@ void FeaturesPlugin_Partition::execute() // second pass of a partition to split shared faces of compsolids aTargetObjects.clear(); aTargetObjects.push_back(aResultShape); - for (CompsolidSubs::iterator anIt = anUnusedSubs.begin(); anIt != anUnusedSubs.end(); ++anIt) - aTargetObjects.insert(aTargetObjects.end(), anIt->second.begin(), anIt->second.end()); + aTargetObjects.insert(aTargetObjects.end(), anUnusedSubs.begin(), anUnusedSubs.end()); aPartitionAlgo.reset(new GeomAlgoAPI_Partition(aTargetObjects, ListOfShape())); @@ -151,13 +123,46 @@ void FeaturesPlugin_Partition::execute() } int aResultIndex = 0; - if(aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) { - for(GeomAPI_ShapeIterator anIt(aResultShape); anIt.more(); anIt.next()) { - storeResult(aBaseObjects, aPlanes, anIt.current(), aMakeShapeList, aResultIndex); + + if (data()->version().empty()) { + // default behaviors of Partition + if(aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) { + for(GeomAPI_ShapeIterator anIt(aResultShape); anIt.more(); anIt.next()) { + storeResult(aBaseObjects, aPlanes, anIt.current(), aMakeShapeList, aResultIndex); + ++aResultIndex; + } + } else { + storeResult(aBaseObjects, aPlanes, aResultShape, aMakeShapeList, aResultIndex); ++aResultIndex; } - } else { - storeResult(aBaseObjects, aPlanes, aResultShape, aMakeShapeList, aResultIndex); + } + else { + // merge hierarchies of compounds containing objects and tools + GeomShapePtr aFirstShape = aResultShape; + GeomAPI_ShapeIterator anIt; + if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) { + anIt = GeomAPI_ShapeIterator(aResultShape); + aFirstShape = anIt.current(); + anIt.next(); + } + + GeomShapePtr aResultCompound = + keepUnusedSubsOfCompound(aFirstShape, anObjects, GeomAPI_ShapeHierarchy(), aMakeShapeList); + + if (anIt.more()) { + if (aResultCompound->shapeType() != GeomAPI_Shape::COMPOUND) { + // put the shape into compound + ListOfShape aShapes; + aShapes.push_back(aResultCompound); + aResultCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes); + } + std::shared_ptr aBuilder(new GeomAlgoAPI_ShapeBuilder); + for (; anIt.more(); anIt.next()) + aBuilder->add(aResultCompound, anIt.current()); + aMakeShapeList->appendAlgo(aBuilder); + } + + storeResult(aBaseObjects, aPlanes, aResultCompound, aMakeShapeList, aResultIndex); ++aResultIndex; } @@ -172,37 +177,20 @@ void FeaturesPlugin_Partition::storeResult( const std::shared_ptr theMakeShape, const int theIndex) { - // Find base. The most complicated is the real modified object (#1799 if box is partitioned by - // two planes the box is the base, not planes, independently on the order in the list). - GeomShapePtr aBaseShape; - for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) { - GeomShapePtr anObjectShape = *anIt; - GeomShapePtr aCandidate = - findBase(anObjectShape, theResultShape, GeomAPI_Shape::VERTEX, theMakeShape); - if(!aCandidate.get()) { - aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::EDGE, theMakeShape); - } - if (!aCandidate.get()) - aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::FACE, theMakeShape); - - if(aCandidate.get()) { - if (!aBaseShape.get() || aBaseShape->shapeType() > aCandidate->shapeType()) { - aBaseShape = aCandidate; - } - } - } - // Create result body. ResultBodyPtr aResultBody = document()->createBody(data(), theIndex); - // Store modified shape. - if(!aBaseShape.get() || aBaseShape->isEqual(theResultShape)) { - aResultBody->store(theResultShape, false); - setResult(aResultBody, theIndex); - return; + // if result is same as one of the base object, no modification was performed + for(ListOfShape::const_iterator anObj = theObjects.cbegin(); anObj != theObjects.cend(); ++anObj) + { + if (anObj->get() && (*anObj)->isSame(theResultShape)) { + aResultBody->store(theResultShape, false); + setResult(aResultBody, theIndex); + return; + } } - aResultBody->storeModified(aBaseShape, theResultShape); + aResultBody->storeModified(theObjects, theResultShape, theMakeShape); std::shared_ptr aMapOfSubShapes = theMakeShape->mapOfSubShapes(); theObjects.insert(theObjects.end(), thePlanes.begin(), thePlanes.end()); @@ -220,192 +208,77 @@ void FeaturesPlugin_Partition::storeResult( } -//================= Auxiliary functions =================================================== - -GeomShapePtr findBase(const GeomShapePtr theObjectShape, - const GeomShapePtr theResultShape, - const GeomAPI_Shape::ShapeType theShapeType, - const std::shared_ptr theMakeShape) -{ - GeomShapePtr aBaseShape; - std::shared_ptr aMapOfSubShapes = theMakeShape->mapOfSubShapes(); - for(GeomAPI_ShapeExplorer anObjectSubShapesExp(theObjectShape, theShapeType); - anObjectSubShapesExp.more(); - anObjectSubShapesExp.next()) { - GeomShapePtr anObjectSubShape = anObjectSubShapesExp.current(); - ListOfShape aModifiedShapes; - theMakeShape->modified(anObjectSubShape, aModifiedShapes); - for(ListOfShape::const_iterator - aModIt = aModifiedShapes.cbegin(); aModIt != aModifiedShapes.cend(); ++aModIt) { - GeomShapePtr aModShape = *aModIt; - if(aMapOfSubShapes->isBound(aModShape)) { - aModShape = aMapOfSubShapes->find(aModShape); - } - if(theResultShape->isSubShape(aModShape)) { - aBaseShape = theObjectShape; - break; - } - } - if(aBaseShape.get()) { - break; - } - } - - return aBaseShape; -} - -static CompsolidSubs::iterator findOrAdd(CompsolidSubs& theList, const GeomShapePtr& theCompsolid) -{ - CompsolidSubs::iterator aFound = theList.begin(); - for (; aFound != theList.end(); ++aFound) - if (aFound->first == theCompsolid) - break; - if (aFound == theList.end()) { - theList.push_back(std::pair(theCompsolid, ListOfShape())); - aFound = --theList.end(); - } - return aFound; -} - -void pullObjectsAndPlanes(const AttributeSelectionListPtr& theSelectedList, - CompsolidSubs& theObjects, ListOfShape& thePlanes) -{ - std::map aMapCompsolidShape; - - int aSize = theSelectedList->size(); - for (int anIndex = 0; anIndex < aSize; ++anIndex) { - AttributeSelectionPtr anObjectAttr = theSelectedList->value(anIndex); - ResultPtr aContext = anObjectAttr->context(); - GeomShapePtr anObject = anObjectAttr->value(); - if (anObject) { - GeomShapePtr anOwnerShape = anObject; - // check the result is a compsolid and store all used subs in a single list - ResultBodyPtr aResCompSolidPtr = ModelAPI_Tools::bodyOwner(aContext); - if (aResCompSolidPtr && aResCompSolidPtr->shape()->shapeType() == GeomAPI_Shape::COMPSOLID) { - std::map::const_iterator - aFound = aMapCompsolidShape.find(aResCompSolidPtr); - if (aFound != aMapCompsolidShape.end()) - anOwnerShape = aFound->second; - else { - anOwnerShape = aResCompSolidPtr->shape(); - aMapCompsolidShape[aResCompSolidPtr] = anOwnerShape; - } - } - - CompsolidSubs::iterator aFound = findOrAdd(theObjects, anOwnerShape); - aFound->second.push_back(anObject); - } - else { - // It could be a construction plane. - thePlanes.push_back(anObjectAttr->context()->shape()); - } - } -} - -void resizePlanes(const CompsolidSubs& theObjects, ListOfShape& thePlanes, - std::shared_ptr& theMakeShapeList) -{ - ListOfShape aSolidsInOperation; - for (CompsolidSubs::const_iterator anIt = theObjects.begin(); anIt != theObjects.end(); ++anIt) - aSolidsInOperation.insert(aSolidsInOperation.end(), anIt->second.begin(), anIt->second.end()); - - std::list > aBoundingPoints = - GeomAlgoAPI_ShapeTools::getBoundingBox(aSolidsInOperation, 1.0); - - ListOfShape aPlanesCopy = thePlanes; - thePlanes.clear(); - - // Resize planes to fit in bounding box - for (ListOfShape::const_iterator anIt = aPlanesCopy.begin(); anIt != aPlanesCopy.end(); ++anIt) { - GeomShapePtr aPlane = *anIt; - GeomShapePtr aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPlane, aBoundingPoints); - std::shared_ptr aMkShCustom(new GeomAlgoAPI_MakeShapeCustom); - aMkShCustom->addModified(aPlane, aTool); - theMakeShapeList->appendAlgo(aMkShCustom); - thePlanes.push_back(aTool); - } -} - -void unusedSubsOfComposolid(const CompsolidSubs& theObjects, CompsolidSubs& theNotUsed) -{ - for (CompsolidSubs::const_iterator aCSIt = theObjects.begin(); - aCSIt != theObjects.end(); ++aCSIt) { - if (aCSIt->first->shapeType() != GeomAPI_Shape::COMPSOLID) - continue; - - // check the compsolid is selected - if (aCSIt->second.size() == 1 && aCSIt->first->isEqual(aCSIt->second.front())) - continue; - - // process all sub-solids of compsolid - ListOfShape aNotUsedSolids; - for (GeomAPI_ShapeExplorer anExp(aCSIt->first, GeomAPI_Shape::SOLID); - anExp.more(); anExp.next()) { - GeomShapePtr aSolidInCompSolid = anExp.current(); - ListOfShape::const_iterator anIt = aCSIt->second.begin(); - for (; anIt != aCSIt->second.end(); ++anIt) - if (aSolidInCompSolid->isEqual(*anIt)) - break; - - if (anIt == aCSIt->second.end()) - aNotUsedSolids.push_back(aSolidInCompSolid); - } - - if (!aNotUsedSolids.empty()) - theNotUsed.push_back(std::pair(aCSIt->first, aNotUsedSolids)); - } -} +//================================================================================================= -static bool cutSubs(const GeomShapePtr& theFirstArgument, - CompsolidSubs& theSubsToCut, +static bool cutSubs(ListOfShape& theSubsToCut, const ListOfShape& theTools, std::shared_ptr& theMakeShapeList, std::string& theError) { - if (theTools.empty()) + if (theSubsToCut.empty() || theTools.empty()) return true; - std::shared_ptr aCutAlgo; - - for (CompsolidSubs::iterator aUIt= theSubsToCut.begin(); aUIt != theSubsToCut.end(); ++aUIt) { - if (aUIt->first == theFirstArgument) - continue; // no need to split unused subs of the first compsolid - - // cut from current list of solids - aCutAlgo.reset( - new GeomAlgoAPI_Boolean(aUIt->second, theTools, GeomAlgoAPI_Boolean::BOOL_CUT)); - if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCutAlgo, "", theError)) - return false; - theMakeShapeList->appendAlgo(aCutAlgo); - - // update list of un-selected objects of the partition - GeomAPI_Shape::ShapeType aType = aUIt->second.front()->shapeType(); - aUIt->second.clear(); - for (GeomAPI_ShapeExplorer anExp(aCutAlgo->shape(), aType); anExp.more(); anExp.next()) - aUIt->second.push_back(anExp.current()); - } + // cut from current list of solids + std::shared_ptr aCutAlgo( + new GeomAlgoAPI_Boolean(theSubsToCut, theTools, GeomAlgoAPI_Tools::BOOL_CUT)); + if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCutAlgo, "", theError)) + return false; + theMakeShapeList->appendAlgo(aCutAlgo); + + // update list of un-selected objects of the partition + GeomAPI_Shape::ShapeType aType = theSubsToCut.front()->shapeType(); + theSubsToCut.clear(); + for (GeomAPI_ShapeExplorer anExp(aCutAlgo->shape(), aType); anExp.more(); anExp.next()) + theSubsToCut.push_back(anExp.current()); return true; } -bool cutUnusedSubs(CompsolidSubs& theObjects, CompsolidSubs& theNotUsed, - std::shared_ptr& theMakeShapeList, - std::string& theError) +bool FeaturesPlugin_Partition::cutSubs( + GeomAPI_ShapeHierarchy& theHierarchy, + ListOfShape& theUsed, + ListOfShape& theNotUsed, + std::shared_ptr& theMakeShapeList, + std::string& theError) { - GeomShapePtr aFirstArgument = theObjects.front().first; + theUsed.clear(); + theNotUsed.clear(); + + GeomAPI_ShapeHierarchy::iterator anIt = theHierarchy.begin(); // compose a set of tools for the CUT operation: // find the list of unused subs of the first argument or use itself - ListOfShape aToolsForUsed; - CompsolidSubs::iterator aUIt = theNotUsed.begin(); - for (; aUIt != theNotUsed.end(); ++aUIt) - if (aUIt->first == aFirstArgument) { - aToolsForUsed.insert(aToolsForUsed.end(), aUIt->second.begin(), aUIt->second.end()); - break; - } - ListOfShape aToolsForUnused; + ListOfShape aToolsForUsed, aToolsForUnused; + GeomShapePtr aFirstArgument = theHierarchy.parent(*anIt, false); + if (aFirstArgument && aFirstArgument->shapeType() == GeomAPI_Shape::COMPSOLID) { + theHierarchy.splitCompound(aFirstArgument, theUsed, aToolsForUsed); + theNotUsed = aToolsForUsed; + } + else { + aFirstArgument = *anIt; + theUsed.push_back(aFirstArgument); + } aToolsForUnused.push_back(aFirstArgument); // cut subs - return cutSubs(aFirstArgument, theObjects, aToolsForUsed, theMakeShapeList, theError) - && cutSubs(aFirstArgument, theNotUsed, aToolsForUnused, theMakeShapeList, theError); + bool isOk = true; + for (++anIt; anIt != theHierarchy.end() && isOk; ++anIt) { + ListOfShape aUsed, aNotUsed; + + GeomShapePtr aParent = theHierarchy.parent(*anIt, false); + if (aParent && aParent->shapeType() == GeomAPI_Shape::COMPSOLID) { + aParent = theHierarchy.parent(*anIt); // get parent once again to mark its subs as processed + theHierarchy.splitCompound(aParent, aUsed, aNotUsed); + } + else + aUsed.push_back(*anIt); + + isOk = ::cutSubs(aUsed, aToolsForUsed, theMakeShapeList, theError) + && ::cutSubs(aNotUsed, aToolsForUnused, theMakeShapeList, theError); + if (isOk) { + theUsed.insert(theUsed.end(), aUsed.begin(), aUsed.end()); + theNotUsed.insert(theNotUsed.end(), aNotUsed.begin(), aNotUsed.end()); + } + } + + return isOk; }