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