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;
90 if(theID == BASE_SHAPE_ID()) {
91 aSubShapesToKeepAttrList->clear();
92 aSubShapesToRemoveAttrList->clear();
94 if (!aBaseShape.get()) {
98 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
99 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
101 GeomShapePtr aSubShape = *anIt;
103 aSubShapesToKeepAttrList->append(aContext, aSubShape);
105 std::list<ResultPtr> anAllSubs;
106 ModelAPI_Tools::allSubs(aResultBody, anAllSubs);
107 std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
108 for(; aSubsIt != anAllSubs.end(); aSubsIt++) {
109 ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
110 if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
111 aSubShapesToKeepAttrList->append(aSub, aSubShape);
118 else if (theID == SUBSHAPES_TO_KEEP_ID())
120 aSubShapesToRemoveAttrList->clear();
122 if (!aBaseShape.get()) {
127 const int aSubsToKeepNb = aSubShapesToKeepAttrList->size();
128 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
129 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
131 GeomShapePtr aSubShape = *anIt;
132 for(anIndex = 0; anIndex < aSubsToKeepNb; ++anIndex) {
133 AttributeSelectionPtr anAttrSelectionInList = aSubShapesToKeepAttrList->value(anIndex);
134 GeomShapePtr aSubShapeToKeep = anAttrSelectionInList->value();
135 if (aSubShapeToKeep.get() && aSubShapeToKeep->isEqual(aSubShape)) {
140 if (anIndex == aSubsToKeepNb) {
142 aSubShapesToRemoveAttrList->append(aContext, aSubShape);
144 std::list<ResultPtr> anAllSubs;
145 ModelAPI_Tools::allSubs(aResultBody, anAllSubs);
146 std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
147 for(; aSubsIt != anAllSubs.end(); aSubsIt++) {
148 ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
149 if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
150 aSubShapesToRemoveAttrList->append(aSub, aSubShape);
158 else if (theID == SUBSHAPES_TO_REMOVE_ID())
160 aSubShapesToKeepAttrList->clear();
162 if (!aBaseShape.get()) {
167 const int aSubsToRemoveNb = aSubShapesToRemoveAttrList->size();
168 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
169 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
171 GeomShapePtr aSubShape = *anIt;
172 for(anIndex = 0; anIndex < aSubsToRemoveNb; ++anIndex) {
173 AttributeSelectionPtr anAttrSelectionInList = aSubShapesToRemoveAttrList->value(anIndex);
174 GeomShapePtr aSubShapeToRemove = anAttrSelectionInList->value();
175 if (aSubShapeToRemove.get() && aSubShapeToRemove->isEqual(aSubShape)) {
180 if (anIndex == aSubsToRemoveNb) {
182 aSubShapesToKeepAttrList->append(aContext, aSubShape);
184 std::list<ResultPtr> anAllSubs;
185 ModelAPI_Tools::allSubs(aResultBody, anAllSubs);
186 std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
187 for(; aSubsIt != anAllSubs.end(); aSubsIt++) {
188 ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
189 if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
190 aSubShapesToKeepAttrList->append(aSub, aSubShape);
199 myChangedInCode = false;
202 //==================================================================================================
203 void FeaturesPlugin_RemoveSubShapes::execute()
205 // Get base shape and sub-shapes list.
206 AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
207 AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_TO_KEEP_ID());
208 if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
213 GeomShapePtr aBaseShape = aShapeAttrSelection->value();
215 GeomShapePtr aResultShape;
216 int aSubsNb = aSubShapesAttrList->size();
218 if(!aBaseShape.get()) {
221 aResultShape = aBaseShape->emptyCopied();
223 // Copy sub-shapes from list to new shape.
224 for(int anIndex = 0; anIndex < aSubsNb; ++anIndex) {
225 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
226 GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
227 GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
229 } else if(aSubsNb == 1) {
230 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(0);
231 aResultShape = anAttrSelectionInList->value();
233 // deleted and copied must be jointed to one list which keeps all the history
234 std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList());
236 // find all removed shapes
237 std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aDeletedSubs(new GeomAlgoAPI_MakeShapeCustom);
238 std::set<GeomAPI_Shape::ShapeType> aTypes; // types that where removed
239 aTypes.insert(GeomAPI_Shape::FACE);
241 std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
242 for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt) {
243 GeomShapePtr aSubShape = *anIt;
244 if (!aSubShape.get() || aSubShape->isNull())
248 for(anIndex = 0; anIndex < aSubsNb; ++anIndex) {
249 AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
250 GeomShapePtr aLeftShape = anAttrSelectionInList->value();
251 if (aSubShape->isEqual(aLeftShape)) {
252 break; // found in a left-list
255 if (anIndex == aSubsNb) { // not found in left
256 aDeletedSubs->addDeleted(aSubShape);
257 aTypes.insert(aSubShape->shapeType());
258 if (aSubShape->shapeType() != GeomAPI_Shape::FACE) {
259 GeomAPI_ShapeExplorer aFaces(aSubShape, GeomAPI_Shape::FACE);
260 for(; aFaces.more(); aFaces.next())
261 aDeletedSubs->addDeleted(aFaces.current());
265 aMakeShapeList->appendAlgo(aDeletedSubs);
267 std::shared_ptr<GeomAlgoAPI_Copy> aCopy(new GeomAlgoAPI_Copy(aResultShape));
268 aResultShape = aCopy->shape();
269 aMakeShapeList->appendAlgo(aCopy);
271 if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
272 aResultShape = GeomAlgoAPI_ShapeTools::groupSharedTopology(aResultShape);
273 if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
274 // if the result has only one sub-shape, discard the compound
275 GeomAPI_ShapeIterator aSubIt(aResultShape);
276 GeomShapePtr aSub = aSubIt.current();
284 ResultBodyPtr aResultBody = document()->createBody(data());
285 aResultBody->storeModified(aBaseShape, aResultShape);
286 for (std::set<GeomAPI_Shape::ShapeType>::iterator aTypeIter = aTypes.begin();
287 aTypeIter != aTypes.end();
290 aResultBody->loadDeletedShapes(aMakeShapeList, aBaseShape, *aTypeIter);
293 aResultBody->loadModifiedShapes(aMakeShapeList,
295 GeomAPI_Shape::FACE);
296 aResultBody->loadModifiedShapes(aMakeShapeList,
298 GeomAPI_Shape::EDGE);
299 aResultBody->loadModifiedShapes(aMakeShapeList,
301 GeomAPI_Shape::VERTEX);
302 setResult(aResultBody);