Salome HOME
test Strickler
[modules/hydro.git] / src / HYDROData / HYDROData_PolylineXY.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include "HYDROData_PolylineXY.h"
20
21 #include "HYDROData_BSplineOperation.h"
22 #include "HYDROData_Document.h"
23 #include "HYDROData_ShapesTool.h"
24 #include "HYDROData_Tool.h"
25 #include "HYDROData_PolylineOperator.h"
26 #include "HYDROData_TopoCurve.h"
27
28 #include <BRep_Builder.hxx>
29 #include <BRepBuilderAPI_MakeEdge.hxx>
30 #include <BRepBuilderAPI_MakeWire.hxx>
31 #include <BRepBuilderAPI_MakePolygon.hxx>
32 #include <BRepBuilderAPI_MakeFace.hxx>
33 #include <BRepOffsetAPI_NormalProjection.hxx>
34 #include <BRepAdaptor_Curve.hxx>
35
36 #ifndef LIGHT_MODE
37 #include <GEOMBase.h>
38 #endif
39
40 #include <GeomAPI_ProjectPointOnCurve.hxx>
41 #include <GeomAdaptor_Curve.hxx>
42 #include <Geom_Line.hxx>
43 #include <Geom_BSplineCurve.hxx>
44
45 #include <GCPnts_AbscissaPoint.hxx>
46 #include <GCPnts_QuasiUniformDeflection.hxx>
47 #include <GCPnts_UniformDeflection.hxx>
48
49 #include <ImageComposer_MetaTypes.h>
50
51 #include <gp_Pnt.hxx>
52 #include <gp_XY.hxx>
53 #include <gp_Pln.hxx>
54
55 #include <NCollection_Map.hxx>
56
57 #include <TCollection_ExtendedString.hxx>
58
59 #include <TDataStd_ListIteratorOfListOfByte.hxx>
60 #include <TColStd_ListIteratorOfListOfInteger.hxx>
61 #include <TColStd_ListIteratorOfListOfReal.hxx>
62
63 #include <TColStd_Array1OfReal.hxx>
64 #include <TColgp_Array1OfPnt.hxx>
65
66 #include <TDataStd_AsciiString.hxx>
67 #include <TDataStd_BooleanList.hxx>
68 #include <TDataStd_ExtStringList.hxx>
69 #include <TDataStd_IntegerList.hxx>
70 #include <TDataStd_ListIteratorOfListOfExtendedString.hxx>
71 #include <TDataStd_RealList.hxx>
72 #include <TDataStd_UAttribute.hxx>
73
74 #include <TopoDS_Iterator.hxx>
75 #include <TopTools_ListIteratorOfListOfShape.hxx>
76 #include <TopTools_HSequenceOfShape.hxx>
77 #include <TopExp_Explorer.hxx>
78 #include <ShapeAnalysis_FreeBounds.hxx>
79 #include <TopoDS.hxx>
80
81 #include <QColor>
82 #include <QPainterPath>
83 #include <QVariant>
84
85 #define _DEVDEBUG_
86 #include "HYDRO_trace.hxx"
87 #include <BRepTools.hxx>
88 #include <sstream>
89 #include <cmath>
90
91 static const Standard_GUID GUID_IS_UNEDITABLE("e5799736-9030-4051-91a4-2e58321fa153");
92
93 const double LOCAL_SELECTION_TOLERANCE = 0.0001;
94
95 TCollection_AsciiString getUniqueSectionName( const NCollection_Sequence<TCollection_AsciiString>& theNamesSeq )
96 {
97   NCollection_Map<TCollection_AsciiString> aNamesMap;
98
99   for ( int i = 1, n = theNamesSeq.Size(); i <= n; ++i )
100   {
101     const TCollection_AsciiString& aSectName = theNamesSeq.Value( i );
102     aNamesMap.Add( aSectName );
103   }
104
105   TCollection_AsciiString aResName;
106
107   int aPrefIdx = 1;
108   do
109   {
110     aResName = TCollection_AsciiString( "Section_" ) + aPrefIdx;
111     ++aPrefIdx;
112   }
113   while ( aNamesMap.Contains( aResName ) );
114
115   return aResName;
116 }
117
118 TCollection_AsciiString getUniqueSectionName( const Handle(TDataStd_ExtStringList)& theNamesList )
119 {
120   NCollection_Sequence<TCollection_AsciiString> aNamesSeq;
121
122   TDataStd_ListIteratorOfListOfExtendedString aNamesIter( theNamesList->List() );
123   for ( ; aNamesIter.More(); aNamesIter.Next() )
124     aNamesSeq.Append( aNamesIter.Value() );
125
126   return getUniqueSectionName( aNamesSeq );
127 }
128
129 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_PolylineXY, HYDROData_IPolyline)
130
131 HYDROData_PolylineXY::HYDROData_PolylineXY()
132 : HYDROData_IPolyline(),
133   myIsInCustomFlag( false )
134 {
135 }
136
137 HYDROData_PolylineXY::~HYDROData_PolylineXY()
138 {
139 }
140
141 QStringList HYDROData_PolylineXY::DumpToPython( const QString&       thePyScriptPath,
142                                                 MapOfTreatedObjects& theTreatedObjects ) const
143 {
144   QStringList aResList = dumpObjectCreation( theTreatedObjects );
145   QString aPolylineName = GetObjPyName();
146
147   // Set the wire color
148   QStringList aWireColorDef;
149
150   QColor aWireColor = GetWireColor();
151   setPythonObjectColor( aWireColorDef, aWireColor, DefaultWireColor(), "SetWireColor" );
152   
153   if ( !aWireColorDef.isEmpty() )
154   {
155     aResList << aWireColorDef;
156     aResList << QString( "" );
157   }
158
159   bool anIsEditable = IsEditable();
160   if ( !anIsEditable )
161   {
162     // If polyline is not editable we try to import the shape from geom
163     TCollection_AsciiString aGeomObjectEntry = GetGeomObjectEntry();
164     if ( !aGeomObjectEntry.IsEmpty() )
165     {
166       QString aSalomeObjName = HYDROData_Tool::GenerateNameForPython( theTreatedObjects, "polyline_sobj" );
167       aResList << QString( "%1 = salome.myStudy.FindObjectID( \"%2\" )" )
168                   .arg( aSalomeObjName ).arg( aGeomObjectEntry.ToCString() );
169
170       aResList << QString( "%1.ImportFromGeomIOR( %2.GetIOR() )" )
171                   .arg( aPolylineName ).arg( aSalomeObjName );
172
173       aResList << QString( "%1.SetGeomObjectEntry( \"%2\" )" )
174                   .arg( aPolylineName ).arg( aGeomObjectEntry.ToCString() );
175     }
176   }
177   else
178   {
179     // Set polyline data
180     NCollection_Sequence<TCollection_AsciiString>           aSectNames;
181     NCollection_Sequence<HYDROData_PolylineXY::SectionType> aSectTypes;
182     NCollection_Sequence<bool>                              aSectClosures;
183     GetSections( aSectNames, aSectTypes, aSectClosures );
184
185     for ( int i = 1, n = aSectNames.Size(); i <= n; ++i )
186     {
187       const TCollection_AsciiString& aSectName = aSectNames.Value( i );
188       const SectionType& aSectType = aSectTypes.Value( i );
189       bool aSectClosure = aSectClosures.Value( i );
190
191       aResList << QString( "%1.AddSection( \"%2\", %3, %4 )" ).arg( aPolylineName )
192                   .arg( aSectName.ToCString() ).arg( aSectType ).arg( aSectClosure );
193
194       HYDROData_IPolyline::PointsList aSectPointsList = GetPoints( i - 1 );
195       for ( int k = 1, aNbPoints = aSectPointsList.Size(); k <= aNbPoints; ++k )
196       {
197         const Point& aSectPoint = aSectPointsList.Value( k );
198
199         QString anXStr = QString::number( aSectPoint.X(), 'f', 2 );
200         QString anYStr = QString::number( aSectPoint.Y(), 'f', 2 );
201         aResList << QString( "%1.AddPoint( %2, gp_XY( %3, %4 ) )" ).arg( aPolylineName )
202           .arg( i - 1 ).arg( anXStr ).arg( anYStr );
203       }
204     }
205   }
206   aResList << QString( "" );
207   aResList << QString( "%1.Update()" ).arg( aPolylineName );
208   aResList << QString( "" );
209
210   return aResList;
211 }
212
213 QVariant HYDROData_PolylineXY::GetDataVariant()
214 {
215   QPainterPath aPath = GetPainterPath();
216
217   QVariant aVarData;
218   aVarData.setValue<QPainterPath>( aPath );
219   
220   return aVarData;
221 }
222
223 QColor HYDROData_PolylineXY::DefaultWireColor()
224 {
225   return QColor( Qt::black );
226 }
227
228 bool HYDROData_PolylineXY::ImportFromGeomIOR( const TCollection_AsciiString& theIOR )
229 {
230 #ifdef LIGHT_MODE
231   return false;
232 #else
233   if ( theIOR.IsEmpty() )
234     return false;
235
236   TopoDS_Shape aShape = GEOMBase::GetShapeFromIOR( theIOR.ToCString() );
237   if ( aShape.IsNull() )
238     return false;
239
240   return ImportShape( aShape, false, NULL );
241 #endif
242 }
243
244 void HYDROData_PolylineXY::SetGeomObjectEntry( const TCollection_AsciiString& theEntry )
245 {
246   TDataStd_AsciiString::Set( myLab.FindChild( DataTag_GeomObjectEntry ), theEntry );
247 }
248
249 TCollection_AsciiString HYDROData_PolylineXY::GetGeomObjectEntry() const
250 {
251   TCollection_AsciiString aRes;
252
253   TDF_Label aLabel = myLab.FindChild( DataTag_GeomObjectEntry, false );
254   if ( !aLabel.IsNull() )
255   {
256     Handle(TDataStd_AsciiString) anAsciiStr;
257     if ( aLabel.FindAttribute( TDataStd_AsciiString::GetID(), anAsciiStr ) )
258       aRes = anAsciiStr->Get();
259   }
260
261   return aRes;
262 }
263
264 bool convertEdgeToSection( const TopoDS_Edge&                                       theEdge,
265                            NCollection_Sequence<TCollection_AsciiString>&           theSectNames,
266                            NCollection_Sequence<HYDROData_PolylineXY::SectionType>& theSectTypes,
267                            NCollection_Sequence<bool>&                              theSectClosures,
268                            NCollection_Sequence<HYDROData_PolylineXY::PointsList>&  theSectPoints,
269                            bool                                                     IsCanBeClosed,
270                            bool                                                     IsInterpolationAllowed,
271                            double                                                   theDeflection )
272 {
273   Standard_Real aFirst = 0.0, aLast = 0.0;
274   Handle(Geom_Curve) anEdgeGeomCurve = BRep_Tool::Curve( theEdge, aFirst, aLast );
275   if ( anEdgeGeomCurve.IsNull() )
276     return false;
277
278   TCollection_AsciiString aSectName = getUniqueSectionName( theSectNames );
279   bool anIsEdgeClosed = anEdgeGeomCurve->IsClosed();
280
281   HYDROData_PolylineXY::SectionType aSectionType = HYDROData_PolylineXY::SECTION_POLYLINE;
282   HYDROData_PolylineXY::PointsList aPointsList;
283
284   if( anEdgeGeomCurve->IsKind( STANDARD_TYPE(Geom_Line) ) )
285   {
286     Handle(Geom_Line) aGeomLine = Handle(Geom_Line)::DownCast( anEdgeGeomCurve );
287
288     gp_Pnt aFirstPoint, aLastPoint;
289     aGeomLine->D0( aFirst, aFirstPoint );
290     aGeomLine->D0( aLast, aLastPoint );
291
292     HYDROData_PolylineXY::Point aSectFirstPoint( aFirstPoint.X(), aFirstPoint.Y() );
293     aPointsList.Append( aSectFirstPoint );
294
295     HYDROData_PolylineXY::Point aSectLastPoint( aLastPoint.X(), aLastPoint.Y() );
296     aPointsList.Append( aSectLastPoint );
297   }
298   else if ( anEdgeGeomCurve->IsKind( STANDARD_TYPE(Geom_BSplineCurve) ) || IsInterpolationAllowed )
299   {
300     aSectionType = HYDROData_PolylineXY::SECTION_SPLINE;
301
302     BRepAdaptor_Curve anAdaptorCurve( theEdge );
303     GCPnts_QuasiUniformDeflection aDiscrete( anAdaptorCurve, theDeflection );
304     //GCPnts_UniformDeflection aDiscrete( anAdaptorCurve, theDeflection );
305
306     int aNbPoints = aDiscrete.NbPoints();
307
308     // Decrease the number of imported poles because of last one 
309     // pole is the closing point which are the start point
310     if ( anIsEdgeClosed ) aNbPoints--;
311
312     for ( int i = 1; i <= aNbPoints; ++i )
313     {
314       const gp_Pnt& aPoint = aDiscrete.Value( i );
315
316       HYDROData_PolylineXY::Point aSectPoint( aPoint.X(), aPoint.Y() );
317       aPointsList.Append( aSectPoint );
318     }
319   }
320   else
321   {
322     // Other curve types are not supported
323     return false;
324   }
325
326   if ( aPointsList.IsEmpty() )
327     return false;
328
329   theSectNames.Append( aSectName );
330   theSectTypes.Append( aSectionType );
331   theSectClosures.Append( anIsEdgeClosed );
332   theSectPoints.Append( aPointsList );
333
334   return true;
335 }
336
337
338 bool convertEdgesToSections( const TopoDS_Edge&                                       theEdge,
339                              NCollection_Sequence<TCollection_AsciiString>&           theSectNames,
340                              NCollection_Sequence<HYDROData_PolylineXY::SectionType>& theSectTypes,
341                              NCollection_Sequence<bool>&                              theSectClosures,
342                              NCollection_Sequence<HYDROData_PolylineXY::PointsList>&  theSectPoints,
343                              bool                                                     IsCanBeClosed,
344                              bool                                                     IsInterpolationAllowed,
345                              double                                                   theDeflection,
346                              const Handle( HYDROData_PolylineXY )&                    theOldPolyline )
347 {
348   //DEBTRACE("convertEdgesToSections")
349   Standard_Real aFirst = 0.0, aLast = 0.0;
350   Handle(Geom_Curve) anEdgeGeomCurve = BRep_Tool::Curve( theEdge, aFirst, aLast );
351   if ( anEdgeGeomCurve.IsNull() )
352     return false;
353
354   bool isPrevious = (theSectTypes.Size() > 0);
355   //DEBTRACE("nb sections: " << theSectTypes.Size());
356   HYDROData_PolylineXY::SectionType prevSectType = HYDROData_PolylineXY::SECTION_SPLINE;;
357   HYDROData_PolylineXY::PointsList prevPointList;
358   bool isPrevClosed = true;
359   if (isPrevious)
360     {
361        prevSectType = theSectTypes.Last();
362        prevPointList = theSectPoints.Last();
363        isPrevClosed = theSectClosures.Last();
364     }
365
366   bool anIsEdgeClosed = anEdgeGeomCurve->IsClosed();
367   anIsEdgeClosed &= IsCanBeClosed; // on split, resulting edges are normally not closed...
368   HYDROData_PolylineXY::SectionType aSectionType ;
369   if( anEdgeGeomCurve->IsKind( STANDARD_TYPE(Geom_Line) ) )
370     {
371       aSectionType = HYDROData_PolylineXY::SECTION_POLYLINE;
372     }
373   else if ( anEdgeGeomCurve->IsKind( STANDARD_TYPE(Geom_BSplineCurve) ) || IsInterpolationAllowed )
374     {
375       aSectionType = HYDROData_PolylineXY::SECTION_SPLINE;
376     }
377   else
378     {
379       // Other curve types are not supported
380       return false;
381     }
382
383   bool isNewSection = !isPrevious || isPrevClosed || anIsEdgeClosed || prevSectType != aSectionType;
384   //DEBTRACE(isNewSection <<": " << !isPrevious << " " << isPrevClosed << " " << anIsEdgeClosed << " " << (prevSectType != aSectionType));
385
386   HYDROData_PolylineXY::PointsList aPointsList;
387   if (!isNewSection)
388     {
389       aPointsList = prevPointList;
390     }
391
392   if( aSectionType == HYDROData_PolylineXY::SECTION_POLYLINE )
393     {
394       //DEBTRACE("SECTION_POLYLINE");
395       Handle(Geom_Line) aGeomLine = Handle(Geom_Line)::DownCast( anEdgeGeomCurve );
396
397       gp_Pnt aFirstPoint, aLastPoint;
398       aGeomLine->D0( aFirst, aFirstPoint );
399       aGeomLine->D0( aLast, aLastPoint );
400       HYDROData_PolylineXY::Point aSectFirstPoint( aFirstPoint.X(), aFirstPoint.Y() );
401       HYDROData_PolylineXY::Point aSectLastPoint( aLastPoint.X(), aLastPoint.Y() );
402      if (!isNewSection)
403         {
404           if (aSectFirstPoint == prevPointList.Last())
405             {
406               //DEBTRACE("points shared: a");//aPointsList.Append( aSectFirstPoint );
407               aPointsList.Append( aSectLastPoint );
408             }
409           else if (aSectLastPoint == prevPointList.Last())
410             {
411               //DEBTRACE("points shared: b");//aPointsList.Append( aSectLastPoint );
412               aPointsList.Append( aSectFirstPoint );
413             }
414           else if (aSectFirstPoint == prevPointList.First())
415             {
416               //DEBTRACE("points shared: c");//aPointsList.Prepend( aSectFirstPoint );
417               aPointsList.Prepend( aSectLastPoint );
418             }
419           else if (aSectLastPoint == prevPointList.First())
420             {
421               //DEBTRACE("points shared: d");//aPointsList.Prepend( aSectLastPoint );
422               aPointsList.Prepend( aSectFirstPoint );
423             }
424           else
425             {
426               //DEBTRACE("no point shared")
427               isNewSection = true; // no point shared, new section
428               aPointsList.Clear();
429               aPointsList.Append( aSectFirstPoint );
430               aPointsList.Append( aSectLastPoint );
431             }
432         }
433      else
434        {
435          //DEBTRACE("new section");
436          aPointsList.Append( aSectFirstPoint );
437          aPointsList.Append( aSectLastPoint );
438        }
439     }
440   else // aSectionType == HYDROData_PolylineXY::SECTION_SPLINE
441     {
442       //DEBTRACE("SECTION_SPLINE");
443       isNewSection = true;
444       aPointsList.Clear();
445
446       BRepAdaptor_Curve anAdaptorCurve(theEdge);
447       if (theOldPolyline.IsNull()) // --- no previous polyline: build a set of points from scratch for the spline
448         {
449           GCPnts_QuasiUniformDeflection aDiscrete(anAdaptorCurve, theDeflection);
450
451           int aNbPoints = aDiscrete.NbPoints();
452
453           // Decrease the number of imported poles because of last one
454           // pole is the closing point which are the start point
455           if (anIsEdgeClosed)
456             aNbPoints--;
457
458           for (int i = 1; i <= aNbPoints; ++i)
459             {
460               const gp_Pnt& aPoint = aDiscrete.Value(i);
461               HYDROData_PolylineXY::Point aSectPoint(aPoint.X(), aPoint.Y());
462               aPointsList.Append(aSectPoint);
463             }
464
465           gp_Pnt endPts[] = {gp_Pnt(aPointsList.First().X(),aPointsList.First().Y(), 0),
466                              gp_Pnt(aPointsList.Last().X(),aPointsList.Last().Y(), 0) };
467           //DEBTRACE("curve start: "<< endPts[0].X() << " " << endPts[0].Y());
468           //DEBTRACE("curve end: "<< endPts[1].X() << " " << endPts[1].Y());
469         }
470       else // --- split of a previous polyline: try to retrieve old sets of points and add intersection points
471         {
472           const gp_Pnt aEndPs[] = { anAdaptorCurve.Value(anAdaptorCurve.FirstParameter()).XYZ(),
473                                     anAdaptorCurve.Value(anAdaptorCurve.LastParameter()).XYZ() };
474           double midPar = (anAdaptorCurve.LastParameter() + anAdaptorCurve.FirstParameter())/2;
475           gp_Pnt midPnt;
476           anAdaptorCurve.D0(midPar, midPnt);
477           //DEBTRACE("curve first point: " << aEndPs[0].X() << " " << aEndPs[0].Y() << " " << aEndPs[0].Z());
478           //DEBTRACE("curve last point: " << aEndPs[1].X() << " " << aEndPs[1].Y() << " " << aEndPs[1].Z());
479           //DEBTRACE("curve mid point: " << midPnt.X() << " " << midPnt.Y() << " " << midPnt.Z());
480
481           std::vector<TopoDS_Wire> aCurves;
482           HYDROData_PolylineOperator::GetWires(theOldPolyline, aCurves);
483
484           int nbSections = theOldPolyline->NbSections();
485           //DEBTRACE("nbSections: "<< nbSections << ", nbCurves: " << aCurves.size() );
486           for (int isec = 0; isec < nbSections; isec++)
487             {
488               //DEBTRACE("section: "<< isec);
489               bool isOldSectionclosed = theOldPolyline->IsClosedSection(isec);
490               TopoDS_Wire aWire = aCurves[isec]; // we suppose sections and wires are in the same order
491               TopExp_Explorer anExp(aWire, TopAbs_EDGE);
492               TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current()); // the first is OK: only one normally with splines
493               BRepAdaptor_Curve adaptorOldCurve(anEdge);
494               double pfirst = adaptorOldCurve.FirstParameter();
495               double plast = adaptorOldCurve.LastParameter();
496               //DEBTRACE("previous curve first last : "<< pfirst << " " << plast);
497               double p[3] = {-1, -1};
498               double d0= ProjectPointToCurve(aEndPs[0].XYZ(), adaptorOldCurve,p[0]);
499               double d1= ProjectPointToCurve(aEndPs[1].XYZ(), adaptorOldCurve,p[1]);
500               double d2= ProjectPointToCurve(midPnt.XYZ(), adaptorOldCurve, p[2]);
501               //DEBTRACE("d0: "<<d0<<" d1: "<<d1<<" d2: "<<d2<<" p0: "<<p[0]<<" p1: "<<p[1]<<" p2: "<<p[2]);
502               if ((d0 < 1.e-3) && (d1 < 1.e-3) && (d2 < 1.e-3)) // we got the good old curve (and the good section)
503                 {
504                   double pmin = p[0];
505                   double pmax = p[1];
506                   bool forward = true;
507                   //DEBTRACE("isOldSectionclosed: " << isOldSectionclosed);
508                   if (!isOldSectionclosed) // no need to check first and last points on an open curve
509                     {
510                       if (pmin > pmax)
511                         {
512                           pmin = p[1];
513                           pmax = p[0];
514                           forward = false;
515                         }
516                     }
517                   else // old section closed: check if we use first or last points...
518                     {
519                       if((pmin < pmax) && ((abs(pmin - pfirst)> 1.e-3) && (abs(pmax - plast) >1.e-3))) // internal points forward
520                         forward = true;
521                       else if ((pmin > pmax) && ((abs(pmin - plast)> 1.e-3) && (abs(pmax - pfirst) >1.e-3))) // internal points reverse
522                         {
523                           pmin = p[1];
524                           pmax = p[0];
525                           forward = false;
526                         }
527                       else if ((abs(pmin - plast) <1.e-3) && (p[2] < pmax)) // forward, replace pmin par pfirst
528                           pmin = pfirst;
529                       else if ((abs(pmin - plast) <1.e-3) && (p[2] > pmax)) // reverse
530                         {
531                           pmin = p[1];
532                           pmax = p[0];
533                           forward = false;
534                         }
535                       else if ((abs(pmax - pfirst) <1.e-3) && (p[2] < pmin)) // reverse
536                         {
537                           pmin = p[1];
538                           pmax = p[0];
539                           forward = false;
540                         }
541                       else if ((abs(pmax - pfirst) <1.e-3) && (p[2] > pmin)) // forward, replace pmax par plast
542                         pmax = plast;
543                    }
544                   //DEBTRACE("forward: "<< forward << " pmin " << pmin <<  " pmax " << pmax);
545                   HYDROData_PolylineXY::Point aFirstPoint, aLastPoint;
546                   if (forward)
547                     {
548                       aFirstPoint = HYDROData_PolylineXY::Point(aEndPs[0].X(), aEndPs[0].Y());
549                       aLastPoint = HYDROData_PolylineXY::Point(aEndPs[1].X(), aEndPs[1].Y());
550                     }
551                   else
552                     {
553                       aFirstPoint = HYDROData_PolylineXY::Point(aEndPs[1].X(), aEndPs[1].Y());
554                       aLastPoint = HYDROData_PolylineXY::Point(aEndPs[0].X(), aEndPs[0].Y());
555                     }
556                   aPointsList.Append(aFirstPoint);
557
558                   HYDROData_PolylineXY::PointsList aSectPoints = theOldPolyline->GetPoints(isec, false);
559                   int nbPoints = aSectPoints.Length();
560                   //DEBTRACE("nbPoints " << nbPoints);
561                   if (forward)
562                     for (int i=1; i<=nbPoints; i++)
563                       {
564                         HYDROData_PolylineXY::Point aPoint = aSectPoints.Value(i);
565                         gp_XYZ p(aPoint.X(), aPoint.Y(), 0);
566                         double param =-1;
567                         double d = ProjectPointToCurve(p, adaptorOldCurve, param);
568                         if ((param > pmin) && (param < pmax))
569                           {
570                             //DEBTRACE("param: " << param);
571                             aPointsList.Append(aPoint);
572                           }
573                       }
574                   else
575                     for (int i=nbPoints; i>0; i--)
576                       {
577                         HYDROData_PolylineXY::Point aPoint = aSectPoints.Value(i);
578                         gp_XYZ p(aPoint.X(), aPoint.Y(), 0);
579                         double param =-1;
580                         double d = ProjectPointToCurve(p, adaptorOldCurve, param);
581                         if ((param > pmin) && (param < pmax))
582                           {
583                             //DEBTRACE("param: " << param);
584                             aPointsList.Append(aPoint);
585                           }
586                       }
587
588                   aPointsList.Append(aLastPoint);
589                 }
590
591             }
592         }
593     }
594
595   if ( aPointsList.IsEmpty() )
596     return false;
597
598   TCollection_AsciiString aSectName = getUniqueSectionName( theSectNames );
599   if (isNewSection)
600     {
601       //DEBTRACE("isNewSection");
602       theSectNames.Append( aSectName );
603       theSectTypes.Append( aSectionType );
604       theSectClosures.Append( anIsEdgeClosed );
605       theSectPoints.Append( aPointsList );
606     }
607   else
608     {
609       //DEBTRACE("sameSection");
610       theSectPoints.SetValue(theSectPoints.Length(), aPointsList);
611     }
612
613   return true;
614 }
615
616 bool HYDROData_PolylineXY::ImportShape( const TopoDS_Shape& theShape,
617                                         bool IsInterpolationAllowed,
618                                         const Handle( HYDROData_PolylineXY )& theOldPolyline,
619                                         bool IsClosureAllowed,
620                                         double theDeviation )
621 {
622   //DEBTRACE("ImportShape");
623   if ( theShape.IsNull() )
624     return false;
625
626   //std::string brepName = this->GetName().toStdString();
627   //brepName += ".brep";
628   //BRepTools::Write( theShape, brepName.c_str() );
629
630   RemoveSections();
631
632   bool anIsCanBeImported = false;
633
634   NCollection_Sequence<TCollection_AsciiString> aSectNames;
635   NCollection_Sequence<SectionType>             aSectTypes;
636   NCollection_Sequence<bool>                    aSectClosures;
637   NCollection_Sequence<PointsList>              aSectPoints;
638
639   if ( theShape.ShapeType() == TopAbs_EDGE )
640   {
641       //DEBTRACE("TopAbs_EDGE");
642     TopoDS_Edge anEdge = TopoDS::Edge( theShape );
643 //    anIsCanBeImported = convertEdgeToSection( anEdge, aSectNames, aSectTypes,
644 //      aSectClosures, aSectPoints, true, IsInterpolationAllowed, theDeviation );
645     anIsCanBeImported = convertEdgesToSections( anEdge, aSectNames, aSectTypes, aSectClosures,
646                                                 aSectPoints, IsClosureAllowed, IsInterpolationAllowed,
647                                                 theDeviation, theOldPolyline );
648   }
649   else if ( theShape.ShapeType() == TopAbs_WIRE )
650   {
651       //DEBTRACE("TopAbs_WIRE");
652     TopTools_SequenceOfShape anEdges;
653     HYDROData_ShapesTool::ExploreShapeToShapes( theShape, TopAbs_EDGE, anEdges );
654
655     anIsCanBeImported = !anEdges.IsEmpty();
656     for ( int i = 1, n = anEdges.Length(); i <= n && anIsCanBeImported; ++i )
657     {
658       TopoDS_Edge aWireEdge = TopoDS::Edge( anEdges.Value( i ) );
659       anIsCanBeImported = convertEdgesToSections( aWireEdge, aSectNames, aSectTypes, aSectClosures,
660                                                   aSectPoints, IsClosureAllowed, IsInterpolationAllowed,
661                                                   theDeviation, theOldPolyline );
662     }
663   }
664
665   if ( anIsCanBeImported )
666   {
667     for ( int i = 1, n = aSectNames.Length(); i <= n; ++i )
668     {
669       const TCollection_AsciiString& aSectName = aSectNames.Value( i );
670       const SectionType& aSectType = aSectTypes.Value( i );
671       bool anIsSectionClosed = aSectClosures.Value( i );
672       const PointsList& aSectPointsList = aSectPoints( i );
673
674       AddSection( aSectName, aSectType, anIsSectionClosed );
675       SetPoints( i - 1, aSectPointsList );
676     }
677   }
678   else
679   {
680     TopoDS_Shape aShape = theShape;
681
682     if ( theShape.ShapeType() == TopAbs_EDGE )
683     {
684       // We make the wire from incoming edge because of other algorithms
685       // are waiting at least the wire from polyline
686       TopoDS_Edge anEdge = TopoDS::Edge( theShape );
687       BRepBuilderAPI_MakeWire aMakeWire( anEdge );
688       aMakeWire.Build();
689       if ( aMakeWire.IsDone() )
690         aShape = aMakeWire.Wire();
691     }
692
693     gp_Pln aPlane( gp_Pnt( 0, 0, 0 ), gp_Dir( 0, 0, 1 ) );
694     BRepBuilderAPI_MakeFace aMakeFace( aPlane );
695     aMakeFace.Build();
696     BRepOffsetAPI_NormalProjection aProj( aMakeFace.Face() );
697     aProj.Add( aShape );
698     aProj.Build();
699     TopoDS_Shape aResult;
700     if( aProj.IsDone() )
701       aResult = aProj.Shape();
702
703     SetShape( aResult );
704   }
705
706   setEditable( anIsCanBeImported );
707   Update();
708   return true;
709 }
710
711 TopoDS_Wire HYDROData_PolylineXY::BuildWire( const SectionType&                  theType,
712                                              const bool&                         theIsClosed,
713                                              const NCollection_Sequence<gp_XYZ>& thePoints )
714 {
715   TopoDS_Wire aWire;
716   if( theType == SECTION_POLYLINE )
717   {
718     int aNbPoints = thePoints.Length();
719     BRepBuilderAPI_MakePolygon aMakeWire;
720     for ( int i = 1, n = aNbPoints; i <= n ; ++i )
721     {
722       gp_XYZ aPoint = thePoints.Value( i );
723       gp_Pnt aPnt( aPoint.X(), aPoint.Y(), aPoint.Z() );
724       aMakeWire.Add( aPnt );
725     }
726     if( theIsClosed && ( aNbPoints > 2 ) )
727       aMakeWire.Close();
728
729     if ( aMakeWire.IsDone() )
730       aWire = aMakeWire.Wire();
731   }
732   else //if( theType == PolylineSection::SECTION_SPLINE )
733   {
734     BRepBuilderAPI_MakeWire aMakeWire;
735
736     if ( thePoints.Size() > 1 )
737     {
738       Handle(Geom_BSplineCurve) aCurve = 
739         HYDROData_BSplineOperation::ComputeCurve( thePoints, theIsClosed, LOCAL_SELECTION_TOLERANCE );
740
741       TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge( aCurve ).Edge();
742       aMakeWire.Add( anEdge );
743     }
744     aMakeWire.Build();
745     if ( aMakeWire.IsDone() )
746       aWire = aMakeWire;
747   }
748
749   return aWire;
750 }
751
752 void HYDROData_PolylineXY::BuildPainterPath( QPainterPath&                       thePath,
753                                              const SectionType&                  theType,
754                                              const bool&                         theIsClosed,
755                                              const NCollection_Sequence<gp_XYZ>& thePoints )
756 {
757   if ( thePoints.IsEmpty() )
758     return;
759
760   if ( theType == SECTION_POLYLINE )
761   {
762     const gp_XYZ& aFirstPoint = thePoints.Value( 1 );
763     thePath.moveTo( aFirstPoint.X(), aFirstPoint.Y() );
764
765     for( int i = 2, n = thePoints.Size(); i <= n; ++i )
766     {
767       const gp_XYZ& aSectPoint = thePoints.Value( i );
768
769       thePath.lineTo( aSectPoint.X(), aSectPoint.Y() );
770     }
771
772     if( theIsClosed )
773       thePath.closeSubpath();
774   }
775   else
776   {
777     Handle(Geom_BSplineCurve) aCurve = 
778       HYDROData_BSplineOperation::ComputeCurve( thePoints, theIsClosed, LOCAL_SELECTION_TOLERANCE );
779     HYDROData_BSplineOperation::ComputePath( aCurve, thePath );
780   }
781 }
782
783 void HYDROData_PolylineXY::Update()
784 {
785   if ( !IsEditable() )
786   {
787     // If polyline is not editable we no need to update it wire
788     ClearChanged();
789     return;
790   }
791
792   HYDROData_IPolyline::Update();
793
794   NCollection_Sequence<TCollection_AsciiString>           aSectNames;
795   NCollection_Sequence<HYDROData_PolylineXY::SectionType> aSectTypes;
796   NCollection_Sequence<bool>                              aSectClosures;
797   GetSections( aSectNames, aSectTypes, aSectClosures );
798
799   //BRepBuilderAPI_MakeWire aMakeWire;
800
801   TopTools_ListOfShape aSectionWiresList;
802
803   for ( int aSectionId = 1, aNbSects = aSectNames.Size(); aSectionId <= aNbSects; aSectionId++ )
804   {
805     TCollection_AsciiString aSectName = aSectNames.Value( aSectionId );
806     SectionType aSectionType = aSectTypes.Value( aSectionId );
807     bool anIsSectionClosed = aSectClosures.Value( aSectionId );
808
809     PointsList aSectPointsList = GetPoints( aSectionId - 1 );
810     if ( aSectPointsList.IsEmpty() )
811       continue;
812     
813     NCollection_Sequence<gp_XYZ> aPoints;
814     for( int i = 1, n = aSectPointsList.Size(); i <= n; ++i )
815     {
816       const Point& aSectPoint = aSectPointsList.Value( i );
817
818       gp_XYZ aPoint( aSectPoint.X(), aSectPoint.Y(), 0.0 );
819       aPoints.Append( aPoint );
820     }
821
822     TopoDS_Wire aSectionWire = BuildWire( aSectionType, anIsSectionClosed, aPoints );
823     if ( !aSectionWire.IsNull() ) {
824       aSectionWiresList.Append( aSectionWire );
825       //aMakeWire.Add( aSectionWire );
826     }
827   }
828 // all input wires in the <aSectionWiresList>
829   Handle(TopTools_HSequenceOfShape) aSeqWires = new TopTools_HSequenceOfShape;
830   Handle(TopTools_HSequenceOfShape) aSeqEdges = new TopTools_HSequenceOfShape;
831   TopTools_ListIteratorOfListOfShape it(aSectionWiresList);
832   for(;it.More();it.Next())
833   {
834     TopExp_Explorer it2(it.Value(), TopAbs_EDGE);
835     for(;it2.More();it2.Next()) 
836       aSeqEdges->Append(it2.Current());
837   }
838
839   BRep_Builder aBB;
840   TopoDS_Compound aCmp;
841   TopoDS_Shape aResult;
842   aBB.MakeCompound(aCmp);
843   if(aSeqEdges->Length() >1)
844   {
845     ShapeAnalysis_FreeBounds::ConnectEdgesToWires( aSeqEdges, 1E-5, Standard_True, aSeqWires );
846
847     if( aSeqWires->Length()==1 )
848       aResult = aSeqWires->Value( 1 );
849     else
850     {
851       for (Standard_Integer i = 1; i <= aSeqWires->Length();i++)
852       {
853         const TopoDS_Shape& aS1 = aSeqWires->Value(i);
854         aBB.Add(aCmp, aS1);
855       }
856       aResult = aCmp;
857     }
858   }
859   else if (aSeqEdges->Length() == 1)
860   {
861     BRepBuilderAPI_MakeWire mkWire (TopoDS::Edge(aSeqEdges->Value(1)));
862     if (mkWire.IsDone())
863       aResult = mkWire.Wire();
864   }
865
866   SetShape( aResult );
867 }
868
869 bool HYDROData_PolylineXY::IsHas2dPrs() const
870 {
871   return true;
872 }
873
874 bool HYDROData_PolylineXY::IsEditable() const
875 {
876   return !myLab.IsAttribute( GUID_IS_UNEDITABLE );
877 }
878
879 void HYDROData_PolylineXY::setEditable( const bool theIsEditable )
880 {
881   if ( !theIsEditable )
882     TDataStd_UAttribute::Set( myLab, GUID_IS_UNEDITABLE );
883   else
884     myLab.ForgetAttribute( GUID_IS_UNEDITABLE );
885 }
886
887 /**
888  * Returns true if polyline is closed
889  */
890 bool HYDROData_PolylineXY::IsClosed(const bool theIsSimpleCheck) const
891 {
892   //DEBTRACE("IsClosed " << theIsSimpleCheck << " " << GetName());
893   bool anIsClosed = false;
894
895   TopoDS_Shape aShape = GetShape();
896   if (aShape.IsNull())
897     return anIsClosed;
898
899   TopTools_SequenceOfShape aWires;
900   HYDROData_ShapesTool::ExploreShapeToShapes(aShape, TopAbs_WIRE, aWires);
901
902   int aNbWires = aWires.Length();
903   if (theIsSimpleCheck)
904     {
905       anIsClosed = aNbWires > 0;
906       for (int i = 1; i <= aNbWires && anIsClosed; ++i)
907         {
908           const TopoDS_Shape& aWire = aWires.Value(i);
909           anIsClosed = BRep_Tool::IsClosed(aWire);
910         }
911     }
912   else
913     {
914       if (aNbWires == 1)
915         anIsClosed = BRep_Tool::IsClosed(aWires.First());
916       else
917         {
918           //DEBTRACE("aNbWires " << aNbWires);
919           Handle(TopTools_HSequenceOfShape) aSeqWires = new TopTools_HSequenceOfShape;
920           Handle(TopTools_HSequenceOfShape) aSeqEdges = new TopTools_HSequenceOfShape;
921           for (int i = 1; i <= aNbWires; ++i)
922             {
923               const TopoDS_Shape& aWire = aWires.Value(i);
924               TopExp_Explorer it2(aWire, TopAbs_EDGE);
925               for (; it2.More(); it2.Next())
926                 aSeqEdges->Append(it2.Current());
927             }
928           if (aSeqEdges->Length() > 1)
929             {
930               //DEBTRACE(aSeqEdges->Length());
931               ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdges, 1E-5, Standard_False, aSeqWires);
932               if (aSeqWires->Length() == 1)
933                 {
934                   //DEBTRACE(aSeqWires->Length());
935                   const TopoDS_Wire& aPolylineWire = TopoDS::Wire(aSeqWires->Value(1));
936                   anIsClosed = BRep_Tool::IsClosed(aPolylineWire);
937                 }
938             }
939         }
940     }
941
942   return anIsClosed;
943 }
944
945 int HYDROData_PolylineXY::GetNbConnectedWires(Handle(TopTools_HSequenceOfShape)& aConnectedWires) const
946 {
947   TopoDS_Shape aShape = GetShape();
948   if (aShape.IsNull())
949     return 0;
950   int aNbconnectedWires = 0;
951   TopTools_SequenceOfShape aWires;
952   HYDROData_ShapesTool::ExploreShapeToShapes(aShape, TopAbs_WIRE, aWires);
953   int aNbWires = aWires.Length();
954   if (aNbWires == 1)
955     {
956       aNbconnectedWires = aNbWires;
957       aConnectedWires->Append(aWires.First());
958     }
959   else
960     {
961       //DEBTRACE("aNbWires " << aNbWires);
962       Handle(TopTools_HSequenceOfShape) aSeqWires = new TopTools_HSequenceOfShape;
963       Handle(TopTools_HSequenceOfShape) aSeqEdges = new TopTools_HSequenceOfShape;
964       for (int i = 1; i <= aNbWires; ++i)
965         {
966           const TopoDS_Shape& aWire = aWires.Value(i);
967           TopExp_Explorer it2(aWire, TopAbs_EDGE);
968           for (; it2.More(); it2.Next())
969             aSeqEdges->Append(it2.Current());
970         }
971       if (aSeqEdges->Length() > 1)
972         {
973           //DEBTRACE(aSeqEdges->Length());
974           ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdges, 1E-5, Standard_False, aSeqWires);
975         }
976       aConnectedWires = aSeqWires;
977       aNbconnectedWires = aConnectedWires->Length();
978       DEBTRACE("aNbconnectedWires " << aNbconnectedWires);
979     }
980 return aNbconnectedWires;
981 }
982
983 double HYDROData_PolylineXY::GetDistance( const int theSectionIndex,
984                                           const int thePointIndex ) const
985 {
986   double aResDistance = -1;
987   if ( theSectionIndex < 0 || theSectionIndex >= NbSections() )
988     return aResDistance;
989
990   if ( thePointIndex == 0 )
991     return 0.0;
992
993   SectionType aSectionType = GetSectionType( theSectionIndex );
994   bool anIsSectionClosed = IsClosedSection( theSectionIndex );
995   PointsList aSectPointsList = GetPoints( theSectionIndex );
996   if ( thePointIndex < 0 || thePointIndex >= aSectPointsList.Size()  )
997     return aResDistance;
998
999   if ( aSectionType == SECTION_POLYLINE )
1000   {
1001     aResDistance = 0.0;
1002   
1003     Point aPrevPoint = aSectPointsList.Value( 1 );
1004     for ( int i = 2, aNbPoints = aSectPointsList.Size(); i <= aNbPoints; ++i )
1005     {
1006       const Point& aSectPoint = aSectPointsList.Value( i );
1007       aResDistance += gp_Pnt2d( aPrevPoint ).Distance( aSectPoint );
1008       aPrevPoint = aSectPoint;
1009
1010       if ( thePointIndex == i - 1 )
1011         break;
1012     }
1013   }
1014   else
1015   {
1016     gp_XYZ aPointToTest;
1017
1018     int aSectNbPoints = aSectPointsList.Size();
1019     NCollection_Sequence<gp_XYZ> aPoints;
1020     for( int i = 1 ; i <= aSectNbPoints; ++i )
1021     {
1022       const Point& aSectPoint = aSectPointsList.Value( i );
1023
1024       gp_XYZ aPoint( aSectPoint.X(), aSectPoint.Y(), 0.0 );
1025       aPoints.Append( aPoint );
1026
1027       if ( thePointIndex == i - 1 )
1028         aPointToTest = aPoint;
1029     }
1030
1031     Handle(Geom_BSplineCurve) aCurve = 
1032       HYDROData_BSplineOperation::ComputeCurve( aPoints, anIsSectionClosed, LOCAL_SELECTION_TOLERANCE );
1033
1034     Quantity_Parameter aFirstParam = aCurve->FirstParameter();
1035     Quantity_Parameter aSecondParam = aCurve->LastParameter();
1036
1037     if ( thePointIndex != aSectNbPoints - 1 )
1038     {
1039       GeomAPI_ProjectPointOnCurve aProject( aPointToTest, aCurve );
1040       aSecondParam = aProject.LowerDistanceParameter();
1041     }
1042
1043     GeomAdaptor_Curve anAdap( aCurve );
1044     
1045     aResDistance = GCPnts_AbscissaPoint::Length( anAdap, aFirstParam, aSecondParam );
1046   }
1047
1048   return aResDistance;
1049 }
1050
1051 int HYDROData_PolylineXY::NbSections() const
1052 {
1053   Handle(TDataStd_ExtStringList) aNamesList;
1054   Handle(TDataStd_IntegerList)   aTypesList;
1055   Handle(TDataStd_BooleanList)   aClosuresList;
1056   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
1057
1058   return !aClosuresList.IsNull() ? aClosuresList->Extent() : 0;
1059 }
1060
1061 void HYDROData_PolylineXY::AddSection( const TCollection_AsciiString& theSectName,
1062                                        const SectionType              theSectionType,
1063                                        const bool                     theIsClosed )
1064 {
1065   Handle(TDataStd_ExtStringList) aNamesList;
1066   Handle(TDataStd_IntegerList)   aTypesList;
1067   Handle(TDataStd_BooleanList)   aClosuresList;
1068   getSectionsLists( aNamesList, aTypesList, aClosuresList );
1069
1070   TCollection_ExtendedString aSectName( theSectName );
1071   if ( aSectName.Length() <= 0 )
1072     aSectName = getUniqueSectionName( aNamesList );
1073
1074   aNamesList->Append( aSectName );
1075   aTypesList->Append( theSectionType );
1076   aClosuresList->Append( theIsClosed );
1077
1078   Changed( Geom_2d );
1079 }
1080
1081 TCollection_AsciiString HYDROData_PolylineXY::GetSectionName( const int theSectionIndex ) const
1082 {
1083   TCollection_AsciiString aResName;
1084
1085   Handle(TDataStd_ExtStringList) aNamesList;
1086   Handle(TDataStd_IntegerList) aTypesList;
1087   Handle(TDataStd_BooleanList) aClosuresList;
1088   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
1089   if ( aNamesList.IsNull() || theSectionIndex >= aNamesList->Extent() )
1090     return aResName;
1091
1092   TDataStd_ListIteratorOfListOfExtendedString aNamesIter( aNamesList->List() );
1093   for ( int i = 0; aNamesIter.More() && i != theSectionIndex; aNamesIter.Next(), ++i );
1094
1095   if ( aNamesIter.More() )
1096     aResName = aNamesIter.Value();
1097
1098   return aResName;
1099 }
1100
1101 void HYDROData_PolylineXY::SetSectionName( const int                      theSectionIndex, 
1102                                            const TCollection_AsciiString& theSectionName )
1103 {
1104   Handle(TDataStd_ExtStringList) aNamesList;
1105   Handle(TDataStd_IntegerList) aTypesList;
1106   Handle(TDataStd_BooleanList) aClosuresList;
1107   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
1108   if ( aNamesList.IsNull() || theSectionIndex >= aNamesList->Extent() )
1109     return;
1110
1111   TDataStd_ListOfExtendedString anOldNamesList;
1112   anOldNamesList = aNamesList->List();
1113
1114   // Refill the existing list
1115   aNamesList->Clear();
1116
1117   TCollection_ExtendedString aNewSectName = theSectionName;
1118
1119   TDataStd_ListIteratorOfListOfExtendedString aNamesIter( anOldNamesList );
1120   for ( int i = 0; aNamesIter.More(); aNamesIter.Next(), ++i )
1121     aNamesList->Append( i == theSectionIndex ? aNewSectName : aNamesIter.Value() );
1122 }
1123
1124 HYDROData_PolylineXY::SectionType HYDROData_PolylineXY::GetSectionType( const int theSectionIndex ) const
1125 {
1126   Handle(TDataStd_ExtStringList) aNamesList;
1127   Handle(TDataStd_IntegerList) aTypesList;
1128   Handle(TDataStd_BooleanList) aClosuresList;
1129   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
1130   if ( aTypesList.IsNull() || theSectionIndex >= aTypesList->Extent() )
1131     return SECTION_POLYLINE;
1132
1133   TColStd_ListIteratorOfListOfInteger aTypesIter( aTypesList->List() );
1134   for ( int i = 0; aTypesIter.More() && i != theSectionIndex; aTypesIter.Next(), ++i );
1135
1136   return aTypesIter.More() ? (SectionType)aTypesIter.Value() : SECTION_POLYLINE;
1137 }
1138
1139 void HYDROData_PolylineXY::SetSectionType( const int         theSectionIndex, 
1140                                            const SectionType theSectionType )
1141 {
1142   Handle(TDataStd_ExtStringList) aNamesList;
1143   Handle(TDataStd_IntegerList) aTypesList;
1144   Handle(TDataStd_BooleanList) aClosuresList;
1145   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
1146   if ( aTypesList.IsNull() || theSectionIndex >= aTypesList->Extent() )
1147     return;
1148
1149   TColStd_ListOfInteger anOldTypesList;
1150   anOldTypesList = aTypesList->List();
1151
1152   // Refill the existing list
1153   aTypesList->Clear();
1154
1155   TColStd_ListIteratorOfListOfInteger aTypesIter( anOldTypesList );
1156   for ( int i = 0; aTypesIter.More(); aTypesIter.Next(), ++i )
1157     aTypesList->Append( i == theSectionIndex ? theSectionType : aTypesIter.Value() );
1158
1159   Changed( Geom_2d );
1160 }
1161
1162 bool HYDROData_PolylineXY::IsClosedSection( const int theSectionIndex ) const
1163 {
1164   Handle(TDataStd_ExtStringList) aNamesList;
1165   Handle(TDataStd_IntegerList) aTypesList;
1166   Handle(TDataStd_BooleanList) aClosuresList;
1167   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
1168   if ( aClosuresList.IsNull() || theSectionIndex >= aClosuresList->Extent() )
1169     return false;
1170
1171   TDataStd_ListIteratorOfListOfByte aClosuresIter( aClosuresList->List() );
1172   for ( int i = 0; aClosuresIter.More() && i != theSectionIndex; aClosuresIter.Next(), ++i );
1173
1174   return aClosuresIter.More() ? (bool)aClosuresIter.Value() : false;
1175 }
1176
1177 void HYDROData_PolylineXY::SetSectionClosed( const int  theSectionIndex, 
1178                                              const bool theIsClosed )
1179 {
1180   Handle(TDataStd_ExtStringList) aNamesList;
1181   Handle(TDataStd_IntegerList) aTypesList;
1182   Handle(TDataStd_BooleanList) aClosuresList;
1183   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
1184   if ( aClosuresList.IsNull() || theSectionIndex >= aClosuresList->Extent() )
1185     return;
1186
1187   TDataStd_ListOfByte anOldClosuresList;
1188   anOldClosuresList = aClosuresList->List();
1189
1190   // Refill the existing list
1191   aClosuresList->Clear();
1192
1193   TDataStd_ListIteratorOfListOfByte aClosuresIter( anOldClosuresList );
1194   for ( int i = 0; aClosuresIter.More(); aClosuresIter.Next(), ++i )
1195     aClosuresList->Append( i == theSectionIndex ? theIsClosed : (bool)aClosuresIter.Value() );
1196
1197   Changed( Geom_2d );
1198 }
1199
1200 void HYDROData_PolylineXY::GetSections( NCollection_Sequence<TCollection_AsciiString>& theSectNames,
1201                                         NCollection_Sequence<SectionType>&             theSectTypes,
1202                                         NCollection_Sequence<bool>&                    theSectClosures ) const
1203 {
1204   theSectNames.Clear();
1205   theSectTypes.Clear();
1206   theSectClosures.Clear();
1207
1208   if( IsCustom() )
1209   {
1210     const_cast<HYDROData_PolylineXY*>( this )->Interpolate();
1211   }
1212
1213   Handle(TDataStd_ExtStringList) aNamesList;
1214   Handle(TDataStd_IntegerList) aTypesList;
1215   Handle(TDataStd_BooleanList) aClosuresList;
1216   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
1217   if ( aNamesList.IsNull() || aTypesList.IsNull() || aClosuresList.IsNull() )
1218     return;
1219
1220   TDataStd_ListIteratorOfListOfExtendedString aNamesIter( aNamesList->List() );
1221   TColStd_ListIteratorOfListOfInteger aTypesIter( aTypesList->List() );
1222   TDataStd_ListIteratorOfListOfByte aClosuresIter( aClosuresList->List() );
1223   for ( ; aNamesIter.More() && aTypesIter.More() && aClosuresIter.More();
1224           aNamesIter.Next(), aTypesIter.Next(), aClosuresIter.Next() )
1225   {
1226     const TCollection_ExtendedString& aSectName = aNamesIter.Value();
1227     SectionType aSectType = (SectionType)aTypesIter.Value();
1228     bool aSectClosures = aClosuresIter.Value();
1229
1230     theSectNames.Append( aSectName );
1231     theSectTypes.Append( aSectType );
1232     theSectClosures.Append( aSectClosures );
1233   }
1234 }
1235
1236 void HYDROData_PolylineXY::RemoveSection( const int theSectionIndex )
1237 {
1238   Handle(TDataStd_ExtStringList) aNamesList;
1239   Handle(TDataStd_IntegerList)   aTypesList;
1240   Handle(TDataStd_BooleanList)   aClosuresList;
1241   getSectionsLists( aNamesList, aTypesList, aClosuresList, false );
1242   if ( aNamesList.IsNull() || theSectionIndex >= aNamesList->Extent() )
1243     return;
1244
1245   if ( aNamesList->Extent() == 1 )
1246   {
1247     removeSectionsLists();
1248     removePointsLists();
1249   }
1250   else
1251   {
1252     TDataStd_ListOfExtendedString anOldNamesList;
1253     anOldNamesList = aNamesList->List();
1254
1255     TColStd_ListOfInteger anOldTypesList;
1256     anOldTypesList = aTypesList->List();
1257
1258     TDataStd_ListOfByte anOldClosuresList;
1259     anOldClosuresList = aClosuresList->List();
1260
1261     // Refill the existing lists
1262     aNamesList->Clear();
1263     aTypesList->Clear();
1264     aClosuresList->Clear();
1265
1266     TDataStd_ListIteratorOfListOfExtendedString aNamesIter( anOldNamesList );
1267     TColStd_ListIteratorOfListOfInteger aTypesIter( anOldTypesList );
1268     TDataStd_ListIteratorOfListOfByte aClosuresIter( anOldClosuresList );
1269     for ( int i = 0; aNamesIter.More() && aTypesIter.More() && aClosuresIter.More();
1270                      aNamesIter.Next(), aTypesIter.Next(), aClosuresIter.Next(), ++i )
1271     {
1272       if ( i == theSectionIndex )
1273         continue; // skip index to remove
1274
1275       aNamesList->Append( aNamesIter.Value() );
1276       aTypesList->Append( aTypesIter.Value() );
1277       aClosuresList->Append( (bool)aClosuresIter.Value() );
1278     }
1279
1280     // Remove points that belongs to removed section
1281     removePointsLists( theSectionIndex );
1282   }
1283
1284   Changed( Geom_2d );
1285 }
1286
1287 void HYDROData_PolylineXY::RemoveSections()
1288 {
1289   removeSectionsLists();
1290   removePointsLists();
1291   Changed( Geom_2d );
1292 }
1293
1294 void HYDROData_PolylineXY::AddPoint( const int    theSectionIndex,
1295                                      const Point& thePoint,
1296                                      const int    thePointIndex )
1297 {
1298   Handle(TDataStd_RealList) aListX, aListY;
1299   getPointsLists( theSectionIndex, aListX, aListY );
1300
1301   if ( thePointIndex < 0 || thePointIndex >= aListX->Extent() )
1302   {
1303     aListX->Append( thePoint.X() );
1304     aListY->Append( thePoint.Y() );
1305   }
1306   else
1307   {
1308     TColStd_ListOfReal anOldListX;
1309     anOldListX = aListX->List();
1310
1311     TColStd_ListOfReal anOldListY;
1312     anOldListY = aListY->List();
1313
1314     // Refill the existing lists
1315     aListX->Clear();
1316     aListY->Clear();
1317
1318     TColStd_ListIteratorOfListOfReal anIterX( anOldListX );
1319     TColStd_ListIteratorOfListOfReal anIterY( anOldListY );
1320     for ( int i = 0; anIterX.More() && anIterY.More(); anIterX.Next(), anIterY.Next(), ++i )
1321     {
1322       double aCoordX = anIterX.Value();
1323       double aCoordY = anIterY.Value();
1324
1325       if ( i == thePointIndex )
1326       {
1327         // Insert our new point
1328         aListX->Append( thePoint.X() );
1329         aListY->Append( thePoint.Y() );
1330       }
1331
1332       aListX->Append( aCoordX );
1333       aListY->Append( aCoordY );
1334     }
1335   }
1336
1337   Changed( Geom_2d );
1338 }
1339
1340 void HYDROData_PolylineXY::SetPoint( const int    theSectionIndex,
1341                                      const Point& thePoint,
1342                                      const int    thePointIndex )
1343 {
1344   Handle(TDataStd_RealList) aListX, aListY;
1345   getPointsLists( theSectionIndex, aListX, aListY );
1346
1347   if ( thePointIndex < 0 )
1348   {
1349     aListX->Prepend( thePoint.X() );
1350     aListY->Prepend( thePoint.Y() );
1351   }
1352   else if ( thePointIndex >= aListX->Extent() )
1353   {
1354     aListX->Append( thePoint.X() );
1355     aListY->Append( thePoint.Y() );
1356   }
1357   else
1358   {
1359     TColStd_ListOfReal anOldListX;
1360     anOldListX = aListX->List();
1361
1362     TColStd_ListOfReal anOldListY;
1363     anOldListY = aListY->List();
1364
1365     // Refill the existing lists
1366     aListX->Clear();
1367     aListY->Clear();
1368
1369     TColStd_ListIteratorOfListOfReal anIterX( anOldListX );
1370     TColStd_ListIteratorOfListOfReal anIterY( anOldListY );
1371     for ( int i = 0; anIterX.More() && anIterY.More(); anIterX.Next(), anIterY.Next(), ++i )
1372     {
1373       double aCoordX = anIterX.Value();
1374       double aCoordY = anIterY.Value();
1375
1376       if ( i == thePointIndex )
1377       {
1378         // Insert our new point instead of old one
1379         aCoordX = thePoint.X();
1380         aCoordY = thePoint.Y();
1381       }
1382
1383       aListX->Append( aCoordX );
1384       aListY->Append( aCoordY );
1385     }
1386   }
1387
1388   Changed( Geom_2d );
1389 }
1390
1391 void HYDROData_PolylineXY::SetPoints( const int         theSectionIndex,
1392                                       const PointsList& thePoints )
1393 {
1394   Handle(TDataStd_RealList) aListX, aListY;
1395   getPointsLists( theSectionIndex, aListX, aListY );
1396
1397   aListX->Clear();
1398   aListY->Clear();
1399
1400   for ( int i = 1, n = thePoints.Length(); i <= n; ++i )
1401   {
1402     const Point& aPoint = thePoints.Value( i );
1403     aListX->Append( aPoint.X() );
1404     aListY->Append( aPoint.Y() );
1405   }
1406 }
1407
1408 void HYDROData_PolylineXY::RemovePoint( const int theSectionIndex,
1409                                         const int thePointIndex )
1410 {
1411   Handle(TDataStd_RealList) aListX, aListY;
1412   getPointsLists( theSectionIndex, aListX, aListY, false );
1413   if ( aListX.IsNull() || aListY.IsNull() || aListX->IsEmpty() )
1414     return;
1415
1416   if ( aListX->Extent() == 1 )
1417   {
1418     removePointsLists( theSectionIndex );
1419   }
1420   else
1421   {
1422     TColStd_ListOfReal anOldListX;
1423     anOldListX = aListX->List();
1424
1425     TColStd_ListOfReal anOldListY;
1426     anOldListY = aListY->List();
1427
1428     // Refill the existing lists
1429     aListX->Clear();
1430     aListY->Clear();
1431
1432     TColStd_ListIteratorOfListOfReal anIterX( anOldListX );
1433     TColStd_ListIteratorOfListOfReal anIterY( anOldListY );
1434     for ( int i = 0; anIterX.More() && anIterY.More(); anIterX.Next(), anIterY.Next(), ++i )
1435     {
1436       if ( i == thePointIndex )
1437         continue; // skip index to remove
1438
1439       aListX->Append( anIterX.Value() );
1440       aListY->Append( anIterY.Value() );
1441     }
1442   }
1443
1444   Changed( Geom_2d );
1445 }
1446
1447 HYDROData_PolylineXY::PointsList HYDROData_PolylineXY::GetPoints( const int theSectionIndex, bool IsConvertToGlobal ) const
1448 {
1449   PointsList aResList;
1450
1451   if( IsCustom() )
1452   {
1453     const_cast<HYDROData_PolylineXY*>( this )->Interpolate();
1454   }
1455  
1456   Handle(TDataStd_RealList) aListX, aListY;
1457   getPointsLists( theSectionIndex, aListX, aListY, false );
1458   if ( aListX.IsNull() || aListY.IsNull() || aListX->IsEmpty() )
1459     return aResList;
1460
1461   TColStd_ListIteratorOfListOfReal anIterX( aListX->List() );
1462   TColStd_ListIteratorOfListOfReal anIterY( aListY->List() );
1463   Handle(HYDROData_Document) aDoc = HYDROData_Document::Document( myLab );
1464   for ( ; anIterX.More() && anIterY.More(); anIterX.Next(), anIterY.Next() )
1465   {
1466     Point aPoint( anIterX.Value(), anIterY.Value() );
1467     if (IsConvertToGlobal)
1468       aDoc->Transform( aPoint, false );
1469     aResList.Append( aPoint );
1470   }
1471
1472   return aResList;
1473 }
1474
1475 QPainterPath HYDROData_PolylineXY::GetPainterPath() const
1476 {
1477   QPainterPath aPath;
1478
1479   NCollection_Sequence<TCollection_AsciiString>           aSectNames;
1480   NCollection_Sequence<HYDROData_PolylineXY::SectionType> aSectTypes;
1481   NCollection_Sequence<bool>                              aSectClosures;
1482   GetSections( aSectNames, aSectTypes, aSectClosures );
1483
1484   for ( int aSectionId = 1, aNbSects = aSectNames.Size(); aSectionId <= aNbSects; aSectionId++ )
1485   {
1486     TCollection_AsciiString aSectName = aSectNames.Value( aSectionId );
1487     SectionType aSectionType = aSectTypes.Value( aSectionId );
1488     bool anIsSectionClosed = aSectClosures.Value( aSectionId );
1489
1490     PointsList aSectPointsList = GetPoints( aSectionId - 1 );
1491     if ( aSectPointsList.IsEmpty() )
1492       continue;
1493
1494     NCollection_Sequence<gp_XYZ> aPoints;
1495     for( int i = 1, n = aSectPointsList.Size(); i <= n; ++i )
1496     {
1497       const Point& aSectPoint = aSectPointsList.Value( i );
1498
1499       gp_XYZ aPoint( aSectPoint.X(), aSectPoint.Y(), 0.0 );
1500       aPoints.Append( aPoint );
1501     }
1502
1503     BuildPainterPath( aPath, aSectionType, anIsSectionClosed, aPoints );
1504   }
1505
1506   return aPath;
1507 }
1508
1509 void HYDROData_PolylineXY::UpdateLocalCS( double theDx, double theDy )
1510 {
1511   NCollection_Sequence<TCollection_AsciiString>           aSectNames;
1512   NCollection_Sequence<HYDROData_PolylineXY::SectionType> aSectTypes;
1513   NCollection_Sequence<bool>                              aSectClosures;
1514   GetSections( aSectNames, aSectTypes, aSectClosures );
1515
1516   gp_XY aDelta( theDx, theDy );
1517   for ( int i = 0, aNbSects = aSectNames.Size(); i < aNbSects; i++ )
1518   {
1519     PointsList aPoints = GetPoints( i );
1520     for( int j = 1, n = aPoints.Size(); j <= n; ++j )
1521     {
1522       Point& aPoint = aPoints.ChangeValue( j );
1523       aPoint += aDelta;
1524     }
1525     SetPoints( i, aPoints );
1526   }
1527   Changed( Geom_2d );
1528 }
1529
1530 void HYDROData_PolylineXY::Transform( const QTransform& theTrsf )
1531 {
1532   NCollection_Sequence<TCollection_AsciiString>           aSectNames;
1533   NCollection_Sequence<HYDROData_PolylineXY::SectionType> aSectTypes;
1534   NCollection_Sequence<bool>                              aSectClosures;
1535   GetSections( aSectNames, aSectTypes, aSectClosures );
1536
1537   for ( int i = 0, aNbSects = aSectNames.Size(); i < aNbSects; i++ ) {
1538     PointsList aPoints = GetPoints( i );
1539     for( int j = 1, n = aPoints.Size(); j <= n; ++j ) {
1540       Point& aPoint = aPoints.ChangeValue( j );
1541
1542       QPointF aTrsfPoint = theTrsf.map( QPointF( aPoint.X(), aPoint.Y() ) );
1543
1544       aPoint.SetX( aTrsfPoint.x() );
1545       aPoint.SetY( aTrsfPoint.y() );
1546     }
1547     SetPoints( i, aPoints );
1548   }
1549
1550   Update();
1551 }
1552
1553 bool HYDROData_PolylineXY::IsCustom() const
1554 {
1555   if( myIsInCustomFlag )
1556     return false;
1557
1558   bool isNull = GetShape().IsNull();
1559   int aNbPoints = 0;
1560
1561   HYDROData_PolylineXY* aThat = const_cast<HYDROData_PolylineXY*>( this );
1562   aThat->myIsInCustomFlag = true;
1563   for( int i=0, n=NbSections(); i<n; i++ )
1564     aNbPoints += NbPoints( i );
1565   aThat->myIsInCustomFlag = false;
1566
1567   return !isNull && aNbPoints == 0;
1568 }
1569
1570 bool HYDROData_PolylineXY::GetIsInCustomFlag() const
1571 {
1572   return myIsInCustomFlag;
1573 }
1574
1575 void HYDROData_PolylineXY::SetIsInCustomFlag( bool theValue )
1576 {
1577   myIsInCustomFlag = theValue;
1578 }
1579
1580 void HYDROData_PolylineXY::Interpolate()
1581 {
1582   ImportShape( GetShape(), true, NULL );
1583 }