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