1 // Copyright (C) 2014-2019 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 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
105 GeomShapePtr aSubShape = *anIt;
107 aSubShapesToKeepAttrList->append(aContext, aSubShape);
109 std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
110 for(; aSubsIt != anAllSubs.end(); aSubsIt++) {
111 ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
112 if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
113 aSubShapesToKeepAttrList->append(aSub, aSubShape);
120 else if (theID == SUBSHAPES_TO_KEEP_ID())
122 aSubShapesToRemoveAttrList->clear();
124 if (!aBaseShape.get()) {
129 // optimization: collect selection attribute values into a map
130 const int aSubsToKeepNb = aSubShapesToKeepAttrList->size();
131 GeomAPI_DataMapOfShapeShape aSubShapesToKeep;
132 for(anIndex = 0; anIndex < aSubsToKeepNb; ++anIndex) {
133 AttributeSelectionPtr anAttrSelectionInList = aSubShapesToKeepAttrList->value(anIndex);
134 GeomShapePtr aSubShapeToKeep = anAttrSelectionInList->value();
135 if (aSubShapeToKeep.get())
136 aSubShapesToKeep.bind(aSubShapeToKeep, aSubShapeToKeep);
139 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
140 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
142 GeomShapePtr aSubShape = *anIt;
143 if (aSubShapesToKeep.isBound(aSubShape))
147 aSubShapesToRemoveAttrList->append(aContext, aSubShape);
150 std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
151 for (; aSubsIt != anAllSubs.end(); aSubsIt++) {
152 ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
153 if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
154 aSubShapesToRemoveAttrList->append(aSub, aSubShape);
161 else if (theID == SUBSHAPES_TO_REMOVE_ID())
163 aSubShapesToKeepAttrList->clear();
165 if (!aBaseShape.get()) {
170 const int aSubsToRemoveNb = aSubShapesToRemoveAttrList->size();
171 GeomAPI_DataMapOfShapeShape aSubShapesToRemove;
172 for(anIndex = 0; anIndex < aSubsToRemoveNb; ++anIndex) {
173 AttributeSelectionPtr anAttrSelectionInList = aSubShapesToRemoveAttrList->value(anIndex);
174 GeomShapePtr aSubShapeToRemove = anAttrSelectionInList->value();
175 if (aSubShapeToRemove.get())
176 aSubShapesToRemove.bind(aSubShapeToRemove, aSubShapeToRemove);
180 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
181 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
183 GeomShapePtr aSubShape = *anIt;
184 if (aSubShapesToRemove.isBound(aSubShape))
188 aSubShapesToKeepAttrList->append(aContext, aSubShape);
191 std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
192 for (; aSubsIt != anAllSubs.end(); aSubsIt++) {
193 ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
194 if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
195 aSubShapesToKeepAttrList->append(aSub, aSubShape);
204 myChangedInCode = false;
207 //==================================================================================================
208 void FeaturesPlugin_RemoveSubShapes::execute()
210 // Get base shape and sub-shapes list.
211 AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
212 AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_TO_KEEP_ID());
213 if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
218 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
220 GeomShapePtr aResultShape;
221 int aSubsNb = aSubShapesAttrList->size();
223 if(!aBaseShape.get()) {
226 aResultShape = aBaseShape->emptyCopied();
228 // Copy sub-shapes from list to new shape.
229 for(int anIndex = 0; anIndex < aSubsNb; ++anIndex) {
230 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
231 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
232 GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
234 } else if(aSubsNb == 1) {
235 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(0);
236 aResultShape = anAttrSelectionInList->value();
238 // deleted and copied must be jointed to one list which keeps all the history
239 std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
241 // find all removed shapes
242 std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aDeletedSubs(new GeomAlgoAPI_MakeShapeCustom);
243 std::set<GeomAPI_Shape::ShapeType> aTypes; // types that where removed
244 aTypes.insert(GeomAPI_Shape::FACE);
246 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
247 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt) {
248 GeomShapePtr aSubShape = *anIt;
249 if (!aSubShape.get() || aSubShape->isNull())
253 for(anIndex = 0; anIndex < aSubsNb; ++anIndex) {
254 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
255 GeomShapePtr aLeftShape = anAttrSelectionInList->value();
256 if (aSubShape->isEqual(aLeftShape)) {
257 break; // found in a left-list
260 if (anIndex == aSubsNb) { // not found in left
261 aDeletedSubs->addDeleted(aSubShape);
262 aTypes.insert(aSubShape->shapeType());
263 if (aSubShape->shapeType() != GeomAPI_Shape::FACE) {
264 GeomAPI_ShapeExplorer aFaces(aSubShape, GeomAPI_Shape::FACE);
265 for(; aFaces.more(); aFaces.next())
266 aDeletedSubs->addDeleted(aFaces.current());
270 aMakeShapeList->appendAlgo(aDeletedSubs);
272 std::shared_ptr<GeomAlgoAPI_Copy> aCopy(new GeomAlgoAPI_Copy(aResultShape));
273 aResultShape = aCopy->shape();
274 aMakeShapeList->appendAlgo(aCopy);
276 if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
277 aResultShape = GeomAlgoAPI_ShapeTools::groupSharedTopology(aResultShape);
278 if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
279 // if the result has only one sub-shape, discard the compound
280 GeomAPI_ShapeIterator aSubIt(aResultShape);
281 GeomShapePtr aSub = aSubIt.current();
289 ResultBodyPtr aResultBody = document()->createBody(data());
290 aResultBody->storeModified(aBaseShape, aResultShape);
291 for (std::set<GeomAPI_Shape::ShapeType>::iterator aTypeIter = aTypes.begin();
292 aTypeIter != aTypes.end();
295 aResultBody->loadDeletedShapes(aMakeShapeList, aBaseShape, *aTypeIter);
298 aResultBody->loadModifiedShapes(aMakeShapeList,
300 GeomAPI_Shape::FACE);
301 aResultBody->loadModifiedShapes(aMakeShapeList,
303 GeomAPI_Shape::EDGE);
304 aResultBody->loadModifiedShapes(aMakeShapeList,
306 GeomAPI_Shape::VERTEX);
307 setResult(aResultBody);