Salome HOME
45b38d4de0821f2c494423c44b21f104e978db38
[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 #define PYTHON_STREAM_ID "KIND_STREAM"
72
73 typedef NCollection_DataMap<Standard_Real, Handle(HYDROData_Profile)> HYDROData_DataMapOfRealOfHDProfile;
74
75 IMPLEMENT_STANDARD_HANDLE(HYDROData_Stream,HYDROData_NaturalObject)
76 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Stream,HYDROData_NaturalObject)
77
78
79 HYDROData_Stream::HYDROData_Stream()
80 : HYDROData_NaturalObject()
81 {
82 }
83
84 HYDROData_Stream::~HYDROData_Stream()
85 {
86 }
87
88 QStringList HYDROData_Stream::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
89 {
90   QStringList aResList;
91
92   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
93   if ( aDocument.IsNull() )
94     return aResList;
95
96   QString aDocName = aDocument->GetDocPyName();
97   QString aStreamName = GetName();
98
99   aResList << QString( "%1 = %2.CreateObject( %3 );" )
100               .arg( aStreamName ).arg( aDocName ).arg( PYTHON_STREAM_ID );
101   aResList << QString( "%1.SetName( \"%2\" );" )
102               .arg( aStreamName ).arg( aStreamName );
103   aResList << QString( "" );
104
105   // TODO
106
107   return aResList;
108 }
109
110 HYDROData_SequenceOfObjects HYDROData_Stream::GetAllReferenceObjects() const
111 {
112   HYDROData_SequenceOfObjects aResSeq = HYDROData_Object::GetAllReferenceObjects();
113
114   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
115   if ( !aHydAxis.IsNull() )
116     aResSeq.Append( aHydAxis );
117
118   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
119   aResSeq.Append( aSeqOfProfiles );
120
121   return aResSeq;
122 }
123
124 TopoDS_Shape HYDROData_Stream::GetTopShape() const
125 {
126   return getTopShape();
127 }
128
129 TopoDS_Shape HYDROData_Stream::GetShape3D() const
130 {
131   return getShape3D();
132 }
133
134 Handle(Geom_BSplineCurve) HYDROData_Stream::buildInterpolationCurve( 
135   const Handle(TColgp_HArray1OfPnt)& theArrayOfPnt )
136 {
137   Handle(Geom_BSplineCurve) aBSpline;
138   GeomAPI_Interpolate anInterpolator (theArrayOfPnt, Standard_False, 1.0e-5); 
139   anInterpolator.Perform() ;
140   if (anInterpolator.IsDone()) 
141     aBSpline = anInterpolator.Curve();
142   return aBSpline; 
143 }
144
145 void HYDROData_Stream::Update()
146 {
147   updateProfilesOrder();
148   UpdatePrs();
149 }
150
151 void HYDROData_Stream::UpdatePrs()
152 {
153   HYDROData_NaturalObject::Update();
154
155   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
156   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
157   if ( aHydAxis.IsNull() || aRefProfiles.Length() < 2 )
158     return; 
159  
160   bool anIsFirst = true;
161   gp_Pnt aPrevFirstPoint, aPrevLastPoint;
162   Handle(TColgp_HArray1OfPnt) anArrayOfFPnt    = new TColgp_HArray1OfPnt(1, aRefProfiles.Length());
163   Handle(TColgp_HArray1OfPnt) anArrayOfLPnt    = new TColgp_HArray1OfPnt(1, aRefProfiles.Length());  
164   TopTools_Array1OfShape anArrOfProfiles(1, aRefProfiles.Length());
165   TopTools_Array1OfShape anArrOf2DProfiles(1, aRefProfiles.Length());
166
167   // Pre-processing
168   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
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     const TopoDS_Shape& aProf3d = aProfile->GetShape3D();
176     gp_XY aPnt1, aPnt2;
177     if ( !aProfile->GetLeftPoint( aPnt1 ) || !aProfile->GetRightPoint( aPnt2 ) )
178       continue;
179     anArrOfProfiles.SetValue(i,aProfile->GetShape3D());//aProfile->GetTopShape();
180     anArrOf2DProfiles.SetValue(i,aProfile->GetTopShape());
181
182     gp_Pnt aCurFirstPoint( aPnt1.X(), aPnt1.Y(), 0 ), aCurFP;
183     gp_Pnt aCurLastPoint(  aPnt2.X(), aPnt2.Y(), 0 ), aCurLP;
184     TopoDS_Vertex aV1, aV2;
185     TopExp::Vertices(TopoDS::Wire(aProf3d), aV1, aV2);
186        gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
187     if(aP1.X() == aPnt1.X() && aP1.Y() == aPnt1.Y())
188       aCurFP = aP1;
189     else
190       aCurLP = aP1;
191     aP1 = BRep_Tool::Pnt(aV2);
192     if(aP1.X() == aPnt2.X() && aP1.Y() == aPnt2.Y())
193       aCurLP = aP1;
194     else
195       aCurFP = aP1;
196     anArrayOfFPnt->SetValue(i,aCurFP);
197     anArrayOfLPnt->SetValue(i,aCurLP);
198   }
199
200   // Construct of the 3D presentation
201   Handle(Geom_BSplineCurve) aBSpline = buildInterpolationCurve (anArrayOfFPnt);
202   if(aBSpline.IsNull())
203     return;
204   TopoDS_Edge anEdgLeft, anEdgRight;
205   BRepBuilderAPI_MakeEdge aMakeEdge(aBSpline);
206   if(aMakeEdge.IsDone()) 
207     anEdgLeft = aMakeEdge.Edge();
208   if(anEdgLeft.IsNull())
209     return;
210   aBSpline.Nullify();
211   aBSpline = buildInterpolationCurve (anArrayOfLPnt);  
212   if(aBSpline.IsNull())
213     return; 
214   aMakeEdge.Init(aBSpline);
215   if(aMakeEdge.IsDone()) 
216     anEdgRight = aMakeEdge.Edge();
217   if(anEdgRight.IsNull())
218     return;
219   BRep_Builder aBB;
220   TopoDS_Compound aCmp;
221   aBB.MakeCompound(aCmp);
222   anIter.Init( aRefProfiles );
223   for (int i=1 ; i < anArrOfProfiles.Length() +1; i++ )  
224     aBB.Add(aCmp, anArrOfProfiles.Value(i));
225   aBB.Add(aCmp,anEdgLeft);
226   aBB.Add(aCmp,anEdgRight);
227   BRepCheck_Analyzer aCh(aCmp);
228   if(aCh.IsValid())
229     SetShape3D(aCmp);
230 #ifdef DEB_UPDATE
231   else {
232     BRepTools::Write(aCmp, "str3d.brep");
233     SetShape3D(aCmp);
234   }
235 #endif
236
237   // Construct the top presentation
238   for(int i=1;i<= anArrayOfLPnt->Length();i++) {
239       gp_Pnt aPnt = anArrayOfFPnt->Value(i);
240       aPnt.SetZ(.0); // make 2d
241       anArrayOfFPnt->SetValue(i, aPnt);
242       aPnt = anArrayOfLPnt->Value(i);
243       aPnt.SetZ(.0);
244       anArrayOfLPnt->SetValue(i, aPnt);
245   }
246   aBSpline.Nullify();
247   aBSpline = buildInterpolationCurve (anArrayOfFPnt);  
248   if(aBSpline.IsNull())
249     return; 
250   aMakeEdge.Init(aBSpline);
251   if(aMakeEdge.IsDone()) 
252       anEdgLeft = aMakeEdge.Edge();
253   aBSpline.Nullify();
254   aBSpline = buildInterpolationCurve (anArrayOfLPnt);  
255   if(aBSpline.IsNull())
256     return; 
257   aMakeEdge.Init(aBSpline);
258   if(aMakeEdge.IsDone()) 
259     anEdgRight = aMakeEdge.Edge();
260   if(anEdgRight.IsNull())
261     return;
262   BRepBuilderAPI_MakeEdge aMakeEdge2(anArrayOfFPnt->Value(1),anArrayOfLPnt->Value(1));
263   TopoDS_Edge aBotEdge, aTopEdge;
264   if(aMakeEdge2.IsDone()) 
265     aBotEdge = aMakeEdge2.Edge();
266   BRepBuilderAPI_MakeEdge aMakeEdge3(anArrayOfFPnt->Value(anArrayOfFPnt->Length()),anArrayOfLPnt->Value(anArrayOfLPnt->Length()));
267   if(aMakeEdge3.IsDone()) 
268     aTopEdge = aMakeEdge3.Edge();
269
270   BRepBuilderAPI_MakeWire aMakeWire( aBotEdge, anEdgLeft, aTopEdge,anEdgRight);
271   TopoDS_Wire aSectProfileWire;
272   if(aMakeWire.IsDone())
273     aSectProfileWire = aMakeWire.Wire();
274   BRepBuilderAPI_MakeFace aMakeFace( aSectProfileWire, Standard_True );
275   TopoDS_Face aFace;
276   aMakeFace.Build();
277   if( aMakeFace.IsDone() )
278     aFace = aMakeFace.Face();
279   aCmp.Nullify();
280   aBB.MakeCompound(aCmp);
281   aBB.Add(aCmp,aFace);
282   for(int i=1;i <= anArrOf2DProfiles.Length(); i++)
283     aBB.Add(aCmp,anArrOf2DProfiles.Value(i));
284   aCh.Init(aCmp);
285   if(aCh.IsValid())
286     SetTopShape(aCmp);
287 #ifdef DEB_UPDATE
288   else {
289     BRepTools::Write(aCmp, "str2d.brep");
290     SetTopShape(aCmp);
291   }
292 #endif 
293
294   // Create the stream groups
295   QString aLeftGroupName = GetName() + "_Left_Bank";
296
297   Handle(HYDROData_ShapesGroup) aLeftGroup = createGroupObject();
298   aLeftGroup->SetName( aLeftGroupName );
299   aLeftGroup->AddShape( anEdgLeft );
300
301   QString aRightGroupName = GetName() + "_Right_Bank";
302
303   Handle(HYDROData_ShapesGroup) aRightGroup = createGroupObject();
304   aRightGroup->SetName( aRightGroupName );
305   aRightGroup->AddShape( anEdgRight );
306
307   QString anInGroupName = GetName() + "_Inlet";
308
309   Handle(HYDROData_ShapesGroup) anInGroup = createGroupObject();
310   anInGroup->SetName( anInGroupName );
311   anInGroup->AddShape( aBotEdge );
312
313   QString anOutGroupName = GetName() + "_Outlet";
314
315   Handle(HYDROData_ShapesGroup) anOutGroup = createGroupObject();
316   anOutGroup->SetName( anOutGroupName );
317   anOutGroup->AddShape( aTopEdge );
318
319   // This peace of code is for testing of functionality of altitude,
320   // will be removed by adv when testing will be finished
321   Handle(HYDROData_IAltitudeObject) anAltObj = GetAltitudeObject();
322   gp_XY aTestPnt( 5, 0 );
323   anAltObj->GetAltitudeForPoint( aTestPnt );
324   // End of test code
325
326 }
327
328 QColor HYDROData_Stream::DefaultFillingColor()
329 {
330   return QColor( Qt::green );
331 }
332
333 QColor HYDROData_Stream::DefaultBorderColor()
334 {
335   return QColor( Qt::transparent );
336 }
337
338 bool HYDROData_Stream::IsValidAsAxis( const Handle(HYDROData_PolylineXY)& theHydAxis )
339 {
340   if ( theHydAxis.IsNull() )
341     return false;
342
343   TopoDS_Shape aHydraulicShape = theHydAxis->GetShape();
344   if ( aHydraulicShape.IsNull() || 
345        aHydraulicShape.ShapeType() != TopAbs_WIRE ||
346        BRep_Tool::IsClosed( aHydraulicShape ) )
347     return false; // The polyline must be a single not closed wire
348
349   return true;
350 }
351
352 TopoDS_Shape getShapeFromGroup( const HYDROData_SequenceOfObjects& theGroups,
353                                 const int                          theGroupId )
354 {
355   TopoDS_Shape aResShape;
356   if ( theGroups.Length() != 4 )
357     return aResShape;
358
359   Handle(HYDROData_ShapesGroup) aGroup =
360     Handle(HYDROData_ShapesGroup)::DownCast( theGroups.Value( theGroupId ) );
361   if ( aGroup.IsNull() )
362     return aResShape;
363
364   TopTools_SequenceOfShape aGroupShapes;
365   aGroup->GetShapes( aGroupShapes );
366
367   if ( !aGroupShapes.IsEmpty() )
368     aResShape = aGroupShapes.First();
369
370   return aResShape;
371 }
372
373 TopoDS_Shape HYDROData_Stream::GetLeftShape() const
374 {
375   HYDROData_SequenceOfObjects aGroups = GetGroups();
376   return getShapeFromGroup( aGroups, 1 );
377 }
378
379 TopoDS_Shape HYDROData_Stream::GetRightShape() const
380 {
381   HYDROData_SequenceOfObjects aGroups = GetGroups();
382   return getShapeFromGroup( aGroups, 2 );
383 }
384
385 TopoDS_Shape HYDROData_Stream::GetInletShape() const
386 {
387   HYDROData_SequenceOfObjects aGroups = GetGroups();
388   return getShapeFromGroup( aGroups, 3 );
389 }
390
391 TopoDS_Shape HYDROData_Stream::GetOutletShape() const
392 {
393   HYDROData_SequenceOfObjects aGroups = GetGroups();
394   return getShapeFromGroup( aGroups, 4 );
395 }
396
397 QColor HYDROData_Stream::getDefaultFillingColor() const
398 {
399   return DefaultFillingColor();
400 }
401
402 QColor HYDROData_Stream::getDefaultBorderColor() const
403 {
404   return DefaultBorderColor();
405 }
406
407 bool HYDROData_Stream::SetHydraulicAxis( const Handle(HYDROData_PolylineXY)& theAxis )
408 {
409   if ( !IsValidAsAxis( theAxis ) )
410     return false;
411
412   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
413   if ( IsEqual( aPrevAxis, theAxis ) )
414     return true;
415
416   SetReferenceObject( theAxis, DataTag_HydraulicAxis );
417
418   // Update the order of profiles
419   updateProfilesOrder();
420
421   // Indicate model of the need to update the stream presentation
422   SetToUpdate( true );
423
424   return true;
425 }
426
427 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetHydraulicAxis() const
428 {
429   return Handle(HYDROData_PolylineXY)::DownCast( 
430            GetReferenceObject( DataTag_HydraulicAxis ) );
431 }
432
433 void HYDROData_Stream::RemoveHydraulicAxis()
434 {
435   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
436   if ( aPrevAxis.IsNull() )
437     return;
438
439   ClearReferenceObjects( DataTag_HydraulicAxis );
440
441   // We remove the reference profiles
442   RemoveProfiles();
443
444   // Indicate model of the need to update the stream presentation
445   SetToUpdate( true );
446 }
447
448 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_PolylineXY)& theHydAxis, 
449                                         const Handle(HYDROData_Profile)& theProfile, 
450                                         const TopoDS_Face& thePlane,
451                                                               Standard_Real& outPar)
452 {
453   if ( theProfile.IsNull() || !IsValidAsAxis( theHydAxis ) )
454     return false; 
455
456   TopoDS_Wire aHydraulicWire = TopoDS::Wire( theHydAxis->GetShape() ); //guide line
457   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
458   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
459     return false;
460
461   BRepProj_Projection aProjector (aProfileWire, thePlane, gp::OZ().Direction());
462   if(!aProjector.IsDone())
463     return false;
464   TopoDS_Shape aPrjProfile = aProjector.Shape();
465   if(aPrjProfile.IsNull())
466     return false;
467   TopoDS_Vertex aV1, aV2;
468   if(aPrjProfile.ShapeType() == TopAbs_EDGE)
469     TopExp::Vertices(TopoDS::Edge(aPrjProfile), aV1, aV2);
470   else if(aPrjProfile.ShapeType() == TopAbs_WIRE)  
471     TopExp::Vertices(TopoDS::Wire(aPrjProfile), aV1, aV2);
472   else if(aPrjProfile.ShapeType() == TopAbs_COMPOUND){
473     TopExp_Explorer anExp(aPrjProfile, TopAbs_WIRE);
474     if(anExp.More()) {
475       TopExp::Vertices(TopoDS::Wire(anExp.Current()), aV1, aV2);
476     } else {
477       anExp.Init(aPrjProfile, TopAbs_EDGE);
478       if(anExp.More()) {
479         TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV1, aV2);
480       }
481     }
482   }
483   if(aV1.IsNull() || aV2.IsNull())
484     return false;
485   gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
486   gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
487   aPnt1.SetZ(0.0);
488   aPnt2.SetZ(0.0);
489   BRepBuilderAPI_MakeEdge aMk(aPnt1, aPnt2); 
490   if(!aMk.IsDone())
491     return false;
492   const TopoDS_Edge& anEdg2 = aMk.Edge();//Section edge
493   Standard_Integer aNum(0);
494   
495   TopExp_Explorer anExplo(aHydraulicWire, TopAbs_EDGE);
496   for(;anExplo.More();anExplo.Next()) aNum++;
497   // check for self-intersection
498   const Standard_Real SquareTolerance = Precision::Confusion()*Precision::Confusion();
499   Standard_Boolean hasInt(false);
500   Standard_Real aSqDist(DBL_MAX);
501   Standard_Integer anIndx(0);
502   BRepExtrema_ExtCC aCC;
503   aCC.Initialize(anEdg2);
504   outPar = 0.0;
505   anExplo.Init(aHydraulicWire, TopAbs_EDGE);
506   for(Standard_Integer j=1;anExplo.More();anExplo.Next(),j++) {
507     const TopoDS_Edge& anEdg1 = TopoDS::Edge(anExplo.Current());
508     if(anEdg1.IsNull())
509       continue;
510     Standard_Boolean hasSol(false);
511     aCC.Perform(anEdg1);
512     if(aCC.IsDone()) {
513     // find minimal dist
514     for(Standard_Integer i=1; i<= aCC.NbExt();i++)
515       if(aCC.SquareDistance(i) < aSqDist) {
516         aSqDist = aCC.SquareDistance(i);
517         anIndx = i;
518         hasSol = true;
519       }  
520     }
521     if(hasSol) {
522       if(aSqDist <= SquareTolerance) { // hasInt
523         const gp_Pnt& aPnt = aCC.PointOnE1(anIndx);
524         if(aNum > 1) {
525           TopExp::Vertices(anEdg1, aV1, aV2, Standard_True);
526           outPar += BRep_Tool::Pnt(aV1).Distance(aPnt);
527         } else {
528           Standard_Real aPar = aCC.ParameterOnE1(anIndx);
529           outPar = aPar;
530         }
531         hasInt = true;
532         break;
533       } else {
534           // no ints-n
535         if(aNum > 1) {
536           TopExp::Vertices(anEdg1, aV1, aV2);
537           outPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
538         }
539       }
540     } else if(aNum > 1) {
541       TopExp::Vertices(anEdg1, aV1, aV2);
542       outPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
543     }
544   }
545   if(hasInt)
546     return true;
547   return false;
548 }
549
550 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_Profile)& theProfile, const TopoDS_Face& thePlane,
551                                        Standard_Real& outPar ) const
552 {
553   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
554
555   return HasIntersection( aHydAxis, theProfile, thePlane, outPar );
556 }
557
558
559 bool HYDROData_Stream::AddProfile( const Handle(HYDROData_Profile)& theProfile )
560 {
561   if ( theProfile.IsNull() )
562     return false;
563
564   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
565   if ( aHydAxis.IsNull() )
566     return false;
567
568   TopoDS_Face aPlane;
569   if(!BuildFace(aHydAxis, aPlane))
570     return false;
571
572   Standard_Real aPar(.0);
573   if ( HasReference( theProfile, DataTag_Profile ) || !HasIntersection( theProfile, aPlane, aPar ) )
574     return false; // Object is already in reference list or it has no intersection
575   
576   int aProfileIndex = insertParameter( aPar );
577   insertProfileInToOrder( theProfile, aProfileIndex );
578   
579   // Indicate model of the need to update the stream presentation
580   SetToUpdate( true );
581
582   return true;
583 }
584
585 HYDROData_SequenceOfObjects HYDROData_Stream::GetProfiles() const
586 {
587   return GetReferenceObjects( DataTag_Profile );
588 }
589
590 bool HYDROData_Stream::RemoveProfile( const Handle(HYDROData_Profile)& theProfile )
591 {
592   if ( theProfile.IsNull() )
593     return false;
594
595   int aProfileIndex = -1;
596
597   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
598   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
599   for ( int i = 0 ; anIter.More(); anIter.Next(), ++i )
600   {
601     Handle(HYDROData_Profile) aProfile =
602       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
603     if ( aProfile.IsNull() )
604       continue;
605
606     if ( IsEqual( theProfile, aProfile ) )
607     {
608       aProfileIndex = i;
609       break;
610     }
611   }
612
613   if ( aProfileIndex == -1 )
614     return false;
615
616   RemoveReferenceObject( theProfile->Label(), DataTag_Profile );
617
618   // Remove parameter for removed profile
619   removeParameter( aProfileIndex );
620
621   // Indicate model of the need to update the stream presentation
622   SetToUpdate( true );
623
624   return true;
625 }
626
627 void HYDROData_Stream::RemoveProfiles()
628 {
629   bool anIsToUpdate = IsMustBeUpdated() || NbReferenceObjects( DataTag_Profile ) > 0;
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   SetToUpdate( anIsToUpdate );
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 ) const
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 = TopoDS::Face(aMkr.Shape());
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_STREAM_ALTITUDE;
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 }