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