Salome HOME
4dfae8672fad9e58e82e208ab9255230e52479db
[modules/hydro.git] / src / HYDROData / HYDROData_Obstacle.cxx
1
2 #include "HYDROData_Obstacle.h"
3
4 #include "HYDROData_Document.h"
5 #include "HYDROData_ShapesGroup.h"
6 #include "HYDROData_ShapesTool.h"
7 #include "HYDROData_Tool.h"
8
9 #include <Basics_Utils.hxx>
10
11 #include <BRepTools.hxx>
12 #include <BRep_Builder.hxx>
13
14 #include <GEOMBase.h>
15
16 #include <IGESControl_Reader.hxx>
17 #include <IGESData_IGESModel.hxx>
18
19 #include <STEPControl_Reader.hxx>
20
21 #include <Interface_Static.hxx>
22
23 #include <TopoDS.hxx>
24 #include <TopoDS_Iterator.hxx>
25 #include <TopoDS_Shape.hxx>
26 #include <TopoDS_Edge.hxx>
27
28 #include <TDataStd_AsciiString.hxx>
29 #include <TDataStd_RealArray.hxx>
30
31 #include <TColStd_SequenceOfAsciiString.hxx>
32
33 #include <TopExp_Explorer.hxx>
34
35 #include <QColor>
36 #include <QFile>
37 #include <QFileInfo>
38 #include <QStringList>
39
40 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic
41
42 #include <HYDROData_Projection.h>
43
44 IMPLEMENT_STANDARD_HANDLE(HYDROData_Obstacle,HYDROData_ArtificialObject)
45 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Obstacle,HYDROData_ArtificialObject)
46
47
48 HYDROData_Obstacle::HYDROData_Obstacle()
49 : HYDROData_ArtificialObject()
50 {
51 }
52
53 HYDROData_Obstacle::~HYDROData_Obstacle()
54 {
55 }
56
57 QStringList HYDROData_Obstacle::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
58 {
59   QStringList aResList = dumpObjectCreation( theTreatedObjects );
60   
61   QString anObstacleName = GetObjPyName();
62
63   TCollection_AsciiString aGeomObjectEntry = GetGeomObjectEntry();
64   QString aFilePath = GetFilePath();
65
66   if ( !aGeomObjectEntry.IsEmpty() )
67   {
68     QString aSalomeObjName = HYDROData_Tool::GenerateNameForPython( theTreatedObjects, "obstacle_sobj" );
69     aResList << QString( "%1 = theStudy.FindObjectID( \"%2\" );" )
70                 .arg( aSalomeObjName ).arg( aGeomObjectEntry.ToCString() );
71
72     aResList << QString( "%1.ImportFromGeomIOR( %2.GetIOR() );" )
73                 .arg( anObstacleName ).arg( aSalomeObjName );
74
75     aResList << QString( "%1.SetGeomObjectEntry( \"%2\" );" )
76                 .arg( anObstacleName ).arg( aGeomObjectEntry.ToCString() );
77     aResList << QString( "" );
78   }
79   else if ( !aFilePath.isEmpty() )
80   {
81     aResList << QString( "%1.ImportFromFile( \"%2\" );" )
82                 .arg( anObstacleName ).arg( aFilePath );
83     aResList << QString( "" );
84   }
85
86   // Write the translation points
87   double aDx, aDy, aDz;
88   if ( getTranslation( aDx, aDy, aDz ) )
89   {
90     aResList << QString( "%1.Translate( %2, %3, %4 );" )
91                 .arg( anObstacleName ).arg( aDx ).arg( aDy ).arg( aDz );
92     aResList << QString( "" );
93   }
94
95   aResList << QString( "%1.Update();" ).arg( anObstacleName );
96   aResList << QString( "" );
97
98   return aResList;
99 }
100
101 void HYDROData_Obstacle::Update()
102 {
103   removeGroupObjects();
104   createGroupObjects();
105   checkAndSetAltitudeObject();
106
107   HYDROData_Entity::Update();
108 }
109
110 bool HYDROData_Obstacle::IsHas2dPrs() const
111 {
112   return true;
113 }
114
115 TopoDS_Shape HYDROData_Obstacle::GetTopShape() const
116 {
117   return getTopShape();
118 }
119
120 TopoDS_Shape HYDROData_Obstacle::GetShape3D() const
121 {
122   return getShape3D();
123 }
124
125 void HYDROData_Obstacle::SetShape3D( const TopoDS_Shape& theShape )
126 {
127   TopoDS_Face aShape2d = HYDROData_Projection::MakeProjection( theShape );
128   HYDROData_ArtificialObject::SetShape3D( theShape );
129   HYDROData_ArtificialObject::SetTopShape( aShape2d );
130 }
131
132 QColor HYDROData_Obstacle::DefaultFillingColor()
133 {
134   return QColor( Qt::yellow );
135 }
136
137 QColor HYDROData_Obstacle::DefaultBorderColor()
138 {
139   return QColor( Qt::transparent );
140 }
141
142 bool HYDROData_Obstacle::ImportFromFile( const QString& theFilePath )
143 {
144   // Check the file existence
145   QFileInfo aFileInfo( theFilePath );
146   if ( !aFileInfo.exists() ) {
147     return false;
148   }
149
150   bool aRes = false;
151   TopoDS_Shape aShape;
152
153   // Import file
154   QString aFileSuf = aFileInfo.suffix().toLower();
155   if ( aFileSuf == "brep" ) {
156     aShape = ImportBREP( theFilePath );
157   } else if ( aFileSuf == "iges" || aFileSuf == "igs" ) {
158     aShape = ImportIGES( theFilePath );
159   } else if ( aFileSuf == "step" ) {
160     aShape = ImportSTEP( theFilePath );
161   }
162  
163   // Check the result shape
164   aRes = !aShape.IsNull();
165
166   // Set shape to the obstacle in case of success
167   if ( aRes ) {
168     SetShape3D( aShape );
169     SetFilePath( theFilePath );
170   }
171
172   return aRes;
173 }
174
175 void HYDROData_Obstacle::SetFilePath( const QString& theFilePath )
176 {
177   TCollection_AsciiString anAsciiStr( theFilePath.toStdString().c_str() );
178   TDataStd_AsciiString::Set( myLab.FindChild( DataTag_FilePath ), anAsciiStr );
179 }
180
181 QString HYDROData_Obstacle::GetFilePath() const
182 {
183   QString aRes;
184
185   TDF_Label aLabel = myLab.FindChild( DataTag_FilePath, false );
186   if ( !aLabel.IsNull() )
187   {
188     Handle(TDataStd_AsciiString) anAsciiStr;
189     if ( aLabel.FindAttribute( TDataStd_AsciiString::GetID(), anAsciiStr ) )
190       aRes = QString( anAsciiStr->Get().ToCString() );
191   }
192
193   return aRes;
194 }
195
196 bool HYDROData_Obstacle::ImportFromGeomIOR( const TCollection_AsciiString& theIOR )
197 {
198   if ( theIOR.IsEmpty() )
199     return false;
200
201   TopoDS_Shape aShape = GEOMBase::GetShapeFromIOR( theIOR.ToCString() );
202   if ( aShape.IsNull() )
203     return false;
204
205   SetShape3D( aShape );
206   
207   return true;
208 }
209
210 void HYDROData_Obstacle::SetGeomObjectEntry( const TCollection_AsciiString& theEntry )
211 {
212   TDataStd_AsciiString::Set( myLab.FindChild( DataTag_GeomObjectEntry ), theEntry );
213 }
214
215 TCollection_AsciiString HYDROData_Obstacle::GetGeomObjectEntry() const
216 {
217   TCollection_AsciiString aRes;
218
219   TDF_Label aLabel = myLab.FindChild( DataTag_GeomObjectEntry, false );
220   if ( !aLabel.IsNull() )
221   {
222     Handle(TDataStd_AsciiString) anAsciiStr;
223     if ( aLabel.FindAttribute( TDataStd_AsciiString::GetID(), anAsciiStr ) )
224       aRes = anAsciiStr->Get();
225   }
226
227   return aRes;
228 }
229
230 void HYDROData_Obstacle::Translate( const double theDx,
231                                     const double theDy,
232                                     const double theDz )
233 {
234   TopoDS_Shape aShape3D = GetShape3D();
235   
236   TopoDS_Shape aTranslatedShape3D = HYDROData_ShapesTool::Translated( aShape3D, theDx, theDy, theDz );
237   if ( aTranslatedShape3D.IsNull() )
238     return;
239
240   SetShape3D( aTranslatedShape3D );
241
242   setTranslation( theDx, theDy, theDz );
243 }
244
245 TopoDS_Shape HYDROData_Obstacle::ImportBREP( const QString& theFilePath ) const
246 {
247   TopoDS_Shape aResShape;
248
249   BRep_Builder aBrepBuilder;
250   BRepTools::Read( aResShape, qPrintable(theFilePath), aBrepBuilder );
251
252   return aResShape;
253 }
254
255 TopoDS_Shape HYDROData_Obstacle::ImportIGES( const QString& theFilePath ) const
256 {
257   TopoDS_Shape aResShape;
258
259   // Set "C" numeric locale to save numbers correctly
260   Kernel_Utils::Localizer loc;
261
262   IGESControl_Reader aReader;
263
264   Interface_Static::SetCVal("xstep.cascade.unit","M");
265
266   try {
267     OCC_CATCH_SIGNALS;
268
269     IFSelect_ReturnStatus status = aReader.ReadFile(qPrintable(theFilePath));
270
271     if (status == IFSelect_RetDone) {
272       // Rescale units
273       Handle(IGESData_IGESModel) aModel =
274         Handle(IGESData_IGESModel)::DownCast(aReader.Model());
275       if (!aModel.IsNull()) {
276         IGESData_GlobalSection aGS = aModel->GlobalSection();
277         aGS.SetUnitFlag(6);
278         aModel->SetGlobalSection(aGS);
279       }
280     
281       aReader.ClearShapes();
282       aReader.TransferRoots();
283
284       aResShape = aReader.OneShape();
285     } 
286     else {
287       aResShape.Nullify();
288     }
289   }
290   catch(Standard_Failure) {
291     aResShape.Nullify();
292   }
293
294   return aResShape;
295 }
296
297 TopoDS_Shape HYDROData_Obstacle::ImportSTEP( const QString& theFilePath ) const
298 {
299   TopoDS_Shape aResShape;
300
301   // Set "C" numeric locale to save numbers correctly
302   Kernel_Utils::Localizer loc;
303
304   STEPControl_Reader aReader;
305
306   // Convert to METERS
307   Interface_Static::SetCVal("xstep.cascade.unit","M");
308   Interface_Static::SetIVal("read.step.ideas", 1);
309   Interface_Static::SetIVal("read.step.nonmanifold", 1);
310
311   BRep_Builder B;
312   TopoDS_Compound compound;
313   B.MakeCompound(compound);
314
315   try {
316     OCC_CATCH_SIGNALS;
317
318     IFSelect_ReturnStatus status = aReader.ReadFile( qPrintable(theFilePath) );
319
320     if (status == IFSelect_RetDone) {
321       // Rescale units
322       // set UnitFlag to units from file
323       TColStd_SequenceOfAsciiString anUnitLengthNames;
324       TColStd_SequenceOfAsciiString anUnitAngleNames;
325       TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
326       aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
327       if (anUnitLengthNames.Length() > 0) {
328         TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
329         if (aLenUnits == "millimetre")
330           Interface_Static::SetCVal("xstep.cascade.unit", "MM");
331         else if (aLenUnits == "centimetre")
332           Interface_Static::SetCVal("xstep.cascade.unit", "CM");
333         else if (aLenUnits == "metre" || aLenUnits.IsEmpty())
334           Interface_Static::SetCVal("xstep.cascade.unit", "M");
335         else if (aLenUnits == "INCH")
336           Interface_Static::SetCVal("xstep.cascade.unit", "INCH");
337         else {
338           // The file contains not supported units
339           return aResShape;
340         }
341       }
342         
343       Standard_Boolean failsonly = Standard_False;
344       aReader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity);
345
346       // Root transfers
347       Standard_Integer nbr = aReader.NbRootsForTransfer();
348       aReader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity);
349
350       for (Standard_Integer n = 1; n <= nbr; n++) {
351         Standard_Boolean ok = aReader.TransferRoot(n);
352         // Collecting resulting entities
353         Standard_Integer nbs = aReader.NbShapes();
354         if (!ok || nbs == 0) {
355           continue; // skip empty root
356         } 
357         else if (nbr == 1 && nbs == 1) { // For a single entity
358           aResShape = aReader.Shape(1);
359           // ATTENTION: this is a workaround for mantis issue 0020442 remark 0010776
360           // It should be removed after patching OCCT for bug OCC22436
361           // (fix for OCCT is expected in service pack next to OCCT6.3sp12)
362           if (aResShape.ShapeType() == TopAbs_COMPOUND) {
363             int nbSub1 = 0;
364             TopoDS_Shape currShape;
365             TopoDS_Iterator It (aResShape, Standard_True, Standard_True);
366             for (; It.More(); It.Next()) {
367               nbSub1++;
368               currShape = It.Value();
369             }
370             if (nbSub1 == 1)
371               aResShape = currShape;
372           }
373           // END workaround
374           break;
375         }
376
377         for (Standard_Integer i = 1; i <= nbs; i++) {
378           TopoDS_Shape aShape = aReader.Shape(i);
379           if (aShape.IsNull()) {
380             continue;
381           }
382           else {
383             B.Add(compound, aShape);
384           }
385         }
386       }
387   
388       if (aResShape.IsNull())
389         aResShape = compound;
390
391       // Check if any BRep entity has been read, there must be at least a vertex
392       if ( !TopExp_Explorer( aResShape, TopAbs_VERTEX ).More() ) {
393         // No geometrical data in the imported file
394         return TopoDS_Shape();
395       }
396     }
397     else {
398       aResShape.Nullify();
399     }
400   }
401   catch (Standard_Failure) {
402     aResShape.Nullify();
403   }
404
405   return aResShape;
406 }
407
408 QColor HYDROData_Obstacle::getDefaultFillingColor() const
409 {
410   return DefaultFillingColor();
411 }
412
413 QColor HYDROData_Obstacle::getDefaultBorderColor() const
414 {
415   return DefaultBorderColor();
416 }
417
418 ObjectKind HYDROData_Obstacle::getAltitudeObjectType() const
419 {
420   return KIND_OBSTACLE_ALTITUDE;
421 }
422
423 void HYDROData_Obstacle::createGroupObjects()
424 {
425   TopoDS_Shape anObstacleShape = GetTopShape();
426   if ( !anObstacleShape.IsNull() )
427   {
428     TopTools_SequenceOfShape aWireEdges;
429     HYDROData_ShapesTool::ExploreShapeToShapes( anObstacleShape, TopAbs_EDGE, aWireEdges );
430     if ( !aWireEdges.IsEmpty() )
431     {
432       QString aWireGroupName = GetName() + "_Outer_Wire";
433
434       Handle(HYDROData_ShapesGroup) anExtWireGroup = createGroupObject();
435       anExtWireGroup->SetName( aWireGroupName );
436      
437       anExtWireGroup->SetShapes( aWireEdges );
438     }
439   }
440 }
441
442 void HYDROData_Obstacle::setTranslation( const double theDx, 
443                                          const double theDy, 
444                                          const double theDz )
445 {
446   TDF_Label aLabel = myLab.FindChild( DataTag_Translation );
447
448   double aCurDx = theDx;
449   double aCurDy = theDy;
450   double aCurDz = theDz;
451
452   double aPrevDx, aPrevDy, aPrevDz;
453   if ( getTranslation( aPrevDx, aPrevDy, aPrevDz ) )
454   {
455     aCurDx += aPrevDx;
456     aCurDy += aPrevDy;
457     aCurDz += aPrevDz;
458   }
459   
460   Handle(TDataStd_RealArray) aCoeffsArray = TDataStd_RealArray::Set( aLabel, 1, 3 );
461   aCoeffsArray->SetValue( 1, aCurDx );
462   aCoeffsArray->SetValue( 2, aCurDy );
463   aCoeffsArray->SetValue( 3, aCurDz );
464 }
465
466 bool HYDROData_Obstacle::getTranslation( double& theDx, double& theDy, double& theDz ) const
467 {
468   theDx = theDy = theDz = 0.0;
469
470   TDF_Label aLabel = myLab.FindChild( DataTag_Translation, false );
471   if ( aLabel.IsNull() )
472     return false;
473
474   Handle(TDataStd_RealArray) aCoeffsArray;
475   if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), aCoeffsArray ) )
476     return false;
477
478   theDx = aCoeffsArray->Value( 1 );
479   theDy = aCoeffsArray->Value( 2 );
480   theDz = aCoeffsArray->Value( 3 );
481
482   return true;
483 }
484