Salome HOME
Merge branch 'BR_coding_rules'
[modules/shaper.git] / src / ModelHighAPI / ModelHighAPI_Tools.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2 // Name   : ModelHighAPI_Tools.cpp
3 // Purpose:
4 //
5 // History:
6 // 07/06/16 - Sergey POKHODENKO - Creation of the file
7
8 //--------------------------------------------------------------------------------------
9 #include "ModelHighAPI_Tools.h"
10 #include <ModelHighAPI_FeatureStore.h>
11 //--------------------------------------------------------------------------------------
12 #include <GeomAPI_Dir.h>
13 #include <GeomAPI_Pnt.h>
14 #include <GeomAPI_Pnt2d.h>
15 //--------------------------------------------------------------------------------------
16 #include <GeomDataAPI_Dir.h>
17 #include <GeomDataAPI_Point.h>
18 #include <GeomDataAPI_Point2D.h>
19 //--------------------------------------------------------------------------------------
20 #include <ModelAPI_AttributeBoolean.h>
21 #include <ModelAPI_AttributeDocRef.h>
22 #include <ModelAPI_AttributeDouble.h>
23 #include <ModelAPI_AttributeIntArray.h>
24 #include <ModelAPI_AttributeInteger.h>
25 #include <ModelAPI_AttributeRefAttr.h>
26 #include <ModelAPI_AttributeRefAttrList.h>
27 #include <ModelAPI_AttributeReference.h>
28 #include <ModelAPI_AttributeRefList.h>
29 #include <ModelAPI_AttributeSelection.h>
30 #include <ModelAPI_AttributeSelectionList.h>
31 #include <ModelAPI_AttributeString.h>
32 #include <ModelAPI_AttributeStringArray.h>
33 #include <ModelAPI_AttributeDoubleArray.h>
34 #include <ModelAPI_Session.h>
35 #include <ModelAPI_Tools.h>
36 #include <ModelAPI_ResultPart.h>
37 //--------------------------------------------------------------------------------------
38 #include <Config_ModuleReader.h>
39 //--------------------------------------------------------------------------------------
40 #include "ModelHighAPI_Double.h"
41 #include "ModelHighAPI_Integer.h"
42 #include "ModelHighAPI_RefAttr.h"
43 #include "ModelHighAPI_Reference.h"
44 #include "ModelHighAPI_Selection.h"
45
46 #include <Events_InfoMessage.h>
47
48 // Have to be included before std headers
49 #include <Python.h>
50
51 #include <algorithm>
52 #include <iostream>
53
54 //--------------------------------------------------------------------------------------
55 void fillAttribute(const std::shared_ptr<GeomAPI_Pnt2d> & theValue,
56                    const std::shared_ptr<GeomDataAPI_Point2D> & theAttribute)
57 {
58   theAttribute->setValue(theValue);
59 }
60
61 void fillAttribute(const std::shared_ptr<GeomDataAPI_Point2D> & theAttribute,
62                    double theX, double theY)
63 {
64   theAttribute->setValue(theX, theY);
65 }
66
67 //--------------------------------------------------------------------------------------
68 void fillAttribute(const std::shared_ptr<GeomAPI_Dir> & theValue,
69                    const std::shared_ptr<GeomDataAPI_Dir> & theAttribute)
70 {
71   theAttribute->setValue(theValue);
72 }
73
74 //--------------------------------------------------------------------------------------
75 void fillAttribute(const std::shared_ptr<GeomAPI_Pnt> & theValue,
76                    const std::shared_ptr<GeomDataAPI_Point> & theAttribute)
77 {
78   theAttribute->setValue(theValue);
79 }
80
81 //--------------------------------------------------------------------------------------
82 void fillAttribute(bool theValue,
83                    const std::shared_ptr<ModelAPI_AttributeBoolean> & theAttribute)
84 {
85   theAttribute->setValue(theValue);
86 }
87
88 //--------------------------------------------------------------------------------------
89 void fillAttribute(const ModelHighAPI_Double & theValue,
90                    const std::shared_ptr<ModelAPI_AttributeDouble> & theAttribute)
91 {
92   theValue.fillAttribute(theAttribute);
93 }
94 void fillAttribute(double theValue,
95                    const std::shared_ptr<ModelAPI_AttributeDouble> & theAttribute)
96 {
97   theAttribute->setValue(theValue);
98 }
99
100 //--------------------------------------------------------------------------------------
101 void fillAttribute(const ModelHighAPI_Integer & theValue,
102                    const std::shared_ptr<ModelAPI_AttributeInteger> & theAttribute)
103 {
104   theValue.fillAttribute(theAttribute);
105 }
106 void fillAttribute(int theValue,
107                    const std::shared_ptr<ModelAPI_AttributeInteger> & theAttribute)
108 {
109   theAttribute->setValue(theValue);
110 }
111
112 //--------------------------------------------------------------------------------------
113 void fillAttribute(const ModelHighAPI_RefAttr & theValue,
114                    const std::shared_ptr<ModelAPI_AttributeRefAttr> & theAttribute)
115 {
116   theValue.fillAttribute(theAttribute);
117 }
118
119 //--------------------------------------------------------------------------------------
120 void fillAttribute(const std::list<ModelHighAPI_RefAttr> & theValue,
121                    const std::shared_ptr<ModelAPI_AttributeRefAttrList> & theAttribute)
122 {
123   theAttribute->clear();
124   for (auto it = theValue.begin(); it != theValue.end(); ++it)
125     it->appendToList(theAttribute);
126 }
127
128 //--------------------------------------------------------------------------------------
129 void fillAttribute(const ModelHighAPI_Reference & theValue,
130                    const std::shared_ptr<ModelAPI_AttributeReference> & theAttribute)
131 {
132   theValue.fillAttribute(theAttribute);
133 }
134
135 //--------------------------------------------------------------------------------------
136 void fillAttribute(const std::list<ModelHighAPI_Reference> & theValue,
137                    const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute)
138 {
139   theAttribute->clear();
140   for (auto it = theValue.begin(); it != theValue.end(); ++it)
141     it->appendToList(theAttribute);
142 }
143
144 //--------------------------------------------------------------------------------------
145 void fillAttribute(const std::shared_ptr<ModelAPI_Object> & theValue,
146                    const std::shared_ptr<ModelAPI_AttributeReference> & theAttribute)
147 {
148   theAttribute->setValue(theValue);
149 }
150
151 //--------------------------------------------------------------------------------------
152 void fillAttribute(const std::list<std::shared_ptr<ModelAPI_Object> > & theValue,
153                    const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute)
154 {
155   theAttribute->clear();
156   for (auto it = theValue.begin(); it != theValue.end(); ++it)
157     theAttribute->append(*it);
158 }
159
160 MODELHIGHAPI_EXPORT
161 void fillAttribute(const std::list<ModelHighAPI_Selection> & theValue,
162                    const std::shared_ptr<ModelAPI_AttributeRefList> & theAttribute)
163 {
164   theAttribute->clear();
165   for (auto it = theValue.begin(); it != theValue.end(); ++it)
166     theAttribute->append(it->resultSubShapePair().first); // use only context
167 }
168
169 //--------------------------------------------------------------------------------------
170 void fillAttribute(const ModelHighAPI_Selection & theValue,
171                    const std::shared_ptr<ModelAPI_AttributeSelection> & theAttribute)
172 {
173   theValue.fillAttribute(theAttribute);
174 }
175
176 //--------------------------------------------------------------------------------------
177 void fillAttribute(const std::list<ModelHighAPI_Selection> & theValue,
178                    const std::shared_ptr<ModelAPI_AttributeSelectionList> & theAttribute)
179 {
180   theAttribute->clear();
181
182   if(!theValue.empty()) {
183     std::string aSelectionType;
184     const ModelHighAPI_Selection& aSelection = theValue.front();
185     theAttribute->setSelectionType(aSelection.shapeType());
186   }
187
188   for (auto it = theValue.begin(); it != theValue.end(); ++it)
189     it->appendToList(theAttribute);
190 }
191
192 //--------------------------------------------------------------------------------------
193 void fillAttribute(const std::string & theValue,
194                    const std::shared_ptr<ModelAPI_AttributeString> & theAttribute)
195 {
196   theAttribute->setValue(theValue);
197 }
198
199 //--------------------------------------------------------------------------------------
200 void fillAttribute(const char * theValue,
201                    const std::shared_ptr<ModelAPI_AttributeString> & theAttribute)
202 {
203   theAttribute->setValue(theValue);
204 }
205
206 //--------------------------------------------------------------------------------------
207 void fillAttribute(const std::list<std::string> & theValue,
208                    const std::shared_ptr<ModelAPI_AttributeStringArray> & theAttribute)
209 {
210   theAttribute->setSize(int(theValue.size()));
211
212   int anIndex = 0;
213   for (auto it = theValue.begin(); it != theValue.end(); ++it, ++anIndex)
214     theAttribute->setValue(anIndex, *it);
215 }
216
217 //--------------------------------------------------------------------------------------
218 void fillAttribute(const std::list<ModelHighAPI_Integer> & theValue,
219                    const std::shared_ptr<ModelAPI_AttributeIntArray> & theAttribute)
220 {
221   theAttribute->setSize(int(theValue.size()));
222
223   int anIndex = 0;
224   for (auto it = theValue.begin(); it != theValue.end(); ++it, ++anIndex)
225     theAttribute->setValue(anIndex, it->intValue()); // use only values, no text support in array
226 }
227
228 //==================================================================================================
229 GeomAPI_Shape::ShapeType shapeTypeByStr(std::string theShapeTypeStr)
230 {
231   GeomAPI_Shape::ShapeType aShapeType = GeomAPI_Shape::SHAPE;
232
233   std::transform(theShapeTypeStr.begin(), theShapeTypeStr.end(),
234                  theShapeTypeStr.begin(), ::tolower);
235
236   if(theShapeTypeStr == "compound") {
237     aShapeType = GeomAPI_Shape::COMPOUND;
238   } else if(theShapeTypeStr == "compsolid") {
239     aShapeType = GeomAPI_Shape::COMPSOLID;
240   } else if(theShapeTypeStr == "solid") {
241     aShapeType = GeomAPI_Shape::SOLID;
242   } else if(theShapeTypeStr == "shell") {
243     aShapeType = GeomAPI_Shape::SHELL;
244   } else if(theShapeTypeStr == "face") {
245     aShapeType = GeomAPI_Shape::FACE;
246   } else if(theShapeTypeStr == "wire") {
247     aShapeType = GeomAPI_Shape::WIRE;
248   } else if(theShapeTypeStr == "edge") {
249     aShapeType = GeomAPI_Shape::EDGE;
250   } else if(theShapeTypeStr == "vertex") {
251     aShapeType = GeomAPI_Shape::VERTEX;
252   } else if(theShapeTypeStr == "shape") {
253     aShapeType = GeomAPI_Shape::SHAPE;
254   }
255
256   return aShapeType;
257 }
258
259 //==================================================================================================
260 GeomAPI_Shape::ShapeType getShapeType(const ModelHighAPI_Selection& theSelection)
261 {
262   GeomAPI_Shape::ShapeType aShapeType = GeomAPI_Shape::SHAPE;
263
264   switch(theSelection.variantType()) {
265     case ModelHighAPI_Selection::VT_ResultSubShapePair: {
266       ResultSubShapePair aPair = theSelection.resultSubShapePair();
267       GeomShapePtr aShape = aPair.second;
268       if(!aShape.get()) {
269         aShape = aPair.first->shape();
270       }
271       if(!aShape.get()) {
272         return aShapeType;
273       }
274       aShapeType = aShape->shapeType();
275       break;
276     }
277     case ModelHighAPI_Selection::VT_TypeSubShapeNamePair: {
278       TypeSubShapeNamePair aPair = theSelection.typeSubShapeNamePair();
279       std::string aType = aPair.first;
280       aShapeType = shapeTypeByStr(aType);
281       break;
282     }
283   }
284
285   return aShapeType;
286 }
287
288 //--------------------------------------------------------------------------------------
289 ModelAPI_AttributeTables::ValueType valueTypeByStr(const std::string& theValueTypeStr)
290 {
291   std::string aType = theValueTypeStr;
292   std::transform(aType.begin(), aType.end(), aType.begin(), ::tolower);
293   if (aType == "boolean")
294     return ModelAPI_AttributeTables::BOOLEAN;
295   else if (aType == "integer")
296     return ModelAPI_AttributeTables::INTEGER;
297   else if (aType == "string")
298     return ModelAPI_AttributeTables::STRING;
299   return ModelAPI_AttributeTables::DOUBLE; // default
300 }
301
302 //--------------------------------------------------------------------------------------
303 std::string strByValueType(const ModelAPI_AttributeTables::ValueType theType)
304 {
305   switch(theType) {
306   case ModelAPI_AttributeTables::BOOLEAN: return "BOOLEAN";
307   case ModelAPI_AttributeTables::INTEGER: return "INTEGER";
308   case ModelAPI_AttributeTables::DOUBLE: return "DOUBLE";
309   case ModelAPI_AttributeTables::STRING: return "STRING";
310   }
311   return ""; // bad case
312 }
313
314 /// stores the features information, recoursively stores sub-documetns features
315 std::string storeFeatures(const std::string& theDocName, DocumentPtr theDoc,
316   std::map<std::string, std::map<std::string, ModelHighAPI_FeatureStore> >& theStore,
317   const bool theCompare) // if false => store
318 {
319   std::map<std::string, std::map<std::string, ModelHighAPI_FeatureStore> >::iterator aDocFind;
320   if (theCompare) {
321      aDocFind = theStore.find(theDocName);
322      if (aDocFind == theStore.end()) {
323        return "Document '" + theDocName + "' not found";
324      }
325   }
326   // store the model features information: iterate all features
327   int aFeaturesCount = 0; // stores the number of compared features for this document to compate
328   std::set<std::string> aProcessed; // processed features names (that are in the current document)
329   std::list<FeaturePtr> allFeatures = theDoc->allFeatures();
330   std::list<FeaturePtr>::iterator allIter = allFeatures.begin();
331   for(; allIter != allFeatures.end(); allIter++) {
332     FeaturePtr aFeat = *allIter;
333     if (theCompare) {
334       std::map<std::string, ModelHighAPI_FeatureStore>::iterator
335         aFeatFind = aDocFind->second.find(aFeat->name());
336       if (aFeatFind == aDocFind->second.end()) {
337         return "Document '" + theDocName + "' feature '" + aFeat->name() + "' not found";
338       }
339       std::string anError = aFeatFind->second.compare(aFeat);
340       if (!anError.empty()) {
341         return anError;
342       }
343       aFeaturesCount++;
344       aProcessed.insert(aFeat->name());
345     } else {
346       theStore[theDocName][aFeat->name()] = ModelHighAPI_FeatureStore(aFeat);
347     }
348     // iterate all results of this feature
349     std::list<ResultPtr> allResults;
350     ModelAPI_Tools::allResults(aFeat, allResults);
351     std::list<ResultPtr>::iterator aRes = allResults.begin();
352     for(; aRes != allResults.end(); aRes++) {
353       // recoursively store features of sub-documents
354       if ((*aRes)->groupName() == ModelAPI_ResultPart::group()) {
355         DocumentPtr aDoc = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRes)->partDoc();
356         if (aDoc.get()) {
357           std::string anError = storeFeatures((*aRes)->data()->name(), aDoc, theStore, theCompare);
358           if (!anError.empty())
359             return anError;
360         }
361       }
362     }
363   }
364   // checks the number of compared features
365   if (theCompare) {
366     if (aDocFind->second.size() != aFeaturesCount) {
367       // search for disappeared feature
368       std::string aLostName;
369       std::map<std::string, ModelHighAPI_FeatureStore>::iterator aLostIter;
370       for(aLostIter = aDocFind->second.begin(); aLostIter != aDocFind->second.end(); aLostIter++) {
371         if (aProcessed.find(aLostIter->first) == aProcessed.end()) {
372           aLostName = aLostIter->first;
373         }
374       }
375       return "For document '" + theDocName +
376         "' the number of features is decreased, there is no feature '" + aLostName + "'";
377     }
378   }
379   return ""; // ok
380 }
381
382 //==================================================================================================
383 bool checkPythonDump()
384 {
385   SessionPtr aSession = ModelAPI_Session::get();
386   // dump all to the python file
387   aSession->startOperation("Check python dump");
388   FeaturePtr aDump = aSession->moduleDocument()->addFeature("Dump");
389   if (aDump.get()) {
390     aDump->string("file_path")->setValue("check_dump.py"); // to the current folder
391     aDump->string("file_format")->setValue("py"); // to the current folder
392     aDump->execute();
393   }
394   bool isProblem = !aDump.get() || !aDump->error().empty(); // after "finish" dump will be removed
395   aSession->finishOperation();
396   if (isProblem)
397     return false; // something is wrong during dump
398
399    // map from document name to feature name to feature data
400   std::map<std::string, std::map<std::string, ModelHighAPI_FeatureStore> > aStore;
401   std::string anError = storeFeatures(
402     aSession->moduleDocument()->kind(), aSession->moduleDocument(), aStore, false);
403   if (!anError.empty()) {
404     Events_InfoMessage anErrorMsg(std::string("checkPythonDump"), anError);
405     anErrorMsg.send();
406     return false;
407   }
408   // close all before importation of the script
409   aSession->closeAll();
410   // execute the dumped
411   PyGILState_STATE gstate = PyGILState_Ensure(); /* acquire python thread */
412   PyObject* PyFileObject = PyFile_FromString("./check_dump.py", "r");
413   PyRun_SimpleFileEx(PyFile_AsFile(PyFileObject), "./check_dump.py", 1);
414   PyGILState_Release(gstate); /* release python thread */
415
416   // compare with the stored data
417   anError = storeFeatures(
418     aSession->moduleDocument()->kind(), aSession->moduleDocument(), aStore, true);
419   if (!anError.empty()) {
420     std::cout<<anError<<std::endl;
421     Events_InfoMessage anErrorMsg(std::string("checkPythonDump"), anError);
422     anErrorMsg.send();
423     return false;
424   }
425
426   return true;
427 }
428
429 //--------------------------------------------------------------------------------------