Salome HOME
1efbd49db537f1febea0888104ffb4c3e91c6e7c
[modules/shaper.git] / src / ExchangeAPI / ExchangeAPI_Import.cpp
1 // Copyright (C) 2014-2023  CEA/DEN, EDF R&D
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 <ModelHighAPI_Dumper.h>
25 #include <ModelHighAPI_Services.h>
26 #include <ModelHighAPI_Tools.h>
27 //--------------------------------------------------------------------------------------
28 #include <ModelAPI_AttributeStringArray.h>
29 #include <ModelAPI_AttributeImage.h>
30 #include <ModelAPI_Session.h>
31 #include <ModelAPI_Tools.h>
32 #include <GeomAlgoAPI_Tools.h>
33 //--------------------------------------------------------------------------------------
34 #include <algorithm>
35 //--------------------------------------------------------------------------------------
36 #include <QPixmap>
37 #include <QDir>
38 #include <QFile>
39 #include <QFileInfo>
40
41 ExchangeAPI_Import::ExchangeAPI_Import(
42     const std::shared_ptr<ModelAPI_Feature> & theFeature)
43 : ModelHighAPI_Interface(theFeature)
44 {
45   initialize();
46 }
47
48 ExchangeAPI_Import::ExchangeAPI_Import(
49     const std::shared_ptr<ModelAPI_Feature> & theFeature,
50     const std::string & theFilePath)
51 : ModelHighAPI_Interface(theFeature)
52 {
53   if (initialize())
54     setFilePath(theFilePath);
55 }
56
57 ExchangeAPI_Import::ExchangeAPI_Import(
58     const std::shared_ptr<ModelAPI_Feature> & theFeature,
59     const std::string & theFilePath,
60     const bool theScalInterUnits,
61     const bool theMaterials,
62     const bool theColor)
63 : ModelHighAPI_Interface(theFeature)
64 {
65   if (initialize())
66     setParameters(theFilePath, theScalInterUnits, theMaterials, theColor);
67 }
68
69 ExchangeAPI_Import::~ExchangeAPI_Import()
70 {
71
72 }
73
74 //--------------------------------------------------------------------------------------
75 void ExchangeAPI_Import::setParameters(const std::string & theFilePath,
76                                        const bool theScalInterUnits,
77                                        const bool theMaterials,
78                                        const bool theColor)
79 {
80   fillAttribute(theFilePath, mystepFilePath);
81   fillAttribute("STEP", myimportType);
82   fillAttribute(theScalInterUnits, myscalInterUnits);
83   fillAttribute(theMaterials,mymaterials);
84   fillAttribute(theColor,mycolors);
85   execute();
86 }
87
88 //--------------------------------------------------------------------------------------
89 void ExchangeAPI_Import::setFilePath(const std::string & theFilePath)
90 {
91
92   std::string anExtension = GeomAlgoAPI_Tools::File_Tools::extension(theFilePath);
93   if (anExtension == "STEP" || anExtension == "STP") {
94     setParameters(theFilePath,true,false,false);
95   } else {
96     fillAttribute(theFilePath, myfilePath);
97     fillAttribute(anExtension, myimportType);
98     execute();
99   }
100 }
101
102 //--------------------------------------------------------------------------------------
103 void ExchangeAPI_Import::dump(ModelHighAPI_Dumper& theDumper) const
104 {
105   FeaturePtr aBase = feature();
106   std::string aPartName = theDumper.name(aBase->document());
107
108   AttributeStringPtr aImportTypeAttr =
109                     aBase->string(ExchangePlugin_ImportFeature::IMPORT_TYPE_ID());
110   std::string aFormat = aImportTypeAttr->value();
111   std::string aFilePath;
112   if (aFormat == "STEP" || aFormat == "STP")
113   {
114     aFilePath = aBase->string(ExchangePlugin_ImportFeature::STEP_FILE_PATH_ID())->value();
115   } else {
116     aFilePath = aBase->string(ExchangePlugin_ImportFeature::FILE_PATH_ID())->value();
117   }
118
119   std::string aFrom = "\\";
120   std::string aTo = "\\\\";
121   for(std::size_t aPos = aFilePath.find(aFrom);
122       aPos != std::string::npos;
123       aPos = aFilePath.find(aFrom, aPos)) {
124     aFilePath.replace(aPos, aFrom.size(), aTo);
125     aPos += aTo.size();
126   }
127   std::string anExtension = GeomAlgoAPI_Tools::File_Tools::extension(aFilePath);
128   if (anExtension == "STP" || anExtension == "STEP"){
129       theDumper << aBase << " = model.addImportSTEP(" << aPartName << ", \""
130                 << aFilePath << "\"" ;
131
132       theDumper << ", " << scalInterUnits()->value()
133                 << ", " << materials()->value()
134                 << ", " << colors()->value() << ")"<< std::endl;
135   } else {
136       theDumper << aBase << " = model.addImport(" << aPartName << ", \""
137             << aFilePath << "\")" << std::endl;
138   }
139
140   // to make import have results
141   theDumper << "model.do()" << std::endl;
142
143   CompositeFeaturePtr aCompositeFeature =
144     std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aBase);
145   if (aCompositeFeature.get()) {
146     int aNbOfSubs = aCompositeFeature->numberOfSubs();
147     for(int anIndex = 0; anIndex < aNbOfSubs; ++anIndex) {
148       std::string aSubFeatureGet =
149         theDumper.name(aBase) + ".subFeature(" + std::to_string((long long)anIndex) + ")";
150       theDumper.dumpSubFeatureNameAndColor(aSubFeatureGet, aCompositeFeature->subFeature(anIndex));
151     }
152   }
153 }
154
155 //--------------------------------------------------------------------------------------
156 ImportPtr addImport(
157     const std::shared_ptr<ModelAPI_Document> & thePart,
158     const std::string & theFilePath)
159 {
160   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(ExchangeAPI_Import::ID());
161   return ImportPtr(new ExchangeAPI_Import(aFeature, theFilePath));
162 }
163
164 ImportPtr addImportSTEP(
165     const std::shared_ptr<ModelAPI_Document> & thePart,
166     const std::string & theFilePath,
167     const bool theScalInterUnits,
168     const bool theMaterials,
169     const bool theColor )
170 {
171   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(ExchangeAPI_Import::ID());
172   return ImportPtr(new ExchangeAPI_Import(aFeature, theFilePath,
173                                           theScalInterUnits, theMaterials, theColor));
174 }
175
176 void importPart(const std::shared_ptr<ModelAPI_Document> & thePart,
177                 const std::string & theFilePath,
178                 const ModelHighAPI_Reference & theAfterThis)
179 {
180   static const bool THE_VISIBLE_FEATURE = false;
181   FeaturePtr aCurrentFeature;
182   if (theAfterThis.feature()) {
183     aCurrentFeature = thePart->currentFeature(THE_VISIBLE_FEATURE);
184     thePart->setCurrentFeature(theAfterThis.feature(), THE_VISIBLE_FEATURE);
185   }
186
187   FeaturePtr aFeature = thePart->addFeature(ExchangePlugin_ImportPart::ID());
188   aFeature->string(ExchangePlugin_ImportPart::FILE_PATH_ID())->setValue(theFilePath);
189
190   // specify the ID of selected document
191   int aTargetPartIndex = 0;
192   SessionPtr aSession = ModelAPI_Session::get();
193   if (aSession->moduleDocument() == thePart) {
194     // Importing to PartSet has 2 choices: import directly to PartSet (if possible)
195     // or create a new part. Because then importing to existing part the document
196     // has to be specified explicitly.
197     // As a result, parse the list of possible target documents and generate new part
198     // if the import document is not applicable on PartSet level
199     // (there is no 'PartSet' in the list of applicable documents).
200     AttributeStringArrayPtr aDocsList =
201         aFeature->stringArray(ExchangePlugin_ImportPart::TARGET_PARTS_LIST_ID());
202     if (aDocsList->size() > 1 && aDocsList->value(1) == "PartSet")
203       aTargetPartIndex = 1;
204   }
205   aFeature->integer(ExchangePlugin_ImportPart::TARGET_PART_ID())->setValue(aTargetPartIndex);
206
207   // restart transaction to execute and delete the macro-feature
208   apply();
209
210   // restore current feature
211   if (aCurrentFeature)
212     thePart->setCurrentFeature(aCurrentFeature, THE_VISIBLE_FEATURE);
213 }
214
215 //-------------------------------------------------------------------------------------------------
216 //-------------------------------------------------------------------------------------------------
217
218 ExchangeAPI_Import_Image::ExchangeAPI_Import_Image(
219     const std::shared_ptr<ModelAPI_Feature> & theFeature)
220 : ModelHighAPI_Interface(theFeature)
221 {
222   initialize();
223 }
224
225 ExchangeAPI_Import_Image::ExchangeAPI_Import_Image(
226     const std::shared_ptr<ModelAPI_Feature> & theFeature,
227     const std::string & theFilePath)
228 : ModelHighAPI_Interface(theFeature)
229 {
230   if (initialize())
231     setFilePath(theFilePath);
232 }
233
234 void ExchangeAPI_Import_Image::setFilePath(const std::string & theFilePath)
235 {
236   fillAttribute(theFilePath, myfilePath);
237   execute();
238 }
239
240 ImportImagePtr addImportImage(
241     const std::shared_ptr<ModelAPI_Document> & thePart,
242     const std::string & theFilePath)
243 {
244   std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(ExchangeAPI_Import_Image::ID());
245   return ImportImagePtr(new ExchangeAPI_Import_Image(aFeature, theFilePath));
246 }
247
248 void ExchangeAPI_Import_Image::dump(ModelHighAPI_Dumper& theDumper) const
249 {
250   FeaturePtr aBase = feature();
251   std::string aPartName = theDumper.name(aBase->document());
252
253   std::string aFilePath =
254     aBase->string(ExchangePlugin_Import_ImageFeature::FILE_PATH_ID())->value();
255
256   // store image into a new file near the dumped python script
257   ResultPtr aResult = aBase->firstResult();
258   std::string aNewImageDir = theDumper.getDumpDir();
259   if (aResult.get() && aResult->hasTexture()) {
260     // get image data
261     int aWidth, aHeight;
262     std::string aFormat;
263     std::list<unsigned char> aByteList;
264     AttributeImagePtr anImageAttr =
265       aResult->data()->image(ModelAPI_ResultBody::IMAGE_ID());
266     anImageAttr->texture(aWidth, aHeight, aByteList, aFormat);
267
268     // convert image data to QPixmap
269     uchar* arr = new uchar[aByteList.size()];
270     std::copy(aByteList.begin(), aByteList.end(), arr);
271     QImage image (arr, aWidth, aHeight, QImage::Format_ARGB32);
272     QPixmap pixmap = QPixmap::fromImage( image );
273
274     // get new file name
275     std::wstring aName = aBase->name();
276     std::string anImageName (aName.begin(), aName.end());
277     std::string aNewImageFile = anImageName + "." + aFormat;
278     QFileInfo aNewFileInfo (QDir(aNewImageDir.c_str()), aNewImageFile.c_str());
279     for (int ii = 1; QFile::exists(aNewFileInfo.absoluteFilePath()); ii++) {
280       // construct the new file name by adding the unique number
281       aNewImageFile = anImageName + "_" + std::to_string(ii) + "." + aFormat;
282       aNewFileInfo.setFile(QDir(aNewImageDir.c_str()), aNewImageFile.c_str());
283     }
284
285     // write image to a new file
286     if (pixmap.save(aNewFileInfo.absoluteFilePath())) {
287       // to dump new file name
288       aFilePath = aNewFileInfo.absoluteFilePath().toStdString();
289     }
290     delete [] arr;
291   }
292
293   theDumper << aBase << " = model.addImportImage(" << aPartName << ", \""
294             << aFilePath << "\")" << std::endl;
295
296   // to make import have results
297   theDumper << "model.do()" << std::endl;
298 }