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