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