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