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