]> SALOME platform Git repositories - modules/hydro.git/blob - src/HYDROData/HYDROData_Stream.cxx
Salome HOME
refs #369: local CS for profiles
[modules/hydro.git] / src / HYDROData / HYDROData_Stream.cxx
1
2 #include "HYDROData_Stream.h"
3
4 #include "HYDROData_Document.h"
5 #include "HYDROData_PolylineXY.h"
6 #include "HYDROData_Profile.h"
7 #include "HYDROData_ShapesGroup.h"
8 #include "HYDROData_ShapesTool.h"
9 #include "HYDROData_IAltitudeObject.h"
10
11 #include <TDataStd_RealArray.hxx>
12
13 #include <Precision.hxx>
14
15 #include <NCollection_DataMap.hxx>
16
17 #include <TColStd_Array1OfReal.hxx>
18 #include <TColStd_ListOfReal.hxx>
19 #include <TColStd_ListIteratorOfListOfReal.hxx>
20 #include <TCollection_CompareOfReal.hxx>
21 #include <TColgp_Array1OfPnt.hxx>
22 #include <TColgp_HArray1OfPnt.hxx>
23
24 #include <TopoDS.hxx>
25 #include <TopoDS_Wire.hxx>
26 #include <TopoDS_Shell.hxx>
27 #include <TopoDS_Face.hxx>
28 #include <TopoDS_Edge.hxx>
29 #include <TopoDS_Vertex.hxx>
30 #include <TopExp.hxx>
31 #include <TopExp_Explorer.hxx>
32
33 #include <Bnd_Box.hxx>
34
35 #include <BRep_Builder.hxx>
36 #include <BRepBuilderAPI_MakeEdge.hxx>
37 #include <BRepBuilderAPI_MakeWire.hxx>
38 #include <BRepBuilderAPI_MakeFace.hxx>
39
40 #include <BRepBndLib.hxx>
41 #include <BRepProj_Projection.hxx>
42 #include <BRepExtrema_ExtCC.hxx>
43 #include <BRepCheck_Analyzer.hxx>
44
45 #include <gp.hxx>
46 #include <gp_Ax1.hxx>
47 #include <gp_Ax2.hxx>
48 #include <gp_Ax3.hxx>
49 #include <gp_Vec.hxx>
50 #include <gp_Pnt.hxx>
51 #include <gp_Pln.hxx>
52
53 #include <GeomAPI_Interpolate.hxx>
54 #include <Geom_BSplineCurve.hxx>
55
56 #include <TopTools_Array1OfShape.hxx>
57
58 #include <SortTools_QuickSortOfReal.hxx>
59
60 #include <QColor>
61 #include <QStringList>
62
63 //#define DEB_STREAM 1
64 #ifdef DEB_STREAM
65 //#define DEB_HASINT 1
66 //#define DEB_UPDATE 1
67 #include <BRepTools.hxx>
68 #include <TCollection_AsciiString.hxx>
69 #endif
70
71 typedef NCollection_DataMap<Standard_Real, Handle(HYDROData_Profile)> HYDROData_DataMapOfRealOfHDProfile;
72
73 IMPLEMENT_STANDARD_HANDLE(HYDROData_Stream,HYDROData_NaturalObject)
74 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Stream,HYDROData_NaturalObject)
75
76
77 HYDROData_Stream::HYDROData_Stream()
78 : HYDROData_NaturalObject()
79 {
80 }
81
82 HYDROData_Stream::~HYDROData_Stream()
83 {
84 }
85
86 QStringList HYDROData_Stream::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
87 {
88   QStringList aResList = dumpObjectCreation( theTreatedObjects );
89   QString aName = GetObjPyName();
90
91   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
92   setPythonReferenceObject( theTreatedObjects, aResList, aHydAxis, "SetHydraulicAxis" );
93
94   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
95   for ( int i = 1, aNb = aSeqOfProfiles.Size(); i <= aNb; ++i )
96   {
97     const Handle(HYDROData_Entity) aProfile = aSeqOfProfiles.Value( i );
98     setPythonReferenceObject( theTreatedObjects, aResList, aProfile, "AddProfile" );
99   }
100
101   aResList << QString( "" );
102   aResList << QString( "%1.Update();" ).arg( aName );
103   aResList << QString( "" );
104
105   return aResList;
106 }
107
108 HYDROData_SequenceOfObjects HYDROData_Stream::GetAllReferenceObjects() const
109 {
110   HYDROData_SequenceOfObjects aResSeq = HYDROData_Object::GetAllReferenceObjects();
111
112   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
113   if ( !aHydAxis.IsNull() )
114     aResSeq.Append( aHydAxis );
115
116   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
117   aResSeq.Append( aSeqOfProfiles );
118
119   return aResSeq;
120 }
121
122 TopoDS_Shape HYDROData_Stream::GetTopShape() const
123 {
124   return getTopShape();
125 }
126
127 TopoDS_Shape HYDROData_Stream::GetShape3D() const
128 {
129   return getShape3D();
130 }
131
132 Handle(Geom_BSplineCurve) HYDROData_Stream::buildInterpolationCurve( 
133   const Handle(TColgp_HArray1OfPnt)& theArrayOfPnt )
134 {
135   Handle(Geom_BSplineCurve) aBSpline;
136   GeomAPI_Interpolate anInterpolator (theArrayOfPnt, Standard_False, 1.0e-5); 
137   anInterpolator.Perform() ;
138   if (anInterpolator.IsDone()) 
139     aBSpline = anInterpolator.Curve();
140   return aBSpline; 
141 }
142
143 void HYDROData_Stream::Update()
144 {
145   updateProfilesOrder();
146   UpdatePrs();
147 }
148
149 bool HYDROData_Stream::IsHas2dPrs() const
150 {
151   return true;
152 }
153
154 bool HYDROData_Stream::CreatePresentations( const Handle(HYDROData_PolylineXY)& theHydAxis,
155                                             const HYDROData_SequenceOfObjects&  theProfiles,
156                                             PrsDefinition&                      thePrs )
157 {
158   if ( theHydAxis.IsNull() || theProfiles.Length() < 2 )
159     return false;
160
161   gp_Pnt aPrevFirstPoint, aPrevLastPoint;
162   Handle(TColgp_HArray1OfPnt) anArrayOfFPnt    = new TColgp_HArray1OfPnt(1, theProfiles.Length());
163   Handle(TColgp_HArray1OfPnt) anArrayOfLPnt    = new TColgp_HArray1OfPnt(1, theProfiles.Length());  
164   TopTools_Array1OfShape anArrOfProfiles(1, theProfiles.Length());
165   TopTools_Array1OfShape anArrOf2DProfiles(1, theProfiles.Length());
166
167   // Pre-processing
168   HYDROData_SequenceOfObjects::Iterator anIter( theProfiles );
169   for (int i=1 ; anIter.More(); anIter.Next(),i++ )
170   {
171     Handle(HYDROData_Profile) aProfile =
172       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
173     if ( aProfile.IsNull() )
174       continue;
175
176     const TopoDS_Shape& aProf3d = aProfile->GetShape3D();
177     gp_XY aPnt1, aPnt2;
178     if ( !aProfile->GetLeftPoint( aPnt1, false ) || !aProfile->GetRightPoint( aPnt2, false ) )
179       continue;
180
181     anArrOfProfiles.SetValue(i,aProfile->GetShape3D());//aProfile->GetTopShape();
182     anArrOf2DProfiles.SetValue(i,aProfile->GetTopShape());
183
184     gp_Pnt aCurFirstPoint( aPnt1.X(), aPnt1.Y(), 0 ), aCurFP;
185     gp_Pnt aCurLastPoint(  aPnt2.X(), aPnt2.Y(), 0 ), aCurLP;
186     TopoDS_Vertex aV1, aV2;
187     TopExp::Vertices(TopoDS::Wire(aProf3d), aV1, aV2);
188        gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
189     if(aP1.X() == aPnt1.X() && aP1.Y() == aPnt1.Y())
190       aCurFP = aP1;
191     else
192       aCurLP = aP1;
193     aP1 = BRep_Tool::Pnt(aV2);
194     if(aP1.X() == aPnt2.X() && aP1.Y() == aPnt2.Y())
195       aCurLP = aP1;
196     else
197       aCurFP = aP1;
198     anArrayOfFPnt->SetValue(i,aCurFP);
199     anArrayOfLPnt->SetValue(i,aCurLP);
200   }
201
202   // Construct of the 3D presentation
203   Handle(Geom_BSplineCurve) aBSpline = buildInterpolationCurve (anArrayOfFPnt);
204   if(aBSpline.IsNull())
205     return false;
206
207   TopoDS_Edge anEdgLeft, anEdgRight;
208   
209   BRepBuilderAPI_MakeEdge aMakeEdge(aBSpline);
210   if(aMakeEdge.IsDone()) 
211     anEdgLeft = aMakeEdge.Edge();
212
213   if(anEdgLeft.IsNull())
214     return false;
215
216   aBSpline.Nullify();
217   aBSpline = buildInterpolationCurve (anArrayOfLPnt);  
218   if(aBSpline.IsNull())
219     return false;
220
221   aMakeEdge.Init(aBSpline);
222   if(aMakeEdge.IsDone()) 
223     anEdgRight = aMakeEdge.Edge();
224
225   if(anEdgRight.IsNull())
226     return false;
227
228   BRep_Builder aBB;
229   TopoDS_Compound aCmp;
230   aBB.MakeCompound(aCmp);
231   anIter.Init( theProfiles );
232   for (int i=1 ; i < anArrOfProfiles.Length() +1; i++ )  
233     aBB.Add(aCmp, anArrOfProfiles.Value(i));
234
235   aBB.Add(aCmp,anEdgLeft);
236   aBB.Add(aCmp,anEdgRight);
237   BRepCheck_Analyzer aCh(aCmp);
238   if(aCh.IsValid())
239     thePrs.myPrs3D = aCmp;
240 #ifdef DEB_UPDATE
241   else {
242     BRepTools::Write(aCmp, "str3d.brep");
243     thePrs.myPrs3D = aCmp;
244   }
245 #endif
246
247   // Construct the top presentation
248   for(int i=1;i<= anArrayOfLPnt->Length();i++) {
249       gp_Pnt aPnt = anArrayOfFPnt->Value(i);
250       aPnt.SetZ(.0); // make 2d
251       anArrayOfFPnt->SetValue(i, aPnt);
252       aPnt = anArrayOfLPnt->Value(i);
253       aPnt.SetZ(.0);
254       anArrayOfLPnt->SetValue(i, aPnt);
255   }
256
257   aBSpline.Nullify();
258   aBSpline = buildInterpolationCurve (anArrayOfFPnt);  
259   if(aBSpline.IsNull())
260     return false; 
261
262   aMakeEdge.Init(aBSpline);
263   if(aMakeEdge.IsDone()) 
264       anEdgLeft = aMakeEdge.Edge();
265
266   aBSpline.Nullify();
267   aBSpline = buildInterpolationCurve (anArrayOfLPnt);  
268   if(aBSpline.IsNull())
269     return false; 
270
271   aMakeEdge.Init(aBSpline);
272   if(aMakeEdge.IsDone()) 
273     anEdgRight = aMakeEdge.Edge();
274   if(anEdgRight.IsNull())
275     return false;
276
277   BRepBuilderAPI_MakeEdge aMakeEdge2(anArrayOfFPnt->Value(1),anArrayOfLPnt->Value(1));
278   TopoDS_Edge aBotEdge, aTopEdge;
279   if(aMakeEdge2.IsDone()) 
280     aBotEdge = aMakeEdge2.Edge();
281
282   BRepBuilderAPI_MakeEdge aMakeEdge3(anArrayOfFPnt->Value(anArrayOfFPnt->Length()),anArrayOfLPnt->Value(anArrayOfLPnt->Length()));
283   if(aMakeEdge3.IsDone()) 
284     aTopEdge = aMakeEdge3.Edge();
285
286   // Make wire for 2D presentation with updating of corresponding edges
287   BRepBuilderAPI_MakeWire aMakeWire;
288   
289   aMakeWire.Add( aBotEdge );
290   thePrs.myInlet = aMakeWire.Edge();
291
292   aMakeWire.Add( anEdgLeft );
293   thePrs.myLeftBank = aMakeWire.Edge();
294
295   aMakeWire.Add( aTopEdge );
296   thePrs.myOutlet = aMakeWire.Edge();
297
298   aMakeWire.Add( anEdgRight );
299   thePrs.myRightBank = aMakeWire.Edge();
300
301   TopoDS_Wire aSectProfileWire;
302   if(aMakeWire.IsDone())
303     aSectProfileWire = aMakeWire.Wire();
304
305   BRepBuilderAPI_MakeFace aMakeFace( aSectProfileWire, Standard_True );
306   TopoDS_Face aFace;
307   aMakeFace.Build();
308   if( aMakeFace.IsDone() )
309     aFace = aMakeFace.Face();
310
311   aCmp.Nullify();
312   aBB.MakeCompound(aCmp);
313   aBB.Add(aCmp,aFace);
314   for(int i=1;i <= anArrOf2DProfiles.Length(); i++)
315     aBB.Add(aCmp,anArrOf2DProfiles.Value(i));
316
317   aCh.Init(aCmp);
318   if(aCh.IsValid())
319    thePrs.myPrs2D = aCmp;
320 #ifdef DEB_UPDATE
321   else {
322     BRepTools::Write(aCmp, "str2d.brep");
323     thePrs.myPrs2D = aCmp;
324   }
325 #endif
326
327   return true;
328 }
329
330 void HYDROData_Stream::UpdatePrs()
331 {
332   HYDROData_NaturalObject::Update();
333
334   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
335   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
336
337   PrsDefinition aResultPrs;
338   if ( !CreatePresentations( aHydAxis, aRefProfiles, aResultPrs ) )
339     return;
340
341   SetShape3D( aResultPrs.myPrs3D );
342   SetTopShape( aResultPrs.myPrs2D );
343
344   // Create the stream groups
345   QString aLeftGroupName = GetName() + "_Left_Bank";
346
347   Handle(HYDROData_ShapesGroup) aLeftGroup = createGroupObject();
348   aLeftGroup->SetName( aLeftGroupName );
349   aLeftGroup->AddShape( aResultPrs.myLeftBank );
350
351   QString aRightGroupName = GetName() + "_Right_Bank";
352
353   Handle(HYDROData_ShapesGroup) aRightGroup = createGroupObject();
354   aRightGroup->SetName( aRightGroupName );
355   aRightGroup->AddShape( aResultPrs.myRightBank );
356
357   QString anInGroupName = GetName() + "_Inlet";
358
359   Handle(HYDROData_ShapesGroup) anInGroup = createGroupObject();
360   anInGroup->SetName( anInGroupName );
361   anInGroup->AddShape( aResultPrs.myInlet );
362
363   QString anOutGroupName = GetName() + "_Outlet";
364
365   Handle(HYDROData_ShapesGroup) anOutGroup = createGroupObject();
366   anOutGroup->SetName( anOutGroupName );
367   anOutGroup->AddShape( aResultPrs.myOutlet );
368 }
369
370 QColor HYDROData_Stream::DefaultFillingColor()
371 {
372   return QColor( Qt::green );
373 }
374
375 QColor HYDROData_Stream::DefaultBorderColor()
376 {
377   return QColor( Qt::transparent );
378 }
379
380 bool HYDROData_Stream::IsValidAsAxis( const Handle(HYDROData_PolylineXY)& theHydAxis )
381 {
382   if ( theHydAxis.IsNull() )
383     return false;
384
385   TopoDS_Shape aHydraulicShape = theHydAxis->GetShape();
386   if ( aHydraulicShape.IsNull() || 
387        aHydraulicShape.ShapeType() != TopAbs_WIRE ||
388        BRep_Tool::IsClosed( aHydraulicShape ) )
389     return false; // The polyline must be a single not closed wire
390
391   return true;
392 }
393
394 TopoDS_Shape getShapeFromGroup( const HYDROData_SequenceOfObjects& theGroups,
395                                 const int                          theGroupId )
396 {
397   TopoDS_Shape aResShape;
398   if ( theGroups.Length() != 4 )
399     return aResShape;
400
401   Handle(HYDROData_ShapesGroup) aGroup =
402     Handle(HYDROData_ShapesGroup)::DownCast( theGroups.Value( theGroupId ) );
403   if ( aGroup.IsNull() )
404     return aResShape;
405
406   TopTools_SequenceOfShape aGroupShapes;
407   aGroup->GetShapes( aGroupShapes );
408
409   if ( !aGroupShapes.IsEmpty() )
410     aResShape = aGroupShapes.First();
411
412   return aResShape;
413 }
414
415 TopoDS_Shape HYDROData_Stream::GetLeftShape() const
416 {
417   HYDROData_SequenceOfObjects aGroups = GetGroups();
418   return getShapeFromGroup( aGroups, 1 );
419 }
420
421 TopoDS_Shape HYDROData_Stream::GetRightShape() const
422 {
423   HYDROData_SequenceOfObjects aGroups = GetGroups();
424   return getShapeFromGroup( aGroups, 2 );
425 }
426
427 TopoDS_Shape HYDROData_Stream::GetInletShape() const
428 {
429   HYDROData_SequenceOfObjects aGroups = GetGroups();
430   return getShapeFromGroup( aGroups, 3 );
431 }
432
433 TopoDS_Shape HYDROData_Stream::GetOutletShape() const
434 {
435   HYDROData_SequenceOfObjects aGroups = GetGroups();
436   return getShapeFromGroup( aGroups, 4 );
437 }
438
439 QColor HYDROData_Stream::getDefaultFillingColor() const
440 {
441   return DefaultFillingColor();
442 }
443
444 QColor HYDROData_Stream::getDefaultBorderColor() const
445 {
446   return DefaultBorderColor();
447 }
448
449 bool HYDROData_Stream::SetHydraulicAxis( const Handle(HYDROData_PolylineXY)& theAxis )
450 {
451   if ( !IsValidAsAxis( theAxis ) )
452     return false;
453
454   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
455   if ( IsEqual( aPrevAxis, theAxis ) )
456     return true;
457
458   SetReferenceObject( theAxis, DataTag_HydraulicAxis );
459
460   // Update the order of profiles
461   updateProfilesOrder();
462
463   // Indicate model of the need to update the stream presentation
464   SetToUpdate( true );
465
466   return true;
467 }
468
469 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetHydraulicAxis() const
470 {
471   return Handle(HYDROData_PolylineXY)::DownCast( 
472            GetReferenceObject( DataTag_HydraulicAxis ) );
473 }
474
475 void HYDROData_Stream::RemoveHydraulicAxis()
476 {
477   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
478   if ( aPrevAxis.IsNull() )
479     return;
480
481   ClearReferenceObjects( DataTag_HydraulicAxis );
482
483   // We remove the reference profiles
484   RemoveProfiles();
485
486   // Indicate model of the need to update the stream presentation
487   SetToUpdate( true );
488 }
489
490 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_Profile)& theProfile,
491                                         const TopoDS_Face&               thePlane,
492                                         Standard_Real&                   theOutPar ) const
493 {
494   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
495   return HasIntersection( aHydAxis, theProfile, thePlane, theOutPar );
496 }
497
498 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_PolylineXY)& theHydAxis, 
499                                         const Handle(HYDROData_Profile)&    theProfile, 
500                                         const TopoDS_Face&                  thePlane,
501                                         Standard_Real&                      theOutPar )
502 {
503   if ( theProfile.IsNull() || !IsValidAsAxis( theHydAxis ) )
504     return false; 
505
506   TopoDS_Wire aHydraulicWire = TopoDS::Wire( theHydAxis->GetShape() ); //guide line
507   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
508   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
509     return false;
510
511   BRepProj_Projection aProjector (aProfileWire, thePlane, gp::OZ().Direction());
512   if(!aProjector.IsDone())
513     return false;
514   TopoDS_Shape aPrjProfile = aProjector.Shape();
515   if(aPrjProfile.IsNull())
516     return false;
517   TopoDS_Vertex aV1, aV2;
518   if(aPrjProfile.ShapeType() == TopAbs_EDGE)
519     TopExp::Vertices(TopoDS::Edge(aPrjProfile), aV1, aV2);
520   else if(aPrjProfile.ShapeType() == TopAbs_WIRE)  
521     TopExp::Vertices(TopoDS::Wire(aPrjProfile), aV1, aV2);
522   else if(aPrjProfile.ShapeType() == TopAbs_COMPOUND){
523     TopExp_Explorer anExp(aPrjProfile, TopAbs_WIRE);
524     if(anExp.More()) {
525       TopExp::Vertices(TopoDS::Wire(anExp.Current()), aV1, aV2);
526     } else {
527       anExp.Init(aPrjProfile, TopAbs_EDGE);
528       if(anExp.More()) {
529         TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV1, aV2);
530       }
531     }
532   }
533   if(aV1.IsNull() || aV2.IsNull())
534     return false;
535   gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
536   gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
537   aPnt1.SetZ(0.0);
538   aPnt2.SetZ(0.0);
539   BRepBuilderAPI_MakeEdge aMk(aPnt1, aPnt2); 
540   if(!aMk.IsDone())
541     return false;
542   const TopoDS_Edge& anEdg2 = aMk.Edge();//Section edge
543   Standard_Integer aNum(0);
544   
545   TopExp_Explorer anExplo(aHydraulicWire, TopAbs_EDGE);
546   for(;anExplo.More();anExplo.Next()) aNum++;
547   // check for self-intersection
548   const Standard_Real SquareTolerance = Precision::Confusion()*Precision::Confusion();
549   Standard_Boolean hasInt(false);
550   Standard_Real aSqDist(DBL_MAX);
551   Standard_Integer anIndx(0);
552   BRepExtrema_ExtCC aCC;
553   aCC.Initialize(anEdg2);
554   theOutPar = 0.0;
555   anExplo.Init(aHydraulicWire, TopAbs_EDGE);
556   for(Standard_Integer j=1;anExplo.More();anExplo.Next(),j++) {
557     const TopoDS_Edge& anEdg1 = TopoDS::Edge(anExplo.Current());
558     if(anEdg1.IsNull())
559       continue;
560     Standard_Boolean hasSol(false);
561     aCC.Perform(anEdg1);
562     if(aCC.IsDone()) {
563     // find minimal dist
564     for(Standard_Integer i=1; i<= aCC.NbExt();i++)
565       if(aCC.SquareDistance(i) < aSqDist) {
566         aSqDist = aCC.SquareDistance(i);
567         anIndx = i;
568         hasSol = true;
569       }  
570     }
571     if(hasSol) {
572       if(aSqDist <= SquareTolerance) { // hasInt
573         const gp_Pnt& aPnt = aCC.PointOnE1(anIndx);
574         if(aNum > 1) {
575           TopExp::Vertices(anEdg1, aV1, aV2, Standard_True);
576           theOutPar += BRep_Tool::Pnt(aV1).Distance(aPnt);
577         } else {
578           Standard_Real aPar = aCC.ParameterOnE1(anIndx);
579           theOutPar = aPar;
580         }
581         hasInt = true;
582         break;
583       } else {
584           // no ints-n
585         if(aNum > 1) {
586           TopExp::Vertices(anEdg1, aV1, aV2);
587           theOutPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
588         }
589       }
590     } else if(aNum > 1) {
591       TopExp::Vertices(anEdg1, aV1, aV2);
592       theOutPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
593     }
594   }
595   if(hasInt)
596     return true;
597   return false;
598 }
599
600 bool HYDROData_Stream::AddProfile( const Handle(HYDROData_Profile)& theProfile )
601 {
602   if ( theProfile.IsNull() )
603     return false;
604
605   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
606   if ( aHydAxis.IsNull() )
607     return false;
608
609   TopoDS_Face aPlane;
610   if(!BuildFace(aHydAxis, aPlane))
611     return false;
612
613   Standard_Real aPar(.0);
614   if ( HasReference( theProfile, DataTag_Profile ) || !HasIntersection( theProfile, aPlane, aPar ) )
615     return false; // Object is already in reference list or it has no intersection
616   
617   int aProfileIndex = insertParameter( aPar );
618   insertProfileInToOrder( theProfile, aProfileIndex );
619   
620   // Indicate model of the need to update the stream presentation
621   SetToUpdate( true );
622
623   return true;
624 }
625
626 bool HYDROData_Stream::SetProfiles( const HYDROData_SequenceOfObjects& theProfiles,
627                                     const bool&                        theIsToOrder )
628 {
629   if ( theIsToOrder )
630   {
631     for ( int i = 1; i <= theProfiles.Length(); ++i )
632     {
633       Handle(HYDROData_Profile) aProfile = 
634         Handle(HYDROData_Profile)::DownCast( theProfiles.Value( i ) );
635       if ( aProfile.IsNull() )
636         continue;
637
638       if ( !AddProfile( aProfile ) )
639         return false;
640     }
641   }
642   else // Just store the sequence of objects as is
643   {
644     bool anIsToUpdate = true;
645
646     HYDROData_SequenceOfObjects anOldProfiles = GetProfiles();
647     if ( anOldProfiles.Length() == theProfiles.Length() )
648     {
649       anIsToUpdate = false;
650
651       for ( int i = 1; i <= theProfiles.Length(); ++i )
652       {
653         Handle(HYDROData_Entity) anOldProfile = anOldProfiles.Value( i );
654         Handle(HYDROData_Entity) aNewProfile = theProfiles.Value( i );
655         if ( !IsEqual( anOldProfile, aNewProfile ) )
656         {
657           anIsToUpdate = true;
658           break;
659         }
660       }
661     }
662     
663     SetReferenceObjects( theProfiles, DataTag_Profile );
664
665     if ( anIsToUpdate )
666       SetToUpdate( true );
667   }
668
669   return true;
670 }
671
672 HYDROData_SequenceOfObjects HYDROData_Stream::GetProfiles() const
673 {
674   return GetReferenceObjects( DataTag_Profile );
675 }
676
677 bool HYDROData_Stream::RemoveProfile( const Handle(HYDROData_Profile)& theProfile )
678 {
679   if ( theProfile.IsNull() )
680     return false;
681
682   int aProfileIndex = -1;
683
684   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
685   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
686   for ( int i = 0 ; anIter.More(); anIter.Next(), ++i )
687   {
688     Handle(HYDROData_Profile) aProfile =
689       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
690     if ( aProfile.IsNull() )
691       continue;
692
693     if ( IsEqual( theProfile, aProfile ) )
694     {
695       aProfileIndex = i;
696       break;
697     }
698   }
699
700   if ( aProfileIndex == -1 )
701     return false;
702
703   RemoveReferenceObject( theProfile->Label(), DataTag_Profile );
704
705   // Remove parameter for removed profile
706   removeParameter( aProfileIndex );
707
708   // Indicate model of the need to update the stream presentation
709   SetToUpdate( true );
710
711   return true;
712 }
713
714 void HYDROData_Stream::RemoveProfiles()
715 {
716   bool anIsToUpdate = IsMustBeUpdated() || NbReferenceObjects( DataTag_Profile ) > 0;
717
718   ClearReferenceObjects( DataTag_Profile );
719
720   // Remove the parameters array
721   removeParametersArray();
722
723   // Indicate model of the need to update the stream presentation
724   SetToUpdate( anIsToUpdate );
725 }
726
727 void HYDROData_Stream::insertProfileInToOrder( const Handle(HYDROData_Profile)& theProfile,
728                                                const int                        theBeforeIndex )
729 {
730   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
731   if ( theProfile.IsNull() || aHydAxis.IsNull() )
732     return; 
733
734   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
735   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
736   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
737     return;
738
739   if ( theBeforeIndex == -1 )
740     AddReferenceObject( theProfile, DataTag_Profile );
741   else
742     InsertReferenceObject( theProfile, DataTag_Profile, theBeforeIndex );
743 }
744
745 bool HYDROData_Stream::BuildFace( const Handle(HYDROData_PolylineXY)& theHydAxis,
746                                   TopoDS_Face&                        thePlane )
747 {
748   if ( !IsValidAsAxis( theHydAxis ) )
749     return false;
750
751   TopoDS_Wire aHydraulicWire = TopoDS::Wire( theHydAxis->GetShape() );
752
753   gp_Ax2 aX2(gp::XOY());
754   gp_Ax3 aX3(aX2);
755   gp_Pln aPln(aX3);   
756   Bnd_Box B;
757   BRepBndLib::Add(aHydraulicWire,B);
758   Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
759   B.Get(axmin,aymin,azmin,axmax,aymax,azmax);
760   BRepBuilderAPI_MakeFace aMkr(aPln, axmin-500., axmax+500., aymin-500., aymax+500.); // to be tuned later according max/ Profile deviation
761   if(!aMkr.IsDone() || aMkr.Shape().IsNull()) return false;
762   thePlane = TopoDS::Face(aMkr.Shape());
763   return true;
764 }
765
766 void HYDROData_Stream::updateProfilesOrder()
767 {
768   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
769   if ( aRefProfiles.IsEmpty() )
770     return;
771
772   // At first we remove all profiles from order
773   RemoveProfiles();
774
775   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
776   if ( aHydAxis.IsNull() )
777     return; 
778
779   TopoDS_Face aPlane;
780   if ( !BuildFace( aHydAxis, aPlane ) )
781     return;
782
783   Standard_Real aPar( .0 );
784
785 #ifdef DEB_HASINT
786   BRep_Builder aBB;
787   TopoDS_Compound aCmp;
788   aBB.MakeCompound(aCmp);
789 #endif
790
791   HYDROData_DataMapOfRealOfHDProfile aDM;  
792   TColStd_ListOfReal aList;
793   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
794   for (int i = 1 ; anIter.More(); anIter.Next(), i++ )
795   {
796     Handle(HYDROData_Profile) aProfile =
797       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
798 #ifdef DEB_HASINT
799   TopoDS_Wire aProfileWire = TopoDS::Wire( aProfile->GetTopShape() );
800   aBB.Add( aCmp, aProfileWire ); 
801 #endif
802     if ( aProfile.IsNull() || !HasIntersection( aProfile, aPlane, aPar ) )
803       continue;
804     
805     aDM.Bind( aPar, aProfile );
806     aList.Append( aPar );
807   }
808   
809   if ( aList.IsEmpty() )
810     return;
811
812   TColStd_Array1OfReal anArr( 1, aList.Extent() );
813
814   TColStd_ListIteratorOfListOfReal it( aList );
815   for ( int j = 1; it.More(); it.Next(), j++ )
816     anArr( j ) = it.Value();
817
818   // sorting
819   if ( aList.Extent() > 1 )
820   {
821     TCollection_CompareOfReal Compar;
822     SortTools_QuickSortOfReal::Sort( anArr, Compar );
823
824     for (int j = 1; j <= anArr.Length(); j++) {
825       const Standard_Real aKey =  anArr(j);
826       const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
827       insertProfileInToOrder( aProfile );
828     }
829   } else if ( aList.Extent() == 1 ) {
830      const Standard_Real aKey = aList.Last();
831      const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
832      insertProfileInToOrder( aProfile );
833   } 
834
835   setParametersArray( anArr );
836
837 #ifdef DEB_HASINT
838   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
839   BRepTools::Write(aHydraulicWire, "Path.brep");
840   BRepTools::Write(aCmp, "Prof.brep");
841 #endif
842 }
843
844 ObjectKind HYDROData_Stream::getAltitudeObjectType() const
845 {
846   return KIND_STREAM_ALTITUDE;
847 }
848
849 void HYDROData_Stream::setParametersArray( const TColStd_Array1OfReal& theArray )
850 {
851   if ( theArray.Length() == 0 )
852   {
853     removeParametersArray();
854     return;
855   }
856
857   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray );
858   
859   Handle(TDataStd_RealArray) aParamsArray = 
860     TDataStd_RealArray::Set( aLabel, theArray.Lower(), theArray.Upper() );
861
862   for ( int i = theArray.Lower(), n = theArray.Upper(); i <= n; ++i )
863   {
864     const Standard_Real& aParam = theArray( i );
865     aParamsArray->SetValue( i, aParam );
866   }
867 }
868
869 TColStd_Array1OfReal* HYDROData_Stream::getParametersArray() const
870 {
871   TColStd_Array1OfReal* anArray = NULL;
872
873   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
874   if ( !aLabel.IsNull() )
875   {
876     Handle(TDataStd_RealArray) aParamsArray;
877     if ( aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
878     {
879       anArray = new TColStd_Array1OfReal( aParamsArray->Lower(), aParamsArray->Upper() );
880       for ( int i = aParamsArray->Lower(), n = aParamsArray->Upper(); i <= n; ++i )
881       {
882         const Standard_Real& aParam = aParamsArray->Value( i );
883         anArray->SetValue( i, aParam );
884       }
885     }
886   }
887
888   return anArray;
889 }
890
891 void HYDROData_Stream::removeParametersArray()
892 {
893   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
894   if ( !aLabel.IsNull() )
895     aLabel.ForgetAllAttributes();
896 }
897
898 int HYDROData_Stream::insertParameter( const Standard_Real& theParam )
899 {
900   int aResIndex = -1;
901
902   TColStd_Array1OfReal* anArr = getParametersArray();
903   if ( anArr )
904   {
905     aResIndex = 0;
906
907     TColStd_Array1OfReal aNewArr( anArr->Lower(), anArr->Upper() + 1 );
908
909     bool isInserted = false;
910     for ( int i = anArr->Lower(), j = i, n = anArr->Upper(); i <= n; ++i, ++j )
911     {
912       const Standard_Real& aStoredParam = anArr->Value( i );
913       if ( !isInserted )
914       {
915         if ( theParam > aStoredParam )
916         {
917           aResIndex++;
918         }
919         else
920         {
921           aNewArr( j ) = theParam;
922           isInserted = true;
923           ++j;
924         }
925       }
926
927       aNewArr( j ) = aStoredParam;
928     }
929
930     if ( !isInserted )
931     {
932       aResIndex = -1;
933       aNewArr( aNewArr.Upper() ) = theParam;
934     }
935     
936     setParametersArray( aNewArr );
937     delete anArr;
938   }
939   else
940   {
941     TColStd_Array1OfReal aNewArr( 1, 1 );
942     aNewArr.SetValue( 1, theParam );
943     setParametersArray( aNewArr );
944   }
945
946   return aResIndex;
947 }
948
949 void HYDROData_Stream::removeParameter( const int& theIndex )
950 {
951   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
952   if ( aLabel.IsNull() )
953     return;
954
955   Handle(TDataStd_RealArray) aParamsArray;
956   if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
957     return;
958
959   if ( aParamsArray->Length() == 1 )
960   {
961     removeParametersArray();
962     return;
963   }
964
965   TColStd_Array1OfReal aNewArr( aParamsArray->Lower(), aParamsArray->Upper() - 1 );
966
967   for ( int i = aParamsArray->Lower(), j = i, k = 0, n = aParamsArray->Upper(); i <= n; ++i, ++k )
968   {
969     const Standard_Real& aStoredParam = aParamsArray->Value( i );
970     if ( k == theIndex )
971       continue;
972
973     aNewArr.SetValue( j, aStoredParam );
974     ++j;
975   }
976
977   setParametersArray( aNewArr );
978 }