Salome HOME
error message for export to TELEMAC
[modules/hydro.git] / src / HYDROData / HYDROData_Stream.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_Stream.h"
20
21 #include "HYDROData_Document.h"
22 #include "HYDROData_PolylineXY.h"
23 #include "HYDROData_Polyline3D.h"
24 #include "HYDROData_Profile.h"
25 #include "HYDROData_ShapesGroup.h"
26 #include "HYDROData_ShapesTool.h"
27 #include "HYDROData_IAltitudeObject.h"
28 #include "HYDROData_IProfilesInterpolator.h"
29 #include "HYDROData_Tool.h"
30 #include "HYDROData_DTM.h"
31 #include <HYDROData_Bathymetry.h>
32
33 #include <TDataStd_RealArray.hxx>
34
35 #include <Precision.hxx>
36
37 #include <NCollection_DataMap.hxx>
38
39 #include <TColStd_Array1OfReal.hxx>
40 #include <TColStd_ListOfReal.hxx>
41 #include <TColStd_ListIteratorOfListOfReal.hxx>
42 #include <TCollection_CompareOfReal.hxx>
43 #include <TColgp_Array1OfPnt.hxx>
44 #include <TColgp_HArray1OfPnt.hxx>
45
46 #include <TopoDS.hxx>
47 #include <TopoDS_Wire.hxx>
48 #include <TopoDS_Shell.hxx>
49 #include <TopoDS_Face.hxx>
50 #include <TopoDS_Edge.hxx>
51 #include <TopoDS_Vertex.hxx>
52 #include <TopExp.hxx>
53 #include <TopExp_Explorer.hxx>
54
55 #include <Bnd_Box.hxx>
56
57 #include <BRep_Builder.hxx>
58 #include <BRepBuilderAPI_MakeEdge.hxx>
59 #include <BRepBuilderAPI_MakeWire.hxx>
60 #include <BRepBuilderAPI_MakeFace.hxx>
61
62 #include <BRepBndLib.hxx>
63 #include <BRepProj_Projection.hxx>
64 #include <BRepExtrema_ExtCC.hxx>
65 #include <BRepCheck_Analyzer.hxx>
66
67 #include <gp.hxx>
68 #include <gp_Ax1.hxx>
69 #include <gp_Ax2.hxx>
70 #include <gp_Ax3.hxx>
71 #include <gp_Vec.hxx>
72 #include <gp_Pnt.hxx>
73 #include <gp_Pln.hxx>
74
75 #include <GeomAPI_Interpolate.hxx>
76 #include <Geom_BSplineCurve.hxx>
77
78 #include <TopTools_HArray1OfShape.hxx>
79 #include <TopTools_IndexedMapOfOrientedShape.hxx>
80
81 #include <SortTools_QuickSortOfReal.hxx>
82
83 #include <QColor>
84 #include <QStringList>
85
86 //#define DEB_STREAM 1
87 #ifdef DEB_STREAM
88 //#define DEB_HASINT 1
89 //#define DEB_UPDATE 1
90 #include <BRepTools.hxx>
91 #include <TCollection_AsciiString.hxx>
92 #endif
93
94 typedef NCollection_DataMap<Standard_Real, Handle(HYDROData_Profile)> HYDROData_DataMapOfRealOfHDProfile;
95
96 IMPLEMENT_STANDARD_HANDLE(HYDROData_Stream,HYDROData_NaturalObject)
97 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Stream,HYDROData_NaturalObject)
98
99
100 HYDROData_Stream::HYDROData_Stream()
101 : HYDROData_NaturalObject( Geom_3d )
102 {
103 }
104
105 HYDROData_Stream::~HYDROData_Stream()
106 {
107 }
108
109 QStringList HYDROData_Stream::DumpToPython( const QString&       thePyScriptPath,
110                                             MapOfTreatedObjects& theTreatedObjects ) const
111 {
112   QStringList aResList = dumpObjectCreation( theTreatedObjects );
113   QString aName = GetObjPyName();
114
115   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
116   setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aHydAxis, "SetHydraulicAxis" );
117
118   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
119   for ( int i = 1, aNb = aSeqOfProfiles.Size(); i <= aNb; ++i )
120   {
121     const Handle(HYDROData_Entity) aProfile = aSeqOfProfiles.Value( i );
122     setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aProfile, "AddProfile" );
123   }
124
125   // Set bottom polyline if exists
126   const Handle(HYDROData_Polyline3D) aBottomPolyline = GetBottomPolyline();
127   if ( !aBottomPolyline.IsNull() ) {
128     setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aBottomPolyline, "SetBottomPolyline" );
129   }
130
131   QString aDDZs = QString::number( GetDDZ(), 'f', 3 );
132   QString aSSteps = QString::number( GetSpatialStep(), 'f', 3 );
133   aResList << QString( "%1.SetDDZ( %2 )" ).arg( aName ).arg( aDDZs );
134   aResList << QString( "%1.SetSpatialStep( %2 )" ).arg( aName ).arg( aSSteps );
135
136   aResList << QString( "" );
137   aResList << QString( "%1.Update()" ).arg( aName );
138   aResList << QString( "" );
139
140   return aResList;
141 }
142
143 HYDROData_SequenceOfObjects HYDROData_Stream::GetAllReferenceObjects() const
144 {
145   HYDROData_SequenceOfObjects aResSeq = HYDROData_Object::GetAllReferenceObjects();
146
147   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
148   if ( !aHydAxis.IsNull() )
149     aResSeq.Append( aHydAxis );
150
151   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
152   aResSeq.Append( aSeqOfProfiles );
153
154   return aResSeq;
155 }
156
157 Handle(Geom_BSplineCurve) HYDROData_Stream::buildInterpolationCurve( 
158   const Handle(TColgp_HArray1OfPnt)& theArrayOfPnt )
159 {
160   Handle(Geom_BSplineCurve) aBSpline;
161   GeomAPI_Interpolate anInterpolator (theArrayOfPnt, Standard_False, 1.0e-5); 
162   anInterpolator.Perform() ;
163   if (anInterpolator.IsDone()) 
164     aBSpline = anInterpolator.Curve();
165   return aBSpline; 
166 }
167
168 void HYDROData_Stream::Update()
169 {
170   if (!GetHydraulicAxis().IsNull())
171     updateProfilesOrder();
172
173   // Update bottom polyline if exists
174   const Handle(HYDROData_Polyline3D) aBottomPolyline = GetBottomPolyline();
175   if ( !aBottomPolyline.IsNull() ) {
176     if ( GenerateBottomPolyline() ) {
177       Handle(HYDROData_PolylineXY) aPolylineXY = aBottomPolyline->GetPolylineXY();
178       if ( !aPolylineXY.IsNull() ) {
179         aPolylineXY->Update();
180       }
181       aBottomPolyline->Update();
182     }
183   }
184
185   Handle_HYDROData_DTM dtm = DTM();
186   dtm->Update();
187   UpdatePrs( dtm );
188
189   HYDROData_NaturalObject::Update();
190 }
191
192 bool HYDROData_Stream::IsHas2dPrs() const
193 {
194   return true;
195 }
196
197 bool HYDROData_Stream::CreatePresentations( const Handle_HYDROData_DTM& theDTM,
198                                             PrsDefinition&              thePrs )
199 {
200   if ( theDTM.IsNull() )
201     return false;
202
203   HYDROData_SequenceOfObjects profiles = theDTM->GetProfiles();
204   if( profiles.Length() < 2 )
205     return false;
206
207   TopoDS_Shape Out3dPres;
208   TopoDS_Shape Out2dPres;
209   TopoDS_Shape OutLeftB;
210   TopoDS_Shape OutRightB;
211   TopoDS_Shape OutInlet;
212   TopoDS_Shape OutOutlet;
213
214   theDTM->GetPresentationShapes(Out3dPres, Out2dPres, OutLeftB, OutRightB, OutInlet, OutOutlet);
215
216   thePrs.myInlet = TopoDS::Wire(OutInlet);
217   thePrs.myOutlet = TopoDS::Wire(OutOutlet);
218   thePrs.myLeftBank = TopoDS::Wire(OutLeftB);
219   thePrs.myRightBank = TopoDS::Wire(OutRightB);
220   thePrs.myPrs2D = Out2dPres;
221   thePrs.myPrs3D = Out3dPres;
222   /*std::vector<TopoDS_Wire> profiles3d;
223   profiles3d.reserve(profiles.Length());
224
225   // Pre-processing
226   HYDROData_SequenceOfObjects::Iterator anIter( profiles );
227   for (int i=1 ; anIter.More(); anIter.Next(),i++ )
228   {
229     Handle(HYDROData_Profile) aProfile =
230       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
231
232     if ( aProfile.IsNull() )
233       continue;
234
235     const TopoDS_Shape& aProfileShape = aProfile->GetShape3D();
236     //TopExp_Explorer exp(aProfileShape, TopAbs_EDGE);
237     profiles3d.push_back( TopoDS::Wire(aProfileShape) );
238   }*/
239
240   return true;
241 }
242
243 void HYDROData_Stream::UpdatePrs( const Handle_HYDROData_DTM& theDTM )
244 {
245   HYDROData_NaturalObject::Update();
246   
247   PrsDefinition aResultPrs;
248   if ( !CreatePresentations( theDTM, aResultPrs ) )
249     return;
250
251   SetShape3D( aResultPrs.myPrs3D );
252   SetTopShape( aResultPrs.myPrs2D );
253
254   // Create the stream groups
255   QString aLeftGroupName = GetName() + "_Left_Bank";
256
257   Handle(HYDROData_ShapesGroup) aLeftGroup = createGroupObject();
258   aLeftGroup->SetName( aLeftGroupName );
259   aLeftGroup->AddShape( aResultPrs.myLeftBank );
260
261   QString aRightGroupName = GetName() + "_Right_Bank";
262
263   Handle(HYDROData_ShapesGroup) aRightGroup = createGroupObject();
264   aRightGroup->SetName( aRightGroupName );
265   aRightGroup->AddShape( aResultPrs.myRightBank );
266
267   QString anInGroupName = GetName() + "_Inlet";
268
269   Handle(HYDROData_ShapesGroup) anInGroup = createGroupObject();
270   anInGroup->SetName( anInGroupName );
271   anInGroup->AddShape( aResultPrs.myInlet );
272
273   QString anOutGroupName = GetName() + "_Outlet";
274   
275   Handle(HYDROData_ShapesGroup) anOutGroup = createGroupObject();
276   anOutGroup->SetName( anOutGroupName );
277   anOutGroup->AddShape( aResultPrs.myOutlet );
278 }
279
280 QColor HYDROData_Stream::DefaultFillingColor() const
281 {
282   return QColor( Qt::green );
283 }
284
285 QColor HYDROData_Stream::DefaultBorderColor() const
286 {
287   return QColor( Qt::transparent );
288 }
289
290 bool HYDROData_Stream::IsValidAsAxis( const Handle(HYDROData_PolylineXY)& theHydAxis )
291 {
292   if ( theHydAxis.IsNull() )
293     return true;
294
295   TopoDS_Shape aHydraulicShape = theHydAxis->GetShape();
296   if ( aHydraulicShape.IsNull() || 
297        aHydraulicShape.ShapeType() != TopAbs_WIRE ||
298        BRep_Tool::IsClosed( aHydraulicShape ) )
299     return false; // The polyline must be a single not closed wire
300
301   return true;
302 }
303
304 TopoDS_Shape HYDROData_Stream::GetLeftShape() const
305 {
306   HYDROData_SequenceOfObjects aGroups = GetGroups();
307   return HYDROData_Tool::getFirstShapeFromGroup( aGroups, 1);
308 }
309
310 TopoDS_Shape HYDROData_Stream::GetRightShape() const
311 {
312   HYDROData_SequenceOfObjects aGroups = GetGroups();
313   return HYDROData_Tool::getFirstShapeFromGroup( aGroups, 2);
314 }
315
316 TopoDS_Shape HYDROData_Stream::GetInletShape() const
317 {
318   HYDROData_SequenceOfObjects aGroups = GetGroups();
319   return HYDROData_Tool::getFirstShapeFromGroup( aGroups, 3);
320 }
321
322 TopoDS_Shape HYDROData_Stream::GetOutletShape() const
323 {
324   HYDROData_SequenceOfObjects aGroups = GetGroups();
325   return HYDROData_Tool::getFirstShapeFromGroup( aGroups, 4);
326 }
327
328 Handle_HYDROData_DTM HYDROData_Stream::DTM() const
329 {
330   const_cast<HYDROData_Stream*>( this )->checkAndSetAltitudeObject();
331   return Handle(HYDROData_DTM)::DownCast( GetAltitudeObject() );
332 }
333
334 double HYDROData_Stream::GetDDZ() const
335 {
336   return DTM()->GetDDZ();
337 }
338
339 void HYDROData_Stream::SetDDZ( double theDDZ )
340 {
341   DTM()->SetDDZ( theDDZ );
342   Changed( Geom_3d );
343 }
344   
345 double HYDROData_Stream::GetSpatialStep() const
346 {
347   return DTM()->GetSpatialStep();
348 }
349
350 void HYDROData_Stream::SetSpatialStep( double theSpatialStep )
351 {
352   DTM()->SetSpatialStep( theSpatialStep );
353   Changed( Geom_3d );
354 }
355
356 bool HYDROData_Stream::SetHydraulicAxis( const Handle(HYDROData_PolylineXY)& theAxis )
357 {
358   if ( !IsValidAsAxis( theAxis ) )
359     return false;
360
361   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
362   if ( IsEqual( aPrevAxis, theAxis ) )
363     return true;
364
365   SetReferenceObject( theAxis, DataTag_HydraulicAxis );
366
367   // Update the order of profiles
368   updateProfilesOrder();
369
370   // Indicate model of the need to update the stream presentation
371   Changed( Geom_3d );
372
373   return true;
374 }
375
376 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetHydraulicAxis() const
377 {
378   return Handle(HYDROData_PolylineXY)::DownCast( 
379            GetReferenceObject( DataTag_HydraulicAxis ) );
380 }
381
382 void HYDROData_Stream::RemoveHydraulicAxis()
383 {
384   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
385   if ( aPrevAxis.IsNull() )
386     return;
387
388   ClearReferenceObjects( DataTag_HydraulicAxis );
389
390   // We remove the reference profiles
391   RemoveProfiles();
392
393   // Indicate model of the need to update the stream presentation
394   Changed( Geom_3d );
395 }
396
397 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_Profile)& theProfile,
398                                         const TopoDS_Face&               thePlane,
399                                         Standard_Real&                   theOutPar ) const
400 {
401   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
402   return HasIntersection( aHydAxis, theProfile, thePlane, theOutPar );
403 }
404
405 #include <BRepAlgo_NormalProjection.hxx>
406
407 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_PolylineXY)& theHydAxis, 
408                                         const Handle(HYDROData_Profile)&    theProfile, 
409                                         const TopoDS_Face&                  thePlane,
410                                         Standard_Real&                      theOutPar )
411 {
412   if ( theProfile.IsNull() /*|| !IsValidAsAxis( theHydAxis )*/ )
413     return false; 
414
415   if (theHydAxis.IsNull())
416     return true; //empty h_axis; its's OK
417
418   TopoDS_Wire aHydraulicWire = TopoDS::Wire( theHydAxis->GetShape() ); //guide line
419   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
420   if ( aProfileWire.IsNull() )
421     return false;
422
423   //BRepProj_Projection aProjector (aProfileWire, thePlane, gp::OZ().Direction());
424   BRepAlgo_NormalProjection nproj(thePlane);
425   nproj.Add(aProfileWire);
426   nproj.SetDefaultParams();
427   nproj.Build();
428   if(!nproj.IsDone())
429     return false;
430   TopoDS_Shape aPrjProfile = nproj.Projection();
431   if(aPrjProfile.IsNull())
432     return false;
433   TopoDS_Vertex aV1, aV2;
434   if(aPrjProfile.ShapeType() == TopAbs_EDGE)
435     TopExp::Vertices(TopoDS::Edge(aPrjProfile), aV1, aV2);
436   else if(aPrjProfile.ShapeType() == TopAbs_WIRE)  
437     TopExp::Vertices(TopoDS::Wire(aPrjProfile), aV1, aV2);
438   else if(aPrjProfile.ShapeType() == TopAbs_COMPOUND){
439     TopExp_Explorer anExp(aPrjProfile, TopAbs_WIRE);
440     if(anExp.More()) {
441       TopExp::Vertices(TopoDS::Wire(anExp.Current()), aV1, aV2);
442     } else {
443       anExp.Init(aPrjProfile, TopAbs_EDGE);
444       if(anExp.More()) {
445         TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV1, aV2);
446       }
447     }
448   }
449   if(aV1.IsNull() || aV2.IsNull())
450     return false;
451   gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
452   gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
453   aPnt1.SetZ(0.0);
454   aPnt2.SetZ(0.0);
455   BRepBuilderAPI_MakeEdge aMk(aPnt1, aPnt2); 
456   if(!aMk.IsDone())
457     return false;
458   const TopoDS_Edge& anEdg2 = aMk.Edge();//Section edge
459   Standard_Integer aNum(0);
460   
461   TopExp_Explorer anExplo(aHydraulicWire, TopAbs_EDGE);
462   for(;anExplo.More();anExplo.Next()) aNum++;
463   // check for self-intersection
464   const Standard_Real SquareTolerance = Precision::Confusion()*Precision::Confusion();
465   Standard_Boolean hasInt(false);
466   Standard_Real aSqDist(DBL_MAX);
467   Standard_Integer anIndx(0);
468   BRepExtrema_ExtCC aCC;
469   aCC.Initialize(anEdg2);
470   theOutPar = 0.0;
471   anExplo.Init(aHydraulicWire, TopAbs_EDGE);
472   for(Standard_Integer j=1;anExplo.More();anExplo.Next(),j++) {
473     const TopoDS_Edge& anEdg1 = TopoDS::Edge(anExplo.Current());
474     if(anEdg1.IsNull())
475       continue;
476     Standard_Boolean hasSol(false);
477     aCC.Perform(anEdg1);
478     if(aCC.IsDone()) {
479     // find minimal dist
480     for(Standard_Integer i=1; i<= aCC.NbExt();i++)
481       if(aCC.SquareDistance(i) < aSqDist) {
482         aSqDist = aCC.SquareDistance(i);
483         anIndx = i;
484         hasSol = true;
485       }  
486     }
487     if(hasSol) {
488       if(aSqDist <= SquareTolerance) { // hasInt
489         const gp_Pnt& aPnt = aCC.PointOnE1(anIndx);
490         if(aNum > 1) {
491           TopExp::Vertices(anEdg1, aV1, aV2, Standard_True);
492           theOutPar += BRep_Tool::Pnt(aV1).Distance(aPnt);
493         } else {
494           Standard_Real aPar = aCC.ParameterOnE1(anIndx);
495           theOutPar = aPar;
496         }
497         hasInt = true;
498         break;
499       } else {
500           // no ints-n
501         if(aNum > 1) {
502           TopExp::Vertices(anEdg1, aV1, aV2);
503           theOutPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
504         }
505       }
506     } else if(aNum > 1) {
507       TopExp::Vertices(anEdg1, aV1, aV2);
508       theOutPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
509     }
510   }
511   if(hasInt)
512     return true;
513   return false;
514 }
515
516 bool HYDROData_Stream::AddProfile( const Handle(HYDROData_Profile)& theProfile )
517 {
518   if ( theProfile.IsNull() )
519     return false;
520
521  // Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
522  // if ( aHydAxis.IsNull() )
523  //   return false;
524
525   TopoDS_Face aPlane;
526   BuildRefFace( aPlane );
527
528   Standard_Real aPar(.0);
529   if ( HasReference( theProfile, DataTag_Profile ) || !HasIntersection( theProfile, aPlane, aPar ) )
530     return false; // Object is already in reference list or it has no intersection
531   
532   int aProfileIndex = insertParameter( aPar );
533   insertProfileInToOrder( theProfile, aProfileIndex );
534   
535   // Indicate model of the need to update the stream presentation
536   Changed( Geom_3d );
537
538   return true;
539 }
540
541 bool HYDROData_Stream::SetProfiles( const HYDROData_SequenceOfObjects& theProfiles,
542                                     const bool&                        theIsToOrder )
543 {
544   if ( theIsToOrder )
545   {
546     for ( int i = 1; i <= theProfiles.Length(); ++i )
547     {
548       Handle(HYDROData_Profile) aProfile = 
549         Handle(HYDROData_Profile)::DownCast( theProfiles.Value( i ) );
550       if ( aProfile.IsNull() )
551         continue;
552
553       if ( !AddProfile( aProfile ) )
554       {
555         DTM()->SetProfiles( HYDROData_SequenceOfObjects() );
556         return false;
557       }
558     }
559   }
560   else // Just store the sequence of objects as is
561   {
562     bool anIsToUpdate = true;
563
564     HYDROData_SequenceOfObjects anOldProfiles = GetProfiles();
565     if ( anOldProfiles.Length() == theProfiles.Length() )
566     {
567       anIsToUpdate = false;
568
569       for ( int i = 1; i <= theProfiles.Length(); ++i )
570       {
571         Handle(HYDROData_Entity) anOldProfile = anOldProfiles.Value( i );
572         Handle(HYDROData_Entity) aNewProfile = theProfiles.Value( i );
573         if ( !IsEqual( anOldProfile, aNewProfile ) )
574         {
575           anIsToUpdate = true;
576           break;
577         }
578       }
579     }
580     
581     SetReferenceObjects( theProfiles, DataTag_Profile );
582
583     if ( anIsToUpdate )
584       Changed( Geom_3d );
585   }
586
587   DTM()->SetProfiles( GetProfiles() );
588   return true;
589 }
590
591 HYDROData_SequenceOfObjects HYDROData_Stream::GetProfiles() const
592 {
593   return GetReferenceObjects( DataTag_Profile );
594 }
595
596 bool HYDROData_Stream::RemoveProfile( const Handle(HYDROData_Profile)& theProfile )
597 {
598   if ( theProfile.IsNull() )
599     return false;
600
601   int aProfileIndex = -1;
602
603   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
604   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
605   for ( int i = 0 ; anIter.More(); anIter.Next(), ++i )
606   {
607     Handle(HYDROData_Profile) aProfile =
608       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
609     if ( aProfile.IsNull() )
610       continue;
611
612     if ( IsEqual( theProfile, aProfile ) )
613     {
614       aProfileIndex = i;
615       break;
616     }
617   }
618
619   if ( aProfileIndex == -1 )
620     return false;
621
622   RemoveReferenceObject( theProfile->Label(), DataTag_Profile );
623
624   // Remove parameter for removed profile
625   removeParameter( aProfileIndex );
626
627   // Indicate model of the need to update the stream presentation
628   Changed( Geom_3d );
629
630   return true;
631 }
632
633 void HYDROData_Stream::RemoveProfiles()
634 {
635   ClearReferenceObjects( DataTag_Profile );
636
637   // Remove the parameters array
638   removeParametersArray();
639
640   // Indicate model of the need to update the stream presentation
641   Changed( Geom_3d );
642 }
643
644 void HYDROData_Stream::insertProfileInToOrder( const Handle(HYDROData_Profile)& theProfile,
645                                                const int                        theBeforeIndex )
646 {
647   //Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
648   if ( theProfile.IsNull() )
649     return; 
650
651   //TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
652   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
653   if ( aProfileWire.IsNull() )
654     return;
655
656   if ( theBeforeIndex == -1 )
657     AddReferenceObject( theProfile, DataTag_Profile );
658   else
659     InsertReferenceObject( theProfile, DataTag_Profile, theBeforeIndex );
660 }
661
662 void HYDROData_Stream::BuildRefFace( TopoDS_Face& thePlane )
663 {
664   thePlane = BRepBuilderAPI_MakeFace(gp_Pln(gp_Pnt(0,0,0),gp_Dir(0,0,1))).Face();
665 }
666
667 void HYDROData_Stream::updateProfilesOrder()
668 {
669   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
670   if ( aRefProfiles.IsEmpty() )
671     return;
672
673   // At first we remove all profiles from order
674   RemoveProfiles();
675
676   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
677   if ( aHydAxis.IsNull() )
678     return; 
679
680   TopoDS_Face aPlane;
681   BuildRefFace( aPlane );
682
683   Standard_Real aPar( .0 );
684
685 #ifdef DEB_HASINT
686   BRep_Builder aBB;
687   TopoDS_Compound aCmp;
688   aBB.MakeCompound(aCmp);
689 #endif
690
691   HYDROData_DataMapOfRealOfHDProfile aDM;  
692   TColStd_ListOfReal aList;
693   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
694   for (int i = 1 ; anIter.More(); anIter.Next(), i++ )
695   {
696     Handle(HYDROData_Profile) aProfile =
697       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
698 #ifdef DEB_HASINT
699   TopoDS_Wire aProfileWire = TopoDS::Wire( aProfile->GetTopShape() );
700   aBB.Add( aCmp, aProfileWire ); 
701 #endif
702     if ( aProfile.IsNull() || !HasIntersection( aProfile, aPlane, aPar ) )
703       continue;
704     
705     aDM.Bind( aPar, aProfile );
706     aList.Append( aPar );
707   }
708   
709   if ( aList.IsEmpty() )
710     return;
711
712   TColStd_Array1OfReal anArr( 1, aList.Extent() );
713
714   TColStd_ListIteratorOfListOfReal it( aList );
715   for ( int j = 1; it.More(); it.Next(), j++ )
716     anArr( j ) = it.Value();
717
718   // sorting
719   if ( aList.Extent() > 1 )
720   {
721     TCollection_CompareOfReal Compar;
722     SortTools_QuickSortOfReal::Sort( anArr, Compar );
723
724     for (int j = 1; j <= anArr.Length(); j++) {
725       const Standard_Real aKey =  anArr(j);
726       const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
727       insertProfileInToOrder( aProfile );
728     }
729   } else if ( aList.Extent() == 1 ) {
730      const Standard_Real aKey = aList.Last();
731      const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
732      insertProfileInToOrder( aProfile );
733   } 
734
735   setParametersArray( anArr );
736
737 #ifdef DEB_HASINT
738   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
739   BRepTools::Write(aHydraulicWire, "Path.brep");
740   BRepTools::Write(aCmp, "Prof.brep");
741 #endif
742 }
743
744 ObjectKind HYDROData_Stream::getAltitudeObjectType() const
745 {
746   return KIND_DTM;
747 }
748
749 void HYDROData_Stream::setParametersArray( const TColStd_Array1OfReal& theArray )
750 {
751   if ( theArray.Length() == 0 )
752   {
753     removeParametersArray();
754     return;
755   }
756
757   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray );
758   
759   Handle(TDataStd_RealArray) aParamsArray = 
760     TDataStd_RealArray::Set( aLabel, theArray.Lower(), theArray.Upper() );
761
762   for ( int i = theArray.Lower(), n = theArray.Upper(); i <= n; ++i )
763   {
764     const Standard_Real& aParam = theArray( i );
765     aParamsArray->SetValue( i, aParam );
766   }
767 }
768
769 TColStd_Array1OfReal* HYDROData_Stream::getParametersArray() const
770 {
771   TColStd_Array1OfReal* anArray = NULL;
772
773   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
774   if ( !aLabel.IsNull() )
775   {
776     Handle(TDataStd_RealArray) aParamsArray;
777     if ( aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
778     {
779       anArray = new TColStd_Array1OfReal( aParamsArray->Lower(), aParamsArray->Upper() );
780       for ( int i = aParamsArray->Lower(), n = aParamsArray->Upper(); i <= n; ++i )
781       {
782         const Standard_Real& aParam = aParamsArray->Value( i );
783         anArray->SetValue( i, aParam );
784       }
785     }
786   }
787
788   return anArray;
789 }
790
791 void HYDROData_Stream::removeParametersArray()
792 {
793   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
794   if ( !aLabel.IsNull() )
795     aLabel.ForgetAllAttributes();
796 }
797
798 int HYDROData_Stream::insertParameter( const Standard_Real& theParam )
799 {
800   int aResIndex = -1;
801
802   TColStd_Array1OfReal* anArr = getParametersArray();
803   if ( anArr )
804   {
805     aResIndex = 0;
806
807     TColStd_Array1OfReal aNewArr( anArr->Lower(), anArr->Upper() + 1 );
808
809     bool isInserted = false;
810     for ( int i = anArr->Lower(), j = i, n = anArr->Upper(); i <= n; ++i, ++j )
811     {
812       const Standard_Real& aStoredParam = anArr->Value( i );
813       if ( !isInserted )
814       {
815         if ( theParam > aStoredParam )
816         {
817           aResIndex++;
818         }
819         else
820         {
821           aNewArr( j ) = theParam;
822           isInserted = true;
823           ++j;
824         }
825       }
826
827       aNewArr( j ) = aStoredParam;
828     }
829
830     if ( !isInserted )
831     {
832       aResIndex = -1;
833       aNewArr( aNewArr.Upper() ) = theParam;
834     }
835     
836     setParametersArray( aNewArr );
837     delete anArr;
838   }
839   else
840   {
841     TColStd_Array1OfReal aNewArr( 1, 1 );
842     aNewArr.SetValue( 1, theParam );
843     setParametersArray( aNewArr );
844   }
845
846   return aResIndex;
847 }
848
849 void HYDROData_Stream::removeParameter( const int& theIndex )
850 {
851   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
852   if ( aLabel.IsNull() )
853     return;
854
855   Handle(TDataStd_RealArray) aParamsArray;
856   if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
857     return;
858
859   if ( aParamsArray->Length() == 1 )
860   {
861     removeParametersArray();
862     return;
863   }
864
865   TColStd_Array1OfReal aNewArr( aParamsArray->Lower(), aParamsArray->Upper() - 1 );
866
867   for ( int i = aParamsArray->Lower(), j = i, k = 0, n = aParamsArray->Upper(); i <= n; ++i, ++k )
868   {
869     const Standard_Real& aStoredParam = aParamsArray->Value( i );
870     if ( k == theIndex )
871       continue;
872
873     aNewArr.SetValue( j, aStoredParam );
874     ++j;
875   }
876
877   setParametersArray( aNewArr );
878 }
879
880 bool HYDROData_Stream::GenerateBottomPolyline()
881 {
882   // Get the document
883   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
884   if ( aDocument.IsNull() ) {
885     return false;
886   }
887
888   // Collect bottom points ( one bottom point from each profile of the stream )
889   HYDROData_Profile::ProfilePoints aBottomPoints;
890   
891   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
892   for ( int i = 1, aNb = aSeqOfProfiles.Size(); i <= aNb; i++ ) {
893     const Handle(HYDROData_Profile) aProfile = 
894       Handle(HYDROData_Profile)::DownCast( aSeqOfProfiles.Value( i ) );
895     if ( aProfile.IsNull() ) {
896       continue;
897     }
898     
899     aBottomPoints.Append( aProfile->GetBottomPoint() );
900   }
901
902   int aNbBottomPoints = aBottomPoints.Size();
903
904   if ( aNbBottomPoints < 2 ) {
905     return false;
906   }
907
908   // Create bottom polyline object if the stream doesn't contain it yet
909   Handle(HYDROData_Polyline3D) aBottom = GetBottomPolyline();
910   if ( aBottom.IsNull() ) {
911     aBottom = Handle(HYDROData_Polyline3D)::DownCast( aDocument->CreateObject( KIND_POLYLINE ) );  
912     QString aBaseName = GetName() + "_bottom";
913     QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName, QStringList(), true );
914     aBottom->SetName( aName );
915
916     SetReferenceObject( aBottom, DataTag_BottomPolyline );
917   }
918   
919   // Create 2D polyline if the bottom polyline doesn't contain it yet
920   Handle(HYDROData_PolylineXY) aPolylineXY = aBottom->GetPolylineXY();
921   if ( aPolylineXY.IsNull() ) {
922     aPolylineXY = Handle(HYDROData_PolylineXY)::DownCast( aDocument->CreateObject( KIND_POLYLINEXY ) );
923     QString aBaseName = GetName() + "_bottom_2d";
924     QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName, QStringList(), true );
925     aPolylineXY->SetName( aName );
926     aBottom->SetPolylineXY( aPolylineXY, false );
927   }
928
929   aPolylineXY->RemoveSections();
930   aPolylineXY->AddSection( "", HYDROData_PolylineXY::SECTION_SPLINE, false );
931   
932   // Create profile if the bottom polyline doesn't contain it yet
933   Handle(HYDROData_ProfileUZ) aProfileUZ = aBottom->GetProfileUZ();
934   if ( aProfileUZ.IsNull() ) {
935     Handle(HYDROData_Profile) aProfile = 
936       Handle(HYDROData_Profile)::DownCast( aDocument->CreateObject( KIND_PROFILE ) );
937     QString aBaseName = GetName() + "_bottom_profile";
938     QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName, QStringList(), true );
939     aProfile->SetName( aName );
940     aProfileUZ = aProfile->GetProfileUZ( true );
941     aBottom->SetProfileUZ( aProfileUZ );
942   }
943   
944   aProfileUZ->RemoveSection( 0 );
945
946   aProfileUZ->CalculateAndAddPoints(aBottomPoints, aPolylineXY);
947   
948   return true;
949 }
950
951 Handle(HYDROData_Polyline3D) HYDROData_Stream::GetBottomPolyline() const
952 {
953   return Handle(HYDROData_Polyline3D)::DownCast( 
954            GetReferenceObject( DataTag_BottomPolyline ) );
955 }
956
957 bool HYDROData_Stream::SetBottomPolyline( const Handle(HYDROData_Polyline3D)& theBottom )
958 {
959   if ( theBottom.IsNull() ) {
960     return false;
961   }
962
963   SetReferenceObject( theBottom, DataTag_BottomPolyline );
964
965   return true;
966 }
967
968 bool HYDROData_Stream::Interpolate( HYDROData_IProfilesInterpolator* theInterpolator )
969 {
970   // Get the document
971   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
972   if ( aDocument.IsNull() ) {
973     return false;
974   }
975   
976   if ( theInterpolator->GetCalculatedProfilesNumber() < 1 ) {
977     theInterpolator->Calculate();
978   }
979
980   if ( theInterpolator->GetErrorCode() != OK ) {
981     return false;
982   }
983
984   bool isOK = true;
985
986   for ( int aProfileInd = 0; aProfileInd < theInterpolator->GetCalculatedProfilesNumber(); aProfileInd++ ) {
987     // Get calculated point coordinates
988     HYDROData_Profile::ProfilePoints aResultPoints = theInterpolator->GetResultProfilePoints( aProfileInd );
989     if ( aResultPoints.IsEmpty() ) {
990       isOK = false;
991       continue;
992     }
993         
994     // Create profile object
995     Handle(HYDROData_Profile) aProfile = 
996       Handle(HYDROData_Profile)::DownCast( aDocument->CreateObject( KIND_PROFILE ) );
997     QString aBaseName = GetName() + "_interp_profile";
998     QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName );
999     aProfile->SetName( aName );
1000
1001     // Fill the profile with points
1002     aProfile->SetProfilePoints( aResultPoints );
1003
1004     // Add profile to the stream
1005     bool isAdded = AddProfile( aProfile );
1006     if ( !isAdded ) {
1007       aProfile->Remove();
1008     }
1009     else
1010       aProfile->Update();
1011   }
1012
1013   if ( isOK )
1014     Update();
1015
1016   return isOK;
1017 }
1018
1019 void HYDROData_Stream::CopyTo( const Handle(HYDROData_Entity)& theDestination,
1020                                bool isGenerateNewName ) const
1021 {
1022   // Get the document
1023   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
1024   if ( aDocument.IsNull() ) {
1025     return;
1026   }
1027
1028   // Call base method
1029   HYDROData_Entity::CopyTo( theDestination, isGenerateNewName );
1030
1031   Handle(HYDROData_Stream) aStreamCopy = 
1032     Handle(HYDROData_Stream)::DownCast( theDestination );
1033
1034   // Copy bottom polyline if exists
1035   if ( !aStreamCopy.IsNull() ) {
1036     const Handle(HYDROData_Polyline3D) aBottom = GetBottomPolyline();
1037     if ( !aBottom.IsNull() ) {
1038       aStreamCopy->ClearReferenceObjects( DataTag_BottomPolyline );
1039       aStreamCopy->GenerateBottomPolyline();
1040       const Handle(HYDROData_Polyline3D) aBottomCopy = aStreamCopy->GetBottomPolyline();
1041       if ( !aBottomCopy.IsNull() && !aBottomCopy->GetPolylineXY().IsNull() ) {
1042         aBottomCopy->GetPolylineXY()->Update();
1043         aBottomCopy->Update();
1044       }
1045     }
1046   }
1047 }
1048
1049 void HYDROData_Stream::CreatePresentations( const Handle(TColgp_HArray1OfPnt)     theArrayOfFPnt,
1050                                             const Handle(TColgp_HArray1OfPnt)     theArrayOfLPnt,
1051                                             const Handle(TopTools_HArray1OfShape) theArrOfProfiles,
1052                                             PrsDefinition&                        thePrs )
1053 {
1054
1055   HYDROData_Bathymetry::AltitudePoints left;
1056   for (int i = theArrayOfLPnt->Lower(); i <= theArrayOfLPnt->Upper(); i++)
1057   {
1058     left.push_back(HYDROData_Bathymetry::AltitudePoint(theArrayOfLPnt->Value(i).X(), 
1059       theArrayOfLPnt->Value(i).Y(),
1060       theArrayOfLPnt->Value(i).Z()));
1061   }
1062
1063   HYDROData_Bathymetry::AltitudePoints right;
1064   for (int i = theArrayOfFPnt->Lower(); i <= theArrayOfFPnt->Upper(); i++)
1065   {
1066     right.push_back(HYDROData_Bathymetry::AltitudePoint(theArrayOfFPnt->Value(i).X(), 
1067       theArrayOfFPnt->Value(i).Y(),
1068       theArrayOfFPnt->Value(i).Z()));
1069   }
1070
1071   std::vector<HYDROData_Bathymetry::AltitudePoints> dummy;
1072   TopTools_IndexedMapOfOrientedShape ll = HYDROData_DTM::Create3DShape(left, right, dummy);
1073
1074   if (!ll.IsEmpty())
1075   {
1076     thePrs.myLeftBank = TopoDS::Wire(ll(1));
1077     thePrs.myRightBank = TopoDS::Wire(ll(2));
1078   }
1079
1080   thePrs.myInlet = TopoDS::Wire(theArrOfProfiles->Value(theArrOfProfiles->Lower())); //TODO check that
1081   thePrs.myOutlet = TopoDS::Wire(theArrOfProfiles->Value(theArrOfProfiles->Upper()));
1082
1083   //make new compound so it's shapes will be in known order to build correct projection
1084   BRep_Builder BB;
1085   TopoDS_Compound newCmp;
1086   BB.MakeCompound(newCmp);
1087   BB.Add(newCmp, thePrs.myLeftBank);
1088   BB.Add(newCmp, thePrs.myInlet);
1089   BB.Add(newCmp, thePrs.myOutlet);
1090   BB.Add(newCmp, thePrs.myRightBank);
1091
1092   thePrs.myPrs3D = newCmp;
1093
1094   HYDROData_DTM::Get2dFaceFrom3dPres( newCmp, TopoDS::Face(thePrs.myPrs2D) ); //__TODO
1095
1096 }