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