Salome HOME
0dc8d70578516ea4ccd4555f391d6efeae63e675
[modules/geom.git] / src / STEPImport / STEPImport.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File:        STEPImport.cxx
24 //  Created:     Wed May 19 14:41:10 2004
25 //  Author:      Pavel TELKOV
26
27 #include "utilities.h"
28
29 #include <Basics_Utils.hxx>
30 #include <Basics_OCCTVersion.hxx>
31
32 #include <TDF_ChildIDIterator.hxx>
33 #include <TDF_Label.hxx>
34 #include <TDataStd_Name.hxx>
35 #include <TDataStd_Comment.hxx>
36 #include <TNaming_Builder.hxx>
37 #include <TNaming_NamedShape.hxx>
38
39 #include <IFSelect_ReturnStatus.hxx>
40 #include <Interface_EntityIterator.hxx>
41 #include <Interface_Graph.hxx>
42 #include <Interface_InterfaceModel.hxx>
43 #include <Interface_Static.hxx>
44 #include <STEPControl_Reader.hxx>
45 #include <StepBasic_Product.hxx>
46 #include <StepBasic_ProductDefinition.hxx>
47 #include <StepBasic_ProductDefinitionFormation.hxx>
48 #include <StepGeom_GeometricRepresentationItem.hxx>
49 #include <StepShape_TopologicalRepresentationItem.hxx>
50 #include <StepRepr_DescriptiveRepresentationItem.hxx>
51 #include <StepRepr_ProductDefinitionShape.hxx>
52 #include <StepRepr_PropertyDefinitionRepresentation.hxx>
53 #include <StepRepr_Representation.hxx>
54 #include <TransferBRep.hxx>
55 #include <Transfer_Binder.hxx>
56 #include <Transfer_TransientProcess.hxx>
57 #include <XSControl_TransferReader.hxx>
58 #include <XSControl_WorkSession.hxx>
59
60 #include <BRep_Builder.hxx>
61
62 #include <TopExp.hxx>
63 #include <TopExp_Explorer.hxx>
64 #include <TopTools_IndexedMapOfShape.hxx>
65 #include <TopoDS_Compound.hxx>
66 #include <TopoDS_Iterator.hxx>
67 #include <TopoDS_Shape.hxx>
68
69 #include <TCollection_AsciiString.hxx>
70 #include <TColStd_SequenceOfAsciiString.hxx>
71
72 #include <Standard_Failure.hxx>
73 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
74
75 #ifdef WIN32
76   #if defined STEPIMPORT_EXPORTS || defined STEPImport_EXPORTS
77     #define STEPIMPORT_EXPORT __declspec( dllexport )
78   #else
79     #define STEPIMPORT_EXPORT __declspec( dllimport )
80   #endif
81 #else
82   #define STEPIMPORT_EXPORT
83 #endif
84
85
86 //=============================================================================
87 /*!
88  *  GetShape()
89  */
90 //=============================================================================
91
92 static TopoDS_Shape GetShape(const Handle(Standard_Transient)        &theEnti,
93                              const Handle(Transfer_TransientProcess) &theTP)
94 {
95   TopoDS_Shape            aResult;
96   Handle(Transfer_Binder) aBinder = theTP->Find(theEnti);
97
98   if (aBinder.IsNull()) {
99     return aResult;
100   }
101
102   aResult = TransferBRep::ShapeResult(aBinder);
103
104   return aResult;
105 }
106
107 //=============================================================================
108 /*!
109  *  GetLabel()
110  */
111 //=============================================================================
112
113 static TDF_Label GetLabel(const Handle(Standard_Transient) &theEnti,
114                           const TDF_Label                  &theShapeLabel,
115                           const TopoDS_Shape               &aShape)
116 {
117   TDF_Label aResult;
118
119   if (theEnti->IsKind
120             (STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
121     // check all named shapes using iterator
122     TDF_ChildIDIterator anIt
123       (theShapeLabel, TDataStd_Name::GetID(), Standard_True);
124
125     for (; anIt.More(); anIt.Next()) {
126       Handle(TDataStd_Name) nameAttr =
127         Handle(TDataStd_Name)::DownCast(anIt.Value());
128
129       if (nameAttr.IsNull()) {
130         continue;
131       }
132
133       TDF_Label aLab = nameAttr->Label();
134       Handle(TNaming_NamedShape) shAttr; 
135
136       if (aLab.FindAttribute(TNaming_NamedShape::GetID(), shAttr) &&
137           shAttr->Get().IsEqual(aShape)) {
138         aResult = aLab;
139       }
140     }
141   }
142
143   // create label and set shape
144   if (aResult.IsNull()) {
145     TDF_TagSource aTag;
146
147     aResult = aTag.NewChild(theShapeLabel);
148
149     TNaming_Builder tnBuild (aResult);
150
151     tnBuild.Generated(aShape);
152   }
153
154   return aResult;
155 }
156
157 //=============================================================================
158 /*!
159  *  StoreName()
160  */
161 //=============================================================================
162
163 static void StoreName(const Handle(Standard_Transient)        &theEnti,
164                       const TopTools_IndexedMapOfShape        &theIndices,
165                       const Handle(Transfer_TransientProcess) &theTP,
166                       const TDF_Label                         &theShapeLabel)
167 {
168   Handle(TCollection_HAsciiString) aName;
169
170   if (theEnti->IsKind(STANDARD_TYPE(StepShape_TopologicalRepresentationItem)) ||
171       theEnti->IsKind(STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
172     aName = Handle(StepRepr_RepresentationItem)::DownCast(theEnti)->Name();
173   } else {
174     Handle(StepBasic_ProductDefinition) PD =
175       Handle(StepBasic_ProductDefinition)::DownCast(theEnti);
176
177     if (PD.IsNull() == Standard_False) {
178       Handle(StepBasic_Product) Prod = PD->Formation()->OfProduct();
179       aName = Prod->Name();
180     }
181   }
182
183   bool isValidName = false;
184
185   if (aName.IsNull() == Standard_False) {
186     isValidName = true;
187
188     if (aName->UsefullLength() < 1) {
189       isValidName = false;
190     } else if (aName->UsefullLength() == 4 &&
191                toupper (aName->Value(1)) == 'N' &&
192                toupper (aName->Value(2)) == 'O' &&
193                toupper (aName->Value(3)) == 'N' &&
194                toupper (aName->Value(4)) == 'E') {
195       // skip 'N0NE' name
196       isValidName = false;
197     } else {
198       // special check to pass names like "Open CASCADE STEP translator 6.3 1"
199       TCollection_AsciiString aSkipName ("Open CASCADE STEP translator");
200
201       if (aName->Length() >= aSkipName.Length()) {
202         if (aName->String().SubString
203                             (1, aSkipName.Length()).IsEqual(aSkipName)) {
204           isValidName = false;
205         }
206       }
207     }
208   }
209
210   if (isValidName) {
211     TCollection_ExtendedString aNameExt (aName->ToCString());
212
213     // find target shape
214     TopoDS_Shape S = GetShape(theEnti, theTP);
215
216     if (S.IsNull()) {
217       return;
218     }
219
220     // as PRODUCT can be included in the main shape
221     // several times, we look here for all iclusions.
222     Standard_Integer isub, nbSubs = theIndices.Extent();
223
224     for (isub = 1; isub <= nbSubs; isub++) {
225       TopoDS_Shape aSub = theIndices.FindKey(isub);
226
227       if (aSub.IsPartner(S)) {
228         TDF_Label L = GetLabel(theEnti, theShapeLabel, aSub);
229
230         // set a name
231         TDataStd_Name::Set(L, aNameExt);
232       }
233     }
234   }
235 }
236
237 //=============================================================================
238 /*!
239  *  StoreMaterial()
240  */
241 //=============================================================================
242
243 static void StoreMaterial
244                     (const Handle(Standard_Transient)        &theEnti,
245                      const TopTools_IndexedMapOfShape        &theIndices,
246                      const Handle(Transfer_TransientProcess) &theTP,
247                      const TDF_Label                         &theShapeLabel)
248 {
249   // Treat Product Definition Shape only.
250   Handle(StepRepr_ProductDefinitionShape) aPDS =
251       Handle(StepRepr_ProductDefinitionShape)::DownCast(theEnti);
252   Handle(StepBasic_ProductDefinition)     aProdDef;
253
254   if(aPDS.IsNull() == Standard_False) {
255     // Product Definition Shape ==> Product Definition
256     aProdDef = aPDS->Definition().ProductDefinition();
257   }
258
259   if (aProdDef.IsNull() == Standard_False) {
260     // Product Definition ==> Property Definition
261     const Interface_Graph    &aGraph = theTP->Graph();
262     Interface_EntityIterator  aSubs  = aGraph.Sharings(aProdDef);
263     TopoDS_Shape              aShape;
264
265     for(aSubs.Start(); aSubs.More(); aSubs.Next()) {
266       Handle(StepRepr_PropertyDefinition) aPropD =
267         Handle(StepRepr_PropertyDefinition)::DownCast(aSubs.Value());
268
269       if(aPropD.IsNull() == Standard_False) {
270         // Property Definition ==> Representation.
271         Interface_EntityIterator aSubs1 = aGraph.Sharings(aPropD);
272
273         for(aSubs1.Start(); aSubs1.More(); aSubs1.Next()) {
274           Handle(StepRepr_PropertyDefinitionRepresentation) aPDR =
275             Handle(StepRepr_PropertyDefinitionRepresentation)::
276               DownCast(aSubs1.Value());
277
278           if(aPDR.IsNull() == Standard_False) {
279             // Property Definition ==> Material Name.
280             Handle(StepRepr_Representation) aRepr = aPDR->UsedRepresentation();
281
282             if(aRepr.IsNull() == Standard_False) {
283               Standard_Integer ir;
284
285               for(ir = 1; ir <= aRepr->NbItems(); ir++) {
286                 Handle(StepRepr_RepresentationItem) aRI = aRepr->ItemsValue(ir);
287                 Handle(StepRepr_DescriptiveRepresentationItem) aDRI =
288                   Handle(StepRepr_DescriptiveRepresentationItem)::DownCast(aRI);
289
290                 if(aDRI.IsNull() == Standard_False) {
291                   // Get shape from Product Definition
292                   Handle(TCollection_HAsciiString) aMatName = aDRI->Name();
293
294                   if(aMatName.IsNull() == Standard_False) {
295                     TCollection_ExtendedString
296                                  aMatNameExt (aMatName->ToCString());
297
298                     if (aShape.IsNull()) {
299                       // Get the shape.
300                       aShape = GetShape(aProdDef, theTP);
301
302                       if (aShape.IsNull()) {
303                         return;
304                       }
305                     }
306
307                     // as PRODUCT can be included in the main shape
308                     // several times, we look here for all iclusions.
309                     Standard_Integer isub, nbSubs = theIndices.Extent();
310
311                     for (isub = 1; isub <= nbSubs; isub++) {
312                       TopoDS_Shape aSub = theIndices.FindKey(isub);
313
314                       if (aSub.IsPartner(aShape)) {
315                         TDF_Label aLabel =
316                           GetLabel(aProdDef, theShapeLabel, aSub);
317
318                         // set a name
319                         TDataStd_Comment::Set(aLabel, aMatNameExt);
320                       }
321                     }
322                   }
323                 }
324               }
325             }
326           }
327         }
328       }
329     }
330   }
331 }
332
333 //=============================================================================
334 /*!
335  *  Import()
336  */
337 //=============================================================================
338
339 extern "C"
340 {
341   STEPIMPORT_EXPORT
342   Handle(TCollection_HAsciiString) GetValue (const TCollection_AsciiString& theFileName,
343                                              const TCollection_AsciiString& theParameterName,
344                                              TCollection_AsciiString&       theError)
345   {
346     Handle(TCollection_HAsciiString) aValue;
347
348     if (theParameterName != "LEN_UNITS") {
349       theError = theParameterName + " parameter reading is not supported by STEP plugin";
350       return aValue;
351     }
352
353     // Set "C" numeric locale to save numbers correctly
354     Kernel_Utils::Localizer loc;
355
356     STEPControl_Reader aReader;
357
358     Interface_Static::SetCVal("xstep.cascade.unit","M");
359     Interface_Static::SetIVal("read.step.ideas", 1);
360     Interface_Static::SetIVal("read.step.nonmanifold", 1);
361
362     try {
363 #if OCC_VERSION_LARGE > 0x06010000
364       OCC_CATCH_SIGNALS;
365 #endif
366       IFSelect_ReturnStatus status = aReader.ReadFile(theFileName.ToCString());
367       if (status == IFSelect_RetDone) {
368         TColStd_SequenceOfAsciiString anUnitLengthNames;
369         TColStd_SequenceOfAsciiString anUnitAngleNames;
370         TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
371         aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
372         if (anUnitLengthNames.Length() > 0) {
373           aValue = new TCollection_HAsciiString( anUnitLengthNames.First() );
374           /*
375           TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
376           if (aLenUnits == "millimetre")
377             aValue = new TCollection_HAsciiString ("MM");
378           else if (aLenUnits == "centimetre")
379             aValue = new TCollection_HAsciiString ("CM");
380           else if (aLenUnits == "metre")
381             aValue = new TCollection_HAsciiString ("M");
382           else if (aLenUnits == "INCH")
383             aValue = new TCollection_HAsciiString ("INCH");
384           // TODO (for other units than mm, cm, m or inch)
385           //else if (aLenUnits == "")
386           //  aValue = new TCollection_HAsciiString ("");
387
388           // tmp begin
389           //std::cout << "$$$ --- " << anUnitLengthNames.First();
390           //for (int ii = 2; ii <= anUnitLengthNames.Length(); ii++)
391           //  std::cout << ", " << anUnitLengthNames.Value(ii);
392           //std::cout << std::endl;
393           // tmp end
394           */
395         }
396       }
397       else {
398         theError = theFileName + " reading failed";
399       }
400     }
401     catch (Standard_Failure) {
402       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
403       theError = aFail->GetMessageString();
404     }
405
406     return aValue;
407   }
408
409   STEPIMPORT_EXPORT
410   TopoDS_Shape Import (const TCollection_AsciiString& theFileName,
411                        const TCollection_AsciiString& theFormatName,
412                        TCollection_AsciiString&       theError,
413                        const TDF_Label&               theShapeLabel)
414   {
415     TopoDS_Shape aResShape;
416
417     // Set "C" numeric locale to save numbers correctly
418     Kernel_Utils::Localizer loc;
419
420     STEPControl_Reader aReader;
421
422     //VSR: 16/09/09: Convert to METERS
423     Interface_Static::SetCVal("xstep.cascade.unit","M");
424     Interface_Static::SetIVal("read.step.ideas", 1);
425     Interface_Static::SetIVal("read.step.nonmanifold", 1);
426
427     BRep_Builder B;
428     TopoDS_Compound compound;
429     B.MakeCompound(compound);
430
431     try {
432       OCC_CATCH_SIGNALS;
433
434       IFSelect_ReturnStatus status = aReader.ReadFile(theFileName.ToCString());
435
436       if (status == IFSelect_RetDone) {
437
438         // Regard or not the model units
439         if (theFormatName == "STEP_SCALE") {
440           // set UnitFlag to units from file
441           TColStd_SequenceOfAsciiString anUnitLengthNames;
442           TColStd_SequenceOfAsciiString anUnitAngleNames;
443           TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
444           aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
445           if (anUnitLengthNames.Length() > 0) {
446             TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
447             if (aLenUnits == "millimetre")
448               Interface_Static::SetCVal("xstep.cascade.unit", "MM");
449             else if (aLenUnits == "centimetre")
450               Interface_Static::SetCVal("xstep.cascade.unit", "CM");
451             else if (aLenUnits == "metre" || aLenUnits.IsEmpty())
452               Interface_Static::SetCVal("xstep.cascade.unit", "M");
453             else if (aLenUnits == "INCH")
454               Interface_Static::SetCVal("xstep.cascade.unit", "INCH");
455             else {
456               theError = "The file contains not supported units.";
457               return aResShape;
458             }
459             // TODO (for other units than mm, cm, m or inch)
460             //else if (aLenUnits == "")
461             //  Interface_Static::SetCVal("xstep.cascade.unit", "???");
462           }
463         }
464         else {
465           //cout<<"need re-scale a model"<<endl;
466           // set UnitFlag to 'meter'
467           Interface_Static::SetCVal("xstep.cascade.unit","M");
468         }
469
470         Standard_Boolean failsonly = Standard_False;
471         aReader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity);
472
473         /* Root transfers */
474         Standard_Integer nbr = aReader.NbRootsForTransfer();
475         aReader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity);
476
477         for (Standard_Integer n = 1; n <= nbr; n++) {
478           Standard_Boolean ok = aReader.TransferRoot(n);
479           /* Collecting resulting entities */
480           Standard_Integer nbs = aReader.NbShapes();
481           if (!ok || nbs == 0)
482           {
483             // THROW_SALOME_CORBA_EXCEPTION("Exception catched in GEOM_Gen_i::ImportStep", SALOME::BAD_PARAM);
484             continue; // skip empty root
485           }
486           /* For a single entity */
487           else if (nbr == 1 && nbs == 1) {
488             aResShape = aReader.Shape(1);
489             // ATTENTION: this is a workaround for mantis issue 0020442 remark 0010776
490             // It should be removed after patching OCCT for bug OCC22436
491             // (fix for OCCT is expected in service pack next to OCCT6.3sp12)
492             if (aResShape.ShapeType() == TopAbs_COMPOUND) {
493               int nbSub1 = 0;
494               TopoDS_Shape currShape;
495               TopoDS_Iterator It (aResShape, Standard_True, Standard_True);
496               for (; It.More(); It.Next()) {
497                 nbSub1++;
498                 currShape = It.Value();
499               }
500               if (nbSub1 == 1)
501                 aResShape = currShape;
502             }
503             // END workaround
504             break;
505           }
506
507           for (Standard_Integer i = 1; i <= nbs; i++) {
508             TopoDS_Shape aShape = aReader.Shape(i);
509             if (aShape.IsNull()) {
510               // THROW_SALOME_CORBA_EXCEPTION("Null shape in GEOM_Gen_i::ImportStep", SALOME::BAD_PARAM) ;
511               //return aResShape;
512               continue;
513             }
514             else {
515               B.Add(compound, aShape);
516             }
517           }
518         }
519         if (aResShape.IsNull())
520           aResShape = compound;
521
522         // Check if any BRep entity has been read, there must be at least a vertex
523         if ( !TopExp_Explorer( aResShape, TopAbs_VERTEX ).More() )
524         {
525           theError = "No geometrical data in the imported file.";
526           return TopoDS_Shape();
527         }
528
529         // BEGIN: Store names and materials of sub-shapes from file
530         TopTools_IndexedMapOfShape anIndices;
531         TopExp::MapShapes(aResShape, anIndices);
532
533         Handle(Interface_InterfaceModel) Model = aReader.WS()->Model();
534         Handle(XSControl_TransferReader) TR = aReader.WS()->TransferReader();
535         if (!TR.IsNull()) {
536           Handle(Transfer_TransientProcess) TP = TR->TransientProcess();
537
538           Standard_Integer nb = Model->NbEntities();
539
540           for (Standard_Integer ie = 1; ie <= nb; ie++) {
541             Handle(Standard_Transient) enti = Model->Value(ie);
542
543             // Store names.
544             StoreName(enti, anIndices, TP, theShapeLabel);
545
546             // Store materials.
547             StoreMaterial(enti, anIndices, TP, theShapeLabel);
548           }
549         }
550         // END: Store names and materials
551       }
552       else {
553 //        switch (status) {
554 //        case IFSelect_RetVoid:
555 //          theError = "Nothing created or No data to process";
556 //          break;
557 //        case IFSelect_RetError:
558 //          theError = "Error in command or input data";
559 //          break;
560 //        case IFSelect_RetFail:
561 //          theError = "Execution was run, but has failed";
562 //          break;
563 //        case IFSelect_RetStop:
564 //          theError = "Execution has been stopped. Quite possible, an exception was raised";
565 //          break;
566 //        default:
567 //          break;
568 //        }
569         theError = "Wrong format of the imported file. Can't import file.";
570         aResShape.Nullify();
571       }
572     }
573     catch (Standard_Failure) {
574       Handle(Standard_Failure) aFail = Standard_Failure::Caught();
575       theError = aFail->GetMessageString();
576       aResShape.Nullify();
577     }
578     // Return previous locale
579     return aResShape;
580   }
581 }