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