]> SALOME platform Git repositories - modules/shaper.git/blob - src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp
Salome HOME
Fix issue related to selection of compsolid in the RemoveSubShapes feature
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_RemoveSubShapes.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "FeaturesPlugin_RemoveSubShapes.h"
22
23 #include <ModelAPI_AttributeSelectionList.h>
24 #include <ModelAPI_AttributeString.h>
25 #include <ModelAPI_ResultBody.h>
26 #include <ModelAPI_ResultConstruction.h>
27 #include <ModelAPI_Session.h>
28 #include <ModelAPI_Tools.h>
29 #include <ModelAPI_Validator.h>
30
31 #include <GeomAPI_ShapeIterator.h>
32 #include <GeomAPI_ShapeExplorer.h>
33
34 #include <GeomAlgoAPI_Copy.h>
35 #include <GeomAlgoAPI_ShapeBuilder.h>
36 #include <GeomAlgoAPI_ShapeTools.h>
37 #include <GeomAlgoAPI_MakeShapeCustom.h>
38
39
40 //==================================================================================================
41 FeaturesPlugin_RemoveSubShapes::FeaturesPlugin_RemoveSubShapes()
42 : myChangedInCode(false)
43 {
44 }
45
46 //==================================================================================================
47 void FeaturesPlugin_RemoveSubShapes::initAttributes()
48 {
49   data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeSelection::typeId());
50
51   data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
52
53   data()->addAttribute(SUBSHAPES_TO_KEEP_ID(), ModelAPI_AttributeSelectionList::typeId());
54
55   data()->addAttribute(SUBSHAPES_TO_REMOVE_ID(), ModelAPI_AttributeSelectionList::typeId());
56 }
57
58 void FeaturesPlugin_RemoveSubShapes::attributeChanged(const std::string& theID)
59 {
60   ModelAPI_Feature::attributeChanged(theID);
61
62   if (myChangedInCode) return;
63
64   AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
65   AttributeSelectionListPtr aSubShapesToKeepAttrList = selectionList(SUBSHAPES_TO_KEEP_ID());
66   AttributeSelectionListPtr aSubShapesToRemoveAttrList = selectionList(SUBSHAPES_TO_REMOVE_ID());
67   if (!aShapeAttrSelection.get()
68       || !aSubShapesToKeepAttrList.get()
69       || !aSubShapesToRemoveAttrList.get())
70   {
71     return;
72   }
73
74   ResultPtr aContext = aShapeAttrSelection->context();
75   ResultBodyPtr aResultBody =
76     std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
77   if (!aResultBody.get()) {
78     aSubShapesToKeepAttrList->clear();
79     aSubShapesToRemoveAttrList->clear();
80     return;
81   }
82   const bool isHasSubs = ModelAPI_Tools::hasSubResults(aResultBody);
83
84   GeomShapePtr aBaseShape = aShapeAttrSelection->value();
85   if(!aBaseShape.get()) {
86     aBaseShape = aContext->shape();
87   }
88
89   myChangedInCode = true;
90
91   if(theID == BASE_SHAPE_ID()) {
92     aSubShapesToKeepAttrList->clear();
93     aSubShapesToRemoveAttrList->clear();
94
95     if (!aBaseShape.get()) {
96       return;
97     }
98
99     std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
100     for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
101     {
102       GeomShapePtr aSubShape = *anIt;
103       if(!isHasSubs) {
104         aSubShapesToKeepAttrList->append(aContext, aSubShape);
105       } else {
106         std::list<ResultPtr> anAllSubs;
107         ModelAPI_Tools::allSubs(aResultBody, anAllSubs);
108         std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
109         for(; aSubsIt != anAllSubs.end(); aSubsIt++) {
110           ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
111           if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
112             aSubShapesToKeepAttrList->append(aSub, aSubShape);
113             break;
114           }
115         }
116       }
117     }
118   }
119   else if (theID == SUBSHAPES_TO_KEEP_ID())
120   {
121     aSubShapesToRemoveAttrList->clear();
122
123     if (!aBaseShape.get()) {
124       return;
125     }
126
127     int anIndex;
128     const int aSubsToKeepNb = aSubShapesToKeepAttrList->size();
129     std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
130     for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
131     {
132       GeomShapePtr aSubShape = *anIt;
133       for(anIndex = 0; anIndex < aSubsToKeepNb; ++anIndex) {
134         AttributeSelectionPtr anAttrSelectionInList = aSubShapesToKeepAttrList->value(anIndex);
135         GeomShapePtr aSubShapeToKeep = anAttrSelectionInList->value();
136         if (aSubShapeToKeep.get() &&
137            (aSubShapeToKeep->isEqual(aSubShape) || aSubShapeToKeep->isSubShape(aSubShape))) {
138           break;
139         }
140       }
141
142       if (anIndex == aSubsToKeepNb) {
143         if(!isHasSubs) {
144           aSubShapesToRemoveAttrList->append(aContext, aSubShape);
145         } else {
146           std::list<ResultPtr> anAllSubs;
147           ModelAPI_Tools::allSubs(aResultBody, anAllSubs);
148           std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
149           for(; aSubsIt != anAllSubs.end(); aSubsIt++) {
150             ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
151             if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
152               aSubShapesToRemoveAttrList->append(aSub, aSubShape);
153               break;
154             }
155           }
156         }
157       }
158     }
159   }
160   else if (theID == SUBSHAPES_TO_REMOVE_ID())
161   {
162     aSubShapesToKeepAttrList->clear();
163
164     if (!aBaseShape.get()) {
165       return;
166     }
167
168     int anIndex;
169     const int aSubsToRemoveNb = aSubShapesToRemoveAttrList->size();
170     std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
171     for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
172     {
173       GeomShapePtr aSubShape = *anIt;
174       for(anIndex = 0; anIndex < aSubsToRemoveNb; ++anIndex) {
175         AttributeSelectionPtr anAttrSelectionInList = aSubShapesToRemoveAttrList->value(anIndex);
176         GeomShapePtr aSubShapeToRemove = anAttrSelectionInList->value();
177         if (aSubShapeToRemove.get() &&
178            (aSubShapeToRemove->isEqual(aSubShape) || aSubShapeToRemove->isSubShape(aSubShape))) {
179           break;
180         }
181       }
182
183       if (anIndex == aSubsToRemoveNb) {
184         if(!isHasSubs) {
185           aSubShapesToKeepAttrList->append(aContext, aSubShape);
186         } else {
187           std::list<ResultPtr> anAllSubs;
188           ModelAPI_Tools::allSubs(aResultBody, anAllSubs);
189           std::list<ResultPtr>::iterator aSubsIt = anAllSubs.begin();
190           for(; aSubsIt != anAllSubs.end(); aSubsIt++) {
191             ResultBodyPtr aSub = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aSubsIt);
192             if (aSub && aSub->shape().get() && aSub->shape()->isSubShape(aSubShape)) {
193               aSubShapesToKeepAttrList->append(aSub, aSubShape);
194               break;
195             }
196           }
197         }
198       }
199     }
200   }
201
202   myChangedInCode = false;
203 }
204
205 //==================================================================================================
206 void FeaturesPlugin_RemoveSubShapes::execute()
207 {
208   // Get base shape and sub-shapes list.
209   AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
210   AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_TO_KEEP_ID());
211   if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
212     return;
213   }
214
215   // Get base shape.
216   GeomShapePtr aBaseShape = aShapeAttrSelection->value();
217
218   GeomShapePtr aResultShape;
219   int aSubsNb = aSubShapesAttrList->size();
220   if(aSubsNb > 1) {
221     if(!aBaseShape.get()) {
222       return;
223     }
224     aResultShape = aBaseShape->emptyCopied();
225
226     // Copy sub-shapes from list to new shape.
227     for(int anIndex = 0; anIndex < aSubsNb; ++anIndex) {
228       AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
229       GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
230       GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
231     }
232   } else if(aSubsNb == 1) {
233     AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(0);
234     aResultShape = anAttrSelectionInList->value();
235   }
236   // deleted and copied must be jointed to one list which keeps all the history
237   GeomAlgoAPI_MakeShapeList aMakeShapeList;
238
239   // find all removed shapes
240   std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aDeletedSubs(new GeomAlgoAPI_MakeShapeCustom);
241   std::set<GeomAPI_Shape::ShapeType> aTypes; // types that where removed
242   aTypes.insert(GeomAPI_Shape::FACE);
243
244   std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
245   for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt) {
246     GeomShapePtr aSubShape = *anIt;
247     if (!aSubShape.get() || aSubShape->isNull())
248       continue;
249
250     int anIndex;
251     for(anIndex = 0; anIndex < aSubsNb; ++anIndex) {
252       AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
253       GeomShapePtr aLeftShape = anAttrSelectionInList->value();
254       if (aSubShape->isEqual(aLeftShape)) {
255         break; // found in a left-list
256       }
257     }
258     if (anIndex == aSubsNb) { // not found in left
259       aDeletedSubs->addDeleted(aSubShape);
260       aTypes.insert(aSubShape->shapeType());
261       if (aSubShape->shapeType() != GeomAPI_Shape::FACE) {
262         GeomAPI_ShapeExplorer aFaces(aSubShape, GeomAPI_Shape::FACE);
263         for(; aFaces.more(); aFaces.next())
264           aDeletedSubs->addDeleted(aFaces.current());
265       }
266     }
267   }
268   aMakeShapeList.appendAlgo(aDeletedSubs);
269
270   std::shared_ptr<GeomAlgoAPI_Copy> aCopy(new GeomAlgoAPI_Copy(aResultShape));
271   aResultShape = aCopy->shape();
272   aMakeShapeList.appendAlgo(aCopy);
273
274   if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
275     aResultShape = GeomAlgoAPI_ShapeTools::groupSharedTopology(aResultShape);
276     if (aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
277       // if the result has only one sub-shape, discard the compound
278       GeomAPI_ShapeIterator aSubIt(aResultShape);
279       GeomShapePtr aSub = aSubIt.current();
280       aSubIt.next();
281       if (!aSubIt.more())
282         aResultShape = aSub;
283     }
284   }
285
286   // Store result.
287   ResultBodyPtr aResultBody = document()->createBody(data());
288   aResultBody->storeModified(aBaseShape, aResultShape, 1);
289   std::set<GeomAPI_Shape::ShapeType>::iterator aTypeIter = aTypes.begin();
290   for(; aTypeIter != aTypes.end(); aTypeIter++)
291     aResultBody->loadDeletedShapes(&aMakeShapeList, aBaseShape, *aTypeIter, 1);
292   aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, aBaseShape, GeomAPI_Shape::FACE,
293       2, "Modified_Face", *aMakeShapeList.mapOfSubShapes().get(), true, false, true);
294   aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, aBaseShape, GeomAPI_Shape::EDGE,
295       3, "Modified_Edge", *aMakeShapeList.mapOfSubShapes().get(), false, false, true);
296   aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, aBaseShape, GeomAPI_Shape::VERTEX,
297       4, "Modified_Vertex", *aMakeShapeList.mapOfSubShapes().get());
298   setResult(aResultBody);
299 }