1 // Copyright (C) 2014-2022 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "FeaturesPlugin_RemoveSubShapes.h"
22 #include <ModelAPI_AttributeSelectionList.h>
23 #include <ModelAPI_AttributeString.h>
24 #include <ModelAPI_ResultBody.h>
25 #include <ModelAPI_ResultConstruction.h>
26 #include <ModelAPI_Session.h>
27 #include <ModelAPI_Tools.h>
28 #include <ModelAPI_Validator.h>
30 #include <GeomAPI_ShapeIterator.h>
31 #include <GeomAPI_ShapeExplorer.h>
33 #include <GeomAlgoAPI_Copy.h>
34 #include <GeomAlgoAPI_ShapeBuilder.h>
35 #include <GeomAlgoAPI_ShapeTools.h>
36 #include <GeomAlgoAPI_MakeShapeCustom.h>
39 //==================================================================================================
40 FeaturesPlugin_RemoveSubShapes::FeaturesPlugin_RemoveSubShapes()
41 : myChangedInCode(false)
45 //==================================================================================================
46 void FeaturesPlugin_RemoveSubShapes::initAttributes()
48 data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeSelection::typeId());
50 data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
52 data()->addAttribute(SUBSHAPES_TO_KEEP_ID(), ModelAPI_AttributeSelectionList::typeId());
54 data()->addAttribute(SUBSHAPES_TO_REMOVE_ID(), ModelAPI_AttributeSelectionList::typeId());
57 void FeaturesPlugin_RemoveSubShapes::attributeChanged(const std::string& theID)
59 ModelAPI_Feature::attributeChanged(theID);
61 if (myChangedInCode) return;
63 AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
64 AttributeSelectionListPtr aSubShapesToKeepAttrList = selectionList(SUBSHAPES_TO_KEEP_ID());
65 AttributeSelectionListPtr aSubShapesToRemoveAttrList = selectionList(SUBSHAPES_TO_REMOVE_ID());
66 if (!aShapeAttrSelection.get()
67 || !aSubShapesToKeepAttrList.get()
68 || !aSubShapesToRemoveAttrList.get())
73 ResultPtr aContext = aShapeAttrSelection->context();
74 ResultBodyPtr aResultBody =
75 std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
76 if (!aResultBody.get()) {
77 aSubShapesToKeepAttrList->clear();
78 aSubShapesToRemoveAttrList->clear();
81 const bool isHasSubs = ModelAPI_Tools::hasSubResults(aResultBody);
83 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
84 if(!aBaseShape.get()) {
85 aBaseShape = aContext->shape();
88 myChangedInCode = true;
89 if (theID == BASE_SHAPE_ID() || theID == SUBSHAPES_TO_KEEP_ID() ||
90 theID == SUBSHAPES_TO_REMOVE_ID()) {
91 std::list<ResultPtr> anAllSubs;
92 ModelAPI_Tools::allSubs(aResultBody, anAllSubs);
94 if(theID == BASE_SHAPE_ID()) {
95 aSubShapesToKeepAttrList->clear();
96 aSubShapesToRemoveAttrList->clear();
98 if (!aBaseShape.get()) {
102 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
103 ListOfShape::const_iterator anIt = aSubShapes.cbegin();
104 for (; anIt != aSubShapes.cend(); ++anIt)
106 GeomShapePtr aSubShape = *anIt;
108 aSubShapesToKeepAttrList->append(aContext, aSubShape);
110 std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
111 for(; aSubsIt != anAllSubs.end(); aSubsIt++) {
112 ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
113 if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
114 aSubShapesToKeepAttrList->append(aSub, aSubShape);
121 else if (theID == SUBSHAPES_TO_KEEP_ID())
123 aSubShapesToRemoveAttrList->clear();
125 if (!aBaseShape.get()) {
130 // optimization: collect selection attribute values into a map
131 const int aSubsToKeepNb = aSubShapesToKeepAttrList->size();
132 GeomAPI_DataMapOfShapeShape aSubShapesToKeep;
133 for(anIndex = 0; anIndex < aSubsToKeepNb; ++anIndex) {
134 AttributeSelectionPtr anAttrSelectionInList = aSubShapesToKeepAttrList->value(anIndex);
135 GeomShapePtr aSubShapeToKeep = anAttrSelectionInList->value();
136 if (aSubShapeToKeep.get())
137 aSubShapesToKeep.bind(aSubShapeToKeep, aSubShapeToKeep);
140 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
141 ListOfShape::const_iterator anIt = aSubShapes.cbegin();
142 for (; anIt != aSubShapes.cend(); ++anIt)
144 GeomShapePtr aSubShape = *anIt;
145 if (aSubShapesToKeep.isBound(aSubShape))
149 aSubShapesToRemoveAttrList->append(aContext, aSubShape);
152 std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
153 for (; aSubsIt != anAllSubs.end(); aSubsIt++) {
154 ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
155 if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
156 aSubShapesToRemoveAttrList->append(aSub, aSubShape);
163 else if (theID == SUBSHAPES_TO_REMOVE_ID())
165 aSubShapesToKeepAttrList->clear();
167 if (!aBaseShape.get()) {
172 const int aSubsToRemoveNb = aSubShapesToRemoveAttrList->size();
173 GeomAPI_DataMapOfShapeShape aSubShapesToRemove;
174 for(anIndex = 0; anIndex < aSubsToRemoveNb; ++anIndex) {
175 AttributeSelectionPtr anAttrSelectionInList = aSubShapesToRemoveAttrList->value(anIndex);
176 GeomShapePtr aSubShapeToRemove = anAttrSelectionInList->value();
177 if (aSubShapeToRemove.get())
178 aSubShapesToRemove.bind(aSubShapeToRemove, aSubShapeToRemove);
182 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
183 ListOfShape::const_iterator anIt = aSubShapes.cbegin();
184 for (; anIt != aSubShapes.cend(); ++anIt)
186 GeomShapePtr aSubShape = *anIt;
187 if (aSubShapesToRemove.isBound(aSubShape))
191 aSubShapesToKeepAttrList->append(aContext, aSubShape);
194 std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
195 for (; aSubsIt != anAllSubs.end(); aSubsIt++) {
196 ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
197 if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
198 aSubShapesToKeepAttrList->append(aSub, aSubShape);
207 myChangedInCode = false;
210 //==================================================================================================
211 void FeaturesPlugin_RemoveSubShapes::execute()
213 // Get base shape and sub-shapes list.
214 AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
215 AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_TO_KEEP_ID());
216 if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
221 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
223 GeomShapePtr aResultShape;
224 int aSubsNb = aSubShapesAttrList->size();
226 if(!aBaseShape.get()) {
229 aResultShape = aBaseShape->emptyCopied();
231 // Copy sub-shapes from list to new shape.
232 for(int anIndex = 0; anIndex < aSubsNb; ++anIndex) {
233 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
234 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
235 GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
237 } else if(aSubsNb == 1) {
238 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(0);
239 aResultShape = anAttrSelectionInList->value();
241 // deleted and copied must be jointed to one list which keeps all the history
242 std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
244 // find all removed shapes
245 std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aDeletedSubs(new GeomAlgoAPI_MakeShapeCustom);
246 std::set<GeomAPI_Shape::ShapeType> aTypes; // types that where removed
247 aTypes.insert(GeomAPI_Shape::FACE);
249 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
250 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt) {
251 GeomShapePtr aSubShape = *anIt;
252 if (!aSubShape.get() || aSubShape->isNull())
256 for(anIndex = 0; anIndex < aSubsNb; ++anIndex) {
257 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
258 GeomShapePtr aLeftShape = anAttrSelectionInList->value();
259 if (aSubShape->isEqual(aLeftShape)) {
260 break; // found in a left-list
263 if (anIndex == aSubsNb) { // not found in left
264 aDeletedSubs->addDeleted(aSubShape);
265 aTypes.insert(aSubShape->shapeType());
266 if (aSubShape->shapeType() != GeomAPI_Shape::FACE) {
267 GeomAPI_ShapeExplorer aFaces(aSubShape, GeomAPI_Shape::FACE);
268 for(; aFaces.more(); aFaces.next())
269 aDeletedSubs->addDeleted(aFaces.current());
273 aMakeShapeList->appendAlgo(aDeletedSubs);
275 std::shared_ptr<GeomAlgoAPI_Copy> aCopy(new GeomAlgoAPI_Copy(aResultShape));
276 aResultShape = aCopy->shape();
277 aMakeShapeList->appendAlgo(aCopy);
279 if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
280 aResultShape = GeomAlgoAPI_ShapeTools::groupSharedTopology(aResultShape);
281 if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
282 // if the result has only one sub-shape, discard the compound
283 GeomAPI_ShapeIterator aSubIt(aResultShape);
284 GeomShapePtr aSub = aSubIt.current();
292 ResultBodyPtr aResultBody = document()->createBody(data());
293 std::list<GeomShapePtr> anOldShapes;
294 anOldShapes.push_back(aBaseShape);
295 aResultBody->storeModified(anOldShapes, aResultShape, aMakeShapeList);
296 for (std::set<GeomAPI_Shape::ShapeType>::iterator aTypeIter = aTypes.begin();
297 aTypeIter != aTypes.end();
300 aResultBody->loadDeletedShapes(aMakeShapeList, aBaseShape, *aTypeIter);
303 aResultBody->loadModifiedShapes(aMakeShapeList,
305 GeomAPI_Shape::FACE);
306 aResultBody->loadModifiedShapes(aMakeShapeList,
308 GeomAPI_Shape::EDGE);
309 aResultBody->loadModifiedShapes(aMakeShapeList,
311 GeomAPI_Shape::VERTEX);
312 setResult(aResultBody);