]> SALOME platform Git repositories - modules/shaper.git/blob - src/FeaturesPlugin/FeaturesPlugin_RemoveSubShapes.cpp
Salome HOME
Merge remote-tracking branch 'remotes/origin/HigherLevelObjectsHistory'
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_RemoveSubShapes.cpp
1 // Copyright (C) 2014-2019  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 email : webmaster.salome@opencascade.com
18 //
19
20 #include "FeaturesPlugin_RemoveSubShapes.h"
21
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>
29
30 #include <GeomAPI_ShapeIterator.h>
31 #include <GeomAPI_ShapeExplorer.h>
32
33 #include <GeomAlgoAPI_Copy.h>
34 #include <GeomAlgoAPI_ShapeBuilder.h>
35 #include <GeomAlgoAPI_ShapeTools.h>
36 #include <GeomAlgoAPI_MakeShapeCustom.h>
37
38
39 //==================================================================================================
40 FeaturesPlugin_RemoveSubShapes::FeaturesPlugin_RemoveSubShapes()
41 : myChangedInCode(false)
42 {
43 }
44
45 //==================================================================================================
46 void FeaturesPlugin_RemoveSubShapes::initAttributes()
47 {
48   data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeSelection::typeId());
49
50   data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
51
52   data()->addAttribute(SUBSHAPES_TO_KEEP_ID(), ModelAPI_AttributeSelectionList::typeId());
53
54   data()->addAttribute(SUBSHAPES_TO_REMOVE_ID(), ModelAPI_AttributeSelectionList::typeId());
55 }
56
57 void FeaturesPlugin_RemoveSubShapes::attributeChanged(const std::string& theID)
58 {
59   ModelAPI_Feature::attributeChanged(theID);
60
61   if (myChangedInCode) return;
62
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())
69   {
70     return;
71   }
72
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();
79     return;
80   }
81   const bool isHasSubs = ModelAPI_Tools::hasSubResults(aResultBody);
82
83   GeomShapePtr aBaseShape = aShapeAttrSelection->value();
84   if(!aBaseShape.get()) {
85     aBaseShape = aContext->shape();
86   }
87
88   myChangedInCode = true;
89
90   if(theID == BASE_SHAPE_ID()) {
91     aSubShapesToKeepAttrList->clear();
92     aSubShapesToRemoveAttrList->clear();
93
94     if (!aBaseShape.get()) {
95       return;
96     }
97
98     std::list<GeomShapePtr> aSubShapes = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aBaseShape);
99     for (ListOfShape::const_iterator anIt = aSubShapes.cbegin(); anIt != aSubShapes.cend(); ++anIt)
100     {
101       GeomShapePtr aSubShape = *anIt;
102       if(!isHasSubs) {
103         aSubShapesToKeepAttrList->append(aContext, aSubShape);
104       } else {
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);
112             break;
113           }
114         }
115       }
116     }
117   }
118   else if (theID == SUBSHAPES_TO_KEEP_ID())
119   {
120     aSubShapesToRemoveAttrList->clear();
121
122     if (!aBaseShape.get()) {
123       return;
124     }
125
126     int anIndex;
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)
130     {
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)) {
136           break;
137         }
138       }
139
140       if (anIndex == aSubsToKeepNb) {
141         if(!isHasSubs) {
142           aSubShapesToRemoveAttrList->append(aContext, aSubShape);
143         } else {
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);
151               break;
152             }
153           }
154         }
155       }
156     }
157   }
158   else if (theID == SUBSHAPES_TO_REMOVE_ID())
159   {
160     aSubShapesToKeepAttrList->clear();
161
162     if (!aBaseShape.get()) {
163       return;
164     }
165
166     int anIndex;
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)
170     {
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)) {
176           break;
177         }
178       }
179
180       if (anIndex == aSubsToRemoveNb) {
181         if(!isHasSubs) {
182           aSubShapesToKeepAttrList->append(aContext, aSubShape);
183         } else {
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);
191               break;
192             }
193           }
194         }
195       }
196     }
197   }
198
199   myChangedInCode = false;
200 }
201
202 //==================================================================================================
203 void FeaturesPlugin_RemoveSubShapes::execute()
204 {
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()) {
209     return;
210   }
211
212   // Get base shape.
213   GeomShapePtr aBaseShape = aShapeAttrSelection->value();
214
215   GeomShapePtr aResultShape;
216   int aSubsNb = aSubShapesAttrList->size();
217   if(aSubsNb > 1) {
218     if(!aBaseShape.get()) {
219       return;
220     }
221     aResultShape = aBaseShape->emptyCopied();
222
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);
228     }
229   } else if(aSubsNb == 1) {
230     AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(0);
231     aResultShape = anAttrSelectionInList->value();
232   }
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());
235
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);
240
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())
245       continue;
246
247     int anIndex;
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
253       }
254     }
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());
262       }
263     }
264   }
265   aMakeShapeList->appendAlgo(aDeletedSubs);
266
267   std::shared_ptr<GeomAlgoAPI_Copy> aCopy(new GeomAlgoAPI_Copy(aResultShape));
268   aResultShape = aCopy->shape();
269   aMakeShapeList->appendAlgo(aCopy);
270
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();
277       aSubIt.next();
278       if (!aSubIt.more())
279         aResultShape = aSub;
280     }
281   }
282
283   // Store result.
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();
288        ++aTypeIter)
289   {
290     aResultBody->loadDeletedShapes(aMakeShapeList, aBaseShape, *aTypeIter);
291   }
292
293   aResultBody->loadModifiedShapes(aMakeShapeList,
294                                   aBaseShape,
295                                   GeomAPI_Shape::FACE);
296   aResultBody->loadModifiedShapes(aMakeShapeList,
297                                   aBaseShape,
298                                   GeomAPI_Shape::EDGE);
299   aResultBody->loadModifiedShapes(aMakeShapeList,
300                                   aBaseShape,
301                                   GeomAPI_Shape::VERTEX);
302   setResult(aResultBody);
303 }