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