Salome HOME
Adapt content of RST files to old Sphinx (1.2.3)
[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_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 int aNumOfSubs = aResultBody->numberOfSubs();
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     for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
99       GeomShapePtr aSubShape = anIt.current();
100       if(aNumOfSubs == 0) {
101         aSubShapesToKeepAttrList->append(aContext, aSubShape);
102       } else {
103         for (int anIndex = 0; anIndex < aResultBody->numberOfSubs(); ++anIndex) {
104           ResultBodyPtr aSubResult = aResultBody->subResult(anIndex);
105           if(aSubResult->shape()->isEqual(aSubShape)) {
106             aSubShapesToKeepAttrList->append(aSubResult, aSubShape);
107             break;
108           }
109         }
110       }
111     }
112   }
113   else if (theID == SUBSHAPES_TO_KEEP_ID())
114   {
115     aSubShapesToRemoveAttrList->clear();
116
117     if (!aBaseShape.get()) {
118       return;
119     }
120
121     int anIndex;
122     const int aSubsToKeepNb = aSubShapesToKeepAttrList->size();
123     for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
124       GeomShapePtr aSubShape = anIt.current();
125       for(anIndex = 0; anIndex < aSubsToKeepNb; ++anIndex) {
126         AttributeSelectionPtr anAttrSelectionInList = aSubShapesToKeepAttrList->value(anIndex);
127         GeomShapePtr aSubShapeToKeep = anAttrSelectionInList->value();
128         if (aSubShapeToKeep.get() && aSubShapeToKeep->isEqual(aSubShape)) {
129           break;
130         }
131       }
132
133       if (anIndex == aSubsToKeepNb) {
134         if(aNumOfSubs == 0) {
135           aSubShapesToRemoveAttrList->append(aContext, aSubShape);
136         } else {
137           for (int anIndex = 0; anIndex < aResultBody->numberOfSubs(); ++anIndex) {
138             ResultBodyPtr aSubResult = aResultBody->subResult(anIndex);
139             if(aSubResult->shape()->isEqual(aSubShape)) {
140               aSubShapesToRemoveAttrList->append(aSubResult, aSubShape);
141               break;
142             }
143           }
144         }
145       }
146     }
147   }
148   else if (theID == SUBSHAPES_TO_REMOVE_ID())
149   {
150     aSubShapesToKeepAttrList->clear();
151
152     if (!aBaseShape.get()) {
153       return;
154     }
155
156     int anIndex;
157     const int aSubsToRemoveNb = aSubShapesToRemoveAttrList->size();
158     for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
159       GeomShapePtr aSubShape = anIt.current();
160       for(anIndex = 0; anIndex < aSubsToRemoveNb; ++anIndex) {
161         AttributeSelectionPtr anAttrSelectionInList = aSubShapesToRemoveAttrList->value(anIndex);
162         GeomShapePtr aSubShapeToRemove = anAttrSelectionInList->value();
163         if (aSubShapeToRemove.get() && aSubShapeToRemove->isEqual(aSubShape)) {
164           break;
165         }
166       }
167
168       if (anIndex == aSubsToRemoveNb) {
169         if(aNumOfSubs == 0) {
170           aSubShapesToKeepAttrList->append(aContext, aSubShape);
171         } else {
172           for (int anIndex = 0; anIndex < aResultBody->numberOfSubs(); ++anIndex) {
173             ResultBodyPtr aSubResult = aResultBody->subResult(anIndex);
174             if(aSubResult->shape()->isEqual(aSubShape)) {
175               aSubShapesToKeepAttrList->append(aSubResult, aSubShape);
176               break;
177             }
178           }
179         }
180       }
181     }
182   }
183
184   myChangedInCode = false;
185 }
186
187 //==================================================================================================
188 void FeaturesPlugin_RemoveSubShapes::execute()
189 {
190   // Get base shape and sub-shapes list.
191   AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
192   AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_TO_KEEP_ID());
193   if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
194     return;
195   }
196
197   // Get base shape.
198   GeomShapePtr aBaseShape = aShapeAttrSelection->value();
199
200   GeomShapePtr aResultShape;
201   int aSubsNb = aSubShapesAttrList->size();
202   if(aSubsNb > 1) {
203     if(!aBaseShape.get()) {
204       return;
205     }
206     aResultShape = aBaseShape->emptyCopied();
207
208     // Copy sub-shapes from list to new shape.
209     for(int anIndex = 0; anIndex < aSubsNb; ++anIndex) {
210       AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
211       GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
212       GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
213     }
214   } else if(aSubsNb == 1) {
215     AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(0);
216     aResultShape = anAttrSelectionInList->value();
217   }
218   // deleted and copied must be jointed to one list which keeps all the history
219   GeomAlgoAPI_MakeShapeList aMakeShapeList;
220
221   // find all removed shapes
222   std::shared_ptr<GeomAlgoAPI_MakeShapeCustom> aDeletedSubs(new GeomAlgoAPI_MakeShapeCustom);
223   std::set<GeomAPI_Shape::ShapeType> aTypes; // types that where removed
224   aTypes.insert(GeomAPI_Shape::FACE);
225   for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
226     if (!anIt.current().get() || anIt.current()->isNull())
227       continue;
228     int anIndex;
229     for(anIndex = 0; anIndex < aSubsNb; ++anIndex) {
230       AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
231       GeomShapePtr aLeftShape = anAttrSelectionInList->value();
232       if (anIt.current()->isEqual(aLeftShape)) {
233         break; // found in a left-list
234       }
235     }
236     if (anIndex == aSubsNb) { // not found in left
237       aDeletedSubs->addDeleted(anIt.current());
238       aTypes.insert(anIt.current()->shapeType());
239       if (anIt.current()->shapeType() != GeomAPI_Shape::FACE) {
240         GeomAPI_ShapeExplorer aFaces(anIt.current(), GeomAPI_Shape::FACE);
241         for(; aFaces.more(); aFaces.next())
242           aDeletedSubs->addDeleted(aFaces.current());
243       }
244     }
245   }
246   aMakeShapeList.appendAlgo(aDeletedSubs);
247
248   std::shared_ptr<GeomAlgoAPI_Copy> aCopy(new GeomAlgoAPI_Copy(aResultShape));
249   aResultShape = aCopy->shape();
250   aMakeShapeList.appendAlgo(aCopy);
251
252   // Store result.
253   ResultBodyPtr aResultBody = document()->createBody(data());
254   aResultBody->storeModified(aBaseShape, aResultShape, 1);
255   std::set<GeomAPI_Shape::ShapeType>::iterator aTypeIter = aTypes.begin();
256   for(; aTypeIter != aTypes.end(); aTypeIter++)
257     aResultBody->loadDeletedShapes(&aMakeShapeList, aBaseShape, *aTypeIter, 1);
258   aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, aBaseShape, GeomAPI_Shape::FACE,
259           2, "Modified_Face", *aMakeShapeList.mapOfSubShapes().get(), true, false, true);
260   aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, aBaseShape, GeomAPI_Shape::EDGE,
261           3, "Modified_Edge", *aMakeShapeList.mapOfSubShapes().get(), false, false, true);
262   aResultBody->loadAndOrientModifiedShapes(&aMakeShapeList, aBaseShape, GeomAPI_Shape::VERTEX,
263           4, "Modified_Vertex", *aMakeShapeList.mapOfSubShapes().get());
264   setResult(aResultBody);
265 }