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