-// Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+// Copyright (C) 2014-2023 CEA, EDF
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
//
// 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<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
#include "FeaturesPlugin_RemoveSubShapes.h"
#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
#include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultCompSolid.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
#include <ModelAPI_Validator.h>
#include <GeomAPI_ShapeIterator.h>
//==================================================================================================
FeaturesPlugin_RemoveSubShapes::FeaturesPlugin_RemoveSubShapes()
+: myChangedInCode(false)
{
}
{
data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeSelection::typeId());
- data()->addAttribute(SUBSHAPES_ID(), ModelAPI_AttributeSelectionList::typeId());
+ data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
+
+ data()->addAttribute(SUBSHAPES_TO_KEEP_ID(), ModelAPI_AttributeSelectionList::typeId());
+
+ data()->addAttribute(SUBSHAPES_TO_REMOVE_ID(), ModelAPI_AttributeSelectionList::typeId());
}
void FeaturesPlugin_RemoveSubShapes::attributeChanged(const std::string& theID)
{
ModelAPI_Feature::attributeChanged(theID);
- if(theID == BASE_SHAPE_ID()) {
- AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
- AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_ID());
- if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
- return;
- }
+ if (myChangedInCode) return;
- aSubShapesAttrList->clear();
+ AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
+ AttributeSelectionListPtr aSubShapesToKeepAttrList = selectionList(SUBSHAPES_TO_KEEP_ID());
+ AttributeSelectionListPtr aSubShapesToRemoveAttrList = selectionList(SUBSHAPES_TO_REMOVE_ID());
+ if (!aShapeAttrSelection.get()
+ || !aSubShapesToKeepAttrList.get()
+ || !aSubShapesToRemoveAttrList.get())
+ {
+ return;
+ }
- ResultPtr aContext = aShapeAttrSelection->context();
- ResultCompSolidPtr aResultCompSolid =
- std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);
- if(!aResultCompSolid.get()) {
- return;
- }
+ ResultPtr aContext = aShapeAttrSelection->context();
+ ResultBodyPtr aResultBody =
+ std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
+ if (!aResultBody.get()) {
+ aSubShapesToKeepAttrList->clear();
+ aSubShapesToRemoveAttrList->clear();
+ return;
+ }
+ const bool isHasSubs = ModelAPI_Tools::hasSubResults(aResultBody);
- GeomShapePtr aBaseShape = aShapeAttrSelection->value();
- if(!aBaseShape.get()) {
- aBaseShape = aContext->shape();
- }
- if(!aBaseShape.get()) {
- return;
+ GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+ if(!aBaseShape.get()) {
+ aBaseShape = aContext->shape();
+ }
+
+ myChangedInCode = true;
+ if (theID == BASE_SHAPE_ID() || theID == SUBSHAPES_TO_KEEP_ID() ||
+ theID == SUBSHAPES_TO_REMOVE_ID()) {
+ std::list<ResultPtr> anAllSubs;
+ ModelAPI_Tools::allSubs(aResultBody, anAllSubs);
+
+ if(theID == BASE_SHAPE_ID()) {
+ aSubShapesToKeepAttrList->clear();
+ aSubShapesToRemoveAttrList->clear();
+
+ if (!aBaseShape.get()) {
+ return;
+ }
+
+ std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
+ ListOfShape::const_iterator anIt = aSubShapes.cbegin();
+ for (; anIt != aSubShapes.cend(); ++anIt)
+ {
+ GeomShapePtr aSubShape = *anIt;
+ if(!isHasSubs) {
+ aSubShapesToKeepAttrList->append(aContext, aSubShape);
+ } else {
+ std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
+ for(; aSubsIt != anAllSubs.end(); aSubsIt++) {
+ ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
+ if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
+ aSubShapesToKeepAttrList->append(aSub, aSubShape);
+ break;
+ }
+ }
+ }
+ }
}
- GeomAPI_Shape::ShapeType aShapeType = aBaseShape->shapeType();
- if(aShapeType != GeomAPI_Shape::WIRE
- && aShapeType != GeomAPI_Shape::SHELL
- && aShapeType != GeomAPI_Shape::COMPSOLID
- && aShapeType != GeomAPI_Shape::COMPOUND) {
- return;
+ else if (theID == SUBSHAPES_TO_KEEP_ID())
+ {
+ aSubShapesToRemoveAttrList->clear();
+
+ if (!aBaseShape.get()) {
+ return;
+ }
+
+ int anIndex;
+ // optimization: collect selection attribute values into a map
+ const int aSubsToKeepNb = aSubShapesToKeepAttrList->size();
+ GeomAPI_DataMapOfShapeShape aSubShapesToKeep;
+ for(anIndex = 0; anIndex < aSubsToKeepNb; ++anIndex) {
+ AttributeSelectionPtr anAttrSelectionInList = aSubShapesToKeepAttrList->value(anIndex);
+ GeomShapePtr aSubShapeToKeep = anAttrSelectionInList->value();
+ if (aSubShapeToKeep.get())
+ aSubShapesToKeep.bind(aSubShapeToKeep, aSubShapeToKeep);
+ }
+
+ std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
+ ListOfShape::const_iterator anIt = aSubShapes.cbegin();
+ for (; anIt != aSubShapes.cend(); ++anIt)
+ {
+ GeomShapePtr aSubShape = *anIt;
+ if (aSubShapesToKeep.isBound(aSubShape))
+ continue;
+
+ if(!isHasSubs) {
+ aSubShapesToRemoveAttrList->append(aContext, aSubShape);
+ }
+ else {
+ std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
+ for (; aSubsIt != anAllSubs.end(); aSubsIt++) {
+ ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
+ if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
+ aSubShapesToRemoveAttrList->append(aSub, aSubShape);
+ break;
+ }
+ }
+ }
+ }
}
- for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
- GeomShapePtr aSubShape = anIt.current();
- const int aNumOfSubs = aResultCompSolid->numberOfSubs();
- if(aNumOfSubs == 0) {
- aSubShapesAttrList->append(aContext, aSubShape);
- } else {
- for(int anIndex = 0; anIndex < aResultCompSolid->numberOfSubs(); ++anIndex) {
- ResultBodyPtr aSubResult = aResultCompSolid->subResult(anIndex);
- if(aSubResult->shape()->isEqual(aSubShape)) {
- aSubShapesAttrList->append(aSubResult, aSubShape);
- break;
+ else if (theID == SUBSHAPES_TO_REMOVE_ID())
+ {
+ aSubShapesToKeepAttrList->clear();
+
+ if (!aBaseShape.get()) {
+ return;
+ }
+
+ int anIndex;
+ const int aSubsToRemoveNb = aSubShapesToRemoveAttrList->size();
+ GeomAPI_DataMapOfShapeShape aSubShapesToRemove;
+ for(anIndex = 0; anIndex < aSubsToRemoveNb; ++anIndex) {
+ AttributeSelectionPtr anAttrSelectionInList = aSubShapesToRemoveAttrList->value(anIndex);
+ GeomShapePtr aSubShapeToRemove = anAttrSelectionInList->value();
+ if (aSubShapeToRemove.get())
+ aSubShapesToRemove.bind(aSubShapeToRemove, aSubShapeToRemove);
+ }
+
+
+ std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
+ ListOfShape::const_iterator anIt = aSubShapes.cbegin();
+ for (; anIt != aSubShapes.cend(); ++anIt)
+ {
+ GeomShapePtr aSubShape = *anIt;
+ if (aSubShapesToRemove.isBound(aSubShape))
+ continue;
+
+ if (!isHasSubs) {
+ aSubShapesToKeepAttrList->append(aContext, aSubShape);
+ }
+ else {
+ std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
+ for (; aSubsIt != anAllSubs.end(); aSubsIt++) {
+ ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
+ if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
+ aSubShapesToKeepAttrList->append(aSub, aSubShape);
+ break;
+ }
}
}
}
}
}
+
+ myChangedInCode = false;
}
//==================================================================================================
{
// Get base shape and sub-shapes list.
AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
- AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_ID());
+ AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_TO_KEEP_ID());
if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
return;
}
AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(0);
aResultShape = anAttrSelectionInList->value();
}
+ // deleted and copied must be jointed to one list which keeps all the history
+ std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
// find all removed shapes
- GeomAlgoAPI_MakeShapeCustom aDeletedSubs;
- for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
- if (!anIt.current().get() || anIt.current()->isNull())
+ std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aDeletedSubs(new GeomAlgoAPI_MakeShapeCustom);
+ std::set<GeomAPI_Shape::ShapeType> aTypes; // types that where removed
+ aTypes.insert(GeomAPI_Shape::FACE);
+
+ std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
+ for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt) {
+ GeomShapePtr aSubShape = *anIt;
+ if (!aSubShape.get() || aSubShape->isNull())
continue;
+
int anIndex;
for(anIndex = 0; anIndex < aSubsNb; ++anIndex) {
AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
GeomShapePtr aLeftShape = anAttrSelectionInList->value();
- if (anIt.current()->isEqual(aLeftShape)) {
+ if (aSubShape->isEqual(aLeftShape)) {
break; // found in a left-list
}
}
if (anIndex == aSubsNb) { // not found in left
- GeomAPI_ShapeExplorer aFaces(anIt.current(), GeomAPI_Shape::FACE);
- for(; aFaces.more(); aFaces.next())
- aDeletedSubs.addDeleted(aFaces.current());
+ aDeletedSubs->addDeleted(aSubShape);
+ aTypes.insert(aSubShape->shapeType());
+ if (aSubShape->shapeType() != GeomAPI_Shape::FACE) {
+ GeomAPI_ShapeExplorer aFaces(aSubShape, GeomAPI_Shape::FACE);
+ for(; aFaces.more(); aFaces.next())
+ aDeletedSubs->addDeleted(aFaces.current());
+ }
}
}
+ aMakeShapeList->appendAlgo(aDeletedSubs);
+ std::shared_ptr<GeomAlgoAPI_Copy> aCopy(new GeomAlgoAPI_Copy(aResultShape));
+ aResultShape = aCopy->shape();
+ aMakeShapeList->appendAlgo(aCopy);
- GeomAlgoAPI_Copy aCopy(aResultShape);
- aResultShape = aCopy.shape();
+ if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
+ aResultShape = GeomAlgoAPI_ShapeTools::groupSharedTopology(aResultShape);
+ if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
+ // if the result has only one sub-shape, discard the compound
+ GeomAPI_ShapeIterator aSubIt(aResultShape);
+ GeomShapePtr aSub = aSubIt.current();
+ aSubIt.next();
+ if (!aSubIt.more())
+ aResultShape = aSub;
+ }
+ }
// Store result.
ResultBodyPtr aResultBody = document()->createBody(data());
- aResultBody->storeModified(aBaseShape, aResultShape, 1);
- aResultBody->loadDeletedShapes(&aDeletedSubs, aBaseShape, GeomAPI_Shape::FACE, 1);
- aResultBody->loadAndOrientModifiedShapes(&aCopy,
- aBaseShape,
- GeomAPI_Shape::FACE,
- 2,
- "Modified_Face",
- *aCopy.mapOfSubShapes().get(),
- true);
+ std::list<GeomShapePtr> anOldShapes;
+ anOldShapes.push_back(aBaseShape);
+ aResultBody->storeModified(anOldShapes, aResultShape, aMakeShapeList);
+ for (std::set<GeomAPI_Shape::ShapeType>::iterator aTypeIter = aTypes.begin();
+ aTypeIter != aTypes.end();
+ ++aTypeIter)
+ {
+ aResultBody->loadDeletedShapes(aMakeShapeList, aBaseShape, *aTypeIter);
+ }
+
+ aResultBody->loadModifiedShapes(aMakeShapeList,
+ aBaseShape,
+ GeomAPI_Shape::FACE);
+ aResultBody->loadModifiedShapes(aMakeShapeList,
+ aBaseShape,
+ GeomAPI_Shape::EDGE);
+ aResultBody->loadModifiedShapes(aMakeShapeList,
+ aBaseShape,
+ GeomAPI_Shape::VERTEX);
setResult(aResultBody);
}