Salome HOME
50228619b33228a2464f82713bf4fa669ba11087
[modules/hydro.git] / src / HYDROData / HYDROData_Profile.cxx
1
2 #include "HYDROData_Profile.h"
3
4 #include "HYDROData_Document.h"
5 #include "HYDROData_Iterator.h"
6 #include "HYDROData_Tool.h"
7 #include "HYDROData_PolylineXY.h"
8
9 #include <boost/math/special_functions/fpclassify.hpp>
10
11 #include <BRepBuilderAPI_MakeEdge.hxx>
12 #include <BRepBuilderAPI_MakeWire.hxx>
13 #include <BRepBuilderAPI_MakePolygon.hxx>
14
15 #include <gp_XY.hxx>
16 #include <gp_XYZ.hxx>
17 #include <gp_Pnt2d.hxx>
18
19 #include <TDataStd_AsciiString.hxx>
20 #include <TDataStd_RealArray.hxx>
21
22 #include <TopoDS_Edge.hxx>
23 #include <TopoDS_Wire.hxx>
24
25 #include <OSD_File.hxx>
26 #include <OSD_Protection.hxx>
27
28 #include <QColor>
29 #include <QStringList>
30
31 IMPLEMENT_STANDARD_HANDLE(HYDROData_Profile, HYDROData_Object)
32 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Profile, HYDROData_Object)
33
34 HYDROData_Profile::HYDROData_Profile()
35 : HYDROData_Object()
36 {
37 }
38
39 HYDROData_Profile::~HYDROData_Profile()
40 {
41 }
42
43 QStringList HYDROData_Profile::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
44 {
45   QStringList aResList = HYDROData_Entity::DumpToPython( theTreatedObjects );
46
47   //TODO
48
49   return aResList;
50 }
51
52 TopoDS_Shape HYDROData_Profile::GetTopShape() const
53 {
54   TopoDS_Wire aWire;
55
56   gp_XY aFirstPoint, aLastPoint;
57   if ( !GetLeftPoint( aFirstPoint ) || !GetRightPoint( aLastPoint ) )
58     return aWire;
59
60   gp_Pnt aPnt1( aFirstPoint.X(), aFirstPoint.Y(), 0 );
61   gp_Pnt aPnt2( aLastPoint.X(),  aLastPoint.Y(),  0 );
62
63   BRepBuilderAPI_MakeEdge aMakeEdge( aPnt1, aPnt2 );
64   TopoDS_Edge anEdge = aMakeEdge;
65
66   BRepBuilderAPI_MakeWire aMakeWire( anEdge );
67   aWire = aMakeWire;
68
69   return aWire;
70 }
71
72 TopoDS_Shape HYDROData_Profile::GetShape3D() const
73 {
74   return getShape3D();
75 }
76
77 void HYDROData_Profile::Update()
78 {
79   HYDROData_Object::Update();
80
81   TopoDS_Wire aWire;
82   Handle(HYDROData_ProfileUZ) aProfile = GetProfileUZ( false );
83   if ( !aProfile.IsNull() )
84   {
85     ProfilePoints aProfilePoints = GetProfilePoints();
86     HYDROData_IPolyline::SectionType aSectionType = aProfile->GetSectionType( 0 );
87
88     aWire = HYDROData_PolylineXY::BuildWire( aSectionType, false, aProfilePoints );
89   }
90   SetShape3D( aWire );
91 }
92
93 QColor HYDROData_Profile::DefaultFillingColor()
94 {
95   return QColor( Qt::transparent );
96 }
97
98 QColor HYDROData_Profile::DefaultBorderColor()
99 {
100   return QColor( Qt::black );
101 }
102
103 QColor HYDROData_Profile::getDefaultFillingColor() const
104 {
105   return DefaultFillingColor();
106 }
107
108 QColor HYDROData_Profile::getDefaultBorderColor() const
109 {
110   return DefaultBorderColor();
111 }
112
113 bool HYDROData_Profile::IsValid() const
114 {
115   gp_XY aFirstPoint, aLastPoint;
116   if ( !GetLeftPoint( aFirstPoint ) || !GetRightPoint( aLastPoint ) )
117     return false;
118
119   int aNbPoints = NbPoints();
120   return aNbPoints > 1;
121 }
122
123 void HYDROData_Profile::SetLeftPoint( const gp_XY& thePoint )
124 {
125   TDF_Label aLabel = myLab.FindChild( DataTag_FirstPoint );
126
127   Handle(TDataStd_RealArray) anArray;
128   if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), anArray ) )
129     anArray = TDataStd_RealArray::Set( aLabel, 0, 1 );
130
131   anArray->SetValue( 0, thePoint.X() );
132   anArray->SetValue( 1, thePoint.Y() );
133
134   SetToUpdate( true );
135 }
136
137 bool HYDROData_Profile::GetLeftPoint( gp_XY& thePoint ) const
138 {
139   TDF_Label aLabel = myLab.FindChild( DataTag_FirstPoint, false );
140   if ( aLabel.IsNull() )
141     return false;
142
143   Handle(TDataStd_RealArray) anArray;
144   if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), anArray ) )
145     return false;
146
147   thePoint.SetX( anArray->Value( 0 ) );
148   thePoint.SetY( anArray->Value( 1 ) );
149
150   return true;
151 }
152
153 void HYDROData_Profile::SetRightPoint( const gp_XY& thePoint )
154 {
155   TDF_Label aLabel = myLab.FindChild( DataTag_LastPoint );
156
157   Handle(TDataStd_RealArray) anArray;
158   if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), anArray ) )
159     anArray = TDataStd_RealArray::Set( aLabel, 0, 1 );
160
161   anArray->SetValue( 0, thePoint.X() );
162   anArray->SetValue( 1, thePoint.Y() );
163
164   SetToUpdate( true );
165 }
166
167 bool HYDROData_Profile::GetRightPoint( gp_XY& thePoint ) const
168 {
169   TDF_Label aLabel = myLab.FindChild( DataTag_LastPoint, false );
170   if ( aLabel.IsNull() )
171     return false;
172
173   Handle(TDataStd_RealArray) anArray;
174   if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), anArray ) )
175     return false;
176
177   thePoint.SetX( anArray->Value( 0 ) );
178   thePoint.SetY( anArray->Value( 1 ) );
179
180   return true;
181 }
182
183 void HYDROData_Profile::Invalidate()
184 {
185   TDF_Label aFirstLabel = myLab.FindChild( DataTag_FirstPoint, false );
186   if ( !aFirstLabel.IsNull() )
187     aFirstLabel.ForgetAllAttributes();
188
189   TDF_Label aLastLabel = myLab.FindChild( DataTag_LastPoint, false );
190   if ( !aLastLabel.IsNull() )
191     aLastLabel.ForgetAllAttributes();
192
193   SetToUpdate( true );
194 }
195
196 Handle(HYDROData_ProfileUZ) HYDROData_Profile::GetProfileUZ( const bool theIsCreate ) const
197 {
198   Handle(HYDROData_ProfileUZ) aProfileUZ;
199
200   TDF_Label aLabel = myLab.FindChild( DataTag_ChildProfileUZ, theIsCreate );
201   if ( aLabel.IsNull() )
202     return aProfileUZ;
203
204   aProfileUZ = Handle(HYDROData_ProfileUZ)::DownCast( HYDROData_Iterator::Object( aLabel ) );
205   if ( aProfileUZ.IsNull() && theIsCreate )
206   {
207     aProfileUZ = Handle(HYDROData_ProfileUZ)::DownCast(
208       HYDROData_Iterator::CreateObject( aLabel, KIND_PROFILEUZ ) );
209   }
210
211   return aProfileUZ;
212 }
213
214 int HYDROData_Profile::NbPoints() const
215 {
216   Handle(HYDROData_ProfileUZ) aProfileUZ = GetProfileUZ( false );
217   return aProfileUZ.IsNull() ? 0 : aProfileUZ->NbPoints();
218 }
219
220 void HYDROData_Profile::RemovePoints()
221 {
222   Handle(HYDROData_ProfileUZ) aProfileUZ = GetProfileUZ( false );
223   if ( !aProfileUZ.IsNull() )
224   {
225     aProfileUZ->RemoveSections();
226     SetToUpdate( true );
227   }
228 }
229
230 void HYDROData_Profile::SetParametricPoints( const HYDROData_ProfileUZ::PointsList& thePoints )
231 {
232   RemovePoints();
233
234   Handle(HYDROData_ProfileUZ) aProfileUZ = GetProfileUZ();
235   for ( int i = 1, n = thePoints.Length(); i <= n ; ++i )
236   {
237     const HYDROData_ProfileUZ::Point& aPoint = thePoints.Value( i );
238     aProfileUZ->AddPoint( 0, aPoint );
239   }
240
241   SetToUpdate( true );
242 }
243
244 HYDROData_ProfileUZ::PointsList HYDROData_Profile::GetParametricPoints() const
245 {
246   Handle(HYDROData_ProfileUZ) aProfileUZ = GetProfileUZ( false );
247   return aProfileUZ.IsNull() ? HYDROData_ProfileUZ::PointsList() : aProfileUZ->GetPoints();
248 }
249
250 void HYDROData_Profile::SetProfilePoints( const ProfilePoints& thePoints )
251 {
252   RemovePoints();
253   if ( thePoints.Length() < 2 )
254     return;
255
256   gp_XY aFirstPoint, aLastPoint;
257
258   Handle(HYDROData_ProfileUZ) aProfileUZ = GetProfileUZ();
259   for ( int i = 1, n = thePoints.Length(); i <= n ; ++i )
260   {
261     const ProfilePoint& aPoint = thePoints.Value( i );
262     gp_XY aPointXY( aPoint.X(), aPoint.Y() );
263
264     if ( i == 1 )
265       aFirstPoint = aPointXY;
266     else if ( i == n )
267       aLastPoint = aPointXY;
268
269     double aDistance = gp_Pnt2d( aFirstPoint ).Distance( aPointXY );
270     
271     HYDROData_ProfileUZ::Point aParPoint( aDistance, aPoint.Z() );
272     aProfileUZ->AddPoint( 0, aParPoint );
273   }
274
275   SetLeftPoint( aFirstPoint );
276   SetRightPoint( aLastPoint );
277 }
278
279 HYDROData_Profile::ProfilePoints HYDROData_Profile::GetProfilePoints() const
280 {
281   ProfilePoints aResPoints;
282
283   gp_XY aFirstPoint, aLastPoint;
284   if ( !GetLeftPoint( aFirstPoint ) || !GetRightPoint( aLastPoint ) )
285     return aResPoints;
286
287   HYDROData_ProfileUZ::PointsList aParametricPoints = GetParametricPoints();
288   if ( aParametricPoints.Length() < 2 )
289     return aResPoints;
290
291   const HYDROData_ProfileUZ::Point& aFirstParPoint = aParametricPoints.First();
292   const HYDROData_ProfileUZ::Point& aLastParPoint = aParametricPoints.Last();
293
294   double aGeoDistance = gp_Pnt2d( aFirstPoint ).Distance( aLastPoint );
295   double aParCommonDist = gp_Pnt2d( aFirstParPoint.X(), 0 ).Distance( gp_Pnt2d( aLastParPoint.X(), 0 ) );
296
297   // Add first point as is
298   aResPoints.Append( ProfilePoint( aFirstPoint.X(), aFirstPoint.Y(), aFirstParPoint.Y() ) );
299
300   // Compute all other points
301   for ( int i = 2, n = aParametricPoints.Length(); i < n ; ++i )
302   {
303     const HYDROData_ProfileUZ::Point& aParPoint = aParametricPoints.Value( i );
304
305     double aParPointDist = gp_Pnt2d( aFirstParPoint.X(), 0 ).Distance( gp_Pnt2d( aParPoint.X(), 0 ) );
306     
307     double aParLen = ( aParPointDist / aParCommonDist ) * aGeoDistance;
308
309     double aRatio = aParLen / ( aGeoDistance - aParLen );
310
311     double aParX = ( aFirstPoint.X() + aRatio * aLastPoint.X() ) / ( 1 + aRatio );
312     double aParY = ( aFirstPoint.Y() + aRatio * aLastPoint.Y() ) / ( 1 + aRatio );
313
314     ProfilePoint aCompPoint( aParX, aParY, aParPoint.Y() );
315     aResPoints.Append( aCompPoint );
316   }
317
318   // Add last point as is
319   aResPoints.Append( ProfilePoint( aLastPoint.X(), aLastPoint.Y(), aLastParPoint.Y() ) );
320
321   return aResPoints;
322 }
323
324 void HYDROData_Profile::SetFilePath( const TCollection_AsciiString& theFilePath )
325 {
326   TDataStd_AsciiString::Set( myLab.FindChild( DataTag_FilePath ), theFilePath );
327 }
328
329 TCollection_AsciiString HYDROData_Profile::GetFilePath() const
330 {
331   TCollection_AsciiString aRes;
332
333   Handle(TDataStd_AsciiString) anAsciiStr;
334   if ( myLab.FindChild( DataTag_FilePath ).FindAttribute( TDataStd_AsciiString::GetID(), anAsciiStr ) )
335     aRes = anAsciiStr->Get();
336
337   return aRes;
338 }
339
340 int HYDROData_Profile::ImportFromFile( const Handle(HYDROData_Document)& theDoc,
341                                        const TCollection_AsciiString&    theFileName,
342                                        NCollection_Sequence<int>&        theBadProfilesIds )
343 {
344   if ( theDoc.IsNull() || theFileName.IsEmpty() )
345     return 0;
346
347   OSD_File aFile( theFileName );
348   if ( !aFile.IsReadable() )
349     return 0;
350
351   aFile.Open( OSD_ReadOnly, OSD_Protection() );
352   if ( !aFile.IsOpen() )
353     return 0;
354
355   NCollection_Sequence<Handle(HYDROData_Profile)> aCreatedProfiles;
356
357   int aProfileId = 1;
358   Handle(HYDROData_Profile) aNewProfile;
359   for ( ; !aFile.IsAtEnd(); ++aProfileId )
360   {
361     if ( aNewProfile.IsNull() )
362       aNewProfile = Handle(HYDROData_Profile)::DownCast( theDoc->CreateObject( KIND_PROFILE ) );
363     
364     bool anIsRead = false;
365     if ( aNewProfile->ImportFromFile( aFile, &anIsRead ) )
366     {
367       aCreatedProfiles.Append( aNewProfile );
368       aNewProfile.Nullify();
369     }
370     else if ( anIsRead )
371     {
372       theBadProfilesIds.Append( aProfileId );
373     }
374   }
375
376   if ( !aNewProfile.IsNull() )
377     aNewProfile->Remove();
378
379   // Close the file
380   aFile.Close();
381
382   for ( int i = 1, n = aCreatedProfiles.Length(); i <= n ; ++i )
383   {
384     Handle(HYDROData_Profile) aProfile = aCreatedProfiles.Value( i );
385
386     QString aProfileName = HYDROData_Tool::GenerateObjectName( theDoc, "Profile" );
387     aProfile->SetName( aProfileName );
388
389     aProfile->SetFilePath( theFileName );
390
391     aProfile->SetBorderColor( HYDROData_Profile::DefaultBorderColor() );
392   }
393
394   return aCreatedProfiles.Length();
395 }
396
397 bool HYDROData_Profile::ImportFromFile( const TCollection_AsciiString& theFileName,
398                                         bool*                          theIsRead )
399 {
400   if ( theIsRead )
401     *theIsRead = false;
402
403   // Try to open the file
404   OSD_File aFile( theFileName );
405   if ( !aFile.IsReadable() )
406     return false;
407
408   aFile.Open( OSD_ReadOnly, OSD_Protection() );
409   if ( !aFile.IsOpen() )
410     return false;
411
412   bool aRes = ImportFromFile( aFile, theIsRead );
413
414   // Close the file
415   aFile.Close();
416
417   if ( aRes )
418   {
419     // Update file path
420     SetFilePath( theFileName );
421   }
422
423   return aRes;
424 }
425
426 bool HYDROData_Profile::ImportFromFile( OSD_File& theFile,
427                                         bool*     theIsRead )
428 {
429   if ( theIsRead )
430     *theIsRead = false;
431
432   if ( !theFile.IsOpen() )
433     return false;
434
435   bool aRes = true;
436
437   bool anIsParametric = false;
438   bool anIsGeoref     = false;
439
440   HYDROData_ProfileUZ::PointsList aPointsUZ;
441   ProfilePoints                   aPointsXYZ;
442
443   double aPrevVal = -DBL_MAX;
444   while ( !theFile.IsAtEnd() )
445   {
446     Standard_Integer aNbRead = 0;
447     TCollection_AsciiString aLine;
448     theFile.ReadLine( aLine, 1024, aNbRead );
449
450     aLine.LeftAdjust(); aLine.RightAdjust();
451     if ( aLine.IsEmpty() )
452     {
453       if ( !anIsParametric && !anIsGeoref )
454         continue; // Definition is not started yet
455
456       break; // Next profile started
457     }
458
459     // Set flag of read status to true
460     if ( theIsRead )
461       *theIsRead = true;
462
463     TCollection_AsciiString aValX = aLine.Token( " \t", 1 );
464     TCollection_AsciiString aValY = aLine.Token( " \t", 2 );
465     TCollection_AsciiString aValZ = aLine.Token( " \t", 3 );
466
467     if ( aValX.IsEmpty() || !aValX.IsRealValue() ||
468          aValY.IsEmpty() || !aValY.IsRealValue() )
469     {
470       aRes = false;
471       break;
472     }
473
474     if ( !anIsParametric && !anIsGeoref )
475     {
476       anIsParametric = aValZ.IsEmpty();
477       anIsGeoref = !aValZ.IsEmpty();
478     }
479
480     double aCoordX = aValX.RealValue();
481     double aCoordY = aValY.RealValue();
482
483     if ( boost::math::isnan( aCoordX ) || boost::math::isinf( aCoordX ) ||
484          boost::math::isnan( aCoordY ) || boost::math::isinf( aCoordY ) )
485       aRes = false;
486
487     if ( anIsParametric )
488     {
489       if ( aCoordX < aPrevVal )
490       {
491         // Move back readed line
492         theFile.Seek( -( aNbRead + 1 ), OSD_FromHere );
493         break;
494       }
495
496       HYDROData_ProfileUZ::Point aPoint( aCoordX, aCoordY );
497       aPointsUZ.Append( aPoint );
498
499       aPrevVal = aCoordX;
500     }
501     else
502     {
503       if ( aValZ.IsEmpty() || !aValZ.IsRealValue() )
504       {
505         aRes = false;
506         break;
507       }
508
509       double aCoordZ = aValZ.RealValue();
510       if ( boost::math::isnan( aCoordZ ) || boost::math::isinf( aCoordZ ) )
511         aRes = false;
512
513       ProfilePoint aPoint( aCoordX, aCoordY, aCoordZ );
514       aPointsXYZ.Append( aPoint );
515     }
516   }
517   
518   aRes = aRes && ( anIsParametric && !aPointsUZ.IsEmpty() || 
519                    anIsGeoref && !aPointsXYZ.IsEmpty() );
520   if ( aRes )
521   {
522     // Update profile points
523     if ( anIsParametric )
524     {
525       SetParametricPoints( aPointsUZ );
526     }
527     else if ( anIsGeoref )
528     {
529       SetProfilePoints( aPointsXYZ );
530     }
531
532     Update();
533   }
534
535   return aRes;
536 }
537
538
539