Salome HOME
46b23bc5576bfadf4cad2b0f9d8d0fa7f71ea1c6
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_ImportResult.cpp
1 // Copyright (C) 2017-2023  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>(
116             (*aDoc)->object(ModelAPI_ResultGroup::group(), aGroupIndex));
117
118         if (!aResultGroup.get() || !aResultGroup->shape().get())
119           continue;
120
121         FeaturePtr aGroupFeature = (*aDoc)->feature(aResultGroup);
122
123         AttributeSelectionListPtr aSelectionList =
124           aGroupFeature->selectionList("group_list");
125
126         if (!ModelAPI_Tools::isInResults(aSelectionList,
127                                          aLocalResults,
128                                          allResultsCashed))// skip group not used in result
129           continue;
130
131         aGlobalResultsCashed.insert (allResultsCashed.begin(), allResultsCashed.end());
132
133         //Check: may be this group already exists in the list
134         bool anIsFound = false;
135         std::list<ResultGroupPtr>::iterator anIter = aGroups.begin();
136         for (; anIter != aGroups.end(); anIter++)
137         {
138           if (*anIter == aResultGroup)
139           {
140             anIsFound = true;
141             break;
142           }
143         }
144         if (!anIsFound)
145           aGroups.push_back (aResultGroup);
146       }
147     }
148   }
149
150   std::list<ResultGroupPtr>::iterator anIter = aGroups.begin();
151   for (; anIter != aGroups.end(); anIter++)
152   {
153     DocumentPtr aDoc = (*anIter)->document();
154
155     FeaturePtr aGroupFeature = aDoc->feature(*anIter);
156
157     AttributeSelectionListPtr aSelectionList =
158       aGroupFeature->selectionList("group_list");
159
160     std::shared_ptr<ModelAPI_Feature> aNewGroupFeature = addFeature("Group");
161     aNewGroupFeature->data()->setName(aGroupFeature->name());
162
163     AttributeSelectionListPtr aNewSelectionList = aNewGroupFeature->selectionList("group_list");
164     aNewSelectionList->setSelectionType (aSelectionList->selectionType());
165     GeomAPI_Shape::ShapeType aTypeOfShape =
166         GeomAPI_Shape::shapeTypeByStr(aSelectionList->selectionType());
167
168     for (int aLocalSelIndex = 0; aLocalSelIndex < aSelectionList->size(); aLocalSelIndex++) {
169
170       AttributeSelectionPtr aLocalSel = aSelectionList->value(aLocalSelIndex);
171       ResultPtr aLocalContext = aLocalSel->context();
172       ResultGroupPtr aLocalGroup = std::dynamic_pointer_cast<ModelAPI_ResultGroup> (aLocalContext);
173       if (aLocalGroup.get())
174       {
175         GeomShapePtr aLocalShape = aGroupFeature->firstResult()->shape();
176         GeomAPI_ShapeExplorer anExplo (aLocalShape, aTypeOfShape);
177         for (; anExplo.more(); anExplo.next())
178         {
179           GeomShapePtr anExploredShape = anExplo.current();
180           std::set<ResultPtr>::iterator aResultIter = aGlobalResultsCashed.begin();
181           for (; aResultIter != aGlobalResultsCashed.end(); aResultIter++)
182           {
183             GeomShapePtr aCashedShape = (*aResultIter)->shape();
184             if (aCashedShape->isSubShape(anExploredShape))
185               aNewSelectionList->append((*aResultIter), anExploredShape);
186           }
187         }
188         break;
189       }
190       else
191       {
192         GeomShapePtr aLocalShape = aLocalSel->value();
193
194         if (aLocalContext.get() && aGlobalResultsCashed.count(aLocalContext))
195           aNewSelectionList->append(aLocalContext, aLocalShape);
196       }
197     }
198   }
199
200   removeResults(aResultIndex);
201 }
202
203 bool FeaturesPlugin_ValidatorImportResults::isValid(const AttributePtr& theAttribute,
204   const std::list<std::string>&, Events_InfoMessage& theError) const
205 {
206   AttributeSelectionListPtr aList =
207     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
208   if (aList->size() == 0) {
209     // LCOV_EXCL_START
210     theError = "Please select sources.";
211     return false;
212     // LCOV_EXCL_STOP
213   }
214   // store documents in the Part-fesatures in order to check
215   // the selection is located in the previous documents
216   std::map<DocumentPtr, int> aDocIndices;
217   DocumentPtr aRoot = ModelAPI_Session::get()->moduleDocument();
218   int aNum = aRoot->size(ModelAPI_Feature::group());
219   for (int a = 0; a < aNum; a++) {
220     FeaturePtr aFeat = std::dynamic_pointer_cast<ModelAPI_Feature>(
221       aRoot->object(ModelAPI_Feature::group(), a));
222     if (aFeat.get() && aFeat->data() && aFeat->data()->isValid() && aFeat->getKind() == "Part" &&
223       aFeat->results().size()) {
224       ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aFeat->firstResult());
225       if (aPart.get() && aPart->partDoc()) {
226         aDocIndices[aPart->partDoc()] = a;
227       }
228     }
229   }
230   int aThisIndex = aDocIndices[aList->owner()->document()];
231   for (int aSelIndex = 0; aSelIndex < aList->size(); aSelIndex++) {
232     AttributeSelectionPtr aSel = aList->value(aSelIndex);
233     ResultPtr aContext = aSel->context();
234     if (!aContext.get()) {
235       // LCOV_EXCL_START
236       theError = "Empty context.";
237       return false;
238       // LCOV_EXCL_STOP
239     }
240     GeomShapePtr aShape = aSel->value();
241     if (aShape.get() && !aShape->isNull() && !aShape->isSame(aContext->shape())) {
242       // LCOV_EXCL_START
243       theError = "Import results does not support selection of sub-shapes";
244       return false;
245       // LCOV_EXCL_STOP
246     }
247     ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aContext);
248     if (!aBody.get()) {
249       // LCOV_EXCL_START
250       theError = "Only results may be selected.";
251       return false;
252       // LCOV_EXCL_STOP
253     }
254     if (!aBody->shape()) {
255       // LCOV_EXCL_START
256       theError = "Result is empty.";
257       return false;
258       // LCOV_EXCL_STOP
259     }
260     int aBodyIndex = aDocIndices[aBody->document()];
261     if (aBodyIndex >= aThisIndex) {
262       theError = "The selected result must be located in earlier part.";
263       return false;
264     }
265   }
266   return true;
267 }
268
269 //============================================================================
270 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_ImportResult::addFeature(
271     std::string theID)
272 {
273   std::shared_ptr<ModelAPI_Feature> aNew = document()->addFeature(theID, false);
274   if (aNew)
275     data()->reflist(FEATURES_ID())->append(aNew);
276   // set as current also after it becomes sub to set correctly enabled for other subs
277   //document()->setCurrentFeature(aNew, false);
278   return aNew;
279 }
280
281 //=================================================================================================
282 int FeaturesPlugin_ImportResult::numberOfSubs(bool /*forTree*/) const
283 {
284   return data()->reflist(FEATURES_ID())->size(true);
285 }
286
287 //=================================================================================================
288 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_ImportResult::subFeature(const int theIndex,
289                                                                           bool /*forTree*/)
290 {
291   ObjectPtr anObj = data()->reflist(FEATURES_ID())->object(theIndex, false);
292   FeaturePtr aRes = std::dynamic_pointer_cast<ModelAPI_Feature>(anObj);
293   return aRes;
294 }
295
296 //=================================================================================================
297 int FeaturesPlugin_ImportResult::subFeatureId(const int theIndex) const
298 {
299   std::shared_ptr<ModelAPI_AttributeRefList> aRefList = std::dynamic_pointer_cast<
300       ModelAPI_AttributeRefList>(data()->attribute(FEATURES_ID()));
301   std::list<ObjectPtr> aFeatures = aRefList->list();
302   std::list<ObjectPtr>::const_iterator anIt = aFeatures.begin();
303   int aResultIndex = 1; // number of the counted (created) features, started from 1
304   int aFeatureIndex = -1; // number of the not-empty features in the list
305   for (; anIt != aFeatures.end(); anIt++) {
306     if (anIt->get())
307       aFeatureIndex++;
308     if (aFeatureIndex == theIndex)
309       break;
310     aResultIndex++;
311   }
312   return aResultIndex;
313 }
314
315 //=================================================================================================
316 bool FeaturesPlugin_ImportResult::isSub(ObjectPtr theObject) const
317 {
318   // check is this feature of result
319   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
320   if (aFeature)
321     return data()->reflist(FEATURES_ID())->isInList(aFeature);
322   return false;
323 }
324
325 //=================================================================================================
326 void FeaturesPlugin_ImportResult::removeFeature(
327     std::shared_ptr<ModelAPI_Feature> theFeature)
328 {
329   if (!data()->isValid())
330     return;
331   AttributeRefListPtr aList = reflist(FEATURES_ID());
332   aList->remove(theFeature);
333 }