Salome HOME
2bbf9f02150a36b0b41d78e908edc24abe9d3465
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_STEPImport.cpp
1 // Copyright (C) 2014-2022  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 <GeomAlgoAPI_STEPImport.h>
21 #include <GeomAlgoAPI_STEPImportXCAF.h>
22
23 #include <TDF_ChildIDIterator.hxx>
24 #include <TDF_Label.hxx>
25 #include <TDataStd_Name.hxx>
26 #include <TDataStd_Comment.hxx>
27 #include <TNaming_Builder.hxx>
28 #include <TNaming_NamedShape.hxx>
29
30 #include <IFSelect_ReturnStatus.hxx>
31 #include <Interface_EntityIterator.hxx>
32 #include <Interface_Graph.hxx>
33 #include <Interface_InterfaceModel.hxx>
34 #include <Interface_Static.hxx>
35
36 #include <STEPCAFControl_Reader.hxx>
37 #include <STEPControl_Reader.hxx>
38 #include <StepBasic_Product.hxx>
39 #include <StepBasic_ProductDefinition.hxx>
40 #include <StepBasic_ProductDefinitionFormation.hxx>
41 #include <StepGeom_GeometricRepresentationItem.hxx>
42 #include <StepShape_TopologicalRepresentationItem.hxx>
43 #include <StepRepr_DescriptiveRepresentationItem.hxx>
44 #include <StepRepr_ProductDefinitionShape.hxx>
45 #include <StepRepr_PropertyDefinitionRepresentation.hxx>
46 #include <StepRepr_Representation.hxx>
47 #include <TransferBRep.hxx>
48 #include <Transfer_Binder.hxx>
49 #include <Transfer_TransientProcess.hxx>
50 #include <XSControl_TransferReader.hxx>
51 #include <XSControl_WorkSession.hxx>
52
53 #include <BRep_Builder.hxx>
54
55 #include <TopExp.hxx>
56 #include <TopExp_Explorer.hxx>
57 #include <TopTools_IndexedMapOfShape.hxx>
58 #include <TopoDS_Compound.hxx>
59 #include <TopoDS_Iterator.hxx>
60
61 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
62 #include <OSD_Exception.hxx>
63
64 //=================================================================================================
65 bool readUnits(STEPControl_Reader& aReader,
66                const bool theScalInterUnits,
67                std::string& theError)
68 {
69   // Regard or not the model units
70   if (!theScalInterUnits) {
71     // set UnitFlag to units from file
72     TColStd_SequenceOfAsciiString anUnitLengthNames;
73     TColStd_SequenceOfAsciiString anUnitAngleNames;
74     TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
75     aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
76     if (anUnitLengthNames.Length() > 0) {
77       TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
78       if (aLenUnits == "millimetre")
79         Interface_Static::SetCVal("xstep.cascade.unit", "MM");
80       else if (aLenUnits == "centimetre")
81         Interface_Static::SetCVal("xstep.cascade.unit", "CM");
82       else if (aLenUnits == "metre" || aLenUnits.IsEmpty())
83         Interface_Static::SetCVal("xstep.cascade.unit", "M");
84       else if (aLenUnits == "INCH")
85         Interface_Static::SetCVal("xstep.cascade.unit", "INCH");
86       else {
87         theError = "The file contains not supported units.";
88         return false;
89       }
90       // TODO (for other units than mm, cm, m or inch)
91       //else if (aLenUnits == "")
92       //  Interface_Static::SetCVal("xstep.cascade.unit", "???");
93     }
94   }
95   else {
96     //cout<<"need re-scale a model"<<endl;
97     // set UnitFlag to 'meter'
98     Interface_Static::SetCVal("xstep.cascade.unit", "M");
99   }
100   return true;
101 }
102
103
104 //==================================================================================================
105 std::shared_ptr<GeomAPI_Shape> STEPImport(const std::string& theFileName,
106                                           const std::string& /*theFormatName*/,
107                                           const bool theScalInterUnits,
108                                           std::string& theError)
109 {
110
111   TopoDS_Shape aResShape;
112
113   // Set "C" numeric locale to save numbers correctly
114   // Kernel_Utils::Localizer loc;
115
116   STEPControl_Reader aReader;
117
118   //VSR: 16/09/09: Convert to METERS
119   Interface_Static::SetCVal("xstep.cascade.unit", "M");
120   Interface_Static::SetIVal("read.step.ideas", 1);
121   Interface_Static::SetIVal("read.step.nonmanifold", 1);
122
123   BRep_Builder B;
124   TopoDS_Compound compound;
125   B.MakeCompound(compound);
126
127   try {
128     OCC_CATCH_SIGNALS;
129
130     IFSelect_ReturnStatus status = aReader.ReadFile(theFileName.c_str());
131
132     if (status == IFSelect_RetDone) {
133       // Regard or not the model units
134       if( !readUnits(aReader, theScalInterUnits, theError)) {
135         std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
136         aGeomShape->setImpl(new TopoDS_Shape());
137         return aGeomShape;
138       }
139
140       Standard_Boolean failsonly = Standard_False;
141       aReader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity);
142
143       /* Root transfers */
144       Standard_Integer nbr = aReader.NbRootsForTransfer();
145       aReader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity);
146
147       for (Standard_Integer n = 1; n <= nbr; n++) {
148         Standard_Boolean ok = aReader.TransferRoot(n);
149         /* Collecting resulting entities */
150         Standard_Integer nbs = aReader.NbShapes();
151         if (!ok || nbs == 0)
152         {
153           continue; // skip empty root
154         }
155         /* For a single entity */
156         else if (nbr == 1 && nbs == 1) {
157           aResShape = aReader.Shape(1);
158           // ATTENTION: this is a workaround for mantis issue 0020442 remark 0010776
159           // It should be removed after patching OCCT for bug OCC22436
160           // (fix for OCCT is expected in service pack next to OCCT6.3sp12)
161           if (aResShape.ShapeType() == TopAbs_COMPOUND) {
162             int nbSub1 = 0;
163             TopoDS_Shape currShape;
164             TopoDS_Iterator It (aResShape, Standard_True, Standard_True);
165             for (; It.More(); It.Next()) {
166               nbSub1++;
167               currShape = It.Value();
168             }
169             if (nbSub1 == 1)
170               aResShape = currShape;
171           }
172           // END workaround
173           break;
174         }
175
176         for (Standard_Integer i = 1; i <= nbs; i++) {
177           TopoDS_Shape aShape = aReader.Shape(i);
178           if (aShape.IsNull()) {
179             //return aResShape;
180             continue;
181           }
182           else {
183             B.Add(compound, aShape);
184           }
185         }
186       }
187       if (aResShape.IsNull())
188         aResShape = compound;
189
190       // Check if any BRep entity has been read, there must be at least a vertex
191       if (!TopExp_Explorer(aResShape, TopAbs_VERTEX).More())
192       {
193         theError = "No geometrical data in the imported file.";
194         std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
195         aGeomShape->setImpl(new TopoDS_Shape());
196         return aGeomShape;
197       }
198     } else {
199       theError = "Wrong format of the imported file. Can't import file.";
200       aResShape.Nullify();
201     }
202   }
203   catch (Standard_Failure const& anException) {
204     theError = anException.GetMessageString();
205     aResShape.Nullify();
206   }
207   // Return previous locale
208   std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
209   aGeomShape->setImpl(new TopoDS_Shape(aResShape));
210   return aGeomShape;
211 }
212
213 //==================================================================================================
214 GeomShapePtr STEPImportAttributs(const std::string& theFileName,
215                                  std::shared_ptr<ModelAPI_ResultBody> theResultBody,
216                                  const bool theScalInterUnits,
217                                  const bool theMaterials,
218                                  const bool /*theColor*/,
219                                  std::map< std::wstring,
220                                  std::list<std::wstring>>& theMaterialShape,
221                                  std::string& theError)
222 {
223
224   try {
225     STEPControl_Reader aReader;
226     std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
227
228     Interface_Static::SetCVal("xstep.cascade.unit", "M");
229     Interface_Static::SetIVal("read.step.ideas", 1);
230     Interface_Static::SetIVal("read.step.nonmanifold", 1);
231
232     try {
233       OCC_CATCH_SIGNALS;
234
235       IFSelect_ReturnStatus status = aReader.ReadFile(theFileName.c_str());
236
237       if (status == IFSelect_RetDone) {
238         // Regard or not the model units
239         if( !readUnits(aReader, theScalInterUnits, theError)) {
240           aGeomShape->setImpl(new TopoDS_Shape());
241           return aGeomShape;
242         }
243       }
244     } catch (Standard_Failure const& anException) {
245       theError = anException.GetMessageString();
246       aGeomShape->setImpl(new TopoDS_Shape());
247       return aGeomShape;
248     }
249
250     STEPCAFControl_Reader aCafreader;
251     aCafreader.SetColorMode(true);
252     aCafreader.SetNameMode(true);
253     aCafreader.SetMatMode(true);
254
255     if (aCafreader.ReadFile(theFileName.c_str()) != IFSelect_RetDone) {
256       theError = "Wrong format of the imported file. Can't import file.";
257       aGeomShape->setImpl(new TopoDS_Shape());
258       return aGeomShape;
259     }
260
261     return readAttributes(aCafreader,
262                           theResultBody,
263                           theMaterials,
264                           theMaterialShape,
265                           theError);
266   } catch (OSD_Exception&) {
267     //Try to load STEP file without colors...
268     return STEPImport(theFileName, "", theScalInterUnits, theError);
269   }
270 }