Salome HOME
Translation of obstacle (Bug #341).
[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 = salome.myStudy.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 TopoDS_Shape HYDROData_Obstacle::GetTopShape() const
111 {
112   return getTopShape();
113 }
114
115 TopoDS_Shape HYDROData_Obstacle::GetShape3D() const
116 {
117   return getShape3D();
118 }
119
120 void HYDROData_Obstacle::SetShape3D( const TopoDS_Shape& theShape )
121 {
122   TopoDS_Face aShape2d = HYDROData_Projection::MakeProjection( theShape );
123   HYDROData_ArtificialObject::SetShape3D( theShape );
124   HYDROData_ArtificialObject::SetTopShape( aShape2d );
125 }
126
127 QColor HYDROData_Obstacle::DefaultFillingColor()
128 {
129   return QColor( Qt::yellow );
130 }
131
132 QColor HYDROData_Obstacle::DefaultBorderColor()
133 {
134   return QColor( Qt::transparent );
135 }
136
137 bool HYDROData_Obstacle::ImportFromFile( const QString& theFilePath )
138 {
139   // Check the file existence
140   QFileInfo aFileInfo( theFilePath );
141   if ( !aFileInfo.exists() ) {
142     return false;
143   }
144
145   bool aRes = false;
146   TopoDS_Shape aShape;
147
148   // Import file
149   QString aFileSuf = aFileInfo.suffix().toLower();
150   if ( aFileSuf == "brep" ) {
151     aShape = ImportBREP( theFilePath );
152   } else if ( aFileSuf == "iges" || aFileSuf == "igs" ) {
153     aShape = ImportIGES( theFilePath );
154   } else if ( aFileSuf == "step" ) {
155     aShape = ImportSTEP( theFilePath );
156   }
157  
158   // Check the result shape
159   aRes = !aShape.IsNull();
160
161   // Set shape to the obstacle in case of success
162   if ( aRes ) {
163     SetShape3D( aShape );
164     SetFilePath( theFilePath );
165   }
166
167   return aRes;
168 }
169
170 void HYDROData_Obstacle::SetFilePath( const QString& theFilePath )
171 {
172   TCollection_AsciiString anAsciiStr( theFilePath.toStdString().c_str() );
173   TDataStd_AsciiString::Set( myLab.FindChild( DataTag_FilePath ), anAsciiStr );
174 }
175
176 QString HYDROData_Obstacle::GetFilePath() const
177 {
178   QString aRes;
179
180   TDF_Label aLabel = myLab.FindChild( DataTag_FilePath, false );
181   if ( !aLabel.IsNull() )
182   {
183     Handle(TDataStd_AsciiString) anAsciiStr;
184     if ( aLabel.FindAttribute( TDataStd_AsciiString::GetID(), anAsciiStr ) )
185       aRes = QString( anAsciiStr->Get().ToCString() );
186   }
187
188   return aRes;
189 }
190
191 bool HYDROData_Obstacle::ImportFromGeomIOR( const TCollection_AsciiString& theIOR )
192 {
193   if ( theIOR.IsEmpty() )
194     return false;
195
196   TopoDS_Shape aShape = GEOMBase::GetShapeFromIOR( theIOR.ToCString() );
197   if ( aShape.IsNull() )
198     return false;
199
200   SetShape3D( aShape );
201   
202   return true;
203 }
204
205 void HYDROData_Obstacle::SetGeomObjectEntry( const TCollection_AsciiString& theEntry )
206 {
207   TDataStd_AsciiString::Set( myLab.FindChild( DataTag_GeomObjectEntry ), theEntry );
208 }
209
210 TCollection_AsciiString HYDROData_Obstacle::GetGeomObjectEntry() const
211 {
212   TCollection_AsciiString aRes;
213
214   TDF_Label aLabel = myLab.FindChild( DataTag_GeomObjectEntry, false );
215   if ( !aLabel.IsNull() )
216   {
217     Handle(TDataStd_AsciiString) anAsciiStr;
218     if ( aLabel.FindAttribute( TDataStd_AsciiString::GetID(), anAsciiStr ) )
219       aRes = anAsciiStr->Get();
220   }
221
222   return aRes;
223 }
224
225 void HYDROData_Obstacle::Translate( const double theDx,
226                                     const double theDy,
227                                     const double theDz )
228 {
229   TopoDS_Shape aShape3D = GetShape3D();
230   
231   TopoDS_Shape aTranslatedShape3D = HYDROData_ShapesTool::Translated( aShape3D, theDx, theDy, theDz );
232   if ( aTranslatedShape3D.IsNull() )
233     return;
234
235   SetShape3D( aTranslatedShape3D );
236
237   setTranslation( theDx, theDy, theDz );
238 }
239
240 TopoDS_Shape HYDROData_Obstacle::ImportBREP( const QString& theFilePath ) const
241 {
242   TopoDS_Shape aResShape;
243
244   BRep_Builder aBrepBuilder;
245   BRepTools::Read( aResShape, qPrintable(theFilePath), aBrepBuilder );
246
247   return aResShape;
248 }
249
250 TopoDS_Shape HYDROData_Obstacle::ImportIGES( const QString& theFilePath ) const
251 {
252   TopoDS_Shape aResShape;
253
254   // Set "C" numeric locale to save numbers correctly
255   Kernel_Utils::Localizer loc;
256
257   IGESControl_Reader aReader;
258
259   Interface_Static::SetCVal("xstep.cascade.unit","M");
260
261   try {
262     OCC_CATCH_SIGNALS;
263
264     IFSelect_ReturnStatus status = aReader.ReadFile(qPrintable(theFilePath));
265
266     if (status == IFSelect_RetDone) {
267       // Rescale units
268       Handle(IGESData_IGESModel) aModel =
269         Handle(IGESData_IGESModel)::DownCast(aReader.Model());
270       if (!aModel.IsNull()) {
271         IGESData_GlobalSection aGS = aModel->GlobalSection();
272         aGS.SetUnitFlag(6);
273         aModel->SetGlobalSection(aGS);
274       }
275     
276       aReader.ClearShapes();
277       aReader.TransferRoots();
278
279       aResShape = aReader.OneShape();
280     } 
281     else {
282       aResShape.Nullify();
283     }
284   }
285   catch(Standard_Failure) {
286     aResShape.Nullify();
287   }
288
289   return aResShape;
290 }
291
292 TopoDS_Shape HYDROData_Obstacle::ImportSTEP( const QString& theFilePath ) const
293 {
294   TopoDS_Shape aResShape;
295
296   // Set "C" numeric locale to save numbers correctly
297   Kernel_Utils::Localizer loc;
298
299   STEPControl_Reader aReader;
300
301   // Convert to METERS
302   Interface_Static::SetCVal("xstep.cascade.unit","M");
303   Interface_Static::SetIVal("read.step.ideas", 1);
304   Interface_Static::SetIVal("read.step.nonmanifold", 1);
305
306   BRep_Builder B;
307   TopoDS_Compound compound;
308   B.MakeCompound(compound);
309
310   try {
311     OCC_CATCH_SIGNALS;
312
313     IFSelect_ReturnStatus status = aReader.ReadFile( qPrintable(theFilePath) );
314
315     if (status == IFSelect_RetDone) {
316       // Rescale units
317       // set UnitFlag to units from file
318       TColStd_SequenceOfAsciiString anUnitLengthNames;
319       TColStd_SequenceOfAsciiString anUnitAngleNames;
320       TColStd_SequenceOfAsciiString anUnitSolidAngleNames;
321       aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames);
322       if (anUnitLengthNames.Length() > 0) {
323         TCollection_AsciiString aLenUnits = anUnitLengthNames.First();
324         if (aLenUnits == "millimetre")
325           Interface_Static::SetCVal("xstep.cascade.unit", "MM");
326         else if (aLenUnits == "centimetre")
327           Interface_Static::SetCVal("xstep.cascade.unit", "CM");
328         else if (aLenUnits == "metre" || aLenUnits.IsEmpty())
329           Interface_Static::SetCVal("xstep.cascade.unit", "M");
330         else if (aLenUnits == "INCH")
331           Interface_Static::SetCVal("xstep.cascade.unit", "INCH");
332         else {
333           // The file contains not supported units
334           return aResShape;
335         }
336       }
337         
338       Standard_Boolean failsonly = Standard_False;
339       aReader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity);
340
341       // Root transfers
342       Standard_Integer nbr = aReader.NbRootsForTransfer();
343       aReader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity);
344
345       for (Standard_Integer n = 1; n <= nbr; n++) {
346         Standard_Boolean ok = aReader.TransferRoot(n);
347         // Collecting resulting entities
348         Standard_Integer nbs = aReader.NbShapes();
349         if (!ok || nbs == 0) {
350           continue; // skip empty root
351         } 
352         else if (nbr == 1 && nbs == 1) { // For a single entity
353           aResShape = aReader.Shape(1);
354           // ATTENTION: this is a workaround for mantis issue 0020442 remark 0010776
355           // It should be removed after patching OCCT for bug OCC22436
356           // (fix for OCCT is expected in service pack next to OCCT6.3sp12)
357           if (aResShape.ShapeType() == TopAbs_COMPOUND) {
358             int nbSub1 = 0;
359             TopoDS_Shape currShape;
360             TopoDS_Iterator It (aResShape, Standard_True, Standard_True);
361             for (; It.More(); It.Next()) {
362               nbSub1++;
363               currShape = It.Value();
364             }
365             if (nbSub1 == 1)
366               aResShape = currShape;
367           }
368           // END workaround
369           break;
370         }
371
372         for (Standard_Integer i = 1; i <= nbs; i++) {
373           TopoDS_Shape aShape = aReader.Shape(i);
374           if (aShape.IsNull()) {
375             continue;
376           }
377           else {
378             B.Add(compound, aShape);
379           }
380         }
381       }
382   
383       if (aResShape.IsNull())
384         aResShape = compound;
385
386       // Check if any BRep entity has been read, there must be at least a vertex
387       if ( !TopExp_Explorer( aResShape, TopAbs_VERTEX ).More() ) {
388         // No geometrical data in the imported file
389         return TopoDS_Shape();
390       }
391     }
392     else {
393       aResShape.Nullify();
394     }
395   }
396   catch (Standard_Failure) {
397     aResShape.Nullify();
398   }
399
400   return aResShape;
401 }
402
403 QColor HYDROData_Obstacle::getDefaultFillingColor() const
404 {
405   return DefaultFillingColor();
406 }
407
408 QColor HYDROData_Obstacle::getDefaultBorderColor() const
409 {
410   return DefaultBorderColor();
411 }
412
413 ObjectKind HYDROData_Obstacle::getAltitudeObjectType() const
414 {
415   return KIND_OBSTACLE_ALTITUDE;
416 }
417
418 void HYDROData_Obstacle::createGroupObjects()
419 {
420   TopoDS_Shape anObstacleShape = GetTopShape();
421   if ( !anObstacleShape.IsNull() )
422   {
423     TopTools_SequenceOfShape aWireEdges;
424     HYDROData_ShapesTool::ExploreShapeToShapes( anObstacleShape, TopAbs_EDGE, aWireEdges );
425     if ( !aWireEdges.IsEmpty() )
426     {
427       QString aWireGroupName = GetName() + "_Outer_Wire";
428
429       Handle(HYDROData_ShapesGroup) anExtWireGroup = createGroupObject();
430       anExtWireGroup->SetName( aWireGroupName );
431      
432       anExtWireGroup->SetShapes( aWireEdges );
433     }
434   }
435 }
436
437 void HYDROData_Obstacle::setTranslation( const double theDx, 
438                                          const double theDy, 
439                                          const double theDz )
440 {
441   TDF_Label aLabel = myLab.FindChild( DataTag_Translation );
442
443   double aCurDx = theDx;
444   double aCurDy = theDy;
445   double aCurDz = theDz;
446
447   double aPrevDx, aPrevDy, aPrevDz;
448   if ( getTranslation( aPrevDx, aPrevDy, aPrevDz ) )
449   {
450     aCurDx += aPrevDx;
451     aCurDy += aPrevDy;
452     aCurDz += aPrevDz;
453   }
454   
455   Handle(TDataStd_RealArray) aCoeffsArray = TDataStd_RealArray::Set( aLabel, 1, 3 );
456   aCoeffsArray->SetValue( 1, aCurDx );
457   aCoeffsArray->SetValue( 2, aCurDy );
458   aCoeffsArray->SetValue( 3, aCurDz );
459 }
460
461 bool HYDROData_Obstacle::getTranslation( double& theDx, double& theDy, double& theDz ) const
462 {
463   theDx = theDy = theDz = 0.0;
464
465   TDF_Label aLabel = myLab.FindChild( DataTag_Translation, false );
466   if ( aLabel.IsNull() )
467     return false;
468
469   Handle(TDataStd_RealArray) aCoeffsArray;
470   if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), aCoeffsArray ) )
471     return false;
472
473   theDx = aCoeffsArray->Value( 1 );
474   theDy = aCoeffsArray->Value( 2 );
475   theDz = aCoeffsArray->Value( 3 );
476
477   return true;
478 }
479