Salome HOME
97f1608131bce21f755c0da02487b7f8ae2221b4
[modules/geom.git] / src / STEPPlugin / STEPPlugin_ImportDriver.cxx
1 // Copyright (C) 2014-2023  CEA/DEN, EDF R&D, OPEN CASCADE
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 // internal includes
21 #include "STEPPlugin_ImportDriver.hxx"
22 #include "STEPPlugin_IImport.hxx"
23
24 // KERNEL includes
25 #include <utilities.h>
26 #include <Basics_Utils.hxx>
27
28 // GEOM includes
29 #include "GEOM_Function.hxx"
30 #include "GEOMImpl_Types.hxx"
31
32 // OOCT includes
33 #include <TDF_ChildIDIterator.hxx>
34 #include <TDF_Label.hxx>
35 #include <TDataStd_Name.hxx>
36 #include <TDataStd_Comment.hxx>
37 #include <TNaming_Builder.hxx>
38 #include <TNaming_NamedShape.hxx>
39 #include <Interface_EntityIterator.hxx>
40 #include <Interface_Graph.hxx>
41 #include <Interface_InterfaceModel.hxx>
42 #include <Interface_Static.hxx>
43 #include <STEPControl_Reader.hxx>
44 #include <StepBasic_Product.hxx>
45 #include <StepBasic_ProductDefinition.hxx>
46 #include <StepBasic_ProductDefinitionFormation.hxx>
47 #include <StepGeom_GeometricRepresentationItem.hxx>
48 #include <StepShape_TopologicalRepresentationItem.hxx>
49 #include <StepRepr_DescriptiveRepresentationItem.hxx>
50 #include <StepRepr_NextAssemblyUsageOccurrence.hxx>
51 #include <StepRepr_ProductDefinitionShape.hxx>
52 #include <StepRepr_PropertyDefinitionRepresentation.hxx>
53 #include <StepRepr_Representation.hxx>
54 #include <TransferBRep.hxx>
55 #include <Transfer_TransientProcess.hxx>
56 #include <XSControl_TransferReader.hxx>
57 #include <XSControl_WorkSession.hxx>
58 #include <BRep_Builder.hxx>
59 #include <TopExp.hxx>
60 #include <TopExp_Explorer.hxx>
61 #include <TopTools_DataMapOfShapeShape.hxx>
62 #include <TopTools_IndexedMapOfShape.hxx>
63 #include <TopTools_ListIteratorOfListOfShape.hxx>
64 #include <TopTools_ListOfShape.hxx>
65 #include <TopTools_MapOfShape.hxx>
66 #include <TopoDS_Compound.hxx>
67 #include <TopoDS_Iterator.hxx>
68 #include <TColStd_SequenceOfAsciiString.hxx>
69
70 #include <StdFail_NotDone.hxx>
71 #include <Standard_Failure.hxx>
72 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
73
74 namespace
75 {
76   //=============================================================================
77   /*!
78    *  GetShape()
79    */
80   //=============================================================================
81
82   TopoDS_Shape GetShape(const Handle(Standard_Transient)        &theEnti,
83                         const Handle(Transfer_TransientProcess) &theTP)
84   {
85     TopoDS_Shape            aResult;
86     Handle(Transfer_Binder) aBinder = theTP->Find(theEnti);
87
88     if (aBinder.IsNull()) {
89       return aResult;
90     }
91
92     aResult = TransferBRep::ShapeResult(aBinder);
93
94     return aResult;
95   }
96
97   //=============================================================================
98   /*!
99    *  GetLabel()
100    */
101   //=============================================================================
102
103   TDF_Label GetLabel(const Handle(Standard_Transient) &theEnti,
104                      const TDF_Label                  &theShapeLabel,
105                      const TopoDS_Shape               &aShape)
106   {
107     TDF_Label aResult;
108
109     if (theEnti->IsKind
110         (STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
111       // check all named shapes using iterator
112       TDF_ChildIDIterator anIt
113         (theShapeLabel, TDataStd_Name::GetID(), Standard_True);
114
115       for (; anIt.More(); anIt.Next()) {
116         Handle(TDataStd_Name) nameAttr =
117           Handle(TDataStd_Name)::DownCast(anIt.Value());
118
119         if (nameAttr.IsNull()) {
120           continue;
121         }
122
123         TDF_Label aLab = nameAttr->Label();
124         Handle(TNaming_NamedShape) shAttr;
125
126         if (aLab.FindAttribute(TNaming_NamedShape::GetID(), shAttr) &&
127             shAttr->Get().IsEqual(aShape)) {
128           aResult = aLab;
129         }
130       }
131     }
132
133     // create label and set shape
134     if (aResult.IsNull()) {
135       TDF_TagSource aTag;
136
137       aResult = aTag.NewChild(theShapeLabel);
138
139       TNaming_Builder tnBuild (aResult);
140
141       tnBuild.Generated(aShape);
142     }
143
144     return aResult;
145   }
146
147   //=============================================================================
148   /*!
149    *  GetAllParents()
150    */
151   //=============================================================================
152
153   Standard_Boolean GetAllParents(const TopoDS_Shape         &theShape,
154                                  const TopoDS_Shape         &theSubShape,
155                                        TopTools_ListOfShape &theParents)
156   {
157     const TopAbs_ShapeEnum aSubShType = theSubShape.ShapeType();
158     Standard_Boolean       aResult    = Standard_False;
159
160     if (theShape.ShapeType() >= aSubShType) {
161       return aResult; // NULL shape
162     }
163
164     TopoDS_Iterator     anIt(theShape);
165     TopTools_MapOfShape aMapFence;
166
167     for (; anIt.More(); anIt.Next()) {
168       const TopoDS_Shape &aSubShape = anIt.Value();
169
170       if (aMapFence.Add(aSubShape)) {
171         if (theSubShape.IsSame(aSubShape)) {
172           // The sub-shape is found. theShape is its parent.
173           theParents.Append(theShape);
174           aResult = Standard_True;
175           break;
176         }
177
178         if (aSubShape.ShapeType() < aSubShType) {
179           if (GetAllParents(aSubShape, theSubShape, theParents)) {
180             // The sub-shape is found.
181             theParents.Append(theShape);
182             aResult = Standard_True;
183             break;
184           }
185         }
186       }
187     }
188
189     return aResult;
190   }
191
192   //=============================================================================
193   /*!
194    *  BuildModifiedShape()
195    */
196   //=============================================================================
197
198   TopoDS_Shape BuildModifiedShape
199               (const TopoDS_Shape                 &theShape,
200                      TopTools_DataMapOfShapeShape &theMapModified)
201   {
202     // Check if the shape is modified.
203     TopoDS_Shape     aFwdShape  = theShape.Oriented(TopAbs_FORWARD);
204     TopoDS_Iterator  anIt(aFwdShape);
205     Standard_Boolean isModified = Standard_False;
206
207     for (; anIt.More(); anIt.Next()) {
208       if (theMapModified.IsBound(anIt.Value())) {
209         isModified = Standard_True;
210         break;
211       }
212     }
213
214     TopoDS_Shape aResult;
215
216     if (isModified) {
217       BRep_Builder aBuilder;
218
219       aResult = aFwdShape.EmptyCopied();
220
221       for (anIt.Initialize(aFwdShape); anIt.More(); anIt.Next()) {
222         const TopoDS_Shape &aSubShape = anIt.Value();
223
224         if (theMapModified.IsBound(aSubShape)) {
225           TopoDS_Shape aModifSubShape = theMapModified.Find(aSubShape);
226
227           if (aModifSubShape.IsNull()) {
228             // Recursively compute the sub-shape.
229             aModifSubShape = BuildModifiedShape(aSubShape, theMapModified);
230           }
231
232           aBuilder.Add(aResult, aModifSubShape);
233         } else {
234           aBuilder.Add(aResult, aSubShape);
235         }
236       }
237
238       // Set the result shape orientation.
239       aResult.Orientation(theShape.Orientation());
240       theMapModified.Bind(theShape, aResult);
241     } else {
242       aResult = theShape;
243     }
244
245     return aResult;
246   }
247
248   //=============================================================================
249   /*!
250    *  CreateAssemblies()
251    */
252   //=============================================================================
253
254   TopoDS_Shape CreateAssemblies
255               (const STEPControl_Reader           &theReader,
256                const TopoDS_Shape                 &theShape,
257                      TopTools_DataMapOfShapeShape &theMapShapeAssembly)
258   {
259     TopoDS_Shape                     aResult = theShape;
260     Handle(XSControl_TransferReader) aTR     = theReader.WS()->TransferReader();
261     TopTools_ListOfShape             aListAssemblies;
262
263     if (!aTR.IsNull()) {
264       Handle(Interface_InterfaceModel)  aModel      = theReader.WS()->Model();
265       Handle(Transfer_TransientProcess) aTP         = aTR->TransientProcess();
266       Standard_Integer                  aNbEntities = aModel->NbEntities();
267       Standard_Integer                  i;
268       Handle(Standard_Type)             aNAUOType   =
269               STANDARD_TYPE(StepRepr_NextAssemblyUsageOccurrence);
270
271       for (i = 1; i <= aNbEntities; i++) {
272         Handle(Standard_Transient) anEnti = aModel->Value(i);
273
274         if (anEnti->IsKind(aNAUOType)) {
275           // This is an assembly. Find target shape
276           TopoDS_Shape aShape = GetShape(anEnti, aTP);
277
278           if (aShape.IsNull()) {
279             continue;
280           }
281
282           if (aShape.ShapeType() != TopAbs_COMPOUND) {
283             aListAssemblies.Append(aShape);
284           }
285         }
286       }
287     }
288
289     // Create assemblies.
290     if (!aListAssemblies.IsEmpty()) {
291       TopTools_ListIteratorOfListOfShape anIter(aListAssemblies);
292       BRep_Builder                       aBuilder;
293
294       for (; anIter.More(); anIter.Next()) {
295         const TopoDS_Shape   &aShape  = anIter.Value();
296         TopTools_ListOfShape  aParents;
297
298         if (GetAllParents(theShape, aShape, aParents) &&
299             aParents.First().ShapeType() == TopAbs_COMPOUND) {
300           TopoDS_Compound                    aComp;
301           TopTools_ListIteratorOfListOfShape aParentIter(aParents);
302
303           // Fill theMapShapeAssembly.
304           for (; aParentIter.More(); aParentIter.Next()) {
305             theMapShapeAssembly.Bind(aParentIter.Value(), TopoDS_Shape());
306           }
307
308           aBuilder.MakeCompound(aComp);
309           aBuilder.Add(aComp, aShape);
310           theMapShapeAssembly.Bind(aShape, aComp);
311         }
312       }
313
314       // Build a new shape.
315       aResult = BuildModifiedShape(theShape, theMapShapeAssembly);
316     }
317
318     return aResult;
319   }
320
321   //=============================================================================
322   /*!
323    *  StoreName()
324    */
325   //=============================================================================
326
327   void StoreName(const Handle(Standard_Transient)        &theEnti,
328                  const TopTools_IndexedMapOfShape        &theIndices,
329                  const Handle(XSControl_WorkSession)     &theWS,
330                  const Handle(Transfer_TransientProcess) &theTP,
331                  const TDF_Label                         &theShapeLabel,
332                        TopTools_DataMapOfShapeShape      &theMapShapeAssembly)
333   {
334     Handle(TCollection_HAsciiString) aName;
335
336     if (theEnti->IsKind(STANDARD_TYPE(StepShape_TopologicalRepresentationItem)) ||
337         theEnti->IsKind(STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
338       aName = Handle(StepRepr_RepresentationItem)::DownCast(theEnti)->Name();
339     } else if (theEnti->IsKind(STANDARD_TYPE(StepRepr_NextAssemblyUsageOccurrence))) {
340       Handle(StepRepr_NextAssemblyUsageOccurrence) aNAUO =
341         Handle(StepRepr_NextAssemblyUsageOccurrence)::DownCast(theEnti);
342
343       Interface_EntityIterator aSubs = theWS->Graph().Sharings(aNAUO);
344
345       for (aSubs.Start(); aSubs.More(); aSubs.Next()) {
346         Handle(StepRepr_ProductDefinitionShape) aPDS =
347           Handle(StepRepr_ProductDefinitionShape)::DownCast(aSubs.Value());
348
349         if(aPDS.IsNull()) {
350           continue;
351         }
352
353         Handle(StepBasic_ProductDefinitionRelationship) aPDR =
354           aPDS->Definition().ProductDefinitionRelationship();
355
356         if (aPDR.IsNull()) {
357           continue;
358         }
359
360         if (aPDR->HasDescription() && aPDR->Description()->UsefullLength() >0) {
361           aName = aPDR->Description();
362         } else if (!aPDR->Name().IsNull() && aPDR->Name()->UsefullLength() >0 ) {
363           aName = aPDR->Name();
364         } else if (!aPDR->Id().IsNull()) {
365           aName = aPDR->Id();
366         }
367       }
368     } else {
369       Handle(StepBasic_ProductDefinition) PD =
370         Handle(StepBasic_ProductDefinition)::DownCast(theEnti);
371
372       if (PD.IsNull() == Standard_False) {
373         Handle(StepBasic_Product) Prod = PD->Formation()->OfProduct();
374         aName = Prod->Name();
375       }
376     }
377
378     bool isValidName = false;
379
380     if (aName.IsNull() == Standard_False) {
381       isValidName = true;
382
383       if (aName->UsefullLength() < 1) {
384         isValidName = false;
385       } else if (aName->UsefullLength() == 4 &&
386                  toupper (aName->Value(1)) == 'N' &&
387                  toupper (aName->Value(2)) == 'O' &&
388                  toupper (aName->Value(3)) == 'N' &&
389                  toupper (aName->Value(4)) == 'E') {
390         // skip 'N0NE' name
391         isValidName = false;
392       } else {
393         // special check to pass names like "Open CASCADE STEP translator 6.3 1"
394         TCollection_AsciiString aSkipName ("Open CASCADE STEP translator");
395
396         if (aName->Length() >= aSkipName.Length()) {
397           if (aName->String().SubString
398               (1, aSkipName.Length()).IsEqual(aSkipName)) {
399             isValidName = false;
400           }
401         }
402       }
403     }
404
405     if (isValidName) {
406       TCollection_ExtendedString aNameExt (aName->ToCString());
407
408       // find target shape
409       TopoDS_Shape S = GetShape(theEnti, theTP);
410
411       if (theMapShapeAssembly.IsBound(S)) {
412         S = theMapShapeAssembly.Find(S);
413       }
414
415       if (S.IsNull()) {
416         return;
417       }
418
419       // as PRODUCT can be included in the main shape
420       // several times, we look here for all iclusions.
421       Standard_Integer isub, nbSubs = theIndices.Extent();
422
423       for (isub = 1; isub <= nbSubs; isub++) {
424         TopoDS_Shape aSub = theIndices.FindKey(isub);
425
426         if (aSub.IsPartner(S)) {
427           TDF_Label L = GetLabel(theEnti, theShapeLabel, aSub);
428
429           // set a name
430           TDataStd_Name::Set(L, aNameExt);
431         }
432       }
433     }
434   }
435
436   //=============================================================================
437   /*!
438    *  StoreMaterial()
439    */
440   //=============================================================================
441
442   void StoreMaterial( const Handle(Standard_Transient)        &theEnti,
443                       const TopTools_IndexedMapOfShape        &theIndices,
444                       const Handle(Transfer_TransientProcess) &theTP,
445                       const TDF_Label                         &theShapeLabel )
446   {
447     // Treat Product Definition Shape only.
448     Handle(StepRepr_ProductDefinitionShape) aPDS =
449       Handle(StepRepr_ProductDefinitionShape)::DownCast(theEnti);
450     Handle(StepBasic_ProductDefinition)     aProdDef;
451
452     if(aPDS.IsNull() == Standard_False) {
453       // Product Definition Shape ==> Product Definition
454       aProdDef = aPDS->Definition().ProductDefinition();
455     }
456
457     if (aProdDef.IsNull() == Standard_False) {
458       // Product Definition ==> Property Definition
459       const Interface_Graph    &aGraph = theTP->Graph();
460       Interface_EntityIterator  aSubs  = aGraph.Sharings(aProdDef);
461       TopoDS_Shape              aShape;
462
463       for(aSubs.Start(); aSubs.More(); aSubs.Next()) {
464         Handle(StepRepr_PropertyDefinition) aPropD =
465           Handle(StepRepr_PropertyDefinition)::DownCast(aSubs.Value());
466
467         if(aPropD.IsNull() == Standard_False) {
468           // Property Definition ==> Representation.
469           Interface_EntityIterator aSubs1 = aGraph.Sharings(aPropD);
470
471           for(aSubs1.Start(); aSubs1.More(); aSubs1.Next()) {
472             Handle(StepRepr_PropertyDefinitionRepresentation) aPDR =
473               Handle(StepRepr_PropertyDefinitionRepresentation)::
474               DownCast(aSubs1.Value());
475
476             if(aPDR.IsNull() == Standard_False) {
477               // Property Definition ==> Material Name.
478               Handle(StepRepr_Representation) aRepr = aPDR->UsedRepresentation();
479
480               if(aRepr.IsNull() == Standard_False) {
481                 Standard_Integer ir;
482
483                 for(ir = 1; ir <= aRepr->NbItems(); ir++) {
484                   Handle(StepRepr_RepresentationItem) aRI = aRepr->ItemsValue(ir);
485                   Handle(StepRepr_DescriptiveRepresentationItem) aDRI =
486                     Handle(StepRepr_DescriptiveRepresentationItem)::DownCast(aRI);
487
488                   if(aDRI.IsNull() == Standard_False) {
489                     // Get shape from Product Definition
490                     Handle(TCollection_HAsciiString) aMatName = aDRI->Name();
491
492                     if(aMatName.IsNull() == Standard_False) {
493                       TCollection_ExtendedString
494                         aMatNameExt (aMatName->ToCString());
495
496                       if (aShape.IsNull()) {
497                         // Get the shape.
498                         aShape = GetShape(aProdDef, theTP);
499
500                         if (aShape.IsNull()) {
501                           return;
502                         }
503                       }
504
505                       // as PRODUCT can be included in the main shape
506                       // several times, we look here for all iclusions.
507                       Standard_Integer isub, nbSubs = theIndices.Extent();
508
509                       for (isub = 1; isub <= nbSubs; isub++) {
510                         TopoDS_Shape aSub = theIndices.FindKey(isub);
511
512                         if (aSub.IsPartner(aShape)) {
513                           TDF_Label aLabel =
514                             GetLabel(aProdDef, theShapeLabel, aSub);
515
516                           // set a name
517                           TDataStd_Comment::Set(aLabel, aMatNameExt);
518                         }
519                       }
520                     }
521                   }
522                 }
523               }
524             }
525           }
526         }
527       }
528     }
529   }
530
531   TCollection_AsciiString ToNamedUnit( const TCollection_AsciiString& unit )
532   {
533     TCollection_AsciiString result = unit;
534     result.LowerCase();
535     if ( result == "mil" ) result = "milliinch";
536     return result;
537   }
538
539   TCollection_AsciiString ToOcctUnit( const TCollection_AsciiString& unit, TCollection_AsciiString& error )
540   {
541     TCollection_AsciiString result = "M", u = ToNamedUnit(unit);
542     u.LowerCase();
543
544     if (u == "inch")
545       result = "INCH";
546     else if (u == "milliinch")
547       result = "MIL";
548     else if (u == "microinch")
549       result = "UIN";
550     else if (u == "foot")
551       result = "FT";
552     else if (u == "mile")
553       result = "MI";
554     else if (u == "metre")
555       result = "M";
556     else if (u == "kilometre")
557       result = "KM";
558     else if (u == "millimetre")
559       result = "MM";
560     else if (u == "centimetre")
561       result = "CM";
562     else if (u == "micrometre")
563       result = "UM";
564     else if (u.IsEmpty())
565       result = "M";
566     else
567       error = "The file contains not supported units";
568
569     // TODO (for other units)
570     // else
571     //  result = "??"
572
573     return result;
574   }
575
576 } // end of namespace
577
578 //=======================================================================
579 //function : GetID
580 //purpose  :
581 //=======================================================================
582 const Standard_GUID& STEPPlugin_ImportDriver::GetID()
583 {
584   static Standard_GUID aGUID("a25f88df-461b-45c0-ab6b-a82101fe6ce7");
585   return aGUID;
586 }
587
588 //=======================================================================
589 //function : STEPPlugin_ImportDriver
590 //purpose  :
591 //=======================================================================
592 STEPPlugin_ImportDriver::STEPPlugin_ImportDriver()
593 {
594 }
595
596 //=======================================================================
597 //function : Execute
598 //purpose  :
599 //=======================================================================
600 Standard_Integer STEPPlugin_ImportDriver::Execute(Handle(TFunction_Logbook)& log) const
601 {
602   if( Label().IsNull() ) return 0;
603   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction( Label() );
604
605   STEPPlugin_IImport aData( aFunction );
606
607   TCollection_AsciiString aFileName = aData.GetFileName().ToCString();
608   bool anIsIgnoreUnits = aData.GetIsIgnoreUnits();
609   bool isCreateAssemblies = aData.GetIsCreateAssemblies();
610   TDF_Label aShapeLabel = aFunction->GetNamingEntry();
611
612   MESSAGE("Import STEP from file " << aFileName.ToCString() );
613
614   TopoDS_Shape aResShape;
615   TCollection_AsciiString anError;
616
617   // Set "C" numeric locale to save numbers correctly
618   Kernel_Utils::Localizer loc;
619
620   STEPControl_Reader aReader;
621
622   //VSR: 16/09/09: Convert to METERS
623   Interface_Static::SetCVal("xstep.cascade.unit","M");
624   Interface_Static::SetIVal("read.step.ideas", 1);
625   Interface_Static::SetIVal("read.step.nonmanifold", 1);
626
627   BRep_Builder B;
628   TopoDS_Compound compound;
629   B.MakeCompound(compound);
630
631   try
632   {
633     OCC_CATCH_SIGNALS;
634     IFSelect_ReturnStatus status = aReader.ReadFile(aFileName.ToCString());
635     if (status == IFSelect_RetDone) {
636       // Regard or not the model units
637       if( anIsIgnoreUnits ) {
638         // set UnitFlag to units from file
639         TColStd_SequenceOfAsciiString anUnitLengthNames;
640         TColStd_SequenceOfAsciiString anUnitAngleNames;
641         TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
642         aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
643         if (anUnitLengthNames.Length() > 0) {
644           TCollection_AsciiString aLenUnits = ToOcctUnit(anUnitLengthNames.First(), anError);
645           Interface_Static::SetCVal("xstep.cascade.unit", aLenUnits.ToCString());
646         }
647       }
648       else {
649         // Need re-scale a model (set UnitFlag to 'meter')
650         Interface_Static::SetCVal("xstep.cascade.unit","M");
651       }
652
653       Standard_Boolean failsonly = Standard_False;
654       aReader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity);
655
656       // Root transfers
657       Standard_Integer aNbRoots = aReader.NbRootsForTransfer();
658       Standard_Integer i;
659
660       aReader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity);
661
662       for (i = 1; i <= aNbRoots; i++) {
663         aReader.TransferRoot(i);
664       }
665
666       // Create result shape
667       const Standard_Integer aNbShapes = aReader.NbShapes();
668       TopTools_ListOfShape   aListResShapes;
669
670       if (isCreateAssemblies) {
671         for (i = 1; i <= aNbShapes; i++) {
672           TopoDS_Shape aShape = aReader.Shape(i);
673
674           if (aShape.IsNull()) {
675             continue;
676           }
677
678           aListResShapes.Append(aShape);
679         }
680       } else {
681         for (i = 1; i <= aNbShapes; i++) {
682           TopoDS_Shape aShape = aReader.Shape(i);
683
684           if (aShape.IsNull()) {
685             continue;
686           }
687
688           if (aShape.ShapeType() == TopAbs_COMPOUND) {
689             int             aNbSub = 0;
690             TopoDS_Shape    aSubShape;
691             TopoDS_Iterator anIt (aShape, Standard_True, Standard_True);
692
693             for (; anIt.More(); anIt.Next()) {
694               aNbSub++;
695               aSubShape = anIt.Value();
696             }
697
698             if (aNbSub == 1) {
699               // Use the single sub-shape
700               aListResShapes.Append(aSubShape);
701             } else if (aNbSub > 1) {
702               // Use the shape
703               aListResShapes.Append(aShape);
704             }
705           } else {
706             // Use the shape itself
707             aListResShapes.Append(aShape);
708           }
709         }
710       }
711
712       // Construct result shape.
713       if (!aListResShapes.IsEmpty()) {
714         if (aListResShapes.Extent() == 1) {
715           // Use the single shape.
716           aResShape = aListResShapes.First();
717         } else {
718           // Make a compound of result shapes.
719           TopTools_ListIteratorOfListOfShape anIt(aListResShapes);
720
721           for (; anIt.More(); anIt.Next()) {
722             B.Add(compound, anIt.Value());
723           }
724
725           aResShape = compound;
726         }
727       }
728
729       if( aResShape.IsNull() ) {
730         StdFail_NotDone::Raise("Null result shape");
731         return 0;
732       }
733
734       // Check if any BRep entity has been read, there must be at least a vertex
735       if ( !TopExp_Explorer( aResShape, TopAbs_VERTEX ).More() )
736         StdFail_NotDone::Raise( "No geometrical data in the imported file." );
737
738       // Create assemblies in the shape, if they are not created yet.
739       TopTools_DataMapOfShapeShape aMapShapeAssembly;
740
741       if (isCreateAssemblies) {
742         aResShape = CreateAssemblies(aReader, aResShape, aMapShapeAssembly);
743       }
744
745       // BEGIN: Store names and materials of sub-shapes from file
746       TopTools_IndexedMapOfShape anIndices;
747       TopExp::MapShapes(aResShape, anIndices);
748
749       Handle(Interface_InterfaceModel) Model = aReader.WS()->Model();
750       Handle(XSControl_TransferReader) TR = aReader.WS()->TransferReader();
751       if (!TR.IsNull()) {
752         Handle(Transfer_TransientProcess) TP = TR->TransientProcess();
753
754         Standard_Integer nb = Model->NbEntities();
755
756         for (Standard_Integer ie = 1; ie <= nb; ie++) {
757           Handle(Standard_Transient) enti = Model->Value(ie);
758
759           // Store names.
760           StoreName(enti, anIndices, aReader.WS(),
761                     TP, aShapeLabel, aMapShapeAssembly);
762
763           // Store materials.
764           StoreMaterial(enti, anIndices, TP, aShapeLabel);
765         }
766       }
767       // END: Store names and materials
768     }
769     else {
770       switch (status) {
771         case IFSelect_RetVoid:
772           anError = "Nothing created or No data to process";
773           break;
774         case IFSelect_RetError:
775           anError = "Error in command or input data";
776           break;
777         case IFSelect_RetFail:
778           anError = "Execution was run, but has failed";
779           break;
780         case IFSelect_RetStop:
781           anError = "Execution has been stopped. Quite possible, an exception was raised";
782           break;
783         default:
784           break;
785       }
786       anError = "Wrong format of the imported file. Can't import file.";
787       aResShape.Nullify();
788     }
789   }
790   catch( Standard_Failure& aFail ) {
791     anError = aFail.GetMessageString();
792     aResShape.Nullify();
793   }
794
795   if( aResShape.IsNull() ) {
796     StdFail_NotDone::Raise( anError.ToCString() );
797     return 0;
798   }
799
800   aFunction->SetValue( aResShape );
801
802   log->SetTouched(Label());
803
804   return 1;
805 }
806
807 //================================================================================
808 /*!
809  * \brief Returns a name of creation operation and names and values of creation parameters
810  */
811 //================================================================================
812
813 bool STEPPlugin_ImportDriver::
814 GetCreationInformation( std::string&             theOperationName,
815                         std::vector<GEOM_Param>& theParams )
816 {
817   if( Label().IsNull() ) return 0;
818   Handle(GEOM_Function) function = GEOM_Function::GetFunction( Label() );
819
820   STEPPlugin_IImport aCI( function );
821   Standard_Integer aType = function->GetType();
822
823   theOperationName = "ImportSTEP";
824
825   switch ( aType ) {
826   case IMPORT_SHAPE:
827     AddParam( theParams, "File name", aCI.GetFileName() );
828     if( aCI.GetIsIgnoreUnits() )
829       AddParam( theParams, "Format", "STEP_SCALE" );
830     AddParam( theParams, "Create Assemblies", aCI.GetIsCreateAssemblies() );
831     break;
832   default:
833     return false;
834   }
835   return true;
836 }
837
838 TCollection_AsciiString
839 STEPPlugin_ImportDriver::GetValue( const TCollection_AsciiString& theFileName,
840                                    const TCollection_AsciiString& theParameterName,
841                                    TCollection_AsciiString&       theError )
842 {
843   TCollection_AsciiString aValue;
844
845   if (theParameterName != "LEN_UNITS") {
846     theError = theParameterName + " parameter reading is not supported by STEP plugin";
847     return TCollection_AsciiString();
848   }
849
850   // Set "C" numeric locale to save numbers correctly
851   Kernel_Utils::Localizer loc;
852
853   STEPControl_Reader aReader;
854
855   Interface_Static::SetCVal( "xstep.cascade.unit","M" );
856   Interface_Static::SetIVal( "read.step.ideas", 1 );
857   Interface_Static::SetIVal( "read.step.nonmanifold", 1 );
858
859   try {
860     OCC_CATCH_SIGNALS;
861     IFSelect_ReturnStatus status = aReader.ReadFile( theFileName.ToCString() );
862     if (status == IFSelect_RetDone) {
863       TColStd_SequenceOfAsciiString anUnitLengthNames;
864       TColStd_SequenceOfAsciiString anUnitAngleNames;
865       TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
866       aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
867       if (anUnitLengthNames.Length() > 0)
868         aValue = ToNamedUnit( anUnitLengthNames.First() );
869     }
870     else {
871       theError = theFileName + " reading failed";
872     }
873   }
874   catch( Standard_Failure& aFail ) {
875     theError = aFail.GetMessageString();
876   }
877   return aValue;
878 }
879
880 IMPLEMENT_STANDARD_RTTIEXT( STEPPlugin_ImportDriver, GEOM_BaseDriver )