]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModelAPI/ModelAPI_Tools.cpp
Salome HOME
Removed GUI-specific features from the ModelAPI tools.
[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 ResultPtr findPartResult(const DocumentPtr& theMain, const DocumentPtr& theSub)\r
206 {\r
207   if (theMain != theSub) { // to optimize and avoid of crash on partset document close (don't touch the sub-document structure)\r
208     for (int a = theMain->size(ModelAPI_ResultPart::group()) - 1; a >= 0; a--) {\r
209       ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(\r
210           theMain->object(ModelAPI_ResultPart::group(), a));\r
211       if (aPart && aPart->data()->document(ModelAPI_ResultPart::DOC_REF())->value() == theSub) {\r
212         return aPart;\r
213       }\r
214     }\r
215   }\r
216   return ResultPtr();\r
217 }\r
218 \r
219 FeaturePtr findPartFeature(const DocumentPtr& theMain, const DocumentPtr& theSub)\r
220 {\r
221   if (theMain != theSub) { // to optimize and avoid of crash on partset document close (don't touch the sub-document structure)\r
222     for (int a = theMain->size(ModelAPI_Feature::group()) - 1; a >= 0; a--) {\r
223       FeaturePtr aPartFeat = std::dynamic_pointer_cast<ModelAPI_Feature>(\r
224           theMain->object(ModelAPI_Feature::group(), a));\r
225       if (aPartFeat.get()) {\r
226         const std::list<std::shared_ptr<ModelAPI_Result> >& aResList = aPartFeat->results();\r
227         std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResList.begin();\r
228         for(; aRes != aResList.end(); aRes++) {\r
229           ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRes);\r
230           if (aPart.get()) {\r
231             if (aPart->isActivated() && aPart->partDoc() == theSub)\r
232               return aPartFeat;\r
233           } else break; // if the first is not Part, others are also not\r
234         }\r
235       }\r
236     }\r
237   }\r
238   return FeaturePtr();\r
239 }\r
240 \r
241 CompositeFeaturePtr compositeOwner(const FeaturePtr& theFeature)\r
242 {\r
243   if (theFeature.get() && theFeature->data()->isValid()) {\r
244     const std::set<std::shared_ptr<ModelAPI_Attribute> >& aRefs = theFeature->data()->refsToMe();\r
245     std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aRefIter = aRefs.begin();\r
246     for(; aRefIter != aRefs.end(); aRefIter++) {\r
247       CompositeFeaturePtr aComp = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>\r
248         ((*aRefIter)->owner());\r
249       if (aComp.get() && aComp->data()->isValid() && aComp->isSub(theFeature))\r
250         return aComp;\r
251     }\r
252   }\r
253   return CompositeFeaturePtr(); // not found\r
254 }\r
255 \r
256 ResultCompSolidPtr compSolidOwner(const ResultPtr& theSub)\r
257 {\r
258   ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theSub);\r
259   if (aBody.get()) {\r
260     FeaturePtr aFeatureOwner = aBody->document()->feature(aBody);\r
261     if (aFeatureOwner.get()) {\r
262       std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aResIter = \r
263         aFeatureOwner->results().cbegin();\r
264       for(; aResIter != aFeatureOwner->results().cend(); aResIter++) {\r
265         ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aResIter);\r
266         if (aComp && aComp->isSub(aBody))\r
267           return aComp;\r
268       }\r
269     }\r
270   }\r
271   return ResultCompSolidPtr(); // not found\r
272 }\r
273 \r
274 bool hasSubResults(const ResultPtr& theResult)\r
275 {\r
276   ResultCompSolidPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(theResult);\r
277   return aCompSolid.get() && aCompSolid->numberOfSubs() > 0;\r
278 }\r
279 \r
280 void allResults(const FeaturePtr& theFeature, std::list<ResultPtr>& theResults)\r
281 {\r
282   if (!theFeature.get()) // safety: for empty feature no results\r
283     return;\r
284   const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();\r
285   std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();\r
286   for (; aRIter != aResults.cend(); aRIter++) {\r
287     theResults.push_back(*aRIter);\r
288     // iterate sub-bodies of compsolid\r
289     ResultCompSolidPtr aComp = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aRIter);\r
290     if (aComp.get()) {\r
291       int aNumSub = aComp->numberOfSubs();\r
292       for(int a = 0; a < aNumSub; a++) {\r
293         theResults.push_back(aComp->subResult(a));\r
294       }\r
295     }\r
296   }\r
297 }\r
298 \r
299 //******************************************************************\r
300 bool allDocumentsActivated(std::string& theNotActivatedNames)\r
301 {\r
302   theNotActivatedNames = "";\r
303   bool anAllPartActivated = true;\r
304 \r
305   DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();\r
306   int aSize = aRootDoc->size(ModelAPI_ResultPart::group());\r
307   for (int i = 0; i < aSize; i++) {\r
308     ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), i);\r
309     ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);\r
310     if (!aPart->isActivated()) {\r
311       anAllPartActivated = false;\r
312       if (!theNotActivatedNames.empty())\r
313         theNotActivatedNames += ", ";\r
314       theNotActivatedNames += aObject->data()->name().c_str();\r
315     }\r
316   }\r
317   return anAllPartActivated;\r
318 }\r
319 \r
320 bool removeFeaturesAndReferences(const std::set<FeaturePtr>& theFeatures,\r
321                                  const bool theFlushRedisplay,\r
322                                  const bool theUseComposite,\r
323                                  const bool theUseRecursion)\r
324 {\r
325 #ifdef DEBUG_REMOVE_FEATURES\r
326   printListInfo(theFeatures, "selection: ");\r
327 #endif\r
328 \r
329   std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;\r
330   ModelAPI_Tools::findAllReferences(theFeatures, aReferences, theUseComposite, theUseRecursion);\r
331 #ifdef DEBUG_REMOVE_FEATURES\r
332   printMapInfo(aReferences, "allDependencies: ");\r
333 #endif\r
334 \r
335   std::set<FeaturePtr> aFeaturesRefsTo;\r
336   ModelAPI_Tools::findRefsToFeatures(theFeatures, aReferences, aFeaturesRefsTo);\r
337 #ifdef DEBUG_REMOVE_FEATURES\r
338   printListInfo(aFeaturesRefsTo, "references: ");\r
339 #endif\r
340 \r
341   std::set<FeaturePtr> aFeatures = theFeatures;\r
342   if (!aFeaturesRefsTo.empty())\r
343     aFeatures.insert(aFeaturesRefsTo.begin(), aFeaturesRefsTo.end());\r
344 #ifdef DEBUG_REMOVE_FEATURES\r
345   printListInfo(aFeatures, "removeFeatures: ");\r
346 #endif\r
347 \r
348   return ModelAPI_Tools::removeFeatures(aFeatures, false);\r
349 }\r
350 \r
351 bool removeFeatures(const std::set<FeaturePtr>& theFeatures,\r
352                     const bool theFlushRedisplay)\r
353 {\r
354   bool isDone = false;\r
355   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),\r
356                                        aLast = theFeatures.end();\r
357   for (; anIt != aLast; anIt++) {\r
358     FeaturePtr aFeature = *anIt;\r
359     if (aFeature.get()) {\r
360       DocumentPtr aDoc = aFeature->document();\r
361       // flush REDISPLAY signal after remove feature\r
362       aDoc->removeFeature(aFeature);\r
363       isDone = true;\r
364     }\r
365   }\r
366   if (isDone && theFlushRedisplay) {\r
367     // the redisplay signal should be flushed in order to erase the feature presentation in the viewer\r
368     // if should be done after removeFeature() of document\r
369     Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));\r
370   }\r
371   return true;\r
372 }\r
373 \r
374 // Fills the references list by all references of the feature from the references map.\r
375 // This is a recusive method to find references by next found feature in the map of references.\r
376 // \param theFeature a feature to find references\r
377 // \param theReferencesMap a map of references\r
378 // \param theReferences an out container of references\r
379 void addRefsToFeature(const FeaturePtr& theFeature,\r
380                       const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferencesMap,\r
381                       std::map<FeaturePtr, std::set<FeaturePtr> >& theProcessedReferences,\r
382                       int theRecLevel,\r
383                       std::set<FeaturePtr>& theReferences)\r
384 {\r
385   if (theRecLevel > RECURSE_TOP_LEVEL)\r
386     return;\r
387   theRecLevel++;\r
388 \r
389   // if the feature is already processed, get the ready references from the map\r
390   if (theProcessedReferences.find(theFeature) != theProcessedReferences.end()) {\r
391     std::set<FeaturePtr> aReferences = theProcessedReferences.at(theFeature);\r
392     theReferences.insert(aReferences.begin(), aReferences.end());\r
393     return;\r
394   }\r
395 \r
396   if (theReferencesMap.find(theFeature) == theReferencesMap.end())\r
397     return; // this feature is not in the selection list, so exists without references to it\r
398   std::set<FeaturePtr> aMainReferences = theReferencesMap.at(theFeature);\r
399 \r
400   std::set<FeaturePtr>::const_iterator anIt = aMainReferences.begin(),\r
401                                        aLast = aMainReferences.end();\r
402 #ifdef DEBUG_REMOVE_FEATURES_RECURSE\r
403   std::string aSpacing;\r
404   for (int i = 0; i < theRecLevel; i++)\r
405     aSpacing.append(" ");\r
406 #endif\r
407 \r
408   for (; anIt != aLast; anIt++) {\r
409     FeaturePtr aRefFeature = *anIt;\r
410 #ifdef DEBUG_REMOVE_FEATURES_RECURSE\r
411   std::cout << aSpacing << " Ref: " << getFeatureInfo(aRefFeature) << std::endl;\r
412 #endif\r
413     if (theReferences.find(aRefFeature) == theReferences.end())\r
414       theReferences.insert(aRefFeature);\r
415     addRefsToFeature(aRefFeature, theReferencesMap, theProcessedReferences, theRecLevel, theReferences);\r
416   }\r
417 }\r
418 \r
419 // For each feature from the feature list it searches references to the feature and append them\r
420 // to the references map. This is a recusive method.\r
421 // \param theFeature a feature to find references\r
422 // \param theReferencesMap a map of references\r
423 // \param theReferences an out container of references\r
424 void findReferences(const std::set<FeaturePtr>& theFeatures,\r
425                     std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,\r
426                     const bool theUseComposite, const bool theUseRecursion, int theRecLevel)\r
427 {\r
428   if (theRecLevel > RECURSE_TOP_LEVEL)\r
429     return;\r
430   theRecLevel++;\r
431   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),\r
432                                         aLast = theFeatures.end();\r
433   for (; anIt != aLast; anIt++) {\r
434     FeaturePtr aFeature = *anIt;\r
435     if (aFeature.get() && theReferences.find(aFeature) == theReferences.end()) {\r
436       DocumentPtr aSelFeatureDoc = aFeature->document();\r
437       std::set<FeaturePtr> aSelRefFeatures;\r
438       aSelFeatureDoc->refsToFeature(aFeature, aSelRefFeatures, false/*do not emit signals*/);\r
439       if (theUseComposite) { // do not filter selection\r
440         theReferences[aFeature] = aSelRefFeatures;\r
441       }\r
442       else { // filter references to skip composition features of the current feature\r
443         std::set<FeaturePtr> aFilteredFeatures;\r
444         std::set<FeaturePtr>::const_iterator anIt = aSelRefFeatures.begin(),\r
445                                              aLast = aSelRefFeatures.end();\r
446         for (; anIt != aLast; anIt++) {\r
447           FeaturePtr aCFeature = *anIt;\r
448           CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCFeature);\r
449           if (aComposite.get() && aComposite->isSub(aFeature))\r
450             continue; /// composite of the current feature should be skipped\r
451           aFilteredFeatures.insert(aCFeature);\r
452         }\r
453         theReferences[aFeature] = aFilteredFeatures;\r
454       }\r
455       if (theUseRecursion) {\r
456 #ifdef DEBUG_CYCLING_1550\r
457         findReferences(aSelRefFeatures, theReferences, theUseComposite, theUseRecursion, theRecLevel);\r
458 #else\r
459         findReferences(theReferences[aFeature], theReferences, theUseComposite, theUseRecursion,\r
460                        theRecLevel);\r
461 #endif\r
462       }\r
463     }\r
464   }\r
465 }\r
466 \r
467 void findAllReferences(const std::set<FeaturePtr>& theFeatures,\r
468                        std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,\r
469                        const bool theUseComposite,\r
470                        const bool theUseRecursion)\r
471 {\r
472   // For dependencies, find main_list:\r
473   // sk_1(ext_1, vertex_1)\r
474   // ext_1(bool_1, sk_3)\r
475   // vertex_1()\r
476   // sk_2(ext_2)\r
477   // ext_2(bool_2)\r
478   // sk_3()\r
479   // Information: bool_1 is not selected, ext_2(bool_2) exists\r
480   // find all referenced features\r
481   std::map<FeaturePtr, std::set<FeaturePtr> > aMainList;\r
482   int aRecLevel = 0;\r
483   findReferences(theFeatures, aMainList, theUseComposite, theUseRecursion, aRecLevel);\r
484 \r
485 #ifdef DEBUG_REMOVE_FEATURES\r
486   printMapInfo(aMainList, "firstDependencies");\r
487 #endif\r
488   // find all dependencies for each object:\r
489   // sk_1(ext_1, vertex_1) + (sk_3, bool_1)\r
490   // ext_1(bool_1, sk_3)\r
491   // vertex_1()\r
492   // sk_2(ext_2) + (bool_1)\r
493   // ext_2(bool_1)\r
494   // sk_3()\r
495   std::map<FeaturePtr, std::set<FeaturePtr> >::const_iterator aMainIt = aMainList.begin(),\r
496                                                               aMainLast = aMainList.end();\r
497   for (; aMainIt != aMainLast; aMainIt++) {\r
498     FeaturePtr aMainListFeature = aMainIt->first;\r
499 \r
500     //std::string aName = aMainListFeature->name();\r
501     std::set<FeaturePtr> aMainRefList = aMainIt->second;\r
502 \r
503 #ifdef DEBUG_REMOVE_FEATURES_RECURSE\r
504     char aBuf[50];\r
505     int n = sprintf(aBuf, "%d", aMainRefList.size());\r
506     std::string aSize(aBuf);\r
507     std::cout << "_findAllReferences for the Feature: " << getFeatureInfo(aMainListFeature)\r
508               << ", references size = " << aSize << std::endl;\r
509 #endif\r
510     std::set<FeaturePtr>::const_iterator anIt = aMainRefList.begin(),\r
511                                          aLast = aMainRefList.end();\r
512     std::set<FeaturePtr> aResultRefList;\r
513     aResultRefList.insert(aMainRefList.begin(), aMainRefList.end());\r
514     for (; anIt != aLast; anIt++) {\r
515       FeaturePtr aFeature = *anIt;\r
516       int aRecLevel = 0;\r
517 #ifdef DEBUG_REMOVE_FEATURES_RECURSE\r
518       std::cout << " Ref: " << getFeatureInfo(aFeature) << std::endl;\r
519 #endif\r
520       aRecLevel++;\r
521       addRefsToFeature(aFeature, aMainList, theReferences, aRecLevel, aResultRefList/*aMainRefList*/);\r
522     }\r
523     theReferences[aMainListFeature] = aResultRefList;\r
524   }\r
525 #ifdef DEBUG_REMOVE_FEATURES_RECURSE\r
526     std::cout << std::endl;\r
527 #endif\r
528 \r
529 #ifdef DEBUG_REMOVE_FEATURES\r
530   printMapInfo(theReferences, "allDependencies");\r
531 #endif\r
532 }\r
533 \r
534 void findRefsToFeatures(const std::set<FeaturePtr>& theFeatures,\r
535                         const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,\r
536                         std::set<FeaturePtr>& theFeaturesRefsTo)\r
537 {\r
538   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),\r
539                                        aLast = theFeatures.end();\r
540   for (; anIt != aLast; anIt++) {\r
541     FeaturePtr aFeature = *anIt;\r
542     if (theReferences.find(aFeature) == theReferences.end())\r
543       continue;\r
544     std::set<FeaturePtr> aRefList = theReferences.at(aFeature);\r
545     std::set<FeaturePtr>::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end();\r
546     for (; aRefIt != aRefLast; aRefIt++) {\r
547       FeaturePtr aRefFeature = *aRefIt;\r
548       CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aRefFeature);\r
549       if (aComposite.get() && aComposite->isSub(aFeature))\r
550         continue; /// composite of the current feature should not be removed\r
551 \r
552       if (theFeatures.find(aRefFeature) == theFeatures.end() && // it is not selected\r
553           theFeaturesRefsTo.find(aRefFeature) == theFeaturesRefsTo.end()) // it is not added\r
554         theFeaturesRefsTo.insert(aRefFeature);\r
555     }\r
556   }\r
557 }\r
558 \r
559 void getConcealedResults(const FeaturePtr& theFeature,\r
560                          std::list<std::shared_ptr<ModelAPI_Result> >& theResults)\r
561 {\r
562   SessionPtr aSession = ModelAPI_Session::get();\r
563 \r
564   std::list<std::pair<std::string, std::list<std::shared_ptr<ModelAPI_Object> > > > aRefs;\r
565   theFeature->data()->referencesToObjects(aRefs);\r
566   std::list<std::pair<std::string, std::list<ObjectPtr> > >::const_iterator\r
567                                                   anIt = aRefs.begin(), aLast = aRefs.end();\r
568   std::set<ResultPtr> alreadyThere; // to avoid duplications\r
569   for (; anIt != aLast; anIt++) {\r
570     if (!aSession->validators()->isConcealed(theFeature->getKind(), anIt->first))\r
571       continue; // use only concealed attributes\r
572     std::list<ObjectPtr> anObjects = (*anIt).second;\r
573     std::list<ObjectPtr>::const_iterator anOIt = anObjects.begin(), anOLast = anObjects.end();\r
574     for (; anOIt != anOLast; anOIt++) {\r
575       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(*anOIt);\r
576       if (aResult && aResult->isConcealed()) {\r
577         if (alreadyThere.find(aResult) == alreadyThere.end()) // issue 1712, avoid duplicates\r
578           alreadyThere.insert(aResult);\r
579         else continue;\r
580         theResults.push_back(aResult);\r
581       }\r
582     }\r
583   }\r
584 }\r
585 \r
586 } // namespace ModelAPI_Tools\r