X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FFeaturesPlugin%2FFeaturesPlugin_Partition.cpp;h=cd4f34cd33a915148c3ba1fc8ebf5da5774cd3fb;hb=a55586483e5dccc5466d6ec241e2147e210d839f;hp=5b0591708e4b79e2d278b5df21798f4ab52a6641;hpb=4223bbeeee6ba7a6a2334208f0fc2d08f309a9ca;p=modules%2Fshaper.git diff --git a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp index 5b0591708..cd4f34cd3 100755 --- a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp @@ -1,224 +1,440 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> - -// File: FeaturesPlugin_Partition.cpp -// Created: 31 Jul 2015 -// Author: Natalia ERMOLAEVA +// Copyright (C) 2014-2017 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 +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// 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 +// +// See http://www.salome-platform.org/ or +// email : webmaster.salome@opencascade.com +// #include "FeaturesPlugin_Partition.h" -#include -#include #include -#include #include +#include +#include #include +#include +#include #include -#include #include +#include #include +#include #include -#include #include #include +#include #include +#include +#include +#include + +#include +#include #include -//================================================================================================= -FeaturesPlugin_Partition::FeaturesPlugin_Partition() -{ -} +typedef std::list > CompsolidSubs; -//================================================================================================= -void FeaturesPlugin_Partition::initAttributes() -{ - AttributeSelectionListPtr aSelection = - std::dynamic_pointer_cast(data()->addAttribute( - FeaturesPlugin_Partition::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId())); - aSelection->setSelectionType("SOLID"); +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); - aSelection = - std::dynamic_pointer_cast(data()->addAttribute( - FeaturesPlugin_Partition::TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId())); - aSelection->setSelectionType("SOLID"); +static void resizePlanes(const CompsolidSubs& theObjects, ListOfShape& thePlanes, + std::shared_ptr& theMakeShapeList); - ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID()); +static void unusedSubsOfComposolid(const CompsolidSubs& theObjects, CompsolidSubs& theNotUsed); - data()->addAttribute(COMBINE_ID(), ModelAPI_AttributeBoolean::typeId()); +static bool cutUnusedSubs(CompsolidSubs& theObjects, CompsolidSubs& theNotUsed, + std::shared_ptr& theMakeShapeList, + std::string& theError); + +static bool isAlgoFailed(const std::shared_ptr& theAlgo, + std::string& theError); + + +//================================================================================================= +FeaturesPlugin_Partition::FeaturesPlugin_Partition() +{ } //================================================================================================= -std::shared_ptr FeaturesPlugin_Partition::getShape(const std::string& theAttrName) +void FeaturesPlugin_Partition::initAttributes() { - std::shared_ptr aObjRef = - std::dynamic_pointer_cast(data()->attribute(theAttrName)); - if (aObjRef) { - std::shared_ptr aConstr = - std::dynamic_pointer_cast(aObjRef->value()); - if (aConstr) - return aConstr->shape(); - } - return std::shared_ptr(); + data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); } //================================================================================================= void FeaturesPlugin_Partition::execute() { - ListOfShape anObjects, aTools, aToolsForNaming; + CompsolidSubs anObjects; + ListOfShape aPlanes; // Getting objects. - AttributeSelectionListPtr anObjectsSelList = selectionList(FeaturesPlugin_Partition::OBJECT_LIST_ID()); - for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) { - std::shared_ptr anObjectAttr = anObjectsSelList->value(anObjectsIndex); - std::shared_ptr anObject = anObjectAttr->value(); - if (!anObject.get()) { - return; - } - anObjects.push_back(anObject); - } - - GeomAlgoAPI_MakeShapeList aMakeShapeList; - std::list > aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(anObjects, 1.0); - - // Getting tools. - AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Partition::TOOL_LIST_ID()); - for (int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) { - std::shared_ptr aToolAttr = aToolsSelList->value(aToolsIndex); - std::shared_ptr aTool = aToolAttr->value(); - if(!aTool.get()) { - // it could be a construction plane - ResultPtr aContext = aToolAttr->context(); - if(aContext.get()) { - aTool = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aContext->shape(), aBoundingPoints); - std::shared_ptr aMkShCustom(new GeomAlgoAPI_MakeShapeCustom); - aMkShCustom->addModified(aContext->shape(), aTool); - aMakeShapeList.append(aMkShCustom); - aTools.push_back(aTool); - aToolsForNaming.push_back(aContext->shape()); - } - } else { - aTools.push_back(aTool); - aToolsForNaming.push_back(aTool); - } + pullObjectsAndPlanes(selectionList(BASE_OBJECTS_ID()), anObjects, aPlanes); + if(anObjects.empty()) { + static const std::string aFeatureError = "Error: No objects for partition."; + setError(aFeatureError); + return; } - // Getting combine flag. - bool isCombine = boolean(COMBINE_ID())->value(); + ListOfShape aBaseObjects; + for (CompsolidSubs::iterator anIt = anObjects.begin(); anIt != anObjects.end(); ++anIt) + aBaseObjects.insert(aBaseObjects.end(), anIt->second.begin(), anIt->second.end()); + aBaseObjects.insert(aBaseObjects.end(), aPlanes.begin(), aPlanes.end()); - if(anObjects.empty()/* || aTools.empty()*/) { - std::string aFeatureError = "Not enough objects for partition operation"; - setError(aFeatureError); + // resize planes to the bounding box of operated shapes + std::shared_ptr aMakeShapeList(new GeomAlgoAPI_MakeShapeList()); + resizePlanes(anObjects, 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()); + + std::string aError; + if (!cutUnusedSubs(anObjects, anUnusedSubs, aMakeShapeList, aError)) { + setError(aError); return; } - int aResultIndex = 0; + // 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()); - if(isCombine) { - // Create single result. - std::shared_ptr aCompoud = GeomAlgoAPI_CompoundBuilder::compound(anObjects); - anObjects.clear(); - anObjects.push_back(aCompoud); - GeomAlgoAPI_Partition aPartitionAlgo(anObjects, aTools); + std::shared_ptr aPartitionAlgo( + new GeomAlgoAPI_Partition(aTargetObjects, aPlanes)); + + // Checking that the algorithm worked properly. + if (isAlgoFailed(aPartitionAlgo, aError)) { + setError(aError); + return; + } + + aMakeShapeList->appendAlgo(aPartitionAlgo); + GeomShapePtr aResultShape = aPartitionAlgo->shape(); + + if (!anUnusedSubs.empty()) { + // 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()); + + aPartitionAlgo.reset(new GeomAlgoAPI_Partition(aTargetObjects, ListOfShape())); // Checking that the algorithm worked properly. - if (!aPartitionAlgo.isDone()) { - static const std::string aFeatureError = "Partition algorithm failed"; - setError(aFeatureError); - return; - } - if (aPartitionAlgo.shape()->isNull()) { - static const std::string aShapeError = "Resulting shape is Null"; - setError(aShapeError); - return; - } - if (!aPartitionAlgo.isValid()) { - std::string aFeatureError = "Warning: resulting shape is not valid"; - setError(aFeatureError); + if (isAlgoFailed(aPartitionAlgo, aError)) { + setError(aError); return; } - if (GeomAlgoAPI_ShapeTools::volume(aPartitionAlgo.shape()) > 1.e-7) { - std::shared_ptr aResultBody = document()->createBody(data(), aResultIndex); - aMakeShapeList.append(aPartitionAlgo.makeShape()); - GeomAPI_DataMapOfShapeShape aMapOfShapes = *aPartitionAlgo.mapOfShapes().get(); - loadNamingDS(aResultBody, anObjects.front(), aToolsForNaming, aPartitionAlgo.shape(), aMakeShapeList, aMapOfShapes); - setResult(aResultBody, aResultIndex); - aResultIndex++; + aMakeShapeList->appendAlgo(aPartitionAlgo); + aResultShape = aPartitionAlgo->shape(); + } + + 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); + ++aResultIndex; } } else { - // Create result for each object. - for (ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) { - std::shared_ptr anObject = *anObjectsIt; - ListOfShape aListWithObject; aListWithObject.push_back(anObject); - GeomAlgoAPI_Partition aPartitionAlgo(aListWithObject, aTools); - - // Checking that the algorithm worked properly. - if (!aPartitionAlgo.isDone()) { - static const std::string aFeatureError = "Partition algorithm failed"; - setError(aFeatureError); - return; + storeResult(aBaseObjects, aPlanes, aResultShape, aMakeShapeList, aResultIndex); + ++aResultIndex; + } + + // Remove the rest results if there were produced in the previous pass. + removeResults(aResultIndex); +} + +//================================================================================================= +void FeaturesPlugin_Partition::storeResult( + ListOfShape& theObjects, ListOfShape& thePlanes, + const GeomShapePtr theResultShape, + 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; } - if (aPartitionAlgo.shape()->isNull()) { - static const std::string aShapeError = "Resulting shape is Null"; - setError(aShapeError); - return; + } + } + + // 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; + } + + const int aDelTag = 1; + /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids + const int aSubTag = 2; + int aModTag = aSubTag + 10000; + const std::string aModName = "Modified"; + + aResultBody->storeModified(aBaseShape, theResultShape, aSubTag); + + std::shared_ptr aMapOfSubShapes = theMakeShape->mapOfSubShapes(); + theObjects.insert(theObjects.end(), thePlanes.begin(), thePlanes.end()); + int anIndex = 1; + for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) { + GeomShapePtr aShape = *anIt; + std::string aModEdgeName = aModName + "_Edge_" + std::to_string((long long)anIndex); + aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::EDGE, + aModTag, aModEdgeName, *aMapOfSubShapes.get(), false, true, true); + std::string aModFaceName = aModName + "_Face_" + std::to_string((long long)anIndex++); + aResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::FACE, + aModTag + 1, aModFaceName, *aMapOfSubShapes.get(), false, true, true); + aResultBody->loadDeletedShapes(theMakeShape.get(), aShape, GeomAPI_Shape::FACE, aDelTag); + } + + setResult(aResultBody, theIndex); +} + + +//================= 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 (!aPartitionAlgo.isValid()) { - std::string aFeatureError = "Warning: resulting shape is not valid"; - setError(aFeatureError); - return; + 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; +} - if (GeomAlgoAPI_ShapeTools::volume(aPartitionAlgo.shape()) > 1.e-7) { - std::shared_ptr aResultBody = document()->createBody(data(), aResultIndex); - aMakeShapeList.append(aPartitionAlgo.makeShape()); - GeomAPI_DataMapOfShapeShape aMapOfShapes = *aPartitionAlgo.mapOfShapes().get(); - loadNamingDS(aResultBody, anObject, aToolsForNaming, aPartitionAlgo.shape(), aMakeShapeList, aMapOfShapes); - setResult(aResultBody, aResultIndex); - aResultIndex++; +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()); } } +} - // remove the rest results if there were produced in the previous pass - removeResults(aResultIndex); +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 FeaturesPlugin_Partition::loadNamingDS(std::shared_ptr theResultBody, - const std::shared_ptr theBaseShape, - const ListOfShape& theTools, - const std::shared_ptr theResultShape, - GeomAlgoAPI_MakeShape& theMakeShape, - GeomAPI_DataMapOfShapeShape& theMapOfShapes) +void unusedSubsOfComposolid(const CompsolidSubs& theObjects, CompsolidSubs& theNotUsed) { - //load result - if(theBaseShape->isEqual(theResultShape)) { - theResultBody->store(theResultShape); - } else { - const int aDeletedTag = 1; - const int aSubsolidsTag = 2; /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids - const int aModifyTag = 100000; - int aModifyToolsTag = 200000; - std::ostringstream aStream; - - theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag); - - std::string aModName = "Modified"; - theResultBody->loadAndOrientModifiedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, - aModifyTag, aModName, theMapOfShapes, true); - theResultBody->loadDeletedShapes(&theMakeShape, theBaseShape, GeomAPI_Shape::FACE, aDeletedTag); - - int anIndex = 1; - for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) { - aStream.str(std::string()); - aStream.clear(); - aStream << aModName << "_" << anIndex++; - theResultBody->loadAndOrientModifiedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, - aModifyToolsTag, aStream.str(), theMapOfShapes, true); - theResultBody->loadDeletedShapes(&theMakeShape, *anIter, GeomAPI_Shape::FACE, aDeletedTag); - aModifyToolsTag += 10000; + 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, + const ListOfShape& theTools, + std::shared_ptr& theMakeShapeList, + std::string& theError) +{ + if (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 (isAlgoFailed(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()); + } + return true; +} + +bool cutUnusedSubs(CompsolidSubs& theObjects, CompsolidSubs& theNotUsed, + std::shared_ptr& theMakeShapeList, + std::string& theError) +{ + GeomShapePtr aFirstArgument = theObjects.front().first; + + // 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; + aToolsForUnused.push_back(aFirstArgument); + + // cut subs + return cutSubs(aFirstArgument, theObjects, aToolsForUsed, theMakeShapeList, theError) + && cutSubs(aFirstArgument, theNotUsed, aToolsForUnused, theMakeShapeList, theError); +} + +bool isAlgoFailed(const std::shared_ptr& theAlgo, std::string& theError) +{ + if (!theAlgo->isDone()) { + theError = "Error: Partition algorithm failed."; + return true; } + if (theAlgo->shape()->isNull()) { + theError = "Error: Resulting shape is Null."; + return true; + } + if (!theAlgo->isValid()) { + theError = "Error: Resulting shape is not valid."; + return true; + } + + theError.clear(); + return false; }