Salome HOME
cdbc3752ed80be47369e61c458b30f9c741dcac5
[modules/hydro.git] / src / HYDROData / HYDROData_PolylineXY.cxx
1
2 #include "HYDROData_PolylineXY.h"
3
4 #include "HYDROData_BSplineOperation.h"
5 #include "HYDROData_Document.h"
6 #include "HYDROData_ShapesTool.h"
7 #include "HYDROData_Tool.h"
8
9 #include <BRep_Builder.hxx>
10 #include <BRepBuilderAPI_MakeEdge.hxx>
11 #include <BRepBuilderAPI_MakeWire.hxx>
12 #include <BRepBuilderAPI_MakePolygon.hxx>
13 #include <BRepBuilderAPI_MakeFace.hxx>
14 #include <BRepOffsetAPI_NormalProjection.hxx>
15
16 #include <GeomAPI_ProjectPointOnCurve.hxx>
17 #include <GeomAdaptor_Curve.hxx>
18 #include <Geom_Line.hxx>
19 #include <Geom_BSplineCurve.hxx>
20
21 #include <GCPnts_AbscissaPoint.hxx>
22
23 #include <ImageComposer_MetaTypes.h>
24
25 #include <gp_Pnt.hxx>
26 #include <gp_XY.hxx>
27 #include <gp_Pln.hxx>
28
29 #include <NCollection_Map.hxx>
30
31 #include <TCollection_ExtendedString.hxx>
32
33 #include <TDataStd_ListIteratorOfListOfByte.hxx>
34 #include <TColStd_ListIteratorOfListOfInteger.hxx>
35 #include <TColStd_ListIteratorOfListOfReal.hxx>
36
37 #include <TColStd_Array1OfReal.hxx>
38
39 #include <TDataStd_BooleanList.hxx>
40 #include <TDataStd_ExtStringList.hxx>
41 #include <TDataStd_IntegerList.hxx>
42 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
43 #include <TDataStd_RealList.hxx>
44 #include <TDataStd_UAttribute.hxx>
45
46 #include <TopoDS_Iterator.hxx>
47 #include <TopTools_ListIteratorOfListOfShape.hxx>
48 #include <TopTools_HSequenceOfShape.hxx>
49 #include <TopExp_Explorer.hxx>
50 #include <ShapeAnalysis_FreeBounds.hxx>
51 #include <TopoDS.hxx>
52
53 #include <QColor>
54 #include <QPainterPath>
55 #include <QVariant>
56
57 static const Standard_GUID GUID_IS_UNEDITABLE("e5799736-9030-4051-91a4-2e58321fa153");
58
59 const double LOCAL_SELECTION_TOLERANCE = 0.0001;
60
61 TCollection_AsciiString getUniqueSectionName( const NCollection_Sequence<TCollection_AsciiString>& theNamesSeq )
62 {
63   NCollection_Map<TCollection_AsciiString> aNamesMap;
64
65   for ( int i = 1, n = theNamesSeq.Size(); i <= n; ++i )
66   {
67     const TCollection_AsciiString& aSectName = theNamesSeq.Value( i );
68     aNamesMap.Add( aSectName );
69   }
70
71   TCollection_AsciiString aResName;
72
73   int aPrefIdx = 1;
74   do
75   {
76     aResName = TCollection_AsciiString( "Section_" ) + aPrefIdx;
77     ++aPrefIdx;
78   }
79   while ( aNamesMap.Contains( aResName ) );
80
81   return aResName;
82 }
83
84 TCollection_AsciiString getUniqueSectionName( const Handle(TDataStd_ExtStringList)& theNamesList )
85 {
86   NCollection_Sequence<TCollection_AsciiString> aNamesSeq;
87
88   TDataStd_ListIteratorOfListOfExtendedString aNamesIter( theNamesList->List() );
89   for ( ; aNamesIter.More(); aNamesIter.Next() )
90     aNamesSeq.Append( aNamesIter.Value() );
91
92   return getUniqueSectionName( aNamesSeq );
93 }
94
95 IMPLEMENT_STANDARD_HANDLE(HYDROData_PolylineXY, HYDROData_IPolyline)
96 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_PolylineXY, HYDROData_IPolyline)
97
98 HYDROData_PolylineXY::HYDROData_PolylineXY()
99 : HYDROData_IPolyline()
100 {
101 }
102
103 HYDROData_PolylineXY::~HYDROData_PolylineXY()
104 {
105 }
106
107 QStringList HYDROData_PolylineXY::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
108 {
109   QStringList aResList = dumpObjectCreation( theTreatedObjects );
110   QString aPolylineName = GetObjPyName();
111
112   // Set the wire color
113   QStringList aWireColorDef;
114
115   QColor aWireColor = GetWireColor();
116   setPythonObjectColor( aWireColorDef, aWireColor, DefaultWireColor(), "SetWireColor" );
117   
118   if ( !aWireColorDef.isEmpty() )
119   {
120     aResList << aWireColorDef;
121     aResList << QString( "" );
122   }
123
124   // Set polilyne data
125   NCollection_Sequence<TCollection_AsciiString>           aSectNames;
126   NCollection_Sequence<HYDROData_PolylineXY::SectionType> aSectTypes;
127   NCollection_Sequence<bool>                              aSectClosures;
128   GetSections( aSectNames, aSectTypes, aSectClosures );
129
130   for ( int i = 1, n = aSectNames.Size(); i <= n; ++i )
131   {
132     const TCollection_AsciiString& aSectName = aSectNames.Value( i );
133     const SectionType& aSectType = aSectTypes.Value( i );
134     bool aSectClosure = aSectClosures.Value( i );
135
136     aResList << QString( "%1.AddSection( \"%2\", %3, %4 );" ).arg( aPolylineName )
137                 .arg( aSectName.ToCString() ).arg( aSectType ).arg( aSectClosure );
138
139     HYDROData_IPolyline::PointsList aSectPointsList = GetPoints( i - 1 );
140     for ( int k = 1, aNbPoints = aSectPointsList.Size(); k <= aNbPoints; ++k )
141     {
142       const Point& aSectPoint = aSectPointsList.Value( k );
143
144       aResList << QString( "%1.AddPoint( %2, gp_XY( %3, %4 ) );" ).arg( aPolylineName )
145         .arg( i - 1 ).arg( aSectPoint.X() ).arg( aSectPoint.Y() );
146     }
147   }
148
149   aResList << QString( "" );
150   aResList << QString( "%1.Update();" ).arg( aPolylineName );
151   aResList << QString( "" );
152
153   return aResList;
154 }
155
156 QVariant HYDROData_PolylineXY::GetDataVariant()
157 {
158   QPainterPath aPath = GetPainterPath();
159
160   QVariant aVarData;
161   aVarData.setValue<QPainterPath>( aPath );
162   
163   return aVarData;
164 }
165
166 QColor HYDROData_PolylineXY::DefaultWireColor()
167 {
168   return QColor( Qt::red );
169 }
170
171 TopoDS_Shape HYDROData_PolylineXY::GetShape() const
172 {
173   return getPolylineShape();
174 }
175
176 bool convertEdgeToSection( const TopoDS_Edge&                                       theEdge,
177                            NCollection_Sequence<TCollection_AsciiString>&           theSectNames,
178                            NCollection_Sequence<HYDROData_PolylineXY::SectionType>& theSectTypes,
179                            NCollection_Sequence<bool>&                              theSectClosures,
180                            NCollection_Sequence<HYDROData_PolylineXY::PointsList>&  theSectPoints,
181                            const bool                                               theIsCanBeClosed )
182 {
183   Standard_Real aFirst = 0.0, aLast = 0.0;
184   Handle(Geom_Curve) anEdgeGeomCurve = BRep_Tool::Curve( theEdge, aFirst, aLast );
185   if ( anEdgeGeomCurve.IsNull() )
186     return false;
187
188   TCollection_AsciiString aSectName = getUniqueSectionName( theSectNames );
189   bool anIsEdgeClosed = anEdgeGeomCurve->IsClosed();
190
191   HYDROData_PolylineXY::SectionType aSectionType = HYDROData_PolylineXY::SECTION_POLYLINE;
192   HYDROData_PolylineXY::PointsList aPointsList;
193
194   if ( anEdgeGeomCurve->IsKind( STANDARD_TYPE(Geom_Line) ) )
195   {
196     Handle(Geom_Line) aGeomLine = Handle(Geom_Line)::DownCast( anEdgeGeomCurve );
197
198     gp_Pnt aFirstPoint, aLastPoint;
199     aGeomLine->D0( aFirst, aFirstPoint );
200     aGeomLine->D0( aLast, aLastPoint );
201
202     HYDROData_PolylineXY::Point aSectFirstPoint( aFirstPoint.X(), aFirstPoint.Y() );
203     aPointsList.Append( aSectFirstPoint );
204
205     HYDROData_PolylineXY::Point aSectLastPoint( aLastPoint.X(), aLastPoint.Y() );
206     aPointsList.Append( aSectLastPoint );
207   }
208   else if ( anEdgeGeomCurve->IsKind( STANDARD_TYPE(Geom_BSplineCurve) ) )
209   {
210     aSectionType = HYDROData_PolylineXY::SECTION_SPLINE;
211
212     Handle(Geom_BSplineCurve) aGeomSpline = 
213       Handle(Geom_BSplineCurve)::DownCast( anEdgeGeomCurve );
214
215     int aNbKnots = aGeomSpline->NbKnots();
216
217     TColStd_Array1OfReal aSplineKnots( 1, aNbKnots );
218     aGeomSpline->Knots( aSplineKnots );
219
220     // Decrease the number of imported knots because of last one 
221     // knot is the closing point which are the start point
222     if ( anIsEdgeClosed ) aNbKnots--;
223
224     for ( int i = 1; i <= aNbKnots; ++i )
225     {
226       const Standard_Real& aKnot = aSplineKnots.Value( i );
227
228       gp_Pnt aPoint;
229       aGeomSpline->D0( aKnot, aPoint );
230
231       HYDROData_PolylineXY::Point aSectPoint( aPoint.X(), aPoint.Y() );
232       aPointsList.Append( aSectPoint );
233     }
234   }
235   else
236   {
237     // Other curve types are not supported
238     return false;
239   }
240
241   if ( aPointsList.IsEmpty() )
242     return false;
243
244   theSectNames.Append( aSectName );
245   theSectTypes.Append( aSectionType );
246   theSectClosures.Append( anIsEdgeClosed );
247   theSectPoints.Append( aPointsList );
248
249   return true;
250 }
251
252 bool HYDROData_PolylineXY::ImportShape( const TopoDS_Shape& theShape )
253 {
254   if ( theShape.IsNull() )
255     return false;
256
257   RemoveSections();
258
259   bool anIsCanBeImported = false;
260
261   NCollection_Sequence<TCollection_AsciiString> aSectNames;
262   NCollection_Sequence<SectionType>             aSectTypes;
263   NCollection_Sequence<bool>                    aSectClosures;
264   NCollection_Sequence<PointsList>              aSectPoints;
265
266   if ( theShape.ShapeType() == TopAbs_EDGE )
267   {
268     TopoDS_Edge anEdge = TopoDS::Edge( theShape );
269     anIsCanBeImported = convertEdgeToSection( anEdge, aSectNames, aSectTypes, aSectClosures, aSectPoints, true );
270   }
271   else if ( theShape.ShapeType() == TopAbs_WIRE )
272   {
273     TopTools_SequenceOfShape anEdges;
274     HYDROData_ShapesTool::ExploreShapeToShapes( theShape, TopAbs_EDGE, anEdges );
275
276     anIsCanBeImported = !anEdges.IsEmpty();
277     for ( int i = 1, n = anEdges.Length(); i <= n && anIsCanBeImported; ++i )
278     {
279       TopoDS_Edge aWireEdge = TopoDS::Edge( anEdges.Value( i ) );
280       anIsCanBeImported = convertEdgeToSection( aWireEdge, aSectNames, aSectTypes, aSectClosures, aSectPoints, false );
281     }
282   }
283
284   if ( anIsCanBeImported )
285   {
286     for ( int i = 1, n = aSectNames.Length(); i <= n; ++i )
287     {
288       const TCollection_AsciiString& aSectName = aSectNames.Value( i );
289       const SectionType& aSectType = aSectTypes.Value( i );
290       bool anIsSectionClosed = aSectClosures.Value( i );
291       const PointsList& aSectPointsList = aSectPoints( i );
292
293       AddSection( aSectName, aSectType, anIsSectionClosed );
294       SetPoints( i - 1, aSectPointsList );
295     }
296   }
297   else
298   {
299     TopoDS_Shape aShape = theShape;
300
301     if ( theShape.ShapeType() == TopAbs_EDGE )
302     {
303       // We make the wire from incoming edge because of other algorithms
304       // are waiting at least the wire from polyline
305       TopoDS_Edge anEdge = TopoDS::Edge( theShape );
306       BRepBuilderAPI_MakeWire aMakeWire( anEdge );
307       aMakeWire.Build();
308       if ( aMakeWire.IsDone() )
309         aShape = aMakeWire.Wire();
310     }
311
312     gp_Pln aPlane( gp_Pnt( 0, 0, 0 ), gp_Dir( 0, 0, 1 ) );
313     BRepBuilderAPI_MakeFace aMakeFace( aPlane );
314     aMakeFace.Build();
315     BRepOffsetAPI_NormalProjection aProj( aMakeFace.Face() );
316     aProj.Add( aShape );
317     aProj.Build();
318     TopoDS_Shape aResult;
319     if( aProj.IsDone() )
320       aResult = aProj.Shape();
321
322     setPolylineShape( aResult );
323   }
324
325   setEditable( anIsCanBeImported );
326
327   return true;
328 }
329
330 TopoDS_Wire HYDROData_PolylineXY::BuildWire( const SectionType&                  theType,
331                                              const bool&                         theIsClosed,
332                                              const NCollection_Sequence<gp_XYZ>& thePoints )
333 {
334   TopoDS_Wire aWire;
335   if( theType == SECTION_POLYLINE )
336   {
337     BRepBuilderAPI_MakePolygon aMakeWire;
338     for ( int i = 1, n = thePoints.Length(); i <= n ; ++i )
339     {
340       gp_XYZ aPoint = thePoints.Value( i );
341       gp_Pnt aPnt( aPoint.X(), aPoint.Y(), aPoint.Z() );
342       aMakeWire.Add( aPnt );
343     }
344     if( theIsClosed )
345       aMakeWire.Close();
346
347     if ( aMakeWire.IsDone() )
348       aWire = aMakeWire.Wire();
349   }
350   else //if( theType == PolylineSection::SECTION_SPLINE )
351   {
352     BRepBuilderAPI_MakeWire aMakeWire;
353
354     if ( thePoints.Size() > 1 )
355     {
356       HYDROData_BSplineOperation aBSpline( thePoints, theIsClosed, LOCAL_SELECTION_TOLERANCE );
357
358       TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aBSpline.Curve() ).Edge();
359       aMakeWire.Add( anEdge );
360     }
361     aMakeWire.Build();
362     if ( aMakeWire.IsDone() )
363       aWire = aMakeWire;
364   }
365
366   return aWire;
367 }
368
369 void HYDROData_PolylineXY::BuildPainterPath( QPainterPath&                       thePath,
370                                              const SectionType&                  theType,
371                                              const bool&                         theIsClosed,
372                                              const NCollection_Sequence<gp_XYZ>& thePoints )
373 {
374   if ( thePoints.IsEmpty() )
375     return;
376
377   if ( theType == SECTION_POLYLINE )
378   {
379     const gp_XYZ& aFirstPoint = thePoints.Value( 1 );
380     thePath.moveTo( aFirstPoint.X(), aFirstPoint.Y() );
381
382     for( int i = 2, n = thePoints.Size(); i <= n; ++i )
383     {
384       const gp_XYZ& aSectPoint = thePoints.Value( i );
385
386       thePath.lineTo( aSectPoint.X(), aSectPoint.Y() );
387     }
388
389     if( theIsClosed )
390       thePath.closeSubpath();
391   }
392   else
393   {
394     HYDROData_BSplineOperation aBSpline( thePoints, theIsClosed, LOCAL_SELECTION_TOLERANCE );
395     aBSpline.ComputePath( thePath );
396   }
397 }
398
399 void HYDROData_PolylineXY::Update()
400 {
401   if ( !IsEditable() )
402   {
403     // If polyline is not editable we no need to update it wire
404     SetToUpdate( false );
405     return;
406   }
407
408   HYDROData_IPolyline::Update();
409
410   NCollection_Sequence<TCollection_AsciiString>           aSectNames;
411   NCollection_Sequence<HYDROData_PolylineXY::SectionType> aSectTypes;
412   NCollection_Sequence<bool>                              aSectClosures;
413   GetSections( aSectNames, aSectTypes, aSectClosures );
414
415   BRepBuilderAPI_MakeWire aMakeWire;
416
417   TopTools_ListOfShape aSectionWiresList;
418
419   for ( int aSectionId = 1, aNbSects = aSectNames.Size(); aSectionId <= aNbSects; aSectionId++ )
420   {
421     TCollection_AsciiString aSectName = aSectNames.Value( aSectionId );
422     SectionType aSectionType = aSectTypes.Value( aSectionId );
423     bool anIsSectionClosed = aSectClosures.Value( aSectionId );
424
425     PointsList aSectPointsList = GetPoints( aSectionId - 1 );
426     if ( aSectPointsList.IsEmpty() )
427       continue;
428     
429     NCollection_Sequence<gp_XYZ> aPoints;
430     for( int i = 1, n = aSectPointsList.Size(); i <= n; ++i )
431     {
432       const Point& aSectPoint = aSectPointsList.Value( i );
433
434       gp_XYZ aPoint( aSectPoint.X(), aSectPoint.Y(), 0.0 );
435       aPoints.Append( aPoint );
436     }
437
438     TopoDS_Wire aSectionWire = BuildWire( aSectionType, anIsSectionClosed, aPoints );
439     if ( !aSectionWire.IsNull() ) {
440       aSectionWiresList.Append( aSectionWire );
441       aMakeWire.Add( aSectionWire );
442     }
443   }
444 // all input wires in the <aSectionWiresList>
445   Handle(TopTools_HSequenceOfShape) aSeqWires = new TopTools_HSequenceOfShape;
446   Handle(TopTools_HSequenceOfShape) aSeqEdges = new TopTools_HSequenceOfShape;
447   TopTools_ListIteratorOfListOfShape it(aSectionWiresList);
448   for(;it.More();it.Next())
449   {
450     TopExp_Explorer it2(it.Value(), TopAbs_EDGE);
451     for(;it2.More();it2.Next()) 
452       aSeqEdges->Append(it2.Current());
453   }
454
455   BRep_Builder aBB;
456   TopoDS_Compound aCmp;
457   TopoDS_Shape aResult;
458   aBB.MakeCompound(aCmp);
459   if(aSeqEdges->Length() >1)
460   {
461     ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdges,1E-5,Standard_False,aSeqWires);
462
463     if( aSeqWires->Length()==1 )
464       aResult = aSeqWires->Value( 1 );
465     else
466     {
467       for (Standard_Integer i = 1; i <= aSeqWires->Length();i++)
468       {
469         const TopoDS_Shape& aS1 = aSeqWires->Value(i);
470         aBB.Add(aCmp, aS1);
471       }
472       aResult = aCmp;
473     }
474   }
475   else if (aSeqEdges->Length() == 1)
476   {
477     BRepBuilderAPI_MakeWire mkWire (TopoDS::Edge(aSeqEdges->Value(1)));
478     if (mkWire.IsDone())
479       aResult = mkWire.Wire();
480   }
481
482   setPolylineShape( aResult );
483 }
484
485 bool HYDROData_PolylineXY::IsEditable() const
486 {
487   return !myLab.IsAttribute( GUID_IS_UNEDITABLE );
488 }
489
490 void HYDROData_PolylineXY::setEditable( const bool theIsEditable )
491 {
492   if ( !theIsEditable )
493     TDataStd_UAttribute::Set( myLab, GUID_IS_UNEDITABLE );
494   else
495     myLab.ForgetAttribute( GUID_IS_UNEDITABLE );
496 }
497
498 /**
499  * Returns true if polyline is closed
500  */
501 bool HYDROData_PolylineXY::IsClosed( const bool theIsSimpleCheck ) const
502 {
503   bool anIsClosed = false;
504
505   TopoDS_Shape aShape = GetShape();
506   if ( aShape.IsNull() )
507     return anIsClosed;
508
509   TopTools_SequenceOfShape aWires;
510   HYDROData_ShapesTool::ExploreShapeToShapes( aShape, TopAbs_WIRE, aWires );
511
512   int aNbWires = aWires.Length();
513   if ( theIsSimpleCheck )
514   {
515     anIsClosed = aNbWires > 0;
516     for ( int i = 1; i <= aNbWires && anIsClosed; ++i )
517     {
518       const TopoDS_Shape& aWire = aWires.Value( i );
519       anIsClosed = BRep_Tool::IsClosed( aWire );
520     }
521   }
522   else
523   {
524     anIsClosed = aNbWires == 1 && BRep_Tool::IsClosed( aWires.First() );
525   }
526
527   return anIsClosed;
528 }
529
530 double HYDROData_PolylineXY::GetDistance( const int theSectionIndex,
531                                           const int thePointIndex ) const
532 {
533   double aResDistance = -1;
534   if ( theSectionIndex < 0 || theSectionIndex >= NbSections() )
535     return aResDistance;
536
537   if ( thePointIndex == 0 )
538     return 0.0;
539
540   SectionType aSectionType = GetSectionType( theSectionIndex );
541   bool anIsSectionClosed = IsClosedSection( theSectionIndex );
542   PointsList aSectPointsList = GetPoints( theSectionIndex );
543   if ( thePointIndex < 0 || thePointIndex >= aSectPointsList.Size()  )
544     return aResDistance;
545
546   if ( aSectionType == SECTION_POLYLINE )
547   {
548     aResDistance = 0.0;
549   
550     Point aPrevPoint = aSectPointsList.Value( 1 );
551     for ( int i = 2, aNbPoints = aSectPointsList.Size(); i <= aNbPoints; ++i )
552     {
553       const Point& aSectPoint = aSectPointsList.Value( i );
554       aResDistance += gp_Pnt2d( aPrevPoint ).Distance( aSectPoint );
555       aPrevPoint = aSectPoint;
556
557       if ( thePointIndex == i - 1 )
558         break;
559     }
560   }
561   else
562   {
563     gp_XYZ aPointToTest;
564
565     int aSectNbPoints = aSectPointsList.Size();
566     NCollection_Sequence<gp_XYZ> aPoints;
567     for( int i = 1 ; i <= aSectNbPoints; ++i )
568     {
569       const Point& aSectPoint = aSectPointsList.Value( i );
570
571       gp_XYZ aPoint( aSectPoint.X(), aSectPoint.Y(), 0.0 );
572       aPoints.Append( aPoint );
573
574       if ( thePointIndex == i - 1 )
575         aPointToTest = aPoint;
576     }
577
578     HYDROData_BSplineOperation aBSpline( aPoints, anIsSectionClosed, LOCAL_SELECTION_TOLERANCE );
579
580     Quantity_Parameter aFirstParam = aBSpline.Curve()->FirstParameter();
581     Quantity_Parameter aSecondParam = aBSpline.Curve()->LastParameter();
582
583     if ( thePointIndex != aSectNbPoints - 1 )
584     {
585       GeomAPI_ProjectPointOnCurve aProject( aPointToTest, aBSpline.Curve() );
586       aSecondParam = aProject.LowerDistanceParameter();
587     }
588
589     GeomAdaptor_Curve anAdap( aBSpline.Curve() );
590     
591     aResDistance = GCPnts_AbscissaPoint::Length( anAdap, aFirstParam, aSecondParam );
592   }
593
594   return aResDistance;
595 }
596
597 int HYDROData_PolylineXY::NbSections() const
598 {
599   Handle(TDataStd_ExtStringList) aNamesList;
600   Handle(TDataStd_IntegerList)   aTypesList;
601   Handle(TDataStd_BooleanList)   aClosuresList;
602   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
603
604   return !aClosuresList.IsNull() ? aClosuresList->Extent() : 0;
605 }
606
607 void HYDROData_PolylineXY::AddSection( const TCollection_AsciiString& theSectName,
608                                        const SectionType              theSectionType,
609                                        const bool                     theIsClosed )
610 {
611   Handle(TDataStd_ExtStringList) aNamesList;
612   Handle(TDataStd_IntegerList)   aTypesList;
613   Handle(TDataStd_BooleanList)   aClosuresList;
614   getSectionsLists( aNamesList, aTypesList, aClosuresList );
615
616   TCollection_ExtendedString aSectName( theSectName );
617   if ( aSectName.Length() <= 0 )
618     aSectName = getUniqueSectionName( aNamesList );
619
620   aNamesList->Append( aSectName );
621   aTypesList->Append( theSectionType );
622   aClosuresList->Append( theIsClosed );
623
624   SetToUpdate( true );
625 }
626
627 TCollection_AsciiString HYDROData_PolylineXY::GetSectionName( const int theSectionIndex ) const
628 {
629   TCollection_AsciiString aResName;
630
631   Handle(TDataStd_ExtStringList) aNamesList;
632   Handle(TDataStd_IntegerList) aTypesList;
633   Handle(TDataStd_BooleanList) aClosuresList;
634   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
635   if ( aNamesList.IsNull() || theSectionIndex >= aNamesList->Extent() )
636     return aResName;
637
638   TDataStd_ListIteratorOfListOfExtendedString aNamesIter( aNamesList->List() );
639   for ( int i = 0; aNamesIter.More() && i != theSectionIndex; aNamesIter.Next(), ++i );
640
641   if ( aNamesIter.More() )
642     aResName = aNamesIter.Value();
643
644   return aResName;
645 }
646
647 void HYDROData_PolylineXY::SetSectionName( const int                      theSectionIndex, 
648                                            const TCollection_AsciiString& theSectionName )
649 {
650   Handle(TDataStd_ExtStringList) aNamesList;
651   Handle(TDataStd_IntegerList) aTypesList;
652   Handle(TDataStd_BooleanList) aClosuresList;
653   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
654   if ( aNamesList.IsNull() || theSectionIndex >= aNamesList->Extent() )
655     return;
656
657   TDataStd_ListOfExtendedString anOldNamesList;
658   anOldNamesList = aNamesList->List();
659
660   // Refill the existing list
661   aNamesList->Clear();
662
663   TCollection_ExtendedString aNewSectName = theSectionName;
664
665   TDataStd_ListIteratorOfListOfExtendedString aNamesIter( anOldNamesList );
666   for ( int i = 0; aNamesIter.More(); aNamesIter.Next(), ++i )
667     aNamesList->Append( i == theSectionIndex ? aNewSectName : aNamesIter.Value() );
668
669   SetToUpdate( true );
670 }
671
672 HYDROData_PolylineXY::SectionType HYDROData_PolylineXY::GetSectionType( const int theSectionIndex ) const
673 {
674   Handle(TDataStd_ExtStringList) aNamesList;
675   Handle(TDataStd_IntegerList) aTypesList;
676   Handle(TDataStd_BooleanList) aClosuresList;
677   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
678   if ( aTypesList.IsNull() || theSectionIndex >= aTypesList->Extent() )
679     return SECTION_POLYLINE;
680
681   TColStd_ListIteratorOfListOfInteger aTypesIter( aTypesList->List() );
682   for ( int i = 0; aTypesIter.More() && i != theSectionIndex; aTypesIter.Next(), ++i );
683
684   return aTypesIter.More() ? (SectionType)aTypesIter.Value() : SECTION_POLYLINE;
685 }
686
687 void HYDROData_PolylineXY::SetSectionType( const int         theSectionIndex, 
688                                            const SectionType theSectionType )
689 {
690   Handle(TDataStd_ExtStringList) aNamesList;
691   Handle(TDataStd_IntegerList) aTypesList;
692   Handle(TDataStd_BooleanList) aClosuresList;
693   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
694   if ( aTypesList.IsNull() || theSectionIndex >= aTypesList->Extent() )
695     return;
696
697   TColStd_ListOfInteger anOldTypesList;
698   anOldTypesList = aTypesList->List();
699
700   // Refill the existing list
701   aTypesList->Clear();
702
703   TColStd_ListIteratorOfListOfInteger aTypesIter( anOldTypesList );
704   for ( int i = 0; aTypesIter.More(); aTypesIter.Next(), ++i )
705     aTypesList->Append( i == theSectionIndex ? theSectionType : aTypesIter.Value() );
706
707   SetToUpdate( true );
708 }
709
710 bool HYDROData_PolylineXY::IsClosedSection( const int theSectionIndex ) const
711 {
712   Handle(TDataStd_ExtStringList) aNamesList;
713   Handle(TDataStd_IntegerList) aTypesList;
714   Handle(TDataStd_BooleanList) aClosuresList;
715   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
716   if ( aClosuresList.IsNull() || theSectionIndex >= aClosuresList->Extent() )
717     return false;
718
719   TDataStd_ListIteratorOfListOfByte aClosuresIter( aClosuresList->List() );
720   for ( int i = 0; aClosuresIter.More() && i != theSectionIndex; aClosuresIter.Next(), ++i );
721
722   return aClosuresIter.More() ? (bool)aClosuresIter.Value() : false;
723 }
724
725 void HYDROData_PolylineXY::SetSectionClosed( const int  theSectionIndex, 
726                                              const bool theIsClosed )
727 {
728   Handle(TDataStd_ExtStringList) aNamesList;
729   Handle(TDataStd_IntegerList) aTypesList;
730   Handle(TDataStd_BooleanList) aClosuresList;
731   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
732   if ( aClosuresList.IsNull() || theSectionIndex >= aClosuresList->Extent() )
733     return;
734
735   TDataStd_ListOfByte anOldClosuresList;
736   anOldClosuresList = aClosuresList->List();
737
738   // Refill the existing list
739   aClosuresList->Clear();
740
741   TDataStd_ListIteratorOfListOfByte aClosuresIter( anOldClosuresList );
742   for ( int i = 0; aClosuresIter.More(); aClosuresIter.Next(), ++i )
743     aClosuresList->Append( i == theSectionIndex ? theIsClosed : (bool)aClosuresIter.Value() );
744
745   SetToUpdate( true );
746 }
747
748 void HYDROData_PolylineXY::GetSections( NCollection_Sequence<TCollection_AsciiString>& theSectNames,
749                                         NCollection_Sequence<SectionType>&             theSectTypes,
750                                         NCollection_Sequence<bool>&                    theSectClosures ) const
751 {
752   theSectNames.Clear();
753   theSectTypes.Clear();
754   theSectClosures.Clear();
755
756   Handle(TDataStd_ExtStringList) aNamesList;
757   Handle(TDataStd_IntegerList) aTypesList;
758   Handle(TDataStd_BooleanList) aClosuresList;
759   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
760   if ( aNamesList.IsNull() || aTypesList.IsNull() || aClosuresList.IsNull() )
761     return;
762
763   TDataStd_ListIteratorOfListOfExtendedString aNamesIter( aNamesList->List() );
764   TColStd_ListIteratorOfListOfInteger aTypesIter( aTypesList->List() );
765   TDataStd_ListIteratorOfListOfByte aClosuresIter( aClosuresList->List() );
766   for ( ; aNamesIter.More() && aTypesIter.More() && aClosuresIter.More();
767           aNamesIter.Next(), aTypesIter.Next(), aClosuresIter.Next() )
768   {
769     const TCollection_ExtendedString& aSectName = aNamesIter.Value();
770     SectionType aSectType = (SectionType)aTypesIter.Value();
771     bool aSectClosures = aClosuresIter.Value();
772
773     theSectNames.Append( aSectName );
774     theSectTypes.Append( aSectType );
775     theSectClosures.Append( aSectClosures );
776   }
777 }
778
779 void HYDROData_PolylineXY::RemoveSection( const int theSectionIndex )
780 {
781   Handle(TDataStd_ExtStringList) aNamesList;
782   Handle(TDataStd_IntegerList)   aTypesList;
783   Handle(TDataStd_BooleanList)   aClosuresList;
784   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
785   if ( aNamesList.IsNull() || theSectionIndex >= aNamesList->Extent() )
786     return;
787
788   if ( aNamesList->Extent() == 1 )
789   {
790     removeSectionsLists();
791     removePointsLists();
792   }
793   else
794   {
795     TDataStd_ListOfExtendedString anOldNamesList;
796     anOldNamesList = aNamesList->List();
797
798     TColStd_ListOfInteger anOldTypesList;
799     anOldTypesList = aTypesList->List();
800
801     TDataStd_ListOfByte anOldClosuresList;
802     anOldClosuresList = aClosuresList->List();
803
804     // Refill the existing lists
805     aNamesList->Clear();
806     aTypesList->Clear();
807     aClosuresList->Clear();
808
809     TDataStd_ListIteratorOfListOfExtendedString aNamesIter( anOldNamesList );
810     TColStd_ListIteratorOfListOfInteger aTypesIter( anOldTypesList );
811     TDataStd_ListIteratorOfListOfByte aClosuresIter( anOldClosuresList );
812     for ( int i = 0; aNamesIter.More() && aTypesIter.More() && aClosuresIter.More();
813                      aNamesIter.Next(), aTypesIter.Next(), aClosuresIter.Next(), ++i )
814     {
815       if ( i == theSectionIndex )
816         continue; // skip index to remove
817
818       aNamesList->Append( aNamesIter.Value() );
819       aTypesList->Append( aTypesIter.Value() );
820       aClosuresList->Append( (bool)aClosuresIter.Value() );
821     }
822
823     // Remove points that belongs to removed section
824     removePointsLists( theSectionIndex );
825   }
826
827   SetToUpdate( true );
828 }
829
830 void HYDROData_PolylineXY::RemoveSections()
831 {
832   removeSectionsLists();
833   removePointsLists();
834   SetToUpdate( true );
835 }
836
837 void HYDROData_PolylineXY::AddPoint( const int    theSectionIndex,
838                                      const Point& thePoint,
839                                      const int    thePointIndex )
840 {
841   Handle(TDataStd_RealList) aListX, aListY;
842   getPointsLists( theSectionIndex, aListX, aListY );
843
844   if ( thePointIndex < 0 || thePointIndex >= aListX->Extent() )
845   {
846     aListX->Append( thePoint.X() );
847     aListY->Append( thePoint.Y() );
848   }
849   else
850   {
851     TColStd_ListOfReal anOldListX;
852     anOldListX = aListX->List();
853
854     TColStd_ListOfReal anOldListY;
855     anOldListY = aListY->List();
856
857     // Refill the existing lists
858     aListX->Clear();
859     aListY->Clear();
860
861     TColStd_ListIteratorOfListOfReal anIterX( anOldListX );
862     TColStd_ListIteratorOfListOfReal anIterY( anOldListY );
863     for ( int i = 0; anIterX.More() && anIterY.More(); anIterX.Next(), anIterY.Next(), ++i )
864     {
865       double aCoordX = anIterX.Value();
866       double aCoordY = anIterY.Value();
867
868       if ( i == thePointIndex )
869       {
870         // Insert our new point
871         aListX->Append( thePoint.X() );
872         aListY->Append( thePoint.Y() );
873       }
874
875       aListX->Append( aCoordX );
876       aListY->Append( aCoordY );
877     }
878   }
879
880   SetToUpdate( true );
881 }
882
883 void HYDROData_PolylineXY::SetPoint( const int    theSectionIndex,
884                                      const Point& thePoint,
885                                      const int    thePointIndex )
886 {
887   Handle(TDataStd_RealList) aListX, aListY;
888   getPointsLists( theSectionIndex, aListX, aListY );
889
890   if ( thePointIndex < 0 )
891   {
892     aListX->Prepend( thePoint.X() );
893     aListY->Prepend( thePoint.Y() );
894   }
895   else if ( thePointIndex >= aListX->Extent() )
896   {
897     aListX->Append( thePoint.X() );
898     aListY->Append( thePoint.Y() );
899   }
900   else
901   {
902     TColStd_ListOfReal anOldListX;
903     anOldListX = aListX->List();
904
905     TColStd_ListOfReal anOldListY;
906     anOldListY = aListY->List();
907
908     // Refill the existing lists
909     aListX->Clear();
910     aListY->Clear();
911
912     TColStd_ListIteratorOfListOfReal anIterX( anOldListX );
913     TColStd_ListIteratorOfListOfReal anIterY( anOldListY );
914     for ( int i = 0; anIterX.More() && anIterY.More(); anIterX.Next(), anIterY.Next(), ++i )
915     {
916       double aCoordX = anIterX.Value();
917       double aCoordY = anIterY.Value();
918
919       if ( i == thePointIndex )
920       {
921         // Insert our new point instead of old one
922         aCoordX = thePoint.X();
923         aCoordY = thePoint.Y();
924       }
925
926       aListX->Append( aCoordX );
927       aListY->Append( aCoordY );
928     }
929   }
930
931   SetToUpdate( true );
932 }
933
934 void HYDROData_PolylineXY::SetPoints( const int         theSectionIndex,
935                                       const PointsList& thePoints )
936 {
937   Handle(TDataStd_RealList) aListX, aListY;
938   getPointsLists( theSectionIndex, aListX, aListY );
939
940   aListX->Clear();
941   aListY->Clear();
942
943   for ( int i = 1, n = thePoints.Length(); i <= n; ++i )
944   {
945     const Point& aPoint = thePoints.Value( i );
946     aListX->Append( aPoint.X() );
947     aListY->Append( aPoint.Y() );
948   }
949 }
950
951 void HYDROData_PolylineXY::RemovePoint( const int theSectionIndex,
952                                         const int thePointIndex )
953 {
954   Handle(TDataStd_RealList) aListX, aListY;
955   getPointsLists( theSectionIndex, aListX, aListY, false );
956   if ( aListX.IsNull() || aListY.IsNull() || aListX->IsEmpty() )
957     return;
958
959   if ( aListX->Extent() == 1 )
960   {
961     removePointsLists( theSectionIndex );
962   }
963   else
964   {
965     TColStd_ListOfReal anOldListX;
966     anOldListX = aListX->List();
967
968     TColStd_ListOfReal anOldListY;
969     anOldListY = aListY->List();
970
971     // Refill the existing lists
972     aListX->Clear();
973     aListY->Clear();
974
975     TColStd_ListIteratorOfListOfReal anIterX( anOldListX );
976     TColStd_ListIteratorOfListOfReal anIterY( anOldListY );
977     for ( int i = 0; anIterX.More() && anIterY.More(); anIterX.Next(), anIterY.Next(), ++i )
978     {
979       if ( i == thePointIndex )
980         continue; // skip index to remove
981
982       aListX->Append( anIterX.Value() );
983       aListY->Append( anIterY.Value() );
984     }
985   }
986
987   SetToUpdate( true );
988 }
989
990 HYDROData_PolylineXY::PointsList HYDROData_PolylineXY::GetPoints( const int theSectionIndex ) const
991 {
992   PointsList aResList;
993
994   Handle(TDataStd_RealList) aListX, aListY;
995   getPointsLists( theSectionIndex, aListX, aListY, false );
996   if ( aListX.IsNull() || aListY.IsNull() || aListX->IsEmpty() )
997     return aResList;
998
999   TColStd_ListIteratorOfListOfReal anIterX( aListX->List() );
1000   TColStd_ListIteratorOfListOfReal anIterY( aListY->List() );
1001   for ( ; anIterX.More() && anIterY.More(); anIterX.Next(), anIterY.Next() )
1002   {
1003     Point aPoint( anIterX.Value(), anIterY.Value() );
1004     aResList.Append( aPoint );
1005   }
1006
1007   return aResList;
1008 }
1009
1010 QPainterPath HYDROData_PolylineXY::GetPainterPath() const
1011 {
1012   QPainterPath aPath;
1013
1014   NCollection_Sequence<TCollection_AsciiString>           aSectNames;
1015   NCollection_Sequence<HYDROData_PolylineXY::SectionType> aSectTypes;
1016   NCollection_Sequence<bool>                              aSectClosures;
1017   GetSections( aSectNames, aSectTypes, aSectClosures );
1018
1019   for ( int aSectionId = 1, aNbSects = aSectNames.Size(); aSectionId <= aNbSects; aSectionId++ )
1020   {
1021     TCollection_AsciiString aSectName = aSectNames.Value( aSectionId );
1022     SectionType aSectionType = aSectTypes.Value( aSectionId );
1023     bool anIsSectionClosed = aSectClosures.Value( aSectionId );
1024
1025     PointsList aSectPointsList = GetPoints( aSectionId - 1 );
1026     if ( aSectPointsList.IsEmpty() )
1027       continue;
1028
1029     NCollection_Sequence<gp_XYZ> aPoints;
1030     for( int i = 1, n = aSectPointsList.Size(); i <= n; ++i )
1031     {
1032       const Point& aSectPoint = aSectPointsList.Value( i );
1033
1034       gp_XYZ aPoint( aSectPoint.X(), aSectPoint.Y(), 0.0 );
1035       aPoints.Append( aPoint );
1036     }
1037
1038     BuildPainterPath( aPath, aSectionType, anIsSectionClosed, aPoints );
1039   }
1040
1041   return aPath;
1042 }
1043
1044