]> SALOME platform Git repositories - modules/shaper.git/blob - src/ExchangeAPI/ExchangeAPI_Import.cpp
Salome HOME
[bos #37570] [CEA] SHAPER hdf tests are failing. Fix Sphere feature attributes order.
[modules/shaper.git] / src / ExchangeAPI / ExchangeAPI_Import.cpp
1 // Copyright (C) 2014-2023  CEA, EDF
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "ExchangeAPI_Import.h"
21 //--------------------------------------------------------------------------------------
22 #include <ExchangePlugin_ImportPart.h>
23 //--------------------------------------------------------------------------------------
24 #include <Locale_Convert.h>
25 //--------------------------------------------------------------------------------------
26 #include <ModelHighAPI_Dumper.h>
27 #include <ModelHighAPI_Services.h>
28 #include <ModelHighAPI_Tools.h>
29 //--------------------------------------------------------------------------------------
30 #include <ModelAPI_AttributeStringArray.h>
31 #include <ModelAPI_AttributeImage.h>
32 #include <ModelAPI_Session.h>
33 #include <ModelAPI_Tools.h>
34 #include <GeomAlgoAPI_Tools.h>
35 //--------------------------------------------------------------------------------------
36 #include <algorithm>
37 //--------------------------------------------------------------------------------------
38 #include <QPixmap>
39 #include <QDir>
40 #include <QFile>
41 #include <QFileInfo>
42
43 ExchangeAPI_Import::ExchangeAPI_Import(
44     const std::shared_ptr<ModelAPI_Feature> & theFeature)
45 : ModelHighAPI_Interface(theFeature)
46 {
47   initialize();
48 }
49
50 ExchangeAPI_Import::ExchangeAPI_Import(
51     const std::shared_ptr<ModelAPI_Feature> & theFeature,
52     const std::string & theFilePath)
53 : ModelHighAPI_Interface(theFeature)
54 {
55   if (initialize())
56     setFilePath(theFilePath);
57 }
58
59 ExchangeAPI_Import::ExchangeAPI_Import(
60     const std::shared_ptr<ModelAPI_Feature> & theFeature,
61     const std::string & /*theFilePath*/,
62     const std::string & theBuffer)
63 : ModelHighAPI_Interface(theFeature)
64 {
65   if (initialize()) {
66     fillAttribute("XAOMem", myimportType);
67     fillAttribute(theBuffer, mymemoryBuffer);
68     execute();
69   }
70 }
71
72 ExchangeAPI_Import::ExchangeAPI_Import(
73     const std::shared_ptr<ModelAPI_Feature> & theFeature,
74     const std::string & theFilePath,
75     const bool theScalInterUnits,
76     const bool theMaterials,
77     const bool theColor)
78 : ModelHighAPI_Interface(theFeature)
79 {
80   if (initialize())
81     setParameters(theFilePath, theScalInterUnits, theMaterials, theColor);
82 }
83
84 ExchangeAPI_Import::~ExchangeAPI_Import()
85 {
86
87 }
88
89 //--------------------------------------------------------------------------------------
90 void ExchangeAPI_Import::setParameters(const std::string & theFilePath,
91                                        const bool theScalInterUnits,
92                                        const bool theMaterials,
93                                        const bool theColor)
94 {
95   fillAttribute(theFilePath, mystepFilePath);
96   fillAttribute("STEP", myimportType);
97   fillAttribute(theScalInterUnits, myscalInterUnits);
98   fillAttribute(theMaterials,mymaterials);
99   fillAttribute(theColor,mycolors);
100   execute();
101 }
102
103 //--------------------------------------------------------------------------------------
104 void ExchangeAPI_Import::setFilePath(const std::string & theFilePath)
105 {
106
107   std::string anExtension = GeomAlgoAPI_Tools::File_Tools::extension(theFilePath);
108   if (anExtension == "STEP" || anExtension == "STP") {
109     setParameters(theFilePath,true,false,false);
110   } else {
111     fillAttribute(theFilePath, myfilePath);
112     fillAttribute(anExtension, myimportType);
113     execute();
114   }
115 }
116
117 //--------------------------------------------------------------------------------------
118 void ExchangeAPI_Import::dump(ModelHighAPI_Dumper& theDumper) const
119 {
120   FeaturePtr aBase = feature();
121   std::string aPartName = theDumper.name(aBase->document());
122
123   AttributeStringPtr aImportTypeAttr =
124     aBase->string(ExchangePlugin_ImportFeature::IMPORT_TYPE_ID());
125   std::string aFormat = aImportTypeAttr->value();
126
127   if (aFormat == "XAOMem") {
128     theDumper << aBase << " = model.addImportXAOMem(" << aPartName << ", aXAOBuff";
129     std::string aGeometryNamePy = Locale::Convert::toString(aBase->data()->name());
130     if (! aGeometryNamePy.empty()) {
131       // add shape name
132       std::replace(aGeometryNamePy.begin(), aGeometryNamePy.end(), ' ', '_');
133       theDumper << "_" << aGeometryNamePy;
134     }
135     theDumper << ")" << std::endl;
136   }
137   else {
138     std::string aFilePath;
139     if (aFormat == "STEP" || aFormat == "STP") {
140       aFilePath = aBase->string(ExchangePlugin_ImportFeature::STEP_FILE_PATH_ID())->value();
141     } else {
142       aFilePath = aBase->string(ExchangePlugin_ImportFeature::FILE_PATH_ID())->value();
143     }
144
145     std::string aFrom = "\\";
146     std::string aTo = "\\\\";
147     for (std::size_t aPos = aFilePath.find(aFrom);
148          aPos != std::string::npos;
149          aPos = aFilePath.find(aFrom, aPos)) {
150       aFilePath.replace(aPos, aFrom.size(), aTo);
151       aPos += aTo.size();
152     }
153     std::string anExtension = GeomAlgoAPI_Tools::File_Tools::extension(aFilePath);
154     if (anExtension == "STP" || anExtension == "STEP") {
155       theDumper << aBase << " = model.addImportSTEP(" << aPartName << ", \""
156                 << aFilePath << "\"" ;
157
158       theDumper << ", " << scalInterUnits()->value()
159                 << ", " << materials()->value()
160                 << ", " << colors()->value() << ")"<< std::endl;
161     }
162     else {
163       theDumper << aBase << " = model.addImport(" << aPartName << ", \""
164                 << aFilePath << "\")" << std::endl;
165     }
166   }
167
168   // to make import have results
169   theDumper << "model.do()" << std::endl;
170
171   CompositeFeaturePtr aCompositeFeature =
172     std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aBase);
173   if (aCompositeFeature.get()) {
174     int aNbOfSubs = aCompositeFeature->numberOfSubs();
175     for(int anIndex = 0; anIndex < aNbOfSubs; ++anIndex) {
176       std::string aSubFeatureGet =
177         theDumper.name(aBase) + ".subFeature(" + std::to_string((long long)anIndex) + ")";
178       theDumper.dumpSubFeatureNameAndColor(aSubFeatureGet, aCompositeFeature->subFeature(anIndex));
179     }
180   }
181 }
182
183 //--------------------------------------------------------------------------------------
184 ImportPtr addImport(
185     const std::shared_ptr<ModelAPI_Document> & thePart,
186     const std::string & theFilePath)
187 {
188   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(ExchangeAPI_Import::ID());
189   return ImportPtr(new ExchangeAPI_Import(aFeature, theFilePath));
190 }
191
192 ImportPtr addImportXAOMem(const std::shared_ptr<ModelAPI_Document> & thePart,
193                           PyObject* theBuffer)
194 {
195   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(ExchangeAPI_Import::ID());
196   std::string aString (PyBytes_AsString(theBuffer));
197   return ImportPtr(new ExchangeAPI_Import(aFeature, "", aString));
198 }
199
200 ImportPtr addImportSTEP(
201     const std::shared_ptr<ModelAPI_Document> & thePart,
202     const std::string & theFilePath,
203     const bool theScalInterUnits,
204     const bool theMaterials,
205     const bool theColor )
206 {
207   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(ExchangeAPI_Import::ID());
208   return ImportPtr(new ExchangeAPI_Import(aFeature, theFilePath,
209                                           theScalInterUnits, theMaterials, theColor));
210 }
211
212 void importPart(const std::shared_ptr<ModelAPI_Document> & thePart,
213                 const std::string & theFilePath,
214                 const ModelHighAPI_Reference & theAfterThis)
215 {
216   static const bool THE_VISIBLE_FEATURE = false;
217   FeaturePtr aCurrentFeature;
218   if (theAfterThis.feature()) {
219     aCurrentFeature = thePart->currentFeature(THE_VISIBLE_FEATURE);
220     thePart->setCurrentFeature(theAfterThis.feature(), THE_VISIBLE_FEATURE);
221   }
222
223   FeaturePtr aFeature = thePart->addFeature(ExchangePlugin_ImportPart::ID());
224   aFeature->string(ExchangePlugin_ImportPart::FILE_PATH_ID())->setValue(theFilePath);
225
226   // specify the ID of selected document
227   int aTargetPartIndex = 0;
228   SessionPtr aSession = ModelAPI_Session::get();
229   if (aSession->moduleDocument() == thePart) {
230     // Importing to PartSet has 2 choices: import directly to PartSet (if possible)
231     // or create a new part. Because then importing to existing part the document
232     // has to be specified explicitly.
233     // As a result, parse the list of possible target documents and generate new part
234     // if the import document is not applicable on PartSet level
235     // (there is no 'PartSet' in the list of applicable documents).
236     AttributeStringArrayPtr aDocsList =
237         aFeature->stringArray(ExchangePlugin_ImportPart::TARGET_PARTS_LIST_ID());
238     if (aDocsList->size() > 1 && aDocsList->value(1) == "PartSet")
239       aTargetPartIndex = 1;
240   }
241   aFeature->integer(ExchangePlugin_ImportPart::TARGET_PART_ID())->setValue(aTargetPartIndex);
242
243   // restart transaction to execute and delete the macro-feature
244   apply();
245
246   // restore current feature
247   if (aCurrentFeature)
248     thePart->setCurrentFeature(aCurrentFeature, THE_VISIBLE_FEATURE);
249 }
250
251 //-------------------------------------------------------------------------------------------------
252 //-------------------------------------------------------------------------------------------------
253
254 ExchangeAPI_Import_Image::ExchangeAPI_Import_Image(
255     const std::shared_ptr<ModelAPI_Feature> & theFeature)
256 : ModelHighAPI_Interface(theFeature)
257 {
258   initialize();
259 }
260
261 ExchangeAPI_Import_Image::ExchangeAPI_Import_Image(
262     const std::shared_ptr<ModelAPI_Feature> & theFeature,
263     const std::string & theFilePath)
264 : ModelHighAPI_Interface(theFeature)
265 {
266   if (initialize())
267     setFilePath(theFilePath);
268 }
269
270 void ExchangeAPI_Import_Image::setFilePath(const std::string & theFilePath)
271 {
272   fillAttribute(theFilePath, myfilePath);
273   execute();
274 }
275
276 ImportImagePtr addImportImage(
277     const std::shared_ptr<ModelAPI_Document> & thePart,
278     const std::string & theFilePath)
279 {
280   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(ExchangeAPI_Import_Image::ID());
281   return ImportImagePtr(new ExchangeAPI_Import_Image(aFeature, theFilePath));
282 }
283
284 void ExchangeAPI_Import_Image::dump(ModelHighAPI_Dumper& theDumper) const
285 {
286   FeaturePtr aBase = feature();
287   std::string aPartName = theDumper.name(aBase->document());
288
289   std::string aFilePath =
290     aBase->string(ExchangePlugin_Import_ImageFeature::FILE_PATH_ID())->value();
291
292   // store image into a new file near the dumped python script
293   ResultPtr aResult = aBase->firstResult();
294   std::string aNewImageDir = theDumper.getDumpDir();
295   if (aResult.get() && aResult->hasTexture()) {
296     // get image data
297     int aWidth, aHeight;
298     std::string aFormat;
299     std::list<unsigned char> aByteList;
300     AttributeImagePtr anImageAttr =
301       aResult->data()->image(ModelAPI_ResultBody::IMAGE_ID());
302     anImageAttr->texture(aWidth, aHeight, aByteList, aFormat);
303
304     // convert image data to QPixmap
305     uchar* arr = new uchar[aByteList.size()];
306     std::copy(aByteList.begin(), aByteList.end(), arr);
307     QImage image (arr, aWidth, aHeight, QImage::Format_ARGB32);
308     QPixmap pixmap = QPixmap::fromImage( image );
309
310     // get new file name
311     std::wstring aName = aBase->name();
312     std::string anImageName (aName.begin(), aName.end());
313     std::string aNewImageFile = anImageName + "." + aFormat;
314     QFileInfo aNewFileInfo (QDir(aNewImageDir.c_str()), aNewImageFile.c_str());
315     for (int ii = 1; QFile::exists(aNewFileInfo.absoluteFilePath()); ii++) {
316       // construct the new file name by adding the unique number
317       aNewImageFile = anImageName + "_" + std::to_string(ii) + "." + aFormat;
318       aNewFileInfo.setFile(QDir(aNewImageDir.c_str()), aNewImageFile.c_str());
319     }
320
321     // write image to a new file
322     if (pixmap.save(aNewFileInfo.absoluteFilePath())) {
323       // to dump new file name
324       aFilePath = aNewFileInfo.absoluteFilePath().toStdString();
325     }
326     delete [] arr;
327   }
328
329   theDumper << aBase << " = model.addImportImage(" << aPartName << ", \""
330             << aFilePath << "\")" << std::endl;
331
332   // to make import have results
333   theDumper << "model.do()" << std::endl;
334 }