Salome HOME
26451: Import Result with Groups
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_ImportResult.cpp
1 // Copyright (C) 2017-2021  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_ImportResult.h"
21
22 #include <ModelAPI_AttributeSelectionList.h>
23 #include <ModelAPI_AttributeRefList.h>
24 #include <ModelAPI_ResultBody.h>
25 #include <ModelAPI_ResultGroup.h>
26 #include <ModelAPI_Session.h>
27 #include <ModelAPI_ResultPart.h>
28 #include <ModelAPI_Tools.h>
29 #include <Events_InfoMessage.h>
30 #include <GeomAPI_ShapeExplorer.h>
31
32 void FeaturesPlugin_ImportResult::initAttributes()
33 {
34   data()->addAttribute(OBJECTS(), ModelAPI_AttributeSelectionList::typeId());
35
36   AttributePtr aFeaturesAttribute =
37     data()->addAttribute(FEATURES_ID(),
38                          ModelAPI_AttributeRefList::typeId());
39   aFeaturesAttribute->setIsArgument(false);
40
41   ModelAPI_Session::get()->validators()->registerNotObligatory(
42       getKind(), FEATURES_ID());
43 }
44
45 void FeaturesPlugin_ImportResult::execute()
46 {
47   // Process groups/fields
48   std::shared_ptr<ModelAPI_AttributeRefList> aRefListOfGroups =
49       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(data()->attribute(FEATURES_ID()));
50
51   // Remove previous groups/fields stored in RefList
52   //std::list<ObjectPtr> anGroupList = aRefListOfGroups->list();
53   //std::list<ObjectPtr>::iterator anGroupIt = anGroupList.begin();
54   const std::list<ObjectPtr>& anGroupList = aRefListOfGroups->list();
55   std::list<ObjectPtr>::const_iterator anGroupIt = anGroupList.begin();
56   for (; anGroupIt != anGroupList.end(); ++anGroupIt) {
57     std::shared_ptr<ModelAPI_Feature> aFeature = ModelAPI_Feature::feature(*anGroupIt);
58     if (aFeature)
59       document()->removeFeature(aFeature);
60   }
61
62   aRefListOfGroups->clear();
63
64   std::set<ResultPtr> aGlobalResultsCashed; // cash to speed up searching in all results selected
65   std::list<ResultGroupPtr> aGroups;
66
67   std::list<ResultPtr> aResults;
68
69   AttributeSelectionListPtr aList = selectionList(OBJECTS());
70   int aResultIndex = 0;
71   for (int aSelIndex = 0; aSelIndex < aList->size(); aSelIndex++)
72   {
73     AttributeSelectionPtr aSel = aList->value(aSelIndex);
74
75     ResultPtr aContext = aSel->context();
76     if (aContext.get())
77       aResults.push_back (aContext);
78     else
79     {
80       FeaturePtr aFeature = aSel->contextFeature();
81       if (aFeature.get())
82       {
83         const std::list<ResultPtr>& aResList = aFeature->results();
84         aResults.assign (aResList.begin(), aResList.end());
85       }
86     }
87   }
88
89   std::list<ResultPtr>::iterator aResIter = aResults.begin();
90   for(; aResIter != aResults.end(); aResIter++)
91   {
92     GeomShapePtr aShape = (*aResIter)->shape();
93     if (!aShape.get() || aShape->isNull())
94       continue;
95
96     std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
97     aResultBody->store(aShape);
98     aResultBody->loadFirstLevel(aShape, "ImportResult");
99     setResult(aResultBody, aResultIndex++);
100
101     std::set<ResultPtr> allResultsCashed; // cash to speed up searching in all results selected
102     std::list<ResultPtr> aLocalResults;
103     aLocalResults.push_back (*aResIter);
104
105     std::list<DocumentPtr> aDocuments; /// documents of Parts
106     aDocuments.push_back ((*aResIter)->document());
107     std::list<DocumentPtr>::iterator aDoc = aDocuments.begin();
108     for(; aDoc != aDocuments.end(); aDoc++)
109     {
110       // groups
111       int aGroupCount = (*aDoc)->size(ModelAPI_ResultGroup::group());
112       for (int aGroupIndex = 0; aGroupIndex < aGroupCount; ++aGroupIndex)
113       {
114         ResultGroupPtr aResultGroup =
115           std::dynamic_pointer_cast<ModelAPI_ResultGroup>((*aDoc)->object(ModelAPI_ResultGroup::group(), aGroupIndex));
116
117         if (!aResultGroup.get() || !aResultGroup->shape().get())
118           continue;
119
120         FeaturePtr aGroupFeature = (*aDoc)->feature(aResultGroup);
121
122         AttributeSelectionListPtr aSelectionList =
123           aGroupFeature->selectionList("group_list");
124
125         if (!ModelAPI_Tools::isInResults(aSelectionList,
126                                          aLocalResults,
127                                          allResultsCashed))// skip group not used in result
128           continue;
129
130         aGlobalResultsCashed.insert (allResultsCashed.begin(), allResultsCashed.end());
131
132         //Check: may be this group already exists in the list
133         bool anIsFound = false;
134         std::list<ResultGroupPtr>::iterator anIter = aGroups.begin();
135         for (; anIter != aGroups.end(); anIter++)
136         {
137           if (*anIter == aResultGroup)
138           {
139             anIsFound = true;
140             break;
141           }
142         }
143         if (!anIsFound)
144           aGroups.push_back (aResultGroup);
145       }
146     }
147   }
148
149   std::list<ResultGroupPtr>::iterator anIter = aGroups.begin();
150   for (; anIter != aGroups.end(); anIter++)
151   {
152     DocumentPtr aDoc = (*anIter)->document();
153
154     FeaturePtr aGroupFeature = aDoc->feature(*anIter);
155
156     AttributeSelectionListPtr aSelectionList =
157       aGroupFeature->selectionList("group_list");
158
159     std::shared_ptr<ModelAPI_Feature> aNewGroupFeature = addFeature("Group");
160     aNewGroupFeature->data()->setName(aGroupFeature->name());
161
162     AttributeSelectionListPtr aNewSelectionList = aNewGroupFeature->selectionList("group_list");
163     aNewSelectionList->setSelectionType (aSelectionList->selectionType());
164     GeomAPI_Shape::ShapeType aTypeOfShape = GeomAPI_Shape::shapeTypeByStr (aSelectionList->selectionType());
165
166     for (int aLocalSelIndex = 0; aLocalSelIndex < aSelectionList->size(); aLocalSelIndex++) {
167
168       AttributeSelectionPtr aLocalSel = aSelectionList->value(aLocalSelIndex);
169       ResultPtr aLocalContext = aLocalSel->context();
170       ResultGroupPtr aLocalGroup = std::dynamic_pointer_cast<ModelAPI_ResultGroup> (aLocalContext);
171       if (aLocalGroup.get())
172       {
173         GeomShapePtr aLocalShape = aGroupFeature->firstResult()->shape();
174         GeomAPI_ShapeExplorer anExplo (aLocalShape, aTypeOfShape);
175         for (; anExplo.more(); anExplo.next())
176         {
177           GeomShapePtr anExploredShape = anExplo.current();
178           std::set<ResultPtr>::iterator aResultIter = aGlobalResultsCashed.begin();
179           for (; aResultIter != aGlobalResultsCashed.end(); aResultIter++)
180           {
181             GeomShapePtr aCashedShape = (*aResultIter)->shape();
182             if (aCashedShape->isSubShape(anExploredShape))
183               aNewSelectionList->append((*aResultIter), anExploredShape);
184           }
185         }
186         break;
187       }
188       else
189       {
190         GeomShapePtr aLocalShape = aLocalSel->value();
191
192         if (aLocalContext.get() && aGlobalResultsCashed.count(aLocalContext))
193           aNewSelectionList->append(aLocalContext, aLocalShape);
194       }
195     }
196   }
197
198   removeResults(aResultIndex);
199 }
200
201 bool FeaturesPlugin_ValidatorImportResults::isValid(const AttributePtr& theAttribute,
202   const std::list<std::string>&, Events_InfoMessage& theError) const
203 {
204   AttributeSelectionListPtr aList =
205     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
206   if (aList->size() == 0) {
207     // LCOV_EXCL_START
208     theError = "Please select sources.";
209     return false;
210     // LCOV_EXCL_STOP
211   }
212   // store documents in the Part-fesatures in order to check
213   // the selection is located in the previous documents
214   std::map<DocumentPtr, int> aDocIndices;
215   DocumentPtr aRoot = ModelAPI_Session::get()->moduleDocument();
216   int aNum = aRoot->size(ModelAPI_Feature::group());
217   for (int a = 0; a < aNum; a++) {
218     FeaturePtr aFeat = std::dynamic_pointer_cast<ModelAPI_Feature>(
219       aRoot->object(ModelAPI_Feature::group(), a));
220     if (aFeat.get() && aFeat->data() && aFeat->data()->isValid() && aFeat->getKind() == "Part" &&
221       aFeat->results().size()) {
222       ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aFeat->firstResult());
223       if (aPart.get() && aPart->partDoc()) {
224         aDocIndices[aPart->partDoc()] = a;
225       }
226     }
227   }
228   int aThisIndex = aDocIndices[aList->owner()->document()];
229   for (int aSelIndex = 0; aSelIndex < aList->size(); aSelIndex++) {
230     AttributeSelectionPtr aSel = aList->value(aSelIndex);
231     ResultPtr aContext = aSel->context();
232     if (!aContext.get()) {
233       // LCOV_EXCL_START
234       theError = "Empty context.";
235       return false;
236       // LCOV_EXCL_STOP
237     }
238     GeomShapePtr aShape = aSel->value();
239     if (aShape.get() && !aShape->isNull() && !aShape->isSame(aContext->shape())) {
240       // LCOV_EXCL_START
241       theError = "Import results does not support selection of sub-shapes";
242       return false;
243       // LCOV_EXCL_STOP
244     }
245     ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
246     if (!aBody.get()) {
247       // LCOV_EXCL_START
248       theError = "Only results may be selected.";
249       return false;
250       // LCOV_EXCL_STOP
251     }
252     if (!aBody->shape()) {
253       // LCOV_EXCL_START
254       theError = "Result is empty.";
255       return false;
256       // LCOV_EXCL_STOP
257     }
258     int aBodyIndex = aDocIndices[aBody->document()];
259     if (aBodyIndex >= aThisIndex) {
260       theError = "The selected result must be located in earlier part.";
261       return false;
262     }
263   }
264   return true;
265 }
266
267 //============================================================================
268 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_ImportResult::addFeature(
269     std::string theID)
270 {
271   std::shared_ptr<ModelAPI_Feature> aNew = document()->addFeature(theID, false);
272   if (aNew)
273     data()->reflist(FEATURES_ID())->append(aNew);
274   // set as current also after it becomes sub to set correctly enabled for other subs
275   //document()->setCurrentFeature(aNew, false);
276   return aNew;
277 }
278
279 //=================================================================================================
280 int FeaturesPlugin_ImportResult::numberOfSubs(bool /*forTree*/) const
281 {
282   return data()->reflist(FEATURES_ID())->size(true);
283 }
284
285 //=================================================================================================
286 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_ImportResult::subFeature(const int theIndex,
287                                                                           bool /*forTree*/)
288 {
289   ObjectPtr anObj = data()->reflist(FEATURES_ID())->object(theIndex, false);
290   FeaturePtr aRes = std::dynamic_pointer_cast<ModelAPI_Feature>(anObj);
291   return aRes;
292 }
293
294 //=================================================================================================
295 int FeaturesPlugin_ImportResult::subFeatureId(const int theIndex) const
296 {
297   std::shared_ptr<ModelAPI_AttributeRefList> aRefList = std::dynamic_pointer_cast<
298       ModelAPI_AttributeRefList>(data()->attribute(FEATURES_ID()));
299   std::list<ObjectPtr> aFeatures = aRefList->list();
300   std::list<ObjectPtr>::const_iterator anIt = aFeatures.begin();
301   int aResultIndex = 1; // number of the counted (created) features, started from 1
302   int aFeatureIndex = -1; // number of the not-empty features in the list
303   for (; anIt != aFeatures.end(); anIt++) {
304     if (anIt->get())
305       aFeatureIndex++;
306     if (aFeatureIndex == theIndex)
307       break;
308     aResultIndex++;
309   }
310   return aResultIndex;
311 }
312
313 //=================================================================================================
314 bool FeaturesPlugin_ImportResult::isSub(ObjectPtr theObject) const
315 {
316   // check is this feature of result
317   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
318   if (aFeature)
319     return data()->reflist(FEATURES_ID())->isInList(aFeature);
320   return false;
321 }
322
323 //=================================================================================================
324 void FeaturesPlugin_ImportResult::removeFeature(
325     std::shared_ptr<ModelAPI_Feature> theFeature)
326 {
327   if (!data()->isValid())
328     return;
329   AttributeRefListPtr aList = reflist(FEATURES_ID());
330   aList->remove(theFeature);
331 }