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