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