]> SALOME platform Git repositories - modules/geom.git/blob - src/STEPPlugin/STEPPlugin_ImportDriver.cxx
Salome HOME
Fix regression of SALOME_TESTS/Grids/geom/import_export_STEP_00/A2
[modules/geom.git] / src / STEPPlugin / STEPPlugin_ImportDriver.cxx
1 // Copyright (C) 2014  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_ProductDefinitionShape.hxx>
51 #include <StepRepr_PropertyDefinitionRepresentation.hxx>
52 #include <StepRepr_Representation.hxx>
53 #include <TransferBRep.hxx>
54 #include <Transfer_TransientProcess.hxx>
55 #include <XSControl_TransferReader.hxx>
56 #include <XSControl_WorkSession.hxx>
57 #include <BRep_Builder.hxx>
58 #include <TopExp.hxx>
59 #include <TopExp_Explorer.hxx>
60 #include <TopTools_IndexedMapOfShape.hxx>
61 #include <TopoDS_Compound.hxx>
62 #include <TopoDS_Iterator.hxx>
63 #include <TColStd_SequenceOfAsciiString.hxx>
64
65 #include <StdFail_NotDone.hxx>
66 #include <Standard_Failure.hxx>
67 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
68
69 //=============================================================================
70 /*!
71  *  GetShape()
72  */
73 //=============================================================================
74
75 TopoDS_Shape GetShape(const Handle(Standard_Transient)        &theEnti,
76                       const Handle(Transfer_TransientProcess) &theTP)
77 {
78   TopoDS_Shape            aResult;
79   Handle(Transfer_Binder) aBinder = theTP->Find(theEnti);
80
81   if (aBinder.IsNull()) {
82     return aResult;
83   }
84
85   aResult = TransferBRep::ShapeResult(aBinder);
86
87   return aResult;
88 }
89
90 //=============================================================================
91 /*!
92  *  GetLabel()
93  */
94 //=============================================================================
95
96 TDF_Label GetLabel(const Handle(Standard_Transient) &theEnti,
97                    const TDF_Label                  &theShapeLabel,
98                    const TopoDS_Shape               &aShape)
99 {
100   TDF_Label aResult;
101
102   if (theEnti->IsKind
103             (STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
104     // check all named shapes using iterator
105     TDF_ChildIDIterator anIt
106       (theShapeLabel, TDataStd_Name::GetID(), Standard_True);
107
108     for (; anIt.More(); anIt.Next()) {
109       Handle(TDataStd_Name) nameAttr =
110         Handle(TDataStd_Name)::DownCast(anIt.Value());
111
112       if (nameAttr.IsNull()) {
113         continue;
114       }
115
116       TDF_Label aLab = nameAttr->Label();
117       Handle(TNaming_NamedShape) shAttr;
118
119       if (aLab.FindAttribute(TNaming_NamedShape::GetID(), shAttr) &&
120           shAttr->Get().IsEqual(aShape)) {
121         aResult = aLab;
122       }
123     }
124   }
125
126   // create label and set shape
127   if (aResult.IsNull()) {
128     TDF_TagSource aTag;
129
130     aResult = aTag.NewChild(theShapeLabel);
131
132     TNaming_Builder tnBuild (aResult);
133
134     tnBuild.Generated(aShape);
135   }
136
137   return aResult;
138 }
139
140 //=============================================================================
141 /*!
142  *  StoreName()
143  */
144 //=============================================================================
145
146 void StoreName( const Handle(Standard_Transient)        &theEnti,
147                 const TopTools_IndexedMapOfShape        &theIndices,
148                 const Handle(Transfer_TransientProcess) &theTP,
149                 const TDF_Label                         &theShapeLabel)
150 {
151   Handle(TCollection_HAsciiString) aName;
152
153   if (theEnti->IsKind(STANDARD_TYPE(StepShape_TopologicalRepresentationItem)) ||
154       theEnti->IsKind(STANDARD_TYPE(StepGeom_GeometricRepresentationItem))) {
155     aName = Handle(StepRepr_RepresentationItem)::DownCast(theEnti)->Name();
156   } else {
157     Handle(StepBasic_ProductDefinition) PD =
158       Handle(StepBasic_ProductDefinition)::DownCast(theEnti);
159
160     if (PD.IsNull() == Standard_False) {
161       Handle(StepBasic_Product) Prod = PD->Formation()->OfProduct();
162       aName = Prod->Name();
163     }
164   }
165
166   bool isValidName = false;
167
168   if (aName.IsNull() == Standard_False) {
169     isValidName = true;
170
171     if (aName->UsefullLength() < 1) {
172       isValidName = false;
173     } else if (aName->UsefullLength() == 4 &&
174                toupper (aName->Value(1)) == 'N' &&
175                toupper (aName->Value(2)) == 'O' &&
176                toupper (aName->Value(3)) == 'N' &&
177                toupper (aName->Value(4)) == 'E') {
178       // skip 'N0NE' name
179       isValidName = false;
180     } else {
181       // special check to pass names like "Open CASCADE STEP translator 6.3 1"
182       TCollection_AsciiString aSkipName ("Open CASCADE STEP translator");
183
184       if (aName->Length() >= aSkipName.Length()) {
185         if (aName->String().SubString
186                             (1, aSkipName.Length()).IsEqual(aSkipName)) {
187           isValidName = false;
188         }
189       }
190     }
191   }
192
193   if (isValidName) {
194     TCollection_ExtendedString aNameExt (aName->ToCString());
195
196     // find target shape
197     TopoDS_Shape S = GetShape(theEnti, theTP);
198
199     if (S.IsNull()) {
200       return;
201     }
202
203     // as PRODUCT can be included in the main shape
204     // several times, we look here for all iclusions.
205     Standard_Integer isub, nbSubs = theIndices.Extent();
206
207     for (isub = 1; isub <= nbSubs; isub++) {
208       TopoDS_Shape aSub = theIndices.FindKey(isub);
209
210       if (aSub.IsPartner(S)) {
211         TDF_Label L = GetLabel(theEnti, theShapeLabel, aSub);
212
213         // set a name
214         TDataStd_Name::Set(L, aNameExt);
215       }
216     }
217   }
218 }
219
220 //=============================================================================
221 /*!
222  *  StoreMaterial()
223  */
224 //=============================================================================
225
226 void StoreMaterial( const Handle(Standard_Transient)        &theEnti,
227                     const TopTools_IndexedMapOfShape        &theIndices,
228                     const Handle(Transfer_TransientProcess) &theTP,
229                     const TDF_Label                         &theShapeLabel )
230 {
231   // Treat Product Definition Shape only.
232   Handle(StepRepr_ProductDefinitionShape) aPDS =
233       Handle(StepRepr_ProductDefinitionShape)::DownCast(theEnti);
234   Handle(StepBasic_ProductDefinition)     aProdDef;
235
236   if(aPDS.IsNull() == Standard_False) {
237     // Product Definition Shape ==> Product Definition
238     aProdDef = aPDS->Definition().ProductDefinition();
239   }
240
241   if (aProdDef.IsNull() == Standard_False) {
242     // Product Definition ==> Property Definition
243     const Interface_Graph    &aGraph = theTP->Graph();
244     Interface_EntityIterator  aSubs  = aGraph.Sharings(aProdDef);
245     TopoDS_Shape              aShape;
246
247     for(aSubs.Start(); aSubs.More(); aSubs.Next()) {
248       Handle(StepRepr_PropertyDefinition) aPropD =
249         Handle(StepRepr_PropertyDefinition)::DownCast(aSubs.Value());
250
251       if(aPropD.IsNull() == Standard_False) {
252         // Property Definition ==> Representation.
253         Interface_EntityIterator aSubs1 = aGraph.Sharings(aPropD);
254
255         for(aSubs1.Start(); aSubs1.More(); aSubs1.Next()) {
256           Handle(StepRepr_PropertyDefinitionRepresentation) aPDR =
257             Handle(StepRepr_PropertyDefinitionRepresentation)::
258               DownCast(aSubs1.Value());
259
260           if(aPDR.IsNull() == Standard_False) {
261             // Property Definition ==> Material Name.
262             Handle(StepRepr_Representation) aRepr = aPDR->UsedRepresentation();
263
264             if(aRepr.IsNull() == Standard_False) {
265               Standard_Integer ir;
266
267               for(ir = 1; ir <= aRepr->NbItems(); ir++) {
268                 Handle(StepRepr_RepresentationItem) aRI = aRepr->ItemsValue(ir);
269                 Handle(StepRepr_DescriptiveRepresentationItem) aDRI =
270                   Handle(StepRepr_DescriptiveRepresentationItem)::DownCast(aRI);
271
272                 if(aDRI.IsNull() == Standard_False) {
273                   // Get shape from Product Definition
274                   Handle(TCollection_HAsciiString) aMatName = aDRI->Name();
275
276                   if(aMatName.IsNull() == Standard_False) {
277                     TCollection_ExtendedString
278                                  aMatNameExt (aMatName->ToCString());
279
280                     if (aShape.IsNull()) {
281                       // Get the shape.
282                       aShape = GetShape(aProdDef, theTP);
283
284                       if (aShape.IsNull()) {
285                         return;
286                       }
287                     }
288
289                     // as PRODUCT can be included in the main shape
290                     // several times, we look here for all iclusions.
291                     Standard_Integer isub, nbSubs = theIndices.Extent();
292
293                     for (isub = 1; isub <= nbSubs; isub++) {
294                       TopoDS_Shape aSub = theIndices.FindKey(isub);
295
296                       if (aSub.IsPartner(aShape)) {
297                         TDF_Label aLabel =
298                           GetLabel(aProdDef, theShapeLabel, aSub);
299
300                         // set a name
301                         TDataStd_Comment::Set(aLabel, aMatNameExt);
302                       }
303                     }
304                   }
305                 }
306               }
307             }
308           }
309         }
310       }
311     }
312   }
313 }
314
315 //=======================================================================
316 //function : GetID
317 //purpose  :
318 //=======================================================================
319 const Standard_GUID& STEPPlugin_ImportDriver::GetID()
320 {
321   static Standard_GUID aGUID("a25f88df-461b-45c0-ab6b-a82101fe6ce7");
322   return aGUID;
323 }
324
325 //=======================================================================
326 //function : STEPPlugin_ImportDriver
327 //purpose  :
328 //=======================================================================
329 STEPPlugin_ImportDriver::STEPPlugin_ImportDriver()
330 {
331 }
332
333 //=======================================================================
334 //function : Execute
335 //purpose  :
336 //=======================================================================
337 Standard_Integer STEPPlugin_ImportDriver::Execute( TFunction_Logbook& log ) const
338 {
339   if( Label().IsNull() ) return 0;
340   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction( Label() );
341
342   STEPPlugin_IImport aData( aFunction );
343
344   TCollection_AsciiString aFileName = aData.GetFileName().ToCString();
345   bool anIsIgnoreUnits = aData.GetIsIgnoreUnits();
346   TDF_Label aShapeLabel = aFunction->GetNamingEntry();
347
348   MESSAGE("Import STEP from file " << aFileName.ToCString() );
349
350   TopoDS_Shape aResShape;
351   TCollection_AsciiString anError;
352
353   // Set "C" numeric locale to save numbers correctly
354   Kernel_Utils::Localizer loc;
355
356   STEPControl_Reader aReader;
357
358   //VSR: 16/09/09: Convert to METERS
359   Interface_Static::SetCVal("xstep.cascade.unit","M");
360   Interface_Static::SetIVal("read.step.ideas", 1);
361   Interface_Static::SetIVal("read.step.nonmanifold", 1);
362
363   BRep_Builder B;
364   TopoDS_Compound compound;
365   B.MakeCompound(compound);
366
367   try
368   {
369     OCC_CATCH_SIGNALS;
370     IFSelect_ReturnStatus status = aReader.ReadFile(aFileName.ToCString());
371     if (status == IFSelect_RetDone) {
372       // Regard or not the model units
373       if( anIsIgnoreUnits ) {
374         // set UnitFlag to units from file
375         TColStd_SequenceOfAsciiString anUnitLengthNames;
376         TColStd_SequenceOfAsciiString anUnitAngleNames;
377         TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
378         aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
379         if (anUnitLengthNames.Length() > 0) {
380           TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
381           if (aLenUnits == "millimetre")
382             Interface_Static::SetCVal("xstep.cascade.unit", "MM");
383           else if (aLenUnits == "centimetre")
384             Interface_Static::SetCVal("xstep.cascade.unit", "CM");
385           else if (aLenUnits == "metre" || aLenUnits.IsEmpty())
386             Interface_Static::SetCVal("xstep.cascade.unit", "M");
387           else if (aLenUnits == "INCH")
388             Interface_Static::SetCVal("xstep.cascade.unit", "INCH");
389           else {
390             anError = "The file contains not supported units.";
391           }
392           // TODO (for other units than mm, cm, m or inch)
393           // else if (aLenUnits == "")
394           // Interface_Static::SetCVal("xstep.cascade.unit", "???");
395         }
396       }
397       else {
398         // Need re-scale a model (set UnitFlag to 'meter')
399         Interface_Static::SetCVal("xstep.cascade.unit","M");
400       }
401
402       Standard_Boolean failsonly = Standard_False;
403       aReader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity);
404
405       // Root transfers
406       Standard_Integer nbr = aReader.NbRootsForTransfer();
407       aReader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity);
408
409       for (Standard_Integer n = 1; n <= nbr; n++) {
410         Standard_Boolean ok = aReader.TransferRoot(n);
411         // Collecting resulting entities
412         Standard_Integer nbs = aReader.NbShapes();
413         if (!ok || nbs == 0)
414           continue; // skip empty root
415
416         // For a single entity
417         else if (nbr == 1 && nbs == 1) {
418           aResShape = aReader.Shape(1);
419           if (aResShape.ShapeType() == TopAbs_COMPOUND) {
420             int nbSub1 = 0;
421             TopoDS_Shape currShape;
422             TopoDS_Iterator It (aResShape, Standard_True, Standard_True);
423             for (; It.More(); It.Next()) {
424               nbSub1++;
425               currShape = It.Value();
426             }
427             if (nbSub1 == 1)
428               aResShape = currShape;
429           }
430           break;
431         }
432
433         for (Standard_Integer i = 1; i <= nbs; i++) {
434           TopoDS_Shape aShape = aReader.Shape(i);
435           if (aShape.IsNull())
436             continue;
437           else
438             B.Add(compound, aShape);
439         }
440       }
441       if( aResShape.IsNull() )
442         aResShape = compound;
443
444       // Check if any BRep entity has been read, there must be at least a vertex
445       if ( !TopExp_Explorer( aResShape, TopAbs_VERTEX ).More() )
446         StdFail_NotDone::Raise( "No geometrical data in the imported file." );
447
448       // BEGIN: Store names and materials of sub-shapes from file
449       TopTools_IndexedMapOfShape anIndices;
450       TopExp::MapShapes(aResShape, anIndices);
451
452       Handle(Interface_InterfaceModel) Model = aReader.WS()->Model();
453       Handle(XSControl_TransferReader) TR = aReader.WS()->TransferReader();
454       if (!TR.IsNull()) {
455         Handle(Transfer_TransientProcess) TP = TR->TransientProcess();
456
457         Standard_Integer nb = Model->NbEntities();
458
459         for (Standard_Integer ie = 1; ie <= nb; ie++) {
460           Handle(Standard_Transient) enti = Model->Value(ie);
461
462           // Store names.
463           StoreName(enti, anIndices, TP, aShapeLabel);
464
465           // Store materials.
466           StoreMaterial(enti, anIndices, TP, aShapeLabel);
467         }
468       }
469       // END: Store names and materials
470     }
471     else {
472       switch (status) {
473         case IFSelect_RetVoid:
474           anError = "Nothing created or No data to process";
475           break;
476         case IFSelect_RetError:
477           anError = "Error in command or input data";
478           break;
479         case IFSelect_RetFail:
480           anError = "Execution was run, but has failed";
481           break;
482         case IFSelect_RetStop:
483           anError = "Execution has been stopped. Quite possible, an exception was raised";
484           break;
485         default:
486           break;
487       }
488       anError = "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     anError = aFail->GetMessageString();
495     aResShape.Nullify();
496   }
497
498   if( aResShape.IsNull() ) {
499     StdFail_NotDone::Raise( anError.ToCString() );
500     return 0;
501   }
502
503   aFunction->SetValue( aResShape );
504
505   log.SetTouched( Label() );
506
507   return 1;
508 }
509
510 //=======================================================================
511 //function : MustExecute
512 //purpose  :
513 //=======================================================================
514 Standard_Boolean STEPPlugin_ImportDriver::MustExecute( const TFunction_Logbook& ) const
515 {
516   return Standard_True;
517 }
518
519 //================================================================================
520 /*!
521  * \brief Returns a name of creation operation and names and values of creation parameters
522  */
523 //================================================================================
524
525 bool STEPPlugin_ImportDriver::
526 GetCreationInformation( std::string&             theOperationName,
527                         std::vector<GEOM_Param>& theParams )
528 {
529   if( Label().IsNull() ) return 0;
530   Handle(GEOM_Function) function = GEOM_Function::GetFunction( Label() );
531
532   STEPPlugin_IImport aCI( function );
533   Standard_Integer aType = function->GetType();
534
535   theOperationName = "ImportSTEP";
536
537   switch ( aType ) {
538   case IMPORT_SHAPE:
539     AddParam( theParams, "File name", aCI.GetFileName() );
540     if( aCI.GetIsIgnoreUnits() )
541       AddParam( theParams, "Format", "STEP_SCALE" );
542     break;
543   default:
544     return false;
545   }
546   return true;
547 }
548
549 TCollection_AsciiString
550 STEPPlugin_ImportDriver::GetValue( const TCollection_AsciiString& theFileName,
551                                      const TCollection_AsciiString& theParameterName,
552                                      TCollection_AsciiString&       theError )
553 {
554   Handle(TCollection_HAsciiString) aValue;
555
556   if (theParameterName != "LEN_UNITS") {
557     theError = theParameterName + " parameter reading is not supported by STEP plugin";
558     return TCollection_AsciiString();
559   }
560
561   // Set "C" numeric locale to save numbers correctly
562   Kernel_Utils::Localizer loc;
563
564   STEPControl_Reader aReader;
565
566   Interface_Static::SetCVal( "xstep.cascade.unit","M" );
567   Interface_Static::SetIVal( "read.step.ideas", 1 );
568   Interface_Static::SetIVal( "read.step.nonmanifold", 1 );
569
570   try {
571     OCC_CATCH_SIGNALS;
572     IFSelect_ReturnStatus status = aReader.ReadFile( theFileName.ToCString() );
573     if (status == IFSelect_RetDone) {
574       TColStd_SequenceOfAsciiString anUnitLengthNames;
575       TColStd_SequenceOfAsciiString anUnitAngleNames;
576       TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
577       aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
578       if (anUnitLengthNames.Length() > 0) {
579         aValue = new TCollection_HAsciiString( anUnitLengthNames.First() );
580         /*
581         TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
582         if (aLenUnits == "millimetre")
583           aValue = new TCollection_HAsciiString ("MM");
584         else if (aLenUnits == "centimetre")
585           aValue = new TCollection_HAsciiString ("CM");
586         else if (aLenUnits == "metre")
587           aValue = new TCollection_HAsciiString ("M");
588         else if (aLenUnits == "INCH")
589           aValue = new TCollection_HAsciiString ("INCH");
590         // TODO (for other units than mm, cm, m or inch)
591         //else if (aLenUnits == "")
592         //  aValue = new TCollection_HAsciiString ("");
593         */
594       }
595     }
596     else {
597       theError = theFileName + " reading failed";
598     }
599   }
600   catch( Standard_Failure ) {
601     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
602     theError = aFail->GetMessageString();
603   }
604   if (!aValue.IsNull())
605     return aValue->String();
606   else
607     return TCollection_AsciiString();
608 }
609
610
611 IMPLEMENT_STANDARD_HANDLE( STEPPlugin_ImportDriver, GEOM_BaseDriver );
612 IMPLEMENT_STANDARD_RTTIEXT( STEPPlugin_ImportDriver, GEOM_BaseDriver );