]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModelHighAPI/ModelHighAPI_Dumper.cpp
Salome HOME
d50d9652ac46677bd9f6cbf5b81f40bf8f2b1c23
[modules/shaper.git] / src / ModelHighAPI / ModelHighAPI_Dumper.cpp
1 // Copyright (C) 2016-20xx CEA/DEN, EDF R&D -->
2
3 // File:        ModelHighAPI_Dumper.cpp
4 // Created:     1 August 2016
5 // Author:      Artem ZHIDKOV
6
7 //--------------------------------------------------------------------------------------
8 #include "ModelHighAPI_Dumper.h"
9
10 #include <GeomAPI_Pnt.h>
11 #include <GeomAPI_Dir.h>
12
13 #include <GeomDataAPI_Dir.h>
14 #include <GeomDataAPI_Point.h>
15 #include <GeomDataAPI_Point2D.h>
16
17 #include <ModelAPI_AttributeBoolean.h>
18 #include <ModelAPI_AttributeDouble.h>
19 #include <ModelAPI_AttributeInteger.h>
20 #include <ModelAPI_AttributeRefAttr.h>
21 #include <ModelAPI_AttributeRefAttrList.h>
22 #include <ModelAPI_AttributeRefList.h>
23 #include <ModelAPI_AttributeSelection.h>
24 #include <ModelAPI_AttributeSelectionList.h>
25 #include <ModelAPI_AttributeString.h>
26 #include <ModelAPI_CompositeFeature.h>
27 #include <ModelAPI_Document.h>
28 #include <ModelAPI_Entity.h>
29 #include <ModelAPI_Feature.h>
30 #include <ModelAPI_Result.h>
31 #include <ModelAPI_ResultPart.h>
32
33 #include <PartSetPlugin_Part.h>
34
35 #include <SketchPlugin_SketchEntity.h>
36
37 #include <OSD_OpenFile.hxx>
38
39 #include <algorithm>
40 #include <fstream>
41
42 //#define DUMP_USER_DEFINED_NAMES
43
44 ModelHighAPI_Dumper* ModelHighAPI_Dumper::mySelf = 0;
45
46 ModelHighAPI_Dumper::ModelHighAPI_Dumper()
47 {
48   clear();
49 }
50
51 void ModelHighAPI_Dumper::setInstance(ModelHighAPI_Dumper* theDumper)
52 {
53   if (mySelf == 0)
54     mySelf = theDumper;
55 }
56
57 ModelHighAPI_Dumper* ModelHighAPI_Dumper::getInstance()
58 {
59   return mySelf;
60 }
61
62 void ModelHighAPI_Dumper::clear(bool bufferOnly)
63 {
64   myDumpBuffer = std::ostringstream();
65   myDumpBuffer << std::setprecision(16);
66
67   clearNotDumped();
68
69   if (!bufferOnly) {
70     myFullDump = std::ostringstream();
71     myFullDump << std::setprecision(16);
72
73     myNames.clear();
74     myModules.clear();
75     myLastEntityWithName = EntityPtr();
76   }
77 }
78
79 void ModelHighAPI_Dumper::clearNotDumped()
80 {
81   myNotDumpedEntities.clear();
82 }
83
84 const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity)
85 {
86   EntityNameMap::const_iterator aFound = myNames.find(theEntity);
87   if (aFound != myNames.end())
88     return aFound->second.first;
89
90   // entity is not found, store it
91   std::string aName;
92   bool isNameDefined = false;
93   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theEntity);
94   if (aFeature) {
95     aName = aFeature->name();
96     isNameDefined = !aName.empty();
97
98     if (!isNameDefined) {
99       static long anIndex = 0;
100       // set default name: feature ID + index
101       std::ostringstream aConverter;
102       aConverter << aFeature->getKind() << "_" << ++anIndex;
103       aName = aConverter.str();
104       std::transform(aName.begin(), aName.end(), aName.begin(), ::tolower);
105     }
106   }
107
108   myNames[theEntity] = std::pair<std::string, bool>(aName, isNameDefined);
109   myNotDumpedEntities.insert(theEntity);
110   return myNames[theEntity].first;
111 }
112
113 const std::string& ModelHighAPI_Dumper::parentName(const FeaturePtr& theEntity)
114 {
115   const std::set<AttributePtr>& aRefs = theEntity->data()->refsToMe();
116   std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
117   for (; aRefIt != aRefs.end(); ++aRefIt) {
118     CompositeFeaturePtr anOwner = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(
119         ModelAPI_Feature::feature((*aRefIt)->owner()));
120     if (anOwner)
121       return name(anOwner);
122   }
123
124   static const std::string DUMMY;
125   return DUMMY;
126 }
127
128 bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theDoc,
129                                   const std::string& theFileName)
130 {
131   // dump top level document feature
132   static const std::string aDocName("partSet");
133   myNames[theDoc] = std::pair<std::string, bool>(aDocName, false);
134   *this << aDocName << " = model.moduleDocument()" << std::endl;
135
136   // dump subfeatures and store result to file
137   return process(theDoc) && exportTo(theFileName);
138 }
139
140 bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theDoc)
141 {
142   bool isOk = true;
143   // dump all features
144   std::list<FeaturePtr> aFeatures = theDoc->allFeatures();
145   std::list<FeaturePtr>::const_iterator aFeatIt = aFeatures.begin();
146   for (; aFeatIt != aFeatures.end(); ++aFeatIt) {
147     if (!isDumped(*aFeatIt))
148       dumpFeature(*aFeatIt);
149
150     // iteratively process composite features
151     CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFeatIt);
152     if (!aCompFeat)
153       continue;
154
155     // sub-part is processed independently, because it provides separate document
156     if ((*aFeatIt)->getKind() == PartSetPlugin_Part::ID()) {
157       ResultPartPtr aPartResult =
158           std::dynamic_pointer_cast<ModelAPI_ResultPart>((*aFeatIt)->lastResult());
159       if (!aPartResult)
160         continue;
161       DocumentPtr aSubDoc = aPartResult->partDoc();
162       // set name of document equal to part name
163       myNames[aSubDoc] = myNames[*aFeatIt];
164
165       isOk = process(aSubDoc) && isOk;
166     } else
167       isOk = process(aCompFeat) && isOk;
168   }
169   return isOk;
170 }
171
172 bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_CompositeFeature>& theComposite)
173 {
174   // dump all sub-features;
175   int aNbSubs = theComposite->numberOfSubs();
176   for (int anIndex = 0; anIndex < aNbSubs; ++anIndex) {
177     FeaturePtr aFeature = theComposite->subFeature(anIndex);
178     if (isDumped(aFeature))
179       continue;
180     bool isForce = true;
181     // check the feature is a sketch entity and a copy of another entity
182     std::shared_ptr<SketchPlugin_SketchEntity> aSketchEntity =
183         std::dynamic_pointer_cast<SketchPlugin_SketchEntity>(aFeature);
184     if (aSketchEntity && aSketchEntity->isCopy())
185       isForce = false;
186     dumpFeature(aFeature, isForce);
187   }
188   // dump command to update model
189   myDumpBuffer << "model.do()" << std::endl;
190   return true;
191 }
192
193 bool ModelHighAPI_Dumper::exportTo(const std::string& theFileName)
194 {
195   std::ofstream aFile;
196   OSD_OpenStream(aFile, theFileName.c_str(), std::ofstream::out);
197   if (!aFile.is_open())
198     return false;
199
200   // standard header
201   for (ModulesMap::const_iterator aModIt = myModules.begin();
202        aModIt != myModules.end(); ++aModIt) {
203     aFile << "from " << aModIt->first << " import ";
204     if (aModIt->second.empty() || 
205         aModIt->second.find(std::string()) != aModIt->second.end())
206       aFile << "*"; // import whole module
207     else {
208       // import specific features
209       std::set<std::string>::const_iterator anObjIt = aModIt->second.begin();
210       aFile << *anObjIt;
211       for (++anObjIt; anObjIt != aModIt->second.end(); ++anObjIt)
212         aFile << ", " << *anObjIt;
213     }
214     aFile << std::endl;
215   }
216   if (!myModules.empty())
217     aFile << std::endl;
218
219   aFile << "import model" << std::endl << std::endl;
220   aFile << "model.begin()" << std::endl;
221
222   // dump collected data
223   aFile << myFullDump.str();
224
225   // standard footer
226   aFile << "model.end()" << std::endl;
227
228   aFile.close();
229   clear();
230
231   return true;
232 }
233
234 void ModelHighAPI_Dumper::importModule(const std::string& theModuleName,
235                                        const std::string& theObject)
236 {
237   myModules[theModuleName].insert(theObject);
238 }
239
240 void ModelHighAPI_Dumper::dumpEntitySetName()
241 {
242   if (!myLastEntityWithName)
243     return;
244
245 #ifdef DUMP_USER_DEFINED_NAMES
246   const std::string& aName = name(myLastEntityWithName);
247   myDumpBuffer << aName;
248   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(myLastEntityWithName);
249   if (aFeature)
250     myDumpBuffer << ".feature()";
251   myDumpBuffer << ".data().setName(\"" << aName << "\")" << std::endl;
252 #endif
253   myNames[myLastEntityWithName].second = false; // don't dump "setName" for the entity twice
254   myLastEntityWithName = EntityPtr();
255 }
256
257 bool ModelHighAPI_Dumper::isDumped(const EntityPtr& theEntity) const
258 {
259   EntityNameMap::const_iterator aFound = myNames.find(theEntity);
260   return aFound != myNames.end();
261 }
262
263 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const char theChar)
264 {
265   myDumpBuffer << theChar;
266   return *this;
267 }
268
269 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const char* theString)
270 {
271   myDumpBuffer << theString;
272   return *this;
273 }
274
275 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::string& theString)
276 {
277   myDumpBuffer << theString;
278   return *this;
279 }
280
281 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const int theValue)
282 {
283   myDumpBuffer << theValue;
284   return *this;
285 }
286
287 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const double theValue)
288 {
289   myDumpBuffer << theValue;
290   return *this;
291 }
292
293 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::shared_ptr<GeomAPI_Pnt>& thePoint)
294 {
295   importModule("GeomAPI", "GeomAPI_Pnt");
296   myDumpBuffer << "GeomAPI_Pnt(" << thePoint->x() << ", "
297                << thePoint->y() << ", " << thePoint->z() << ")";
298   return *this;
299 }
300
301 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::shared_ptr<GeomAPI_Dir>& theDir)
302 {
303   importModule("GeomAPI", "GeomAPI_Dir");
304   myDumpBuffer << "GeomAPI_Dir(" << theDir->x() << ", "
305                << theDir->y() << ", " << theDir->z() << ")";
306   return *this;
307 }
308
309 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
310     const std::shared_ptr<GeomDataAPI_Dir>& theDir)
311 {
312   myDumpBuffer << theDir->x() << ", " << theDir->y() << ", " << theDir->z();
313   return *this;
314 }
315
316 static void dumpArray(std::ostringstream& theOutput, int theSize,
317                       double* theValues, std::string* theTexts)
318 {
319   for (int i = 0; i < theSize; ++i) {
320     if (i > 0)
321       theOutput << ", ";
322     if (theTexts[i].empty())
323       theOutput << theValues[i];
324     else
325       theOutput << "\"" << theTexts[i] << "\"";
326   }
327 }
328
329 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
330     const std::shared_ptr<GeomDataAPI_Point>& thePoint)
331 {
332   static const int aSize = 3;
333   double aValues[aSize] = {thePoint->x(), thePoint->y(), thePoint->z()};
334   std::string aTexts[aSize] = {thePoint->textX(), thePoint->textY(), thePoint->textZ()};
335   dumpArray(myDumpBuffer, aSize, aValues, aTexts);
336   return *this;
337 }
338
339 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
340     const std::shared_ptr<GeomDataAPI_Point2D>& thePoint)
341 {
342   static const int aSize = 2;
343   double aValues[aSize] = {thePoint->x(), thePoint->y()};
344   std::string aTexts[aSize] = {thePoint->textX(), thePoint->textY()};
345   dumpArray(myDumpBuffer, aSize, aValues, aTexts);
346   return *this;
347 }
348
349 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
350     const std::shared_ptr<ModelAPI_AttributeBoolean>& theAttrBool)
351 {
352   myDumpBuffer << (theAttrBool->value() ? "True" : "False");
353   return *this;
354 }
355
356 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
357     const std::shared_ptr<ModelAPI_AttributeInteger>& theAttrInt)
358 {
359   std::string aText = theAttrInt->text();
360   if (aText.empty())
361     myDumpBuffer << theAttrInt->value();
362   else
363     myDumpBuffer << "\"" << aText << "\"";
364   return *this;
365 }
366
367 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
368     const std::shared_ptr<ModelAPI_AttributeDouble>& theAttrReal)
369 {
370   std::string aText = theAttrReal->text();
371   if (aText.empty())
372     myDumpBuffer << theAttrReal->value();
373   else
374     myDumpBuffer << "\"" << aText << "\"";
375   return *this;
376 }
377
378 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
379     const std::shared_ptr<ModelAPI_AttributeString>& theAttrStr)
380 {
381   myDumpBuffer << "\"" << theAttrStr->value() << "\"";
382   return *this;
383 }
384
385 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FeaturePtr& theEntity)
386 {
387   myDumpBuffer << name(theEntity);
388   if (myNames[theEntity].second)
389     myLastEntityWithName = theEntity;
390   myNotDumpedEntities.erase(theEntity);
391   return *this;
392 }
393
394 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const ObjectPtr& theObject)
395 {
396   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
397   myDumpBuffer << name(aFeature);
398   return *this;
399 }
400
401 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const AttributePtr& theAttr)
402 {
403   FeaturePtr anOwner = ModelAPI_Feature::feature(theAttr->owner());
404   myDumpBuffer << name(anOwner) << "." << attributeGetter(anOwner, theAttr->id()) << "()";
405   return *this;
406 }
407
408 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
409     const std::shared_ptr<ModelAPI_AttributeRefAttr>& theRefAttr)
410 {
411   if (theRefAttr->isObject())
412     *this << theRefAttr->object();
413   else
414     *this << theRefAttr->attr();
415   return *this;
416 }
417
418 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
419     const std::shared_ptr<ModelAPI_AttributeRefAttrList>& theRefAttrList)
420 {
421   myDumpBuffer << "[";
422   std::list<std::pair<ObjectPtr, AttributePtr> > aList = theRefAttrList->list();
423   bool isAdded = false;
424   std::list<std::pair<ObjectPtr, AttributePtr> >::const_iterator anIt = aList.begin();
425   for (; anIt != aList.end(); ++anIt) {
426     if (isAdded)
427       myDumpBuffer << ", ";
428     else
429       isAdded = true;
430     if (anIt->first)
431       *this << anIt->first;
432     else if (anIt->second)
433       * this << anIt->second;
434   }
435   myDumpBuffer << "]";
436   return *this;
437 }
438
439 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
440     const std::shared_ptr<ModelAPI_AttributeRefList>& theRefList)
441 {
442   static const int aThreshold = 2;
443   // if number of elements in the list if greater than a threshold,
444   // dump it in a separate line with specific name
445   std::string aDumped = myDumpBuffer.str();
446   if (aDumped.empty() || theRefList->size() <= aThreshold) {
447     myDumpBuffer << "[";
448     std::list<ObjectPtr> aList = theRefList->list();
449     bool isAdded = false;
450     std::list<ObjectPtr>::const_iterator anIt = aList.begin();
451     for (; anIt != aList.end(); ++anIt) {
452       if (isAdded)
453         myDumpBuffer << ", ";
454       else
455         isAdded = true;
456
457       *this << *anIt;
458     }
459     myDumpBuffer << "]";
460   } else {
461     // clear buffer and store list "as is"
462     myDumpBuffer = std::ostringstream();
463     *this << theRefList;
464     // save buffer and clear it again
465     std::string aDumpedList = myDumpBuffer.str();
466     myDumpBuffer = std::ostringstream();
467     // obtain name of list
468     FeaturePtr anOwner = ModelAPI_Feature::feature(theRefList->owner());
469     std::string aListName = name(anOwner) + "_objects";
470     // store all previous data
471     myDumpBuffer << aListName << " = " << aDumpedList << std::endl
472                  << aDumped << aListName;
473   }
474   return *this;
475 }
476
477 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
478     const std::shared_ptr<ModelAPI_AttributeSelection>& theAttrSelect)
479 {
480   myDumpBuffer << "model.selection(";
481
482   if(!theAttrSelect->isInitialized()) {
483     myDumpBuffer << ")";
484     return *this;
485   }
486
487   GeomShapePtr aShape = theAttrSelect->value();
488   if(!aShape.get()) {
489     aShape = theAttrSelect->context()->shape();
490   }
491
492   if(!aShape.get()) {
493     myDumpBuffer << ")";
494     return *this;
495   }
496
497   myDumpBuffer << "\"" << aShape->shapeTypeStr() << "\", \"" << theAttrSelect->namingName() << "\")";
498   return *this;
499 }
500
501 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
502     const std::shared_ptr<ModelAPI_AttributeSelectionList>& theAttrSelList)
503 {
504   myDumpBuffer << "[";
505
506   GeomShapePtr aShape;
507   std::string aShapeTypeStr;
508
509   bool isAdded = false;
510
511   for(int anIndex = 0; anIndex < theAttrSelList->size(); ++anIndex) {
512     AttributeSelectionPtr anAttribute = theAttrSelList->value(anIndex);
513     aShape = anAttribute->value();
514     if(!aShape.get()) {
515       aShape = anAttribute->context()->shape();
516     }
517
518     if(!aShape.get()) {
519       continue;
520     }
521
522     if(isAdded) {
523       myDumpBuffer << ", ";
524     } else {
525       isAdded = true;
526     }
527     myDumpBuffer << "model.selection(\"" << aShape->shapeTypeStr() << "\", \"" << anAttribute->namingName() << "\")";
528   }
529
530   myDumpBuffer << "]";
531   return *this;
532 }
533
534 /// Dump std::endl
535 MODELHIGHAPI_EXPORT
536 ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
537                                 std::basic_ostream<char>& (*theEndl)(std::basic_ostream<char>&))
538 {
539   theDumper.myDumpBuffer << theEndl;
540   theDumper.dumpEntitySetName();
541
542   // store all not-dumped entities first
543   std::set<EntityPtr> aNotDumped = theDumper.myNotDumpedEntities;
544   std::string aBufCopy = theDumper.myDumpBuffer.str();
545   theDumper.clear(true);
546   std::set<EntityPtr>::const_iterator anIt = aNotDumped.begin();
547   for (; anIt != aNotDumped.end(); ++anIt) {
548     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
549     theDumper.dumpFeature(aFeature, true);
550   }
551
552   // then store currently dumped string
553   theDumper.myFullDump << aBufCopy;
554
555   return theDumper;
556 }