Salome HOME
Feature selector widget for recover feature.
[modules/shaper.git] / src / ModelAPI / ModelAPI_Tools.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D\r
2 \r
3 // File:        ModelAPI_Tools.cpp\r
4 // Created:     06 Aug 2014\r
5 // Author:      Vitaly Smetannikov\r
6 \r
7 #include "ModelAPI_Tools.h"\r
8 #include <ModelAPI_Session.h>\r
9 #include <ModelAPI_Document.h>\r
10 #include <ModelAPI_Object.h>\r
11 #include <ModelAPI_AttributeDouble.h>\r
12 #include <ModelAPI_ResultParameter.h>\r
13 #include <ModelAPI_ResultPart.h>\r
14 #include <ModelAPI_AttributeDocRef.h>\r
15 #include <ModelAPI_Validator.h>\r
16 #include <list>\r
17 #include <map>\r
18 #include <iostream>\r
19 \r
20 #include <Events_Loop.h>\r
21 #include <ModelAPI_Events.h>\r
22 \r
23 #define RECURSE_TOP_LEVEL 50\r
24 \r
25 //#define DEBUG_REMOVE_FEATURES\r
26 //#define DEBUG_REMOVE_FEATURES_RECURSE\r
27 //#define DEBUG_CYCLING_1550\r
28 \r
29 #ifdef DEBUG_REMOVE_FEATURES_RECURSE\r
30 #include <sstream>\r
31 std::string getFeatureInfo(FeaturePtr theFeature)\r
32 {\r
33   if (!theFeature.get())\r
34     return "";\r
35   //std::ostringstream aPtrStr;\r
36   //aPtrStr << "[" << theFeature.get() << "] ";\r
37   std::string aFeatureInfo = /*aPtrStr.str() + */theFeature->name();\r
38   CompositeFeaturePtr aComposite = ModelAPI_Tools::compositeOwner(theFeature);\r
39   if (aComposite.get()) {\r
40       aFeatureInfo = aFeatureInfo + "[in " + aComposite->name() + "]";\r
41   }\r
42   return aFeatureInfo;\r
43 }\r
44 #endif\r
45 \r
46 #ifdef DEBUG_REMOVE_FEATURES\r
47 void printMapInfo(const std::map<FeaturePtr, std::set<FeaturePtr> >& theMainList,\r
48                   const std::string& thePrefix)\r
49 {\r
50   std::map<FeaturePtr, std::set<FeaturePtr> >::const_iterator aMainIt = theMainList.begin(),\r
51                                                               aMainLast = theMainList.end();\r
52   std::string anInfo;\r
53   for (; aMainIt != aMainLast; aMainIt++) {\r
54     FeaturePtr aMainListFeature = aMainIt->first;\r
55     std::set<FeaturePtr> aMainRefList = aMainIt->second;\r
56     std::set<FeaturePtr>::const_iterator anIt = aMainRefList.begin(), aLast = aMainRefList.end();\r
57     std::string aRefsInfo;\r
58     for (; anIt != aLast; anIt++) {\r
59       aRefsInfo += (*anIt)->name().c_str();\r
60       if (anIt != aLast)\r
61         aRefsInfo += ", ";\r
62     }\r
63     if (!aRefsInfo.empty()) {\r
64       anInfo = anInfo + aMainListFeature->name().c_str() + ": " + aRefsInfo + "\n";\r
65     }\r
66   }\r
67   std::cout << thePrefix.c_str() << " [feature: references to]: \n" << anInfo.c_str() << std::endl;\r
68 }\r
69 \r
70 void printListInfo(const std::set<FeaturePtr>& theMainList,\r
71                   const std::string& thePrefix)\r
72 {\r
73   std::set<FeaturePtr>::const_iterator aMainIt = theMainList.begin(),\r
74                                        aMainLast = theMainList.end();\r
75   std::string anInfo;\r
76   for (; aMainIt != aMainLast; aMainIt++) {\r
77     FeaturePtr aRefFeature = *aMainIt;\r
78     anInfo += aRefFeature->name().c_str();\r
79     if (aMainIt != aMainLast)\r
80       anInfo += ", ";\r
81   }\r
82   std::cout << thePrefix.c_str() << ": " << anInfo.c_str() << std::endl;\r
83 }\r
84 #endif\r
85 \r
86 namespace ModelAPI_Tools {\r
87 \r
88 std::shared_ptr<GeomAPI_Shape> shape(const ResultPtr& theResult)\r
89 {\r
90   return theResult->shape();\r
91 }\r
92 \r
93 void shapesOfType(const FeaturePtr& theFeature,\r
94                   const GeomAPI_Shape::ShapeType& theType,\r
95                   std::set<GeomShapePtr>& theShapes)\r
96 {\r
97   std::list<ResultPtr> aResults = theFeature->results();\r
98   std::list<ResultPtr>::const_iterator aRIter = aResults.cbegin();\r
99   for (; aRIter != aResults.cend(); aRIter++) {\r
100     ResultPtr aResult = *aRIter;\r
101     GeomShapePtr aShape = aResult->shape();\r
102     if (aShape.get() && aShape->shapeType() == theType)\r
103       theShapes.insert(aShape);\r
104   }\r
105 }\r
106 \r
107 const char* toString(ModelAPI_ExecState theExecState) \r
108 {\r
109 #define TO_STRING(__NAME__) case __NAME__: return #__NAME__;\r
110   switch (theExecState) {\r
111   TO_STRING(ModelAPI_StateDone)\r
112   TO_STRING(ModelAPI_StateMustBeUpdated)\r
113   TO_STRING(ModelAPI_StateExecFailed)\r
114   TO_STRING(ModelAPI_StateInvalidArgument)\r
115   TO_STRING(ModelAPI_StateNothing)\r
116   default: return "Unknown ExecState.";\r
117   }\r
118 #undef TO_STRING\r
119 }\r
120 \r
121 std::string getFeatureError(const FeaturePtr& theFeature)\r
122 {\r
123   std::string anError;\r
124   if (!theFeature.get() || !theFeature->data()->isValid() || theFeature->isAction())\r
125     return anError;\r
126 \r
127   // to be removed later, this error should be got from the feature\r
128   if (theFeature->data()->execState() == ModelAPI_StateDone ||\r
129       theFeature->data()->execState() == ModelAPI_StateMustBeUpdated)\r
130     return anError;\r
131 \r
132   // set error indication\r
133   anError = theFeature->error();\r
134   if (anError.empty()) {\r
135     bool isDone = ( theFeature->data()->execState() == ModelAPI_StateDone\r
136                  || theFeature->data()->execState() == ModelAPI_StateMustBeUpdated );\r
137     if (!isDone) {\r
138       anError = toString(theFeature->data()->execState());\r
139       // If the feature is Composite and error is StateInvalidArgument,\r
140       // error text should include error of first invalid sub-feature. Otherwise\r
141       // it is not clear what is the reason of the invalid argument.\r
142       if (theFeature->data()->execState() == ModelAPI_StateInvalidArgument) {\r
143         CompositeFeaturePtr aComposite =\r
144                     std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);\r
145         if (aComposite) {\r
146           for (int i = 0, aSize = aComposite->numberOfSubs(); i < aSize; i++) {\r
147             FeaturePtr aSubFeature = aComposite->subFeature(i);\r
148             std::string aSubFeatureError = getFeatureError(aSubFeature);\r
149             if (!aSubFeatureError.empty()) {\r
150               anError = anError + " in " + aSubFeature->getKind() + ".\n" + aSubFeatureError;\r
151               break;\r
152             }\r
153           }\r
154         }\r
155       }\r
156     }\r
157   }\r
158 \r
159   return anError;\r
160 }\r
161 \r
162 ObjectPtr objectByName(const DocumentPtr& theDocument, const std::string& theGroup, const std::string& theName)\r
163 {\r
164   for (int anIndex = 0; anIndex < theDocument->size(theGroup); ++anIndex) {\r
165     ObjectPtr anObject = theDocument->object(theGroup, anIndex);\r
166     if (anObject->data()->name() == theName)\r
167       return anObject;\r
168   }\r
169   // not found\r
170   return ObjectPtr();\r
171 }\r
172 \r
173 bool findVariable(const DocumentPtr& theDocument, FeaturePtr theSearcher,\r
174                   const std::string& theName, double& outValue, ResultParameterPtr& theParam)\r
175 {\r
176   ObjectPtr aParamObj = objectByName(theDocument, ModelAPI_ResultParameter::group(), theName);\r
177   theParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aParamObj);\r
178   if (!theParam.get())\r
179     return false;\r
180   // avoid usage of parameters created later than the initial parameter\r
181   if (theSearcher.get() && theDocument->isLater(theDocument->feature(theParam), theSearcher))\r
182     return false;\r
183   AttributeDoublePtr aValueAttribute = theParam->data()->real(ModelAPI_ResultParameter::VALUE());\r
184   outValue = aValueAttribute->value();\r
185   return true;\r
186 }\r
187 \r
188 bool findVariable(FeaturePtr theSearcher, const std::string& theName, double& outValue, ResultParameterPtr& theParam,\r
189                   const DocumentPtr& theDocument)\r
190 {\r
191   SessionPtr aSession = ModelAPI_Session::get();\r
192   std::list<DocumentPtr> aDocList;\r
193   DocumentPtr aDocument = theDocument.get() ? theDocument : aSession->activeDocument();\r
194   if (findVariable(aDocument, theSearcher, theName, outValue, theParam))\r
195     return true;\r
196   DocumentPtr aRootDocument = aSession->moduleDocument();\r
197   if (aDocument != aRootDocument) {\r
198     // any parameters in PartSet is okindependently on the Part position (issu #1504)\r
199     if (findVariable(aRootDocument, FeaturePtr(), theName, outValue, theParam))\r
200       return true;\r
201   }\r
202   return false;\r
203 }\r
204 \r
205 static std::map<int, std::vector<int> > myColorMap;\r
206 \r
207 void appendValues(std::vector<int>& theRGB, const int theRed, const int theGreen, const int theBlue)\r
208 {\r
209   theRGB.push_back(theRed);\r
210   theRGB.push_back(theGreen);\r
211   theRGB.push_back(theBlue);\r
212 }\r
213 \r
214 bool containsValues(std::map<int, std::vector<int> >& theColorMap, std::vector<int>& theValues)\r
215 {\r
216   std::map<int, std::vector<int> >::const_iterator anIt = theColorMap.begin(), aLast = theColorMap.end();\r
217   bool isFound = false;\r
218   for (; anIt != aLast && !isFound; anIt++) {\r
219     std::vector<int> aValues = anIt->second;\r
220     isFound = aValues[0] == theValues[0] &&\r
221               aValues[1] == theValues[1] &&\r
222               aValues[2] == theValues[2];\r
223   }\r
224   return isFound;\r
225 }\r
226 \r
227 std::vector<int> HSVtoRGB(int theH, int theS, int theV)\r
228 {\r
229   std::vector<int> aRGB;\r
230   if (theH < 0 || theH > 360 ||\r
231       theS < 0 || theS > 100 ||\r
232       theV < 0 || theV > 100)\r
233     return aRGB;\r
234 \r
235   int aHi = (int)theH/60;\r
236 \r
237   double aV = theV;\r
238   double aVmin = (100 - theS)*theV/100;\r
239 \r
240   double anA = (theV - aVmin)* (theH % 60) / 60;\r
241 \r
242   double aVinc = aVmin + anA;\r
243   double aVdec = theV - anA;\r
244 \r
245   double aPercentToValue = 255./100;\r
246   int aV_int    = (int)(aV*aPercentToValue);\r
247   int aVinc_int = (int)(aVinc*aPercentToValue);\r
248   int aVmin_int = (int)(aVmin*aPercentToValue);\r
249   int aVdec_int = (int)(aVdec*aPercentToValue);\r
250 \r
251   switch(aHi) {\r
252     case 0: appendValues(aRGB, aV_int,    aVinc_int, aVmin_int); break;\r
253     case 1: appendValues(aRGB, aVdec_int, aV_int,    aVmin_int); break;\r
254     case 2: appendValues(aRGB, aVmin_int, aV_int,    aVinc_int); break;\r
255     case 3: appendValues(aRGB, aVmin_int, aVdec_int, aV_int); break;\r
256     case 4: appendValues(aRGB, aVinc_int, aVmin_int, aV_int); break;\r
257     case 5: appendValues(aRGB, aV_int,    aVmin_int, aVdec_int); break;\r
258     default: break;\r
259   }\r
260   return aRGB;\r
261 }\r
262 \r
263 \r
264 void fillColorMap()\r
265 {\r
266   if (!myColorMap.empty())\r
267     return;\r
268 \r
269   int i = 0;\r
270   for (int s = 100; s > 0; s = s - 50)\r
271   {\r
272     for (int v = 100; v >= 40; v = v - 20)\r
273     {\r
274       for (int h = 0; h < 359 ; h = h + 60)\r
275       {\r
276         std::vector<int> aColor = HSVtoRGB(h, s, v);\r
277         if (containsValues(myColorMap, aColor))\r
278           continue;\r
279         myColorMap[i] = aColor;\r
280         i++;\r
281       }\r
282     }\r
283   }\r
284 }\r
285 \r
286 void findRandomColor(std::vector<int>& theValues)\r
287 {\r
288   theValues.clear();\r
289   if (myColorMap.empty()) {\r
290     fillColorMap();\r
291   }\r
292 \r
293   size_t aSize = myColorMap.size();\r
294   int anIndex = rand() % aSize;\r
295   if (myColorMap.find(anIndex) != myColorMap.end()) {\r
296     theValues = myColorMap.at(anIndex);\r
297   }\r
298 }\r
299 \r
300 ResultPtr findPartResult(const DocumentPtr& theMain, const DocumentPtr& theSub)\r
301 {\r
302   if (theMain != theSub) { // to optimize and avoid of crash on partset document close (don't touch the sub-document structure)\r
303     for (int a = theMain->size(ModelAPI_ResultPart::group()) - 1; a >= 0; a--) {\r
304       ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(\r
305           theMain->object(ModelAPI_ResultPart::group(), a));\r
306       if (aPart && aPart->data()->document(ModelAPI_ResultPart::DOC_REF())->value() == theSub) {\r
307         return aPart;\r
308       }\r
309     }\r
310   }\r
311   return ResultPtr();\r
312 }\r
313 \r
314 FeaturePtr findPartFeature(const DocumentPtr& theMain, const DocumentPtr& theSub)\r
315 {\r
316   if (theMain != theSub) { // to optimize and avoid of crash on partset document close (don't touch the sub-document structure)\r
317     for (int a = theMain->size(ModelAPI_Feature::group()) - 1; a >= 0; a--) {\r
318       FeaturePtr aPartFeat = std::dynamic_pointer_cast<ModelAPI_Feature>(\r
319           theMain->object(ModelAPI_Feature::group(), a));\r
320       if (aPartFeat.get()) {\r
321         const std::list<std::shared_ptr<ModelAPI_Result> >& aResList = aPartFeat->results();\r
322         std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResList.begin();\r
323         for(; aRes != aResList.end(); aRes++) {\r
324           ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRes);\r
325           if (aPart.get()) {\r
326             if (aPart->isActivated() && aPart->partDoc() == theSub)\r
327               return aPartFeat;\r
328           } else break; // if the first is not Part, others are also not\r
329         }\r
330       }\r
331     }\r
332   }\r
333   return FeaturePtr();\r
334 }\r
335 \r
336 CompositeFeaturePtr compositeOwner(const FeaturePtr& theFeature)\r
337 {\r
338   if (theFeature.get() && theFeature->data()->isValid()) {\r
339     const std::set<std::shared_ptr<ModelAPI_Attribute> >& aRefs = theFeature->data()->refsToMe();\r
340     std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aRefIter = aRefs.begin();\r
341     for(; aRefIter != aRefs.end(); aRefIter++) {\r
342       CompositeFeaturePtr aComp = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>\r
343         ((*aRefIter)->owner());\r
344       if (aComp.get() && aComp->data()->isValid() && aComp->isSub(theFeature))\r
345         return aComp;\r
346     }\r
347   }\r
348   return CompositeFeaturePtr(); // not found\r
349 }\r
350 \r
351 ResultCompSolidPtr compSolidOwner(const ResultPtr& theSub)\r
352 {\r
353   ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theSub);\r
354   if (aBody.get()) {\r
355     FeaturePtr aFeatureOwner = aBody->document()->feature(aBody);\r
356     if (aFeatureOwner.get()) {\r
357       std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter = \r
358         aFeatureOwner->results().cbegin();\r
359       for(; aResIter != aFeatureOwner->results().cend(); aResIter++) {\r
360         ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aResIter);\r
361         if (aComp && aComp->isSub(aBody))\r
362           return aComp;\r
363       }\r
364     }\r
365   }\r
366   return ResultCompSolidPtr(); // not found\r
367 }\r
368 \r
369 bool hasSubResults(const ResultPtr& theResult)\r
370 {\r
371   ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theResult);\r
372   return aCompSolid.get() && aCompSolid->numberOfSubs() > 0;\r
373 }\r
374 \r
375 void allResults(const FeaturePtr& theFeature, std::list<ResultPtr>& theResults)\r
376 {\r
377   if (!theFeature.get()) // safety: for empty feature no results\r
378     return;\r
379   const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();\r
380   std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();\r
381   for (; aRIter != aResults.cend(); aRIter++) {\r
382     theResults.push_back(*aRIter);\r
383     // iterate sub-bodies of compsolid\r
384     ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aRIter);\r
385     if (aComp.get()) {\r
386       int aNumSub = aComp->numberOfSubs();\r
387       for(int a = 0; a < aNumSub; a++) {\r
388         theResults.push_back(aComp->subResult(a));\r
389       }\r
390     }\r
391   }\r
392 }\r
393 \r
394 //******************************************************************\r
395 bool allDocumentsActivated(std::string& theNotActivatedNames)\r
396 {\r
397   theNotActivatedNames = "";\r
398   bool anAllPartActivated = true;\r
399 \r
400   DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();\r
401   int aSize = aRootDoc->size(ModelAPI_ResultPart::group());\r
402   for (int i = 0; i < aSize; i++) {\r
403     ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), i);\r
404     ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);\r
405     if (!aPart->isActivated()) {\r
406       anAllPartActivated = false;\r
407       if (!theNotActivatedNames.empty())\r
408         theNotActivatedNames += ", ";\r
409       theNotActivatedNames += aObject->data()->name().c_str();\r
410     }\r
411   }\r
412   return anAllPartActivated;\r
413 }\r
414 \r
415 bool removeFeaturesAndReferences(const std::set<FeaturePtr>& theFeatures,\r
416                                  const bool theFlushRedisplay,\r
417                                  const bool theUseComposite,\r
418                                  const bool theUseRecursion)\r
419 {\r
420 #ifdef DEBUG_REMOVE_FEATURES\r
421   printListInfo(theFeatures, "selection: ");\r
422 #endif\r
423 \r
424   std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;\r
425   ModelAPI_Tools::findAllReferences(theFeatures, aReferences, theUseComposite, theUseRecursion);\r
426 #ifdef DEBUG_REMOVE_FEATURES\r
427   printMapInfo(aReferences, "allDependencies: ");\r
428 #endif\r
429 \r
430   std::set<FeaturePtr> aFeaturesRefsTo;\r
431   ModelAPI_Tools::findRefsToFeatures(theFeatures, aReferences, aFeaturesRefsTo);\r
432 #ifdef DEBUG_REMOVE_FEATURES\r
433   printListInfo(aFeaturesRefsTo, "references: ");\r
434 #endif\r
435 \r
436   std::set<FeaturePtr> aFeatures = theFeatures;\r
437   if (!aFeaturesRefsTo.empty())\r
438     aFeatures.insert(aFeaturesRefsTo.begin(), aFeaturesRefsTo.end());\r
439 #ifdef DEBUG_REMOVE_FEATURES\r
440   printListInfo(aFeatures, "removeFeatures: ");\r
441 #endif\r
442 \r
443   return ModelAPI_Tools::removeFeatures(aFeatures, false);\r
444 }\r
445 \r
446 bool removeFeatures(const std::set<FeaturePtr>& theFeatures,\r
447                     const bool theFlushRedisplay)\r
448 {\r
449   bool isDone = false;\r
450   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),\r
451                                        aLast = theFeatures.end();\r
452   for (; anIt != aLast; anIt++) {\r
453     FeaturePtr aFeature = *anIt;\r
454     if (aFeature.get()) {\r
455       DocumentPtr aDoc = aFeature->document();\r
456       // flush REDISPLAY signal after remove feature\r
457       aDoc->removeFeature(aFeature);\r
458       isDone = true;\r
459     }\r
460   }\r
461   if (isDone && theFlushRedisplay) {\r
462     // the redisplay signal should be flushed in order to erase the feature presentation in the viewer\r
463     // if should be done after removeFeature() of document\r
464     Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));\r
465   }\r
466   return true;\r
467 }\r
468 \r
469 // Fills the references list by all references of the feature from the references map.\r
470 // This is a recusive method to find references by next found feature in the map of references.\r
471 // \param theFeature a feature to find references\r
472 // \param theReferencesMap a map of references\r
473 // \param theReferences an out container of references\r
474 void addRefsToFeature(const FeaturePtr& theFeature,\r
475                       const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferencesMap,\r
476                       std::map<FeaturePtr, std::set<FeaturePtr> >& theProcessedReferences,\r
477                       int theRecLevel,\r
478                       std::set<FeaturePtr>& theReferences)\r
479 {\r
480   if (theRecLevel > RECURSE_TOP_LEVEL)\r
481     return;\r
482   theRecLevel++;\r
483 \r
484   // if the feature is already processed, get the ready references from the map\r
485   if (theProcessedReferences.find(theFeature) != theProcessedReferences.end()) {\r
486     std::set<FeaturePtr> aReferences = theProcessedReferences.at(theFeature);\r
487     theReferences.insert(aReferences.begin(), aReferences.end());\r
488     return;\r
489   }\r
490 \r
491   if (theReferencesMap.find(theFeature) == theReferencesMap.end())\r
492     return; // this feature is not in the selection list, so exists without references to it\r
493   std::set<FeaturePtr> aMainReferences = theReferencesMap.at(theFeature);\r
494 \r
495   std::set<FeaturePtr>::const_iterator anIt = aMainReferences.begin(),\r
496                                        aLast = aMainReferences.end();\r
497 #ifdef DEBUG_REMOVE_FEATURES_RECURSE\r
498   std::string aSpacing;\r
499   for (int i = 0; i < theRecLevel; i++)\r
500     aSpacing.append(" ");\r
501 #endif\r
502 \r
503   for (; anIt != aLast; anIt++) {\r
504     FeaturePtr aRefFeature = *anIt;\r
505 #ifdef DEBUG_REMOVE_FEATURES_RECURSE\r
506   std::cout << aSpacing << " Ref: " << getFeatureInfo(aRefFeature) << std::endl;\r
507 #endif\r
508     if (theReferences.find(aRefFeature) == theReferences.end())\r
509       theReferences.insert(aRefFeature);\r
510     addRefsToFeature(aRefFeature, theReferencesMap, theProcessedReferences, theRecLevel, theReferences);\r
511   }\r
512 }\r
513 \r
514 // For each feature from the feature list it searches references to the feature and append them\r
515 // to the references map. This is a recusive method.\r
516 // \param theFeature a feature to find references\r
517 // \param theReferencesMap a map of references\r
518 // \param theReferences an out container of references\r
519 void findReferences(const std::set<FeaturePtr>& theFeatures,\r
520                     std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,\r
521                     const bool theUseComposite, const bool theUseRecursion, int theRecLevel)\r
522 {\r
523   if (theRecLevel > RECURSE_TOP_LEVEL)\r
524     return;\r
525   theRecLevel++;\r
526   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),\r
527                                         aLast = theFeatures.end();\r
528   for (; anIt != aLast; anIt++) {\r
529     FeaturePtr aFeature = *anIt;\r
530     if (aFeature.get() && theReferences.find(aFeature) == theReferences.end()) {\r
531       DocumentPtr aSelFeatureDoc = aFeature->document();\r
532       std::set<FeaturePtr> aSelRefFeatures;\r
533       aSelFeatureDoc->refsToFeature(aFeature, aSelRefFeatures, false/*do not emit signals*/);\r
534       if (theUseComposite) { // do not filter selection\r
535         theReferences[aFeature] = aSelRefFeatures;\r
536       }\r
537       else { // filter references to skip composition features of the current feature\r
538         std::set<FeaturePtr> aFilteredFeatures;\r
539         std::set<FeaturePtr>::const_iterator anIt = aSelRefFeatures.begin(),\r
540                                              aLast = aSelRefFeatures.end();\r
541         for (; anIt != aLast; anIt++) {\r
542           FeaturePtr aCFeature = *anIt;\r
543           CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCFeature);\r
544           if (aComposite.get() && aComposite->isSub(aFeature))\r
545             continue; /// composite of the current feature should be skipped\r
546           aFilteredFeatures.insert(aCFeature);\r
547         }\r
548         theReferences[aFeature] = aFilteredFeatures;\r
549       }\r
550       if (theUseRecursion) {\r
551 #ifdef DEBUG_CYCLING_1550\r
552         findReferences(aSelRefFeatures, theReferences, theUseComposite, theUseRecursion, theRecLevel);\r
553 #else\r
554         findReferences(theReferences[aFeature], theReferences, theUseComposite, theUseRecursion,\r
555                        theRecLevel);\r
556 #endif\r
557       }\r
558     }\r
559   }\r
560 }\r
561 \r
562 void findAllReferences(const std::set<FeaturePtr>& theFeatures,\r
563                        std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,\r
564                        const bool theUseComposite,\r
565                        const bool theUseRecursion)\r
566 {\r
567   // For dependencies, find main_list:\r
568   // sk_1(ext_1, vertex_1)\r
569   // ext_1(bool_1, sk_3)\r
570   // vertex_1()\r
571   // sk_2(ext_2)\r
572   // ext_2(bool_2)\r
573   // sk_3()\r
574   // Information: bool_1 is not selected, ext_2(bool_2) exists\r
575   // find all referenced features\r
576   std::map<FeaturePtr, std::set<FeaturePtr> > aMainList;\r
577   int aRecLevel = 0;\r
578   findReferences(theFeatures, aMainList, theUseComposite, theUseRecursion, aRecLevel);\r
579 \r
580 #ifdef DEBUG_REMOVE_FEATURES\r
581   printMapInfo(aMainList, "firstDependencies");\r
582 #endif\r
583   // find all dependencies for each object:\r
584   // sk_1(ext_1, vertex_1) + (sk_3, bool_1)\r
585   // ext_1(bool_1, sk_3)\r
586   // vertex_1()\r
587   // sk_2(ext_2) + (bool_1)\r
588   // ext_2(bool_1)\r
589   // sk_3()\r
590   std::map<FeaturePtr, std::set<FeaturePtr> >::const_iterator aMainIt = aMainList.begin(),\r
591                                                               aMainLast = aMainList.end();\r
592   for (; aMainIt != aMainLast; aMainIt++) {\r
593     FeaturePtr aMainListFeature = aMainIt->first;\r
594 \r
595     //std::string aName = aMainListFeature->name();\r
596     std::set<FeaturePtr> aMainRefList = aMainIt->second;\r
597 \r
598 #ifdef DEBUG_REMOVE_FEATURES_RECURSE\r
599     char aBuf[50];\r
600     int n = sprintf(aBuf, "%d", aMainRefList.size());\r
601     std::string aSize(aBuf);\r
602     std::cout << "_findAllReferences for the Feature: " << getFeatureInfo(aMainListFeature)\r
603               << ", references size = " << aSize << std::endl;\r
604 #endif\r
605     std::set<FeaturePtr>::const_iterator anIt = aMainRefList.begin(),\r
606                                          aLast = aMainRefList.end();\r
607     std::set<FeaturePtr> aResultRefList;\r
608     aResultRefList.insert(aMainRefList.begin(), aMainRefList.end());\r
609     for (; anIt != aLast; anIt++) {\r
610       FeaturePtr aFeature = *anIt;\r
611       int aRecLevel = 0;\r
612 #ifdef DEBUG_REMOVE_FEATURES_RECURSE\r
613       std::cout << " Ref: " << getFeatureInfo(aFeature) << std::endl;\r
614 #endif\r
615       aRecLevel++;\r
616       addRefsToFeature(aFeature, aMainList, theReferences, aRecLevel, aResultRefList/*aMainRefList*/);\r
617     }\r
618     theReferences[aMainListFeature] = aResultRefList;\r
619   }\r
620 #ifdef DEBUG_REMOVE_FEATURES_RECURSE\r
621     std::cout << std::endl;\r
622 #endif\r
623 \r
624 #ifdef DEBUG_REMOVE_FEATURES\r
625   printMapInfo(theReferences, "allDependencies");\r
626 #endif\r
627 }\r
628 \r
629 void findRefsToFeatures(const std::set<FeaturePtr>& theFeatures,\r
630                         const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,\r
631                         std::set<FeaturePtr>& theFeaturesRefsTo)\r
632 {\r
633   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),\r
634                                        aLast = theFeatures.end();\r
635   for (; anIt != aLast; anIt++) {\r
636     FeaturePtr aFeature = *anIt;\r
637     if (theReferences.find(aFeature) == theReferences.end())\r
638       continue;\r
639     std::set<FeaturePtr> aRefList = theReferences.at(aFeature);\r
640     std::set<FeaturePtr>::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end();\r
641     for (; aRefIt != aRefLast; aRefIt++) {\r
642       FeaturePtr aRefFeature = *aRefIt;\r
643       CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aRefFeature);\r
644       if (aComposite.get() && aComposite->isSub(aFeature))\r
645         continue; /// composite of the current feature should not be removed\r
646 \r
647       if (theFeatures.find(aRefFeature) == theFeatures.end() && // it is not selected\r
648           theFeaturesRefsTo.find(aRefFeature) == theFeaturesRefsTo.end()) // it is not added\r
649         theFeaturesRefsTo.insert(aRefFeature);\r
650     }\r
651   }\r
652 }\r
653 \r
654 void getConcealedResults(const FeaturePtr& theFeature,\r
655                          std::list<std::shared_ptr<ModelAPI_Result> >& theResults)\r
656 {\r
657   SessionPtr aSession = ModelAPI_Session::get();\r
658 \r
659   std::list<std::pair<std::string, std::list<std::shared_ptr<ModelAPI_Object> > > > aRefs;\r
660   theFeature->data()->referencesToObjects(aRefs);\r
661   std::list<std::pair<std::string, std::list<ObjectPtr> > >::const_iterator\r
662                                                   anIt = aRefs.begin(), aLast = aRefs.end();\r
663   std::set<ResultPtr> alreadyThere; // to avoid duplications\r
664   for (; anIt != aLast; anIt++) {\r
665     if (!aSession->validators()->isConcealed(theFeature->getKind(), anIt->first))\r
666       continue; // use only concealed attributes\r
667     std::list<ObjectPtr> anObjects = (*anIt).second;\r
668     std::list<ObjectPtr>::const_iterator anOIt = anObjects.begin(), anOLast = anObjects.end();\r
669     for (; anOIt != anOLast; anOIt++) {\r
670       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(*anOIt);\r
671       if (aResult && aResult->isConcealed()) {\r
672         if (alreadyThere.find(aResult) == alreadyThere.end()) // issue 1712, avoid duplicates\r
673           alreadyThere.insert(aResult);\r
674         else continue;\r
675         theResults.push_back(aResult);\r
676       }\r
677     }\r
678   }\r
679 }\r
680 \r
681 } // namespace ModelAPI_Tools\r