Salome HOME
Issue #608: Usage of OCCT in interface -- Wrap classes by SWIG
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_STEPImport.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 #include <GeomAlgoAPI_STEPImport.h>
4
5 #include <TDF_ChildIDIterator.hxx>
6 #include <TDF_Label.hxx>
7 #include <TDataStd_Name.hxx>
8 #include <TDataStd_Comment.hxx>
9 #include <TNaming_Builder.hxx>
10 #include <TNaming_NamedShape.hxx>
11
12 #include <IFSelect_ReturnStatus.hxx>
13 #include <Interface_EntityIterator.hxx>
14 #include <Interface_Graph.hxx>
15 #include <Interface_InterfaceModel.hxx>
16 #include <Interface_Static.hxx>
17 #include <STEPControl_Reader.hxx>
18 #include <StepBasic_Product.hxx>
19 #include <StepBasic_ProductDefinition.hxx>
20 #include <StepBasic_ProductDefinitionFormation.hxx>
21 #include <StepGeom_GeometricRepresentationItem.hxx>
22 #include <StepShape_TopologicalRepresentationItem.hxx>
23 #include <StepRepr_DescriptiveRepresentationItem.hxx>
24 #include <StepRepr_ProductDefinitionShape.hxx>
25 #include <StepRepr_PropertyDefinitionRepresentation.hxx>
26 #include <StepRepr_Representation.hxx>
27 #include <TransferBRep.hxx>
28 #include <Transfer_Binder.hxx>
29 #include <Transfer_TransientProcess.hxx>
30 #include <XSControl_TransferReader.hxx>
31 #include <XSControl_WorkSession.hxx>
32
33 #include <BRep_Builder.hxx>
34
35 #include <TopExp.hxx>
36 #include <TopExp_Explorer.hxx>
37 #include <TopTools_IndexedMapOfShape.hxx>
38 #include <TopoDS_Compound.hxx>
39 #include <TopoDS_Iterator.hxx>
40
41 #include <TColStd_SequenceOfAsciiString.hxx>
42
43 #include <Standard_Failure.hxx>
44 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
45
46 //=============================================================================
47 /*!
48  *  GetShape()
49  */
50 //=============================================================================
51
52 static TopoDS_Shape GetShape(const Handle(Standard_Transient)        &theEnti,
53                              const Handle(Transfer_TransientProcess) &theTP)
54 {
55   TopoDS_Shape            aResult;
56   Handle(Transfer_Binder) aBinder = theTP->Find(theEnti);
57
58   if (aBinder.IsNull()) {
59     return aResult;
60   }
61
62   aResult = TransferBRep::ShapeResult(aBinder);
63
64   return aResult;
65 }
66
67 //=============================================================================
68 /*!
69  *  GetLabel()
70  */
71 //=============================================================================
72
73 static TDF_Label GetLabel(const Handle(Standard_Transient) &theEnti,
74                           const TDF_Label                  &theShapeLabel,
75                           const TopoDS_Shape               &aShape)
76 {
77   TDF_Label aResult;
78
79   if (theEnti->IsKind
80             (STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
81     // check all named shapes using iterator
82     TDF_ChildIDIterator anIt
83       (theShapeLabel, TDataStd_Name::GetID(), Standard_True);
84
85     for (; anIt.More(); anIt.Next()) {
86       Handle(TDataStd_Name) nameAttr =
87         Handle(TDataStd_Name)::DownCast(anIt.Value());
88
89       if (nameAttr.IsNull()) {
90         continue;
91       }
92
93       TDF_Label aLab = nameAttr->Label();
94       Handle(TNaming_NamedShape) shAttr; 
95
96       if (aLab.FindAttribute(TNaming_NamedShape::GetID(), shAttr) &&
97           shAttr->Get().IsEqual(aShape)) {
98         aResult = aLab;
99       }
100     }
101   }
102
103   // create label and set shape
104   if (aResult.IsNull()) {
105     TDF_TagSource aTag;
106
107     aResult = aTag.NewChild(theShapeLabel);
108
109     TNaming_Builder tnBuild (aResult);
110
111     tnBuild.Generated(aShape);
112   }
113
114   return aResult;
115 }
116
117 //=============================================================================
118 /*!
119  *  StoreName()
120  */
121 //=============================================================================
122
123 static void StoreName(const Handle(Standard_Transient)        &theEnti,
124                       const TopTools_IndexedMapOfShape        &theIndices,
125                       const Handle(Transfer_TransientProcess) &theTP,
126                       const TDF_Label                         &theShapeLabel)
127 {
128   Handle(TCollection_HAsciiString) aName;
129
130   if (theEnti->IsKind(STANDARD_TYPE(StepShape_TopologicalRepresentationItem)) ||
131       theEnti->IsKind(STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
132     aName = Handle(StepRepr_RepresentationItem)::DownCast(theEnti)->Name();
133   } else {
134     Handle(StepBasic_ProductDefinition) PD =
135       Handle(StepBasic_ProductDefinition)::DownCast(theEnti);
136
137     if (PD.IsNull() == Standard_False) {
138       Handle(StepBasic_Product) Prod = PD->Formation()->OfProduct();
139       aName = Prod->Name();
140     }
141   }
142
143   bool isValidName = false;
144
145   if (aName.IsNull() == Standard_False) {
146     isValidName = true;
147
148     if (aName->UsefullLength() < 1) {
149       isValidName = false;
150     } else if (aName->UsefullLength() == 4 &&
151                toupper (aName->Value(1)) == 'N' &&
152                toupper (aName->Value(2)) == 'O' &&
153                toupper (aName->Value(3)) == 'N' &&
154                toupper (aName->Value(4)) == 'E') {
155       // skip 'N0NE' name
156       isValidName = false;
157     } else {
158       // special check to pass names like "Open CASCADE STEP translator 6.3 1"
159       TCollection_AsciiString aSkipName ("Open CASCADE STEP translator");
160
161       if (aName->Length() >= aSkipName.Length()) {
162         if (aName->String().SubString
163                             (1, aSkipName.Length()).IsEqual(aSkipName)) {
164           isValidName = false;
165         }
166       }
167     }
168   }
169
170   if (isValidName) {
171     TCollection_ExtendedString aNameExt (aName->ToCString());
172
173     // find target shape
174     TopoDS_Shape S = GetShape(theEnti, theTP);
175
176     if (S.IsNull()) {
177       return;
178     }
179
180     // as PRODUCT can be included in the main shape
181     // several times, we look here for all iclusions.
182     Standard_Integer isub, nbSubs = theIndices.Extent();
183
184     for (isub = 1; isub <= nbSubs; isub++) {
185       TopoDS_Shape aSub = theIndices.FindKey(isub);
186
187       if (aSub.IsPartner(S)) {
188         TDF_Label L = GetLabel(theEnti, theShapeLabel, aSub);
189
190         // set a name
191         TDataStd_Name::Set(L, aNameExt);
192       }
193     }
194   }
195 }
196
197 //=============================================================================
198 /*!
199  *  StoreMaterial()
200  */
201 //=============================================================================
202
203 static void StoreMaterial
204                     (const Handle(Standard_Transient)        &theEnti,
205                      const TopTools_IndexedMapOfShape        &theIndices,
206                      const Handle(Transfer_TransientProcess) &theTP,
207                      const TDF_Label                         &theShapeLabel)
208 {
209   // Treat Product Definition Shape only.
210   Handle(StepRepr_ProductDefinitionShape) aPDS =
211       Handle(StepRepr_ProductDefinitionShape)::DownCast(theEnti);
212   Handle(StepBasic_ProductDefinition)     aProdDef;
213
214   if(aPDS.IsNull() == Standard_False) {
215     // Product Definition Shape ==> Product Definition
216     aProdDef = aPDS->Definition().ProductDefinition();
217   }
218
219   if (aProdDef.IsNull() == Standard_False) {
220     // Product Definition ==> Property Definition
221     const Interface_Graph    &aGraph = theTP->Graph();
222     Interface_EntityIterator  aSubs  = aGraph.Sharings(aProdDef);
223     TopoDS_Shape              aShape;
224
225     for(aSubs.Start(); aSubs.More(); aSubs.Next()) {
226       Handle(StepRepr_PropertyDefinition) aPropD =
227         Handle(StepRepr_PropertyDefinition)::DownCast(aSubs.Value());
228
229       if(aPropD.IsNull() == Standard_False) {
230         // Property Definition ==> Representation.
231         Interface_EntityIterator aSubs1 = aGraph.Sharings(aPropD);
232
233         for(aSubs1.Start(); aSubs1.More(); aSubs1.Next()) {
234           Handle(StepRepr_PropertyDefinitionRepresentation) aPDR =
235             Handle(StepRepr_PropertyDefinitionRepresentation)::
236               DownCast(aSubs1.Value());
237
238           if(aPDR.IsNull() == Standard_False) {
239             // Property Definition ==> Material Name.
240             Handle(StepRepr_Representation) aRepr = aPDR->UsedRepresentation();
241
242             if(aRepr.IsNull() == Standard_False) {
243               Standard_Integer ir;
244
245               for(ir = 1; ir <= aRepr->NbItems(); ir++) {
246                 Handle(StepRepr_RepresentationItem) aRI = aRepr->ItemsValue(ir);
247                 Handle(StepRepr_DescriptiveRepresentationItem) aDRI =
248                   Handle(StepRepr_DescriptiveRepresentationItem)::DownCast(aRI);
249
250                 if(aDRI.IsNull() == Standard_False) {
251                   // Get shape from Product Definition
252                   Handle(TCollection_HAsciiString) aMatName = aDRI->Name();
253
254                   if(aMatName.IsNull() == Standard_False) {
255                     TCollection_ExtendedString
256                                  aMatNameExt (aMatName->ToCString());
257
258                     if (aShape.IsNull()) {
259                       // Get the shape.
260                       aShape = GetShape(aProdDef, theTP);
261
262                       if (aShape.IsNull()) {
263                         return;
264                       }
265                     }
266
267                     // as PRODUCT can be included in the main shape
268                     // several times, we look here for all iclusions.
269                     Standard_Integer isub, nbSubs = theIndices.Extent();
270
271                     for (isub = 1; isub <= nbSubs; isub++) {
272                       TopoDS_Shape aSub = theIndices.FindKey(isub);
273
274                       if (aSub.IsPartner(aShape)) {
275                         TDF_Label aLabel =
276                           GetLabel(aProdDef, theShapeLabel, aSub);
277
278                         // set a name
279                         TDataStd_Comment::Set(aLabel, aMatNameExt);
280                       }
281                     }
282                   }
283                 }
284               }
285             }
286           }
287         }
288       }
289     }
290   }
291 }
292
293 //=============================================================================
294 /*!
295  *  Import()
296  */
297 //=============================================================================
298
299 Handle(TCollection_HAsciiString) GetValue (const TCollection_AsciiString& theFileName,
300                                            const TCollection_AsciiString& theParameterName,
301                                            TCollection_AsciiString&       theError)
302 {
303   Handle(TCollection_HAsciiString) aValue;
304
305   if (theParameterName != "LEN_UNITS") {
306     theError = theParameterName + " parameter reading is not supported by STEP plugin";
307     return aValue;
308   }
309
310   // Set "C" numeric locale to save numbers correctly
311   // Kernel_Utils::Localizer loc;
312
313   STEPControl_Reader aReader;
314
315   Interface_Static::SetCVal("xstep.cascade.unit","M");
316   Interface_Static::SetIVal("read.step.ideas", 1);
317   Interface_Static::SetIVal("read.step.nonmanifold", 1);
318
319   try {
320 #if OCC_VERSION_LARGE > 0x06010000
321     OCC_CATCH_SIGNALS;
322 #endif
323     IFSelect_ReturnStatus status = aReader.ReadFile(theFileName.ToCString());
324     if (status == IFSelect_RetDone) {
325       TColStd_SequenceOfAsciiString anUnitLengthNames;
326       TColStd_SequenceOfAsciiString anUnitAngleNames;
327       TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
328       aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
329       if (anUnitLengthNames.Length() > 0) {
330         aValue = new TCollection_HAsciiString( anUnitLengthNames.First() );
331         /*
332         TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
333         if (aLenUnits == "millimetre")
334           aValue = new TCollection_HAsciiString ("MM");
335         else if (aLenUnits == "centimetre")
336           aValue = new TCollection_HAsciiString ("CM");
337         else if (aLenUnits == "metre")
338           aValue = new TCollection_HAsciiString ("M");
339         else if (aLenUnits == "INCH")
340           aValue = new TCollection_HAsciiString ("INCH");
341         // TODO (for other units than mm, cm, m or inch)
342         //else if (aLenUnits == "")
343         //  aValue = new TCollection_HAsciiString ("");
344
345         // tmp begin
346         //std::cout << "$$$ --- " << anUnitLengthNames.First();
347         //for (int ii = 2; ii <= anUnitLengthNames.Length(); ii++)
348         //  std::cout << ", " << anUnitLengthNames.Value(ii);
349         //std::cout << std::endl;
350         // tmp end
351         */
352       }
353     }
354     else {
355       theError = theFileName + " reading failed";
356     }
357   }
358   catch (Standard_Failure) {
359     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
360     theError = aFail->GetMessageString();
361   }
362
363   return aValue;
364 }
365
366 TopoDS_Shape STEPImport(const std::string& theFileName,
367                         const std::string& theFormatName,
368                         std::string& theError)
369 {
370   TopoDS_Shape aResShape;
371
372   // Set "C" numeric locale to save numbers correctly
373   // Kernel_Utils::Localizer loc;
374
375   STEPControl_Reader aReader;
376
377   //VSR: 16/09/09: Convert to METERS
378   Interface_Static::SetCVal("xstep.cascade.unit","M");
379   Interface_Static::SetIVal("read.step.ideas", 1);
380   Interface_Static::SetIVal("read.step.nonmanifold", 1);
381
382   BRep_Builder B;
383   TopoDS_Compound compound;
384   B.MakeCompound(compound);
385
386   try {
387     OCC_CATCH_SIGNALS;
388
389     IFSelect_ReturnStatus status = aReader.ReadFile(theFileName.c_str());
390
391     if (status == IFSelect_RetDone) {
392
393       // Regard or not the model units
394       if (theFormatName == "STEP_SCALE") {
395         // set UnitFlag to units from file
396         TColStd_SequenceOfAsciiString anUnitLengthNames;
397         TColStd_SequenceOfAsciiString anUnitAngleNames;
398         TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
399         aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
400         if (anUnitLengthNames.Length() > 0) {
401           TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
402           if (aLenUnits == "millimetre")
403             Interface_Static::SetCVal("xstep.cascade.unit", "MM");
404           else if (aLenUnits == "centimetre")
405             Interface_Static::SetCVal("xstep.cascade.unit", "CM");
406           else if (aLenUnits == "metre" || aLenUnits.IsEmpty())
407             Interface_Static::SetCVal("xstep.cascade.unit", "M");
408           else if (aLenUnits == "INCH")
409             Interface_Static::SetCVal("xstep.cascade.unit", "INCH");
410           else {
411             theError = "The file contains not supported units.";
412             return aResShape;
413           }
414           // TODO (for other units than mm, cm, m or inch)
415           //else if (aLenUnits == "")
416           //  Interface_Static::SetCVal("xstep.cascade.unit", "???");
417         }
418       }
419       else {
420         //cout<<"need re-scale a model"<<endl;
421         // set UnitFlag to 'meter'
422         Interface_Static::SetCVal("xstep.cascade.unit","M");
423       }
424
425       Standard_Boolean failsonly = Standard_False;
426       aReader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity);
427
428       /* Root transfers */
429       Standard_Integer nbr = aReader.NbRootsForTransfer();
430       aReader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity);
431
432       for (Standard_Integer n = 1; n <= nbr; n++) {
433         Standard_Boolean ok = aReader.TransferRoot(n);
434         /* Collecting resulting entities */
435         Standard_Integer nbs = aReader.NbShapes();
436         if (!ok || nbs == 0)
437         {
438           // THROW_SALOME_CORBA_EXCEPTION("Exception catched in GEOM_Gen_i::ImportStep", SALOME::BAD_PARAM);
439           continue; // skip empty root
440         }
441         /* For a single entity */
442         else if (nbr == 1 && nbs == 1) {
443           aResShape = aReader.Shape(1);
444           // ATTENTION: this is a workaround for mantis issue 0020442 remark 0010776
445           // It should be removed after patching OCCT for bug OCC22436
446           // (fix for OCCT is expected in service pack next to OCCT6.3sp12)
447           if (aResShape.ShapeType() == TopAbs_COMPOUND) {
448             int nbSub1 = 0;
449             TopoDS_Shape currShape;
450             TopoDS_Iterator It (aResShape, Standard_True, Standard_True);
451             for (; It.More(); It.Next()) {
452               nbSub1++;
453               currShape = It.Value();
454             }
455             if (nbSub1 == 1)
456               aResShape = currShape;
457           }
458           // END workaround
459           break;
460         }
461
462         for (Standard_Integer i = 1; i <= nbs; i++) {
463           TopoDS_Shape aShape = aReader.Shape(i);
464           if (aShape.IsNull()) {
465             // THROW_SALOME_CORBA_EXCEPTION("Null shape in GEOM_Gen_i::ImportStep", SALOME::BAD_PARAM) ;
466             //return aResShape;
467             continue;
468           }
469           else {
470             B.Add(compound, aShape);
471           }
472         }
473       }
474       if (aResShape.IsNull())
475         aResShape = compound;
476
477       // Check if any BRep entity has been read, there must be at least a vertex
478       if ( !TopExp_Explorer( aResShape, TopAbs_VERTEX ).More() )
479       {
480         theError = "No geometrical data in the imported file.";
481         return TopoDS_Shape();
482       }
483     } else {
484       theError = "Wrong format of the imported file. Can't import file.";
485       aResShape.Nullify();
486     }
487   }
488   catch (Standard_Failure) {
489     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
490     theError = aFail->GetMessageString();
491     aResShape.Nullify();
492   }
493   // Return previous locale
494   return aResShape;
495 }