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