Salome HOME
bbf3be1d0b188845e951282ebeeee317539c8107
[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_AttributeSelection.h>
22 #include <ModelAPI_AttributeString.h>
23 #include <ModelAPI_CompositeFeature.h>
24 #include <ModelAPI_Document.h>
25 #include <ModelAPI_Entity.h>
26 #include <ModelAPI_Feature.h>
27 #include <ModelAPI_Result.h>
28 #include <ModelAPI_ResultPart.h>
29
30 #include <PartSetPlugin_Part.h>
31
32 #include <OSD_OpenFile.hxx>
33
34 #include <algorithm>
35 #include <fstream>
36
37 //#define DUMP_USER_DEFINED_NAMES
38
39 ModelHighAPI_Dumper* ModelHighAPI_Dumper::mySelf = 0;
40
41 ModelHighAPI_Dumper::ModelHighAPI_Dumper()
42 {
43   clear();
44 }
45
46 void ModelHighAPI_Dumper::setInstance(ModelHighAPI_Dumper* theDumper)
47 {
48   if (mySelf == 0)
49     mySelf = theDumper;
50 }
51
52 ModelHighAPI_Dumper* ModelHighAPI_Dumper::getInstance()
53 {
54   return mySelf;
55 }
56
57 void ModelHighAPI_Dumper::clear()
58 {
59   myDumpBuffer = std::ostringstream();
60   myDumpBuffer << std::setprecision(16);
61 }
62
63 const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity)
64 {
65   EntityNameMap::const_iterator aFound = myNames.find(theEntity);
66   if (aFound != myNames.end())
67     return aFound->second.first;
68
69   // entity is not found, store it
70   std::string aName;
71   bool isNameDefined = false;
72   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theEntity);
73   if (aFeature) {
74     aName = aFeature->name();
75     isNameDefined = !aName.empty();
76
77     if (!isNameDefined) {
78       static long anIndex = 0;
79       // set default name: feature ID + index
80       std::ostringstream aConverter;
81       aConverter << aFeature->getKind() << "_" << ++anIndex;
82       aName = aConverter.str();
83       std::transform(aName.begin(), aName.end(), aName.begin(), ::tolower);
84     }
85   }
86
87   myNames[theEntity] = std::pair<std::string, bool>(aName, isNameDefined);
88   return myNames[theEntity].first;
89 }
90
91 const std::string& ModelHighAPI_Dumper::parentName(const FeaturePtr& theEntity)
92 {
93   const std::set<AttributePtr>& aRefs = theEntity->data()->refsToMe();
94   std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
95   for (; aRefIt != aRefs.end(); ++aRefIt) {
96     CompositeFeaturePtr anOwner = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(
97         ModelAPI_Feature::feature((*aRefIt)->owner()));
98     if (anOwner)
99       return name(anOwner);
100   }
101
102   static const std::string DUMMY;
103   return DUMMY;
104 }
105
106 bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theDoc,
107                                   const std::string& theFileName)
108 {
109   // dump top level document feature
110   static const std::string aDocName("partSet");
111   myNames[theDoc] = std::pair<std::string, bool>(aDocName, false);
112   *this << aDocName << " = model.moduleDocument()" << std::endl;
113
114   // dump subfeatures and store result to file
115   return process(theDoc) && exportTo(theFileName);
116 }
117
118 bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theDoc)
119 {
120   bool isOk = true;
121   // dump all features
122   std::list<FeaturePtr> aFeatures = theDoc->allFeatures();
123   std::list<FeaturePtr>::const_iterator aFeatIt = aFeatures.begin();
124   for (; aFeatIt != aFeatures.end(); ++aFeatIt) {
125     dumpFeature(*aFeatIt);
126     // iteratively process composite features
127     CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFeatIt);
128     if (!aCompFeat)
129       continue;
130
131     // sub-part is processed independently, because it provides separate document
132     if ((*aFeatIt)->getKind() == PartSetPlugin_Part::ID()) {
133       ResultPartPtr aPartResult =
134           std::dynamic_pointer_cast<ModelAPI_ResultPart>((*aFeatIt)->lastResult());
135       if (!aPartResult)
136         continue;
137       DocumentPtr aSubDoc = aPartResult->partDoc();
138       // set name of document equal to part name
139       myNames[aSubDoc] = myNames[*aFeatIt];
140
141       isOk = process(aSubDoc) && isOk;
142     } else 
143       isOk = process(aCompFeat) && isOk;
144   }
145   return isOk;
146 }
147
148 bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_CompositeFeature>& theComposite)
149 {
150   // dump all sub-features;
151   int aNbSubs = theComposite->numberOfSubs();
152   for (int anIndex = 0; anIndex < aNbSubs; ++anIndex) {
153     FeaturePtr aFeature = theComposite->subFeature(anIndex);
154     dumpFeature(aFeature, true);
155   }
156   // dump command to update model
157   myDumpBuffer << "model.do()" << std::endl;
158   return true;
159 }
160
161 bool ModelHighAPI_Dumper::exportTo(const std::string& theFileName)
162 {
163   std::ofstream aFile;
164   OSD_OpenStream(aFile, theFileName.c_str(), std::ofstream::out);
165   if (!aFile.is_open())
166     return false;
167
168   // standard header
169   for (ModulesMap::const_iterator aModIt = myModules.begin();
170        aModIt != myModules.end(); ++aModIt) {
171     aFile << "from " << aModIt->first << " import ";
172     if (aModIt->second.empty() || 
173         aModIt->second.find(std::string()) != aModIt->second.end())
174       aFile << "*"; // import whole module
175     else {
176       // import specific features
177       std::set<std::string>::const_iterator anObjIt = aModIt->second.begin();
178       aFile << *anObjIt;
179       for (++anObjIt; anObjIt != aModIt->second.end(); ++anObjIt)
180         aFile << ", " << *anObjIt;
181     }
182     aFile << std::endl;
183   }
184   if (!myModules.empty())
185     aFile << std::endl;
186
187   aFile << "import model" << std::endl << std::endl;
188   aFile << "model.begin()" << std::endl;
189
190   // dump collected data
191   aFile << myDumpBuffer.str();
192
193   // standard footer
194   aFile << "model.end()" << std::endl;
195
196   aFile.close();
197   clear();
198
199   return true;
200 }
201
202 void ModelHighAPI_Dumper::importModule(const std::string& theModuleName,
203                                        const std::string& theObject)
204 {
205   myModules[theModuleName].insert(theObject);
206 }
207
208 void ModelHighAPI_Dumper::dumpEntitySetName()
209 {
210   if (!myLastEntityWithName)
211     return;
212
213 #ifdef DUMP_USER_DEFINED_NAMES
214   const std::string& aName = name(myLastEntityWithName);
215   myDumpBuffer << aName;
216   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(myLastEntityWithName);
217   if (aFeature)
218     myDumpBuffer << ".feature()";
219   myDumpBuffer << ".data().setName(\"" << aName << "\")" << std::endl;
220 #endif
221   myLastEntityWithName = EntityPtr();
222 }
223
224 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const char theChar)
225 {
226   myDumpBuffer << theChar;
227   return *this;
228 }
229
230 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const char* theString)
231 {
232   myDumpBuffer << theString;
233   return *this;
234 }
235
236 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::string& theString)
237 {
238   myDumpBuffer << theString;
239   return *this;
240 }
241
242 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const int theValue)
243 {
244   myDumpBuffer << theValue;
245   return *this;
246 }
247
248 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const double theValue)
249 {
250   myDumpBuffer << theValue;
251   return *this;
252 }
253
254 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::shared_ptr<GeomAPI_Pnt>& thePoint)
255 {
256   importModule("GeomAPI", "GeomAPI_Pnt");
257   myDumpBuffer << "GeomAPI_Pnt(" << thePoint->x() << ", "
258                << thePoint->y() << ", " << thePoint->z() << ")";
259   return *this;
260 }
261
262 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::shared_ptr<GeomAPI_Dir>& theDir)
263 {
264   importModule("GeomAPI", "GeomAPI_Dir");
265   myDumpBuffer << "GeomAPI_Dir(" << theDir->x() << ", "
266                << theDir->y() << ", " << theDir->z() << ")";
267   return *this;
268 }
269
270 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
271     const std::shared_ptr<GeomDataAPI_Dir>& theDir)
272 {
273   myDumpBuffer << theDir->x() << ", " << theDir->y() << ", " << theDir->z();
274   return *this;
275 }
276
277 static void dumpArray(std::ostringstream& theOutput, int theSize,
278                       double* theValues, std::string* theTexts)
279 {
280   for (int i = 0; i < theSize; ++i) {
281     if (i > 0)
282       theOutput << ", ";
283     if (theTexts[i].empty())
284       theOutput << theValues[i];
285     else
286       theOutput << "\"" << theTexts[i] << "\"";
287   }
288 }
289
290 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
291     const std::shared_ptr<GeomDataAPI_Point>& thePoint)
292 {
293   static const int aSize = 3;
294   double aValues[aSize] = {thePoint->x(), thePoint->y(), thePoint->z()};
295   std::string aTexts[aSize] = {thePoint->textX(), thePoint->textY(), thePoint->textZ()};
296   dumpArray(myDumpBuffer, aSize, aValues, aTexts);
297   return *this;
298 }
299
300 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
301     const std::shared_ptr<GeomDataAPI_Point2D>& thePoint)
302 {
303   static const int aSize = 2;
304   double aValues[aSize] = {thePoint->x(), thePoint->y()};
305   std::string aTexts[aSize] = {thePoint->textX(), thePoint->textY()};
306   dumpArray(myDumpBuffer, aSize, aValues, aTexts);
307   return *this;
308 }
309
310 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
311     const std::shared_ptr<ModelAPI_AttributeBoolean>& theAttrBool)
312 {
313   myDumpBuffer << (theAttrBool->value() ? "True" : "False");
314   return *this;
315 }
316
317 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
318     const std::shared_ptr<ModelAPI_AttributeInteger>& theAttrInt)
319 {
320   std::string aText = theAttrInt->text();
321   if (aText.empty())
322     myDumpBuffer << theAttrInt->value();
323   else
324     myDumpBuffer << "\"" << aText << "\"";
325   return *this;
326 }
327
328 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
329     const std::shared_ptr<ModelAPI_AttributeDouble>& theAttrReal)
330 {
331   std::string aText = theAttrReal->text();
332   if (aText.empty())
333     myDumpBuffer << theAttrReal->value();
334   else
335     myDumpBuffer << "\"" << aText << "\"";
336   return *this;
337 }
338
339 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
340     const std::shared_ptr<ModelAPI_AttributeString>& theAttrStr)
341 {
342   myDumpBuffer << "\"" << theAttrStr->value() << "\"";
343   return *this;
344 }
345
346 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const EntityPtr& theEntity)
347 {
348   myDumpBuffer << name(theEntity);
349   if (myNames[theEntity].second)
350     myLastEntityWithName = theEntity;
351   return *this;
352 }
353
354 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
355     const std::shared_ptr<ModelAPI_AttributeRefAttr>& theRefAttr)
356 {
357   if (theRefAttr->isObject())
358     myDumpBuffer << name(theRefAttr->object());
359   else {
360     AttributePtr anAttr = theRefAttr->attr();
361     FeaturePtr anOwner = ModelAPI_Feature::feature(anAttr->owner());
362     myDumpBuffer << name(anOwner) << "." << attributeGetter(anOwner, anAttr->id()) << "()";
363   }
364   return *this;
365 }
366
367 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
368     const std::shared_ptr<ModelAPI_AttributeSelection>& theAttrSelect)
369 {
370   myDumpBuffer << "\"" << theAttrSelect->namingName() << "\"";
371   return *this;
372 }
373
374 /// Dump std::endl
375 MODELHIGHAPI_EXPORT
376 ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
377                                 std::basic_ostream<char>& (*theEndl)(std::basic_ostream<char>&))
378 {
379   theDumper.myDumpBuffer << theEndl;
380   theDumper.dumpEntitySetName();
381   return theDumper;
382 }