Salome HOME
Insert single profiles in to the stream order.
[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
8 #include <BRep_Builder.hxx>
9 #include <BRepBuilderAPI_MakeEdge.hxx>
10 #include <BRepBuilderAPI_MakeWire.hxx>
11 #include <BRepBuilderAPI_MakeFace.hxx>
12
13 #include <TDataStd_RealArray.hxx>
14
15 #include <TopoDS.hxx>
16 #include <TopoDS_Wire.hxx>
17 #include <TopoDS_Shell.hxx>
18 #include <TopoDS_Face.hxx>
19 #include <TopoDS_Edge.hxx>
20 #include <TopoDS_Vertex.hxx>
21 #include <TopExp.hxx>
22 #include <TopExp_Explorer.hxx>
23 #include <BRepProj_Projection.hxx>
24 #include <BRepExtrema_ExtCC.hxx>
25 #include <gp_Ax1.hxx>
26 #include <gp_Ax2.hxx>
27 #include <gp_Ax3.hxx>
28 #include <gp_Vec.hxx>
29 #include <gp_Pnt.hxx>
30 #include <gp_Pln.hxx>
31 #include <gp.hxx>
32 #include <Bnd_Box.hxx>
33 #include <BRepBndLib.hxx>
34 #include <TColStd_Array1OfReal.hxx>
35 #include <Precision.hxx>
36 #include <QStringList>
37
38 #include <NCollection_DataMap.hxx>
39 typedef NCollection_DataMap<Standard_Real, Handle(HYDROData_Profile)> HYDROData_DataMapOfRealOfHDProfile;
40 //typedef HYDROData_DataMapOfRealOfHDProfile::Iterator HYDROData_DataMapIteratorOfDataMapOfRealOfHDProfile;
41 #include <TColStd_ListOfReal.hxx>
42 #include <TColStd_ListIteratorOfListOfReal.hxx>
43 #include <TCollection_CompareOfReal.hxx>
44 #include <SortTools_QuickSortOfReal.hxx>
45 //#define DEB_HASINT 1
46 #ifdef DEB_HASINT
47 #include <BRepTools.hxx>
48 #include <TCollection_AsciiString.hxx>
49 #include <BRep_Builder.hxx>
50 #endif
51
52 #define PYTHON_STREAM_ID "KIND_STREAM"
53
54 IMPLEMENT_STANDARD_HANDLE(HYDROData_Stream,HYDROData_NaturalObject)
55 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Stream,HYDROData_NaturalObject)
56
57
58 HYDROData_Stream::HYDROData_Stream()
59 : HYDROData_NaturalObject()
60 {
61 }
62
63 HYDROData_Stream::~HYDROData_Stream()
64 {
65 }
66
67 QStringList HYDROData_Stream::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
68 {
69   QStringList aResList;
70
71   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
72   if ( aDocument.IsNull() )
73     return aResList;
74
75   QString aDocName = aDocument->GetDocPyName();
76   QString aStreamName = GetName();
77
78   aResList << QString( "%1 = %2.CreateObject( %3 );" )
79               .arg( aStreamName ).arg( aDocName ).arg( PYTHON_STREAM_ID );
80   aResList << QString( "%1.SetName( \"%2\" );" )
81               .arg( aStreamName ).arg( aStreamName );
82   aResList << QString( "" );
83
84   // TODO
85
86   return aResList;
87 }
88
89 HYDROData_SequenceOfObjects HYDROData_Stream::GetAllReferenceObjects() const
90 {
91   HYDROData_SequenceOfObjects aResSeq = HYDROData_Object::GetAllReferenceObjects();
92
93   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
94   if ( !aHydAxis.IsNull() )
95     aResSeq.Append( aHydAxis );
96
97   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
98   aResSeq.Append( aSeqOfProfiles );
99
100   return aResSeq;
101 }
102
103 TopoDS_Shape HYDROData_Stream::GetTopShape() const
104 {
105   return getTopShape();
106 }
107
108 TopoDS_Shape HYDROData_Stream::GetShape3D() const
109 {
110   return getShape3D();
111 }
112
113 void HYDROData_Stream::Update()
114 {
115   HYDROData_NaturalObject::Update();
116
117   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
118   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
119   if ( aHydAxis.IsNull() || aRefProfiles.IsEmpty() )
120     return; 
121
122   TopoDS_Shell a2dShell;
123   BRep_Builder a2dShellBuilder;
124   a2dShellBuilder.MakeShell( a2dShell );
125
126   bool anIsFirst = true;
127   gp_Pnt aPrevFirstPoint, aPrevLastPoint;
128   
129   // Construct the top presentation
130   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
131   for ( ; anIter.More(); anIter.Next() )
132   {
133     Handle(HYDROData_Profile) aProfile =
134       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
135     if ( aProfile.IsNull() )
136       continue;
137
138     gp_XY aPnt1, aPnt2;
139     if ( !aProfile->GetFirstPoint( aPnt1 ) || !aProfile->GetLastPoint( aPnt2 ) )
140       continue;
141     
142     gp_Pnt aCurFirstPoint( aPnt1.X(), aPnt1.Y(), 0 );
143     gp_Pnt aCurLastPoint(  aPnt2.X(), aPnt2.Y(), 0 );
144
145     if ( anIsFirst )
146     {
147       aPrevFirstPoint = aCurFirstPoint;
148       aPrevLastPoint = aCurLastPoint;
149       anIsFirst = false;
150       continue;
151     }
152
153     BRepBuilderAPI_MakeEdge aFirstEdge( aPrevFirstPoint, aPrevLastPoint );
154     BRepBuilderAPI_MakeEdge aSecondEdge( aPrevLastPoint, aCurLastPoint );
155     BRepBuilderAPI_MakeEdge aThirdEdge( aCurLastPoint, aCurFirstPoint );
156     BRepBuilderAPI_MakeEdge aFourthEdge( aCurFirstPoint, aPrevFirstPoint );
157
158     BRepBuilderAPI_MakeWire aMakeWire( aFirstEdge.Edge(), aSecondEdge.Edge(), 
159                                        aThirdEdge.Edge(), aFourthEdge.Edge() );
160     
161     TopoDS_Wire aSectProfileWire = aMakeWire.Wire();
162     
163     BRepBuilderAPI_MakeFace aMakeFace( aSectProfileWire, Standard_True );
164     aMakeFace.Build();
165     if( aMakeFace.IsDone() )
166     {
167       a2dShellBuilder.Add( a2dShell, aMakeFace.Face() );
168     }
169
170     aPrevFirstPoint = aCurFirstPoint;
171     aPrevLastPoint = aCurLastPoint;
172   }
173
174   SetTopShape( a2dShell );
175
176   // Construct the 3D presentation
177   /// TODO
178 }
179
180 bool HYDROData_Stream::SetHydraulicAxis( const Handle(HYDROData_PolylineXY)& theAxis )
181 {
182   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
183
184   if ( theAxis.IsNull() )
185   {
186     RemoveHydraulicAxis();
187     return !aPrevAxis.IsNull();
188   }
189
190   if ( IsEqual( aPrevAxis, theAxis ) )
191     return false;
192
193   TopoDS_Wire aHydraulicWire = TopoDS::Wire( theAxis->GetShape() );
194   if ( aHydraulicWire.IsNull() )
195     return false; // The polyline must be a single wire
196
197   SetReferenceObject( theAxis, DataTag_HydraulicAxis );
198
199   // Update the order of profiles
200   updateProfilesOrder();
201
202   // Indicate model of the need to update the stream presentation
203   SetToUpdate( true );
204
205   return true;
206 }
207
208 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetHydraulicAxis() const
209 {
210   return Handle(HYDROData_PolylineXY)::DownCast( 
211            GetReferenceObject( DataTag_HydraulicAxis ) );
212 }
213
214 void HYDROData_Stream::RemoveHydraulicAxis()
215 {
216   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
217   if ( aPrevAxis.IsNull() )
218     return;
219
220   ClearReferenceObjects( DataTag_HydraulicAxis );
221
222   // We remove the reference profiles
223   RemoveProfiles();
224
225   // Indicate model of the need to update the stream presentation
226   SetToUpdate( true );
227 }
228
229 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_Profile)& theProfile, const TopoDS_Face& thePlane,
230                                                                            Standard_Real& outPar ) const
231 {
232   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
233   if ( theProfile.IsNull() || aHydAxis.IsNull() )
234     return false; 
235
236   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() ); //guide line
237   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
238   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
239     return false;
240
241   BRepProj_Projection aProjector (aProfileWire, thePlane, gp::OZ().Direction());
242   if(!aProjector.IsDone())
243     return false;
244   TopoDS_Shape aPrjProfile = aProjector.Shape();
245   if(aPrjProfile.IsNull())
246     return false;
247   TopoDS_Vertex aV1, aV2;
248   if(aPrjProfile.ShapeType() == TopAbs_EDGE)
249           TopExp::Vertices(TopoDS::Edge(aPrjProfile), aV1, aV2);          
250   else if(aPrjProfile.ShapeType() == TopAbs_WIRE)  
251           TopExp::Vertices(TopoDS::Wire(aPrjProfile), aV1, aV2);          
252   else if(aPrjProfile.ShapeType() == TopAbs_COMPOUND){
253     TopExp_Explorer anExp(aPrjProfile, TopAbs_WIRE);
254         if(anExp.More()) {
255                 TopExp::Vertices(TopoDS::Wire(anExp.Current()), aV1, aV2);        
256         } else {
257           anExp.Init(aPrjProfile, TopAbs_EDGE);
258           if(anExp.More()) {
259                 TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV1, aV2);        
260           }
261         }
262   }
263   if(aV1.IsNull() || aV2.IsNull())
264         return false;
265   gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
266   gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
267   aPnt1.SetZ(0.0);
268   aPnt2.SetZ(0.0);
269   BRepBuilderAPI_MakeEdge aMk(aPnt1, aPnt2); 
270   if(!aMk.IsDone())
271     return false;
272   const TopoDS_Edge& anEdg2 = aMk.Edge();//Section edge
273   Standard_Integer aNum(0);
274   
275   TopExp_Explorer anExplo(aHydraulicWire, TopAbs_EDGE);
276   for(;anExplo.More();anExplo.Next()) aNum++;
277   // check for self-intersection
278   const Standard_Real SquareTolerance = Precision::Confusion()*Precision::Confusion();
279   Standard_Boolean hasInt(false);
280   Standard_Real aSqDist(DBL_MAX);
281   Standard_Integer anIndx(0);
282   BRepExtrema_ExtCC aCC;
283   aCC.Initialize(anEdg2);
284   outPar = 0.0;
285   anExplo.Init(aHydraulicWire, TopAbs_EDGE);
286   for(Standard_Integer j=1;anExplo.More();anExplo.Next(),j++) {
287         const TopoDS_Edge& anEdg1 = TopoDS::Edge(anExplo.Current());
288         if(anEdg1.IsNull())
289           continue;     
290         Standard_Boolean hasSol(false);
291         aCC.Perform(anEdg1);
292     if(aCC.IsDone()) {
293         // find minimal dist
294     for(Standard_Integer i=1; i<= aCC.NbExt();i++)
295       if(aCC.SquareDistance(i) < aSqDist) {
296         aSqDist = aCC.SquareDistance(i);
297         anIndx = i;
298                 hasSol = true;          
299           }  
300         }
301         if(hasSol) {   
302                 if(aSqDist <= SquareTolerance) { // hasInt
303         const gp_Pnt& aPnt = aCC.PointOnE1(anIndx);
304         if(aNum > 1) {
305           TopExp::Vertices(anEdg1, aV1, aV2, Standard_True);
306                   outPar += BRep_Tool::Pnt(aV1).Distance(aPnt);
307             } else {
308           Standard_Real aPar = aCC.ParameterOnE1(anIndx);
309                   outPar = aPar;
310             }
311                 hasInt = true;
312             break;
313                 } else {
314                   // no ints-n
315         if(aNum > 1) {
316           TopExp::Vertices(anEdg1, aV1, aV2);
317               outPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
318             }
319           }
320         } else if(aNum > 1) {
321           TopExp::Vertices(anEdg1, aV1, aV2);
322               outPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
323         }
324   }
325   if(hasInt)
326     return true;
327   return false;
328 }
329
330
331 bool HYDROData_Stream::AddProfile( const Handle(HYDROData_Profile)& theProfile )
332 {
333   if ( theProfile.IsNull() )
334     return false;
335
336   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
337   if ( aHydAxis.IsNull() )
338     return false;
339
340   TopoDS_Face aPlane;
341   if(!BuildFace(aHydAxis, aPlane))
342     return false;
343
344   Standard_Real aPar(.0);
345   if ( HasReference( theProfile, DataTag_Profile ) || !HasIntersection( theProfile, aPlane, aPar ) )
346     return false; // Object is already in reference list or it has no intersection
347   
348   int aProfileIndex = insertParameter( aPar );
349   insertProfileInToOrder( theProfile, aProfileIndex );
350   
351   // Indicate model of the need to update the stream presentation
352   SetToUpdate( true );
353
354   return true;
355 }
356
357 HYDROData_SequenceOfObjects HYDROData_Stream::GetProfiles() const
358 {
359   return GetReferenceObjects( DataTag_Profile );
360 }
361
362 bool HYDROData_Stream::RemoveProfile( const Handle(HYDROData_Profile)& theProfile )
363 {
364   if ( theProfile.IsNull() )
365     return false;
366
367   int aProfileIndex = -1;
368
369   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
370   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
371   for ( int i = 0 ; anIter.More(); anIter.Next(), ++i )
372   {
373     Handle(HYDROData_Profile) aProfile =
374       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
375     if ( aProfile.IsNull() )
376       continue;
377
378     if ( IsEqual( theProfile, aProfile ) )
379     {
380       aProfileIndex = i;
381       break;
382     }
383   }
384
385   if ( aProfileIndex == -1 )
386     return false;
387
388   RemoveReferenceObject( theProfile->Label(), DataTag_Profile );
389
390   // Remove parameter for removed profile
391   removeParameter( aProfileIndex );
392
393   // Indicate model of the need to update the stream presentation
394   SetToUpdate( true );
395
396   return true;
397 }
398
399 void HYDROData_Stream::RemoveProfiles()
400 {
401   bool anIsToUpdate = IsMustBeUpdated() || NbReferenceObjects( DataTag_Profile ) > 0;
402
403   ClearReferenceObjects( DataTag_Profile );
404
405   // Remove the parameters array
406   removeParametersArray();
407
408   // Indicate model of the need to update the stream presentation
409   SetToUpdate( anIsToUpdate );
410 }
411
412 void HYDROData_Stream::insertProfileInToOrder( const Handle(HYDROData_Profile)& theProfile,
413                                                const int                        theBeforeIndex )
414 {
415   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
416   if ( theProfile.IsNull() || aHydAxis.IsNull() )
417     return; 
418
419   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
420   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
421   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
422     return;
423
424   if ( theBeforeIndex == -1 )
425     AddReferenceObject( theProfile, DataTag_Profile );
426   else
427     InsertReferenceObject( theProfile, DataTag_Profile, theBeforeIndex );
428 }
429
430 bool HYDROData_Stream::BuildFace( const Handle(HYDROData_PolylineXY)& theHydAxis, TopoDS_Face& thePlane) const
431 {
432   if ( theHydAxis.IsNull() ) return false;
433   TopoDS_Wire aHydraulicWire = TopoDS::Wire( theHydAxis->GetShape() );
434   if(aHydraulicWire.IsNull()) return false;
435   gp_Ax2 aX2(gp::XOY());
436   gp_Ax3 aX3(aX2);
437   gp_Pln aPln(aX3);   
438   Bnd_Box B;
439   BRepBndLib::Add(aHydraulicWire,B);
440   Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
441   B.Get(axmin,aymin,azmin,axmax,aymax,azmax);
442   BRepBuilderAPI_MakeFace aMkr(aPln, axmin-500., axmax+500., aymin-500., aymax+500.); // to be tuned later according max/ Profile deviation
443   if(!aMkr.IsDone() || aMkr.Shape().IsNull()) return false;
444   thePlane = TopoDS::Face(aMkr.Shape());
445   return true;
446 }
447
448 void HYDROData_Stream::updateProfilesOrder()
449 {
450   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
451   if ( aRefProfiles.IsEmpty() )
452     return;
453
454   // At first we remove all profiles from order
455   RemoveProfiles();
456
457   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
458   if ( aHydAxis.IsNull() )
459     return; 
460
461   TopoDS_Face aPlane;
462   if ( !BuildFace( aHydAxis, aPlane ) )
463     return;
464
465   Standard_Real aPar( .0 );
466
467 #ifdef DEB_HASINT
468   BRep_Builder aBB;
469   TopoDS_Compound aCmp;
470   aBB.MakeCompound(aCmp);
471 #endif
472
473   HYDROData_DataMapOfRealOfHDProfile aDM;  
474   TColStd_ListOfReal aList;
475   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
476   for (int i = 1 ; anIter.More(); anIter.Next(), i++ )
477   {
478     Handle(HYDROData_Profile) aProfile =
479       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
480 #ifdef DEB_HASINT
481   TopoDS_Wire aProfileWire = TopoDS::Wire( aProfile->GetTopShape() );
482   aBB.Add( aCmp, aProfileWire ); 
483 #endif
484     if ( aProfile.IsNull() || !HasIntersection( aProfile, aPlane, aPar ) )
485       continue;
486         
487     aDM.Bind( aPar, aProfile );
488           aList.Append( aPar );
489   }
490   
491   if ( aList.IsEmpty() )
492     return;
493
494   TColStd_Array1OfReal anArr( 1, aList.Extent() );
495
496   TColStd_ListIteratorOfListOfReal it( aList );
497   for ( int j = 1; it.More(); it.Next(), j++ )
498     anArr( j ) = it.Value();
499
500   // sorting
501   if ( aList.Extent() > 1 )
502   {
503     TCollection_CompareOfReal Compar;
504     SortTools_QuickSortOfReal::Sort( anArr, Compar );
505
506     for (int j = 1; j <= anArr.Length(); j++) {
507       const Standard_Real aKey =  anArr(j);
508       const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
509       insertProfileInToOrder( aProfile );
510     }
511   } else if ( aList.Extent() == 1 ) {
512      const Standard_Real aKey = aList.Last();
513      const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
514      insertProfileInToOrder( aProfile );
515   } 
516
517   setParametersArray( anArr );
518
519 #ifdef DEB_HASINT
520   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
521   BRepTools::Write(aHydraulicWire, "Path.brep");
522   BRepTools::Write(aCmp, "Prof.brep");
523 #endif
524 }
525
526 void HYDROData_Stream::setParametersArray( const TColStd_Array1OfReal& theArray )
527 {
528   if ( theArray.Length() == 0 )
529   {
530     removeParametersArray();
531     return;
532   }
533
534   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray );
535   
536   Handle(TDataStd_RealArray) aParamsArray = 
537     TDataStd_RealArray::Set( aLabel, theArray.Lower(), theArray.Upper() );
538
539   for ( int i = theArray.Lower(), n = theArray.Upper(); i <= n; ++i )
540   {
541     const Standard_Real& aParam = theArray( i );
542     aParamsArray->SetValue( i, aParam );
543   }
544 }
545
546 TColStd_Array1OfReal* HYDROData_Stream::getParametersArray() const
547 {
548   TColStd_Array1OfReal* anArray = NULL;
549
550   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
551   if ( !aLabel.IsNull() )
552   {
553     Handle(TDataStd_RealArray) aParamsArray;
554     if ( aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
555     {
556       anArray = new TColStd_Array1OfReal( aParamsArray->Lower(), aParamsArray->Upper() );
557       for ( int i = aParamsArray->Lower(), n = aParamsArray->Upper(); i <= n; ++i )
558       {
559         const Standard_Real& aParam = aParamsArray->Value( i );
560         anArray->SetValue( i, aParam );
561       }
562     }
563   }
564
565   return anArray;
566 }
567
568 void HYDROData_Stream::removeParametersArray()
569 {
570   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
571   if ( !aLabel.IsNull() )
572     aLabel.ForgetAllAttributes();
573 }
574
575 int HYDROData_Stream::insertParameter( const Standard_Real& theParam )
576 {
577   int aResIndex = -1;
578
579   TColStd_Array1OfReal* anArr = getParametersArray();
580   if ( anArr )
581   {
582     aResIndex = 0;
583
584     TColStd_Array1OfReal aNewArr( anArr->Lower(), anArr->Upper() + 1 );
585
586     bool isInserted = false;
587     for ( int i = anArr->Lower(), j = i, n = anArr->Upper(); i <= n; ++i, ++j )
588     {
589       const Standard_Real& aStoredParam = anArr->Value( i );
590       if ( !isInserted )
591       {
592         if ( theParam > aStoredParam )
593         {
594           aResIndex++;
595         }
596         else
597         {
598           aNewArr( j ) = theParam;
599           isInserted = true;
600           ++j;
601         }
602       }
603
604       aNewArr( j ) = aStoredParam;
605     }
606
607     if ( !isInserted )
608     {
609       aResIndex = -1;
610       aNewArr( aNewArr.Upper() ) = theParam;
611     }
612     
613     setParametersArray( aNewArr );
614     delete anArr;
615   }
616   else
617   {
618     TColStd_Array1OfReal aNewArr( 1, 1 );
619     aNewArr.SetValue( 1, theParam );
620     setParametersArray( aNewArr );
621   }
622
623   return aResIndex;
624 }
625
626 void HYDROData_Stream::removeParameter( const int& theIndex )
627 {
628   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
629   if ( aLabel.IsNull() )
630     return;
631
632   Handle(TDataStd_RealArray) aParamsArray;
633   if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
634     return;
635
636   TColStd_Array1OfReal aNewArr( aParamsArray->Lower(), aParamsArray->Upper() - 1 );
637
638   for ( int i = aParamsArray->Lower(), j = i, k = 0, n = aParamsArray->Upper(); i <= n; ++i, ++k )
639   {
640     const Standard_Real& aStoredParam = aParamsArray->Value( i );
641     if ( k == theIndex )
642       continue;
643
644     aNewArr.SetValue( j, aStoredParam );
645     ++j;
646   }
647
648   setParametersArray( aNewArr );
649 }