Salome HOME
e75dc36897878f078e09ed44db9b59fc5793e0f1
[modules/hydro.git] / src / HYDROData / HYDROData_Stream.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include "HYDROData_Stream.h"
20
21 #include "HYDROData_Document.h"
22 #include "HYDROData_PolylineXY.h"
23 #include "HYDROData_Polyline3D.h"
24 #include "HYDROData_Profile.h"
25 #include "HYDROData_ShapesGroup.h"
26 #include "HYDROData_ShapesTool.h"
27 #include "HYDROData_IAltitudeObject.h"
28 #include "HYDROData_IProfilesInterpolator.h"
29 #include "HYDROData_Tool.h"
30 #include "HYDROData_DTM.h"
31 #include "HYDROData_LISM.h"
32
33 #include <HYDROData_Bathymetry.h>
34
35 #include <TDataStd_RealArray.hxx>
36
37 #include <Precision.hxx>
38
39 #include <NCollection_DataMap.hxx>
40
41 #include <TColStd_Array1OfReal.hxx>
42 #include <TColStd_ListOfReal.hxx>
43 #include <TColStd_ListIteratorOfListOfReal.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_HArray1OfShape.hxx>
80 #include <TopTools_IndexedMapOfOrientedShape.hxx>
81 #include <TopTools_ListIteratorOfListOfShape.hxx>
82 #include <TopTools_SequenceOfShape.hxx>
83 #include <TopTools_IndexedMapOfShape.hxx>
84
85 #include <QColor>
86 #include <QStringList>
87 #include <QVector>
88
89 //#define DEB_STREAM 1
90 #ifdef DEB_STREAM
91 //#define DEB_HASINT 1
92 //#define DEB_UPDATE 1
93 #include <BRepTools.hxx>
94 #include <TCollection_AsciiString.hxx>
95 #endif
96
97 #define _DEVDEBUG_
98 #include "HYDRO_trace.hxx"
99
100 #include <assert.h>
101
102 typedef NCollection_DataMap<Standard_Real, Handle(HYDROData_Profile)> HYDROData_DataMapOfRealOfHDProfile;
103
104 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Stream,HYDROData_NaturalObject)
105
106
107 HYDROData_Stream::HYDROData_Stream()
108 : HYDROData_NaturalObject( Geom_3d )
109 {
110 }
111
112 HYDROData_Stream::~HYDROData_Stream()
113 {
114 }
115
116 QStringList HYDROData_Stream::DumpToPython( const QString&       thePyScriptPath,
117                                             MapOfTreatedObjects& theTreatedObjects ) const
118 {
119   QStringList aResList = dumpObjectCreation( theTreatedObjects );
120   QString aName = GetObjPyName();
121
122   int interpMethod = GetInterpolationMethod();
123   QString anInterpMethod = QString::number( interpMethod );
124   aResList << QString( "%1.SetInterpolationMethod( %2 )" ).arg( aName ).arg( anInterpMethod );
125
126   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
127   setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aHydAxis, "SetHydraulicAxis" );
128
129   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
130   for ( int i = 1, aNb = aSeqOfProfiles.Size(); i <= aNb; ++i )
131   {
132     const Handle(HYDROData_Entity) aProfile = aSeqOfProfiles.Value( i );
133     setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aProfile, "AddProfile" );
134   }
135
136   // Set bottom polyline if exists
137   const Handle(HYDROData_Polyline3D) aBottomPolyline = GetBottomPolyline();
138   if ( !aBottomPolyline.IsNull() ) {
139     setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aBottomPolyline, "SetBottomPolyline" );
140   }
141
142   if (interpMethod==0)
143   {
144     QString aDDZs = QString::number( GetDDZ(), 'f', 3 );
145     QString aSSteps = QString::number( GetSpatialStep(), 'f', 3 );
146     aResList << QString( "%1.SetDDZ( %2 )" ).arg( aName ).arg( aDDZs );
147     aResList << QString( "%1.SetSpatialStep( %2 )" ).arg( aName ).arg( aSSteps );
148   }
149   else if (interpMethod==1)
150   {
151     Handle(HYDROData_PolylineXY) aLeftBank = GetLeftBank();
152     setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aLeftBank, "SetLeftBank" );
153     Handle(HYDROData_PolylineXY) aRightBank = GetRightBank();
154     setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aRightBank, "SetRightBank" );
155
156     QString aHaxStep = QString::number( GetHaxStep(), 'f', 3 );
157     QString aNbProfilePoints = QString::number( GetNbProfilePoints() );
158     aResList << QString( "%1.SetHaxStep( %2 )" ).arg( aName ).arg( aHaxStep );
159     aResList << QString( "%1.SetNbProfilePoints( %2 )" ).arg( aName ).arg( aNbProfilePoints );
160   }
161
162   aResList << QString( "" );
163   aResList << QString( "%1.Update()" ).arg( aName );
164   aResList << QString( "" );
165
166   return aResList;
167 }
168
169 HYDROData_SequenceOfObjects HYDROData_Stream::GetAllReferenceObjects() const
170 {
171   HYDROData_SequenceOfObjects aResSeq = HYDROData_Object::GetAllReferenceObjects();
172
173   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
174   if ( !aHydAxis.IsNull() )
175     aResSeq.Append( aHydAxis );
176
177   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
178   aResSeq.Append( aSeqOfProfiles );
179
180   return aResSeq;
181 }
182
183 Handle(Geom_BSplineCurve) HYDROData_Stream::buildInterpolationCurve( 
184   const Handle(TColgp_HArray1OfPnt)& theArrayOfPnt )
185 {
186   Handle(Geom_BSplineCurve) aBSpline;
187   GeomAPI_Interpolate anInterpolator (theArrayOfPnt, Standard_False, 1.0e-5); 
188   anInterpolator.Perform() ;
189   if (anInterpolator.IsDone()) 
190     aBSpline = anInterpolator.Curve();
191   return aBSpline; 
192 }
193
194 void HYDROData_Stream::GetWarnings(NCollection_DataMap<Handle(HYDROData_Profile), QSet<QString>>& warnings)
195 {
196   warnings = myWarnings;
197 }  
198
199 void HYDROData_Stream::Update()
200 {
201   if (GetInterpolationMethod() == 0)
202   {
203     if (!GetHydraulicAxis().IsNull())
204       updateProfilesOrder();
205
206     // Update bottom polyline if exists
207     const Handle(HYDROData_Polyline3D) aBottomPolyline = GetBottomPolyline();
208     if ( !aBottomPolyline.IsNull() ) {
209       if ( GenerateBottomPolyline() ) {
210         Handle(HYDROData_PolylineXY) aPolylineXY = aBottomPolyline->GetPolylineXY();
211         if ( !aPolylineXY.IsNull() ) {
212           aPolylineXY->Update();
213         }
214         aBottomPolyline->Update();
215       }
216     }
217
218     Handle(HYDROData_DTM) dtm = DTM();
219     dtm->Update();
220     UpdatePrs( dtm );
221
222     myWarnings.Clear();
223     dtm->GetWarnings(myWarnings);
224   }
225   else
226   {
227     Handle(HYDROData_LISM) lism = LISM();
228     lism->Update();
229     UpdatePrs( lism );
230
231     myWarnings.Clear();
232     //lism->GetWarnings(myWarnings);
233     //TODO warnings
234   }
235
236   HYDROData_NaturalObject::Update();
237 }
238
239 bool HYDROData_Stream::IsHas2dPrs() const
240 {
241   return true;
242 }
243
244 bool HYDROData_Stream::CreatePresentations( const Handle(HYDROData_DTM)& theDTM,
245                                             PrsDefinition&              thePrs )
246 {
247   if ( theDTM.IsNull() )
248     return false;
249
250   HYDROData_SequenceOfObjects profiles = theDTM->GetProfiles();
251   if( profiles.Length() < 2 )
252     return false;
253
254   TopoDS_Shape Out3dPres;
255   TopoDS_Shape Out2dPres;
256   TopoDS_Shape OutLeftB;
257   TopoDS_Shape OutRightB;
258   TopoDS_Shape OutInlet;
259   TopoDS_Shape OutOutlet;
260
261   theDTM->GetPresentationShapes(Out3dPres, Out2dPres, OutLeftB, OutRightB, OutInlet, OutOutlet);
262
263   thePrs.myInlet = OutInlet;
264   thePrs.myOutlet = OutOutlet;
265   thePrs.myLeftBank = OutLeftB;
266   thePrs.myRightBank = OutRightB;
267   thePrs.myPrs2D = Out2dPres;
268   thePrs.myPrs3D = Out3dPres;
269   /*std::vector<TopoDS_Wire> profiles3d;
270   profiles3d.reserve(profiles.Length());
271
272   // Pre-processing
273   HYDROData_SequenceOfObjects::Iterator anIter( profiles );
274   for (int i=1 ; anIter.More(); anIter.Next(),i++ )
275   {
276     Handle(HYDROData_Profile) aProfile =
277       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
278
279     if ( aProfile.IsNull() )
280       continue;
281
282     const TopoDS_Shape& aProfileShape = aProfile->GetShape3D();
283     //TopExp_Explorer exp(aProfileShape, TopAbs_EDGE);
284     profiles3d.push_back( TopoDS::Wire(aProfileShape) );
285   }*/
286
287   return true;
288 }
289
290 void HYDROData_Stream::internalUpdatePrs( const PrsDefinition& aResultPrs )
291 {
292   SetShape3D( aResultPrs.myPrs3D );
293   SetTopShape( aResultPrs.myPrs2D );
294
295   // Create the stream groups
296   QString aLeftGroupName = GetName() + "_Left_Bank";
297
298   Handle(HYDROData_ShapesGroup) aLeftGroup = createGroupObject();
299   aLeftGroup->SetName( aLeftGroupName );
300   aLeftGroup->AddShape( aResultPrs.myLeftBank );
301
302   QString aRightGroupName = GetName() + "_Right_Bank";
303
304   Handle(HYDROData_ShapesGroup) aRightGroup = createGroupObject();
305   aRightGroup->SetName( aRightGroupName );
306   aRightGroup->AddShape( aResultPrs.myRightBank );
307
308   QString anInGroupName = GetName() + "_Inlet";
309
310   Handle(HYDROData_ShapesGroup) anInGroup = createGroupObject();
311   anInGroup->SetName( anInGroupName );
312   anInGroup->AddShape( aResultPrs.myInlet );
313
314   QString anOutGroupName = GetName() + "_Outlet";
315   
316   Handle(HYDROData_ShapesGroup) anOutGroup = createGroupObject();
317   anOutGroup->SetName( anOutGroupName );
318   anOutGroup->AddShape( aResultPrs.myOutlet );
319 }
320
321
322 void HYDROData_Stream::UpdatePrs( const Handle(HYDROData_DTM)& theDTM )
323 {
324   HYDROData_NaturalObject::Update();
325   
326   PrsDefinition aResultPrs;
327   if ( !CreatePresentations( theDTM, aResultPrs ) )
328     return;
329
330   internalUpdatePrs(aResultPrs);
331 }
332
333 void HYDROData_Stream::UpdatePrs( const Handle(HYDROData_LISM)& theLISM )
334 {
335   HYDROData_NaturalObject::Update();
336   PrsDefinition prsDef;
337   theLISM->GetShapePresentations(prsDef);
338
339   internalUpdatePrs(prsDef);
340 }
341
342 QColor HYDROData_Stream::DefaultFillingColor() const
343 {
344   return QColor( Qt::green );
345 }
346
347 QColor HYDROData_Stream::DefaultBorderColor() const
348 {
349   return QColor( Qt::transparent );
350 }
351
352 bool HYDROData_Stream::IsValidAsAxis( const Handle(HYDROData_PolylineXY)& theHydAxis )
353 {
354   if ( theHydAxis.IsNull() )
355     return true;
356
357   TopoDS_Shape aHydraulicShape = theHydAxis->GetShape();
358   if ( aHydraulicShape.IsNull() || 
359        aHydraulicShape.ShapeType() != TopAbs_WIRE ||
360        BRep_Tool::IsClosed( aHydraulicShape ) )
361     return false; // The polyline must be a single not closed wire
362
363   return true;
364 }
365
366 TopoDS_Shape HYDROData_Stream::GetLeftShape() const
367 {
368   HYDROData_SequenceOfObjects aGroups = GetGroups();
369   return HYDROData_Tool::getFirstShapeFromGroup( aGroups, 1);
370 }
371
372 TopoDS_Shape HYDROData_Stream::GetRightShape() const
373 {
374   HYDROData_SequenceOfObjects aGroups = GetGroups();
375   return HYDROData_Tool::getFirstShapeFromGroup( aGroups, 2);
376 }
377
378 TopoDS_Shape HYDROData_Stream::GetInletShape() const
379 {
380   HYDROData_SequenceOfObjects aGroups = GetGroups();
381   return HYDROData_Tool::getFirstShapeFromGroup( aGroups, 3);
382 }
383
384 TopoDS_Shape HYDROData_Stream::GetOutletShape() const
385 {
386   HYDROData_SequenceOfObjects aGroups = GetGroups();
387   return HYDROData_Tool::getFirstShapeFromGroup( aGroups, 4);
388 }
389
390 Handle(HYDROData_DTM) HYDROData_Stream::DTM() const
391 {
392   const_cast<HYDROData_Stream*>( this )->checkAndSetAltitudeObject();
393   return Handle(HYDROData_DTM)::DownCast( GetAltitudeObject() );
394 }
395
396 Handle(HYDROData_LISM) HYDROData_Stream::LISM() const
397 {
398   const_cast<HYDROData_Stream*>( this )->checkAndSetAltitudeObject();
399   return Handle(HYDROData_LISM)::DownCast( GetAltitudeObject() );
400 }
401
402 double HYDROData_Stream::GetDDZ() const
403 {
404   return DTM()->GetDDZ();
405 }
406
407 void HYDROData_Stream::SetDDZ( double theDDZ )
408 {
409   DTM()->SetDDZ( theDDZ );
410   Changed( Geom_3d );
411 }
412
413 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetLeftBank() const
414 {
415   return LISM()->GetLeftBank();
416 }
417
418 void HYDROData_Stream::SetLeftBank( const Handle(HYDROData_PolylineXY)& theBank )
419 {
420   LISM()->SetLeftBank( theBank );
421   Changed( Geom_3d );
422 }
423
424 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetRightBank() const
425 {
426   return LISM()->GetRightBank();
427 }
428
429 void HYDROData_Stream::SetRightBank( const Handle(HYDROData_PolylineXY)& theBank )
430 {
431   LISM()->SetRightBank( theBank );
432   Changed( Geom_3d );
433 }
434   
435   
436 double HYDROData_Stream::GetHaxStep() const
437 {
438   return LISM()->GetHaxStep();
439 }
440
441 void HYDROData_Stream::SetHaxStep( double theHaxStep )
442 {
443   LISM()->SetHaxStep( theHaxStep );
444   Changed( Geom_3d );
445 }
446
447 int HYDROData_Stream::GetNbProfilePoints() const
448 {
449   return LISM()->GetNbProfilePoints();
450 }
451
452 void HYDROData_Stream::SetNbProfilePoints( int theNbPoints )
453 {
454   LISM()->SetNbProfilePoints( theNbPoints );
455   Changed( Geom_3d );
456 }
457   
458 double HYDROData_Stream::GetSpatialStep() const
459 {
460   if (GetInterpolationMethod() == 0)
461     return DTM()->GetSpatialStep();
462   else
463     return LISM()->GetHaxStep();
464 }
465
466 void HYDROData_Stream::SetSpatialStep( double theSpatialStep )
467 {
468   if (GetInterpolationMethod() == 0 )  
469     DTM()->SetSpatialStep( theSpatialStep );
470   else
471     LISM()->SetHaxStep( theSpatialStep );
472   Changed( Geom_3d );
473 }
474
475 bool HYDROData_Stream::SetHydraulicAxis( const Handle(HYDROData_PolylineXY)& theAxis )
476 {
477   if (GetInterpolationMethod() == 0)
478   {
479     if ( !IsValidAsAxis( theAxis ) )
480       return false;
481
482     Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
483     if ( IsEqual( aPrevAxis, theAxis ) )
484       return true;
485
486     SetReferenceObject( theAxis, DataTag_HydraulicAxis );
487
488     // Update the order of profiles
489     updateProfilesOrder();
490
491     // Indicate model of the need to update the stream presentation
492     Changed( Geom_3d );
493   }
494   else
495   {
496     LISM()->SetHydraulicAxis( theAxis );
497     Changed( Geom_3d );
498   }
499
500   return true;
501 }
502
503 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetHydraulicAxis() const
504 {
505   if (GetInterpolationMethod() == 0)
506     return Handle(HYDROData_PolylineXY)::DownCast( GetReferenceObject( DataTag_HydraulicAxis ) );
507   else
508     return LISM()->GetHydraulicAxis();
509 }
510
511 void HYDROData_Stream::RemoveHydraulicAxis()
512 {
513   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
514   if ( aPrevAxis.IsNull() )
515     return;
516
517   ClearReferenceObjects( DataTag_HydraulicAxis );
518
519   // We remove the reference profiles
520   RemoveProfiles();
521
522   // Indicate model of the need to update the stream presentation
523   Changed( Geom_3d );
524 }
525
526 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_Profile)& theProfile,
527                                         const TopoDS_Face&               thePlane,
528                                         Standard_Real&                   theOutPar ) const
529 {
530   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
531   return HasIntersection( aHydAxis, theProfile, thePlane, theOutPar );
532 }
533
534 #include <BRepAlgo_NormalProjection.hxx>
535
536 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_PolylineXY)& theHydAxis, 
537                                         const Handle(HYDROData_Profile)&    theProfile, 
538                                         const TopoDS_Face&                  thePlane,
539                                         Standard_Real&                      theOutPar )
540 {
541   if ( theProfile.IsNull() /*|| !IsValidAsAxis( theHydAxis )*/ )
542     return false; 
543
544   if (theHydAxis.IsNull())
545     return true; //empty h_axis; its's OK
546
547   TopoDS_Wire aHydraulicWire = TopoDS::Wire( theHydAxis->GetShape() ); //guide line
548   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
549   if ( aProfileWire.IsNull() )
550     {
551       DEBTRACE("aProfileWire.IsNull");
552       return false;
553     }
554
555   //BRepProj_Projection aProjector (aProfileWire, thePlane, gp::OZ().Direction());
556   BRepAlgo_NormalProjection nproj(thePlane);
557   nproj.Add(aProfileWire);
558   nproj.SetDefaultParams();
559   nproj.Build();
560   if(!nproj.IsDone())
561     {
562       DEBTRACE("!nproj.IsDone");
563       return false;
564     }
565   TopoDS_Shape aPrjProfile = nproj.Projection();
566   if(aPrjProfile.IsNull())
567     {
568       DEBTRACE("aPrjProfile.IsNull");
569       return false;
570     }
571   TopoDS_Vertex aV1, aV2;
572   if(aPrjProfile.ShapeType() == TopAbs_EDGE)
573     TopExp::Vertices(TopoDS::Edge(aPrjProfile), aV1, aV2);
574   else if(aPrjProfile.ShapeType() == TopAbs_WIRE)  
575     TopExp::Vertices(TopoDS::Wire(aPrjProfile), aV1, aV2);
576   else if(aPrjProfile.ShapeType() == TopAbs_COMPOUND){
577     TopExp_Explorer anExp(aPrjProfile, TopAbs_WIRE);
578     if(anExp.More()) {
579       TopExp::Vertices(TopoDS::Wire(anExp.Current()), aV1, aV2);
580     } else {
581       anExp.Init(aPrjProfile, TopAbs_EDGE);
582       if(anExp.More()) {
583         TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV1, aV2);
584       }
585     }
586   }
587   if(aV1.IsNull() || aV2.IsNull())
588     {
589       DEBTRACE("aV1.IsNull() || aV2.IsNull()");
590       return false;
591     }
592   gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
593   gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
594   aPnt1.SetZ(0.0);
595   aPnt2.SetZ(0.0);
596   BRepBuilderAPI_MakeEdge aMk(aPnt1, aPnt2); 
597   if(!aMk.IsDone())
598     {
599       DEBTRACE("!aMk.IsDone()");
600       return false;
601     }
602   const TopoDS_Edge& anEdg2 = aMk.Edge();//Section edge
603   Standard_Integer aNum(0);
604   
605   TopExp_Explorer anExplo(aHydraulicWire, TopAbs_EDGE);
606   for(;anExplo.More();anExplo.Next()) aNum++;
607   // check for self-intersection
608   const Standard_Real SquareTolerance = Precision::Confusion()*Precision::Confusion();
609   Standard_Boolean hasInt(false);
610   Standard_Real aSqDist(DBL_MAX);
611   Standard_Integer anIndx(0);
612   BRepExtrema_ExtCC aCC;
613   aCC.Initialize(anEdg2);
614   theOutPar = 0.0;
615   anExplo.Init(aHydraulicWire, TopAbs_EDGE);
616   for(Standard_Integer j=1;anExplo.More();anExplo.Next(),j++) {
617     const TopoDS_Edge& anEdg1 = TopoDS::Edge(anExplo.Current());
618     if(anEdg1.IsNull())
619       continue;
620     Standard_Boolean hasSol(false);
621     aCC.Perform(anEdg1);
622     if(aCC.IsDone()) {
623     // find minimal dist
624     for(Standard_Integer i=1; i<= aCC.NbExt();i++)
625       if(aCC.SquareDistance(i) < aSqDist) {
626         aSqDist = aCC.SquareDistance(i);
627         anIndx = i;
628         hasSol = true;
629       }  
630     }
631     if(hasSol) {
632       if(aSqDist <= SquareTolerance) { // hasInt
633         const gp_Pnt& aPnt = aCC.PointOnE1(anIndx);
634         if(aNum > 1) {
635           TopExp::Vertices(anEdg1, aV1, aV2, Standard_True);
636           theOutPar += BRep_Tool::Pnt(aV1).Distance(aPnt);
637         } else {
638           Standard_Real aPar = aCC.ParameterOnE1(anIndx);
639           theOutPar = aPar;
640         }
641         hasInt = true;
642         break;
643       } else {
644           // no ints-n
645         if(aNum > 1) {
646           TopExp::Vertices(anEdg1, aV1, aV2);
647           theOutPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
648         }
649       }
650     } else if(aNum > 1) {
651       TopExp::Vertices(anEdg1, aV1, aV2);
652       theOutPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
653     }
654   }
655   if(hasInt)
656     return true;
657   DEBTRACE("!hasInt " << aPnt1.X() << " " << aPnt1.Y() << " " << aPnt2.X() << " " << aPnt2.Y() << " --- " << aSqDist);
658   return false;
659 }
660
661 bool HYDROData_Stream::AddProfile( const Handle(HYDROData_Profile)& theProfile )
662 {
663   if ( theProfile.IsNull() )
664     return false;
665
666  // Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
667  // if ( aHydAxis.IsNull() )
668  //   return false;
669
670   TopoDS_Face aPlane;
671   BuildRefFace( aPlane );
672
673   Standard_Real aPar(.0);
674   if ( HasReference( theProfile, DataTag_Profile ) || !HasIntersection( theProfile, aPlane, aPar ) )
675     return false; // Object is already in reference list or it has no intersection
676   //DEBTRACE("AddProfile - insertParameter " << aPar);
677   int aProfileIndex = insertParameter( aPar );
678   insertProfileInToOrder( theProfile, aProfileIndex );
679
680   if (GetInterpolationMethod()==0)
681     DTM()->SetProfiles( GetProfiles() );
682   else
683     LISM()->SetProfiles( GetProfiles() );
684   
685   // Indicate model of the need to update the stream presentation
686   Changed( Geom_3d );
687
688   return true;
689 }
690
691 bool HYDROData_Stream::SetProfiles( const HYDROData_SequenceOfObjects& theProfiles,
692                                     const bool&                        theIsToOrder )
693 {
694   DEBTRACE(" --- SetProfiles " <<theIsToOrder );
695   if ( theIsToOrder )
696   {
697     for ( int i = 1; i <= theProfiles.Length(); ++i )
698     {
699       Handle(HYDROData_Profile) aProfile = 
700         Handle(HYDROData_Profile)::DownCast( theProfiles.Value( i ) );
701       if ( aProfile.IsNull() )
702         continue;
703
704       if ( !AddProfile( aProfile ) )
705       {
706         DTM()->SetProfiles( HYDROData_SequenceOfObjects() );
707         return false;
708       }
709     }
710   }
711   else // Just store the sequence of objects as is
712   {
713     bool anIsToUpdate = true;
714
715     HYDROData_SequenceOfObjects anOldProfiles = GetProfiles();
716     if ( anOldProfiles.Length() == theProfiles.Length() )
717     {
718       anIsToUpdate = false;
719
720       for ( int i = 1; i <= theProfiles.Length(); ++i )
721       {
722         Handle(HYDROData_Entity) anOldProfile = anOldProfiles.Value( i );
723         Handle(HYDROData_Entity) aNewProfile = theProfiles.Value( i );
724         if ( !IsEqual( anOldProfile, aNewProfile ) )
725         {
726           anIsToUpdate = true;
727           break;
728         }
729       }
730     }
731     
732     SetReferenceObjects( theProfiles, DataTag_Profile );
733
734     if ( anIsToUpdate )
735       Changed( Geom_3d );
736   }
737
738   if (GetInterpolationMethod()==0)
739     DTM()->SetProfiles( GetProfiles() );
740   else
741     LISM()->SetProfiles( GetProfiles() );
742   return true;
743 }
744
745 HYDROData_SequenceOfObjects HYDROData_Stream::GetProfiles() const
746 {
747   return GetReferenceObjects( DataTag_Profile );
748 }
749
750 bool HYDROData_Stream::RemoveProfile( const Handle(HYDROData_Profile)& theProfile )
751 {
752   if ( theProfile.IsNull() )
753     return false;
754
755   int aProfileIndex = -1;
756
757   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
758   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
759   for ( int i = 0 ; anIter.More(); anIter.Next(), ++i )
760   {
761     Handle(HYDROData_Profile) aProfile =
762       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
763     if ( aProfile.IsNull() )
764       continue;
765
766     if ( IsEqual( theProfile, aProfile ) )
767     {
768       aProfileIndex = i;
769       break;
770     }
771   }
772
773   if ( aProfileIndex == -1 )
774     return false;
775
776   RemoveReferenceObject( theProfile->Label(), DataTag_Profile );
777
778   // Remove parameter for removed profile
779   removeParameter( aProfileIndex );
780
781   // Indicate model of the need to update the stream presentation
782   Changed( Geom_3d );
783
784   return true;
785 }
786
787 void HYDROData_Stream::RemoveProfiles()
788 {
789   ClearReferenceObjects( DataTag_Profile );
790
791   // Remove the parameters array
792   removeParametersArray();
793
794   // Indicate model of the need to update the stream presentation
795   Changed( Geom_3d );
796 }
797
798
799 int HYDROData_Stream::GetInterpolationMethod() const
800 {
801   return GetInteger( DataTag_InterpMethod );
802 }
803
804 void HYDROData_Stream::SetInterpolationMethod( int theMethod ) //if DTM => 0 ; if LISM => 1
805 {
806   SetInteger( DataTag_InterpMethod, theMethod );
807   Changed( Geom_3d );
808 }
809
810
811 void HYDROData_Stream::insertProfileInToOrder( const Handle(HYDROData_Profile)& theProfile,
812                                                const int                        theBeforeIndex )
813 {
814   //Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
815   if ( theProfile.IsNull() )
816     return; 
817
818   //TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
819   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
820   if ( aProfileWire.IsNull() )
821     return;
822
823   if ( theBeforeIndex == -1 )
824     AddReferenceObject( theProfile, DataTag_Profile );
825   else
826     InsertReferenceObject( theProfile, DataTag_Profile, theBeforeIndex );
827 }
828
829 void HYDROData_Stream::BuildRefFace( TopoDS_Face& thePlane )
830 {
831   thePlane = BRepBuilderAPI_MakeFace(gp_Pln(gp_Pnt(0,0,0),gp_Dir(0,0,1))).Face();
832 }
833
834 void HYDROData_Stream::updateProfilesOrder()
835 {
836   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
837   if ( aRefProfiles.IsEmpty() )
838     return;
839
840   // At first we remove all profiles from order
841   RemoveProfiles();
842
843   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
844   if ( aHydAxis.IsNull() )
845     return; 
846
847   TopoDS_Face aPlane;
848   BuildRefFace( aPlane );
849
850   Standard_Real aPar( .0 );
851
852 #ifdef DEB_HASINT
853   BRep_Builder aBB;
854   TopoDS_Compound aCmp;
855   aBB.MakeCompound(aCmp);
856 #endif
857
858   HYDROData_DataMapOfRealOfHDProfile aDM;  
859   TColStd_ListOfReal aList;
860   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
861   for (int i = 1 ; anIter.More(); anIter.Next(), i++ )
862   {
863     Handle(HYDROData_Profile) aProfile =
864       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
865 #ifdef DEB_HASINT
866   TopoDS_Wire aProfileWire = TopoDS::Wire( aProfile->GetTopShape() );
867   aBB.Add( aCmp, aProfileWire ); 
868 #endif
869     if ( aProfile.IsNull() || !HasIntersection( aProfile, aPlane, aPar ) )
870       continue;
871     
872     aDM.Bind( aPar, aProfile );
873     aList.Append( aPar );
874   }
875   
876   if ( aList.IsEmpty() )
877     return;
878
879   QVector<double> anArr( aList.Extent() );
880
881   TColStd_ListIteratorOfListOfReal it( aList );
882   for ( int j = 1; it.More(); it.Next(), j++ )
883     anArr[j-1] = it.Value();
884
885   // sorting
886   if ( aList.Extent() > 1 )
887   {
888     //TCollection_CompareOfReal Compar;
889     //SortTools_QuickSortOfReal::Sort( anArr, Compar );
890     std::sort( anArr.begin(), anArr.end() );
891
892     for (int j = 1; j <= anArr.size(); j++) {
893       const Standard_Real aKey =  anArr[j-1];
894       const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
895       insertProfileInToOrder( aProfile );
896     }
897   } else if ( aList.Extent() == 1 ) {
898      const Standard_Real aKey = aList.Last();
899      const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
900      insertProfileInToOrder( aProfile );
901   } 
902
903   setParametersArray( anArr );
904
905 #ifdef DEB_HASINT
906   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
907   BRepTools::Write(aHydraulicWire, "Path.brep");
908   BRepTools::Write(aCmp, "Prof.brep");
909 #endif
910 }
911
912 ObjectKind HYDROData_Stream::getAltitudeObjectType() const
913 {
914   int InterpMethod = GetInterpolationMethod();
915   if (InterpMethod == 1)
916     return KIND_LISM;
917   else
918     return KIND_DTM;
919 }
920
921 void HYDROData_Stream::setParametersArray( const QVector<double>& theArray )
922 {
923   if ( theArray.size() == 0 )
924   {
925     removeParametersArray();
926     return;
927   }
928
929   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray );
930   
931   int n = theArray.size();
932   Handle(TDataStd_RealArray) aParamsArray = 
933     TDataStd_RealArray::Set( aLabel, 1, n );
934   aParamsArray->SetID(TDataStd_RealArray::GetID());
935   for ( int i = 0; i < n; ++i )
936   {
937     const Standard_Real& aParam = theArray[i];
938     aParamsArray->SetValue( i+1, aParam );
939   }
940 }
941
942 TColStd_Array1OfReal* HYDROData_Stream::getParametersArray() const
943 {
944   TColStd_Array1OfReal* anArray = NULL;
945
946   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
947   if ( !aLabel.IsNull() )
948   {
949     Handle(TDataStd_RealArray) aParamsArray;
950     if ( aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
951     {
952       anArray = new TColStd_Array1OfReal( aParamsArray->Lower(), aParamsArray->Upper() );
953       for ( int i = aParamsArray->Lower(), n = aParamsArray->Upper(); i <= n; ++i )
954       {
955         const Standard_Real& aParam = aParamsArray->Value( i );
956         anArray->SetValue( i, aParam );
957       }
958     }
959   }
960
961   return anArray;
962 }
963
964 void HYDROData_Stream::removeParametersArray()
965 {
966   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
967   if ( !aLabel.IsNull() )
968     aLabel.ForgetAllAttributes();
969 }
970
971 int HYDROData_Stream::insertParameter( const Standard_Real& theParam )
972 {
973   int aResIndex = -1;
974
975   TColStd_Array1OfReal* anArr = getParametersArray();
976   if ( anArr )
977   {
978     aResIndex = 0;
979
980     QVector<double> aNewArr( anArr->Upper() +1 );
981     bool isInserted = false;
982     for ( int i = anArr->Lower(), j = i, n = anArr->Upper(); i <= n; ++i, ++j )
983     {
984       const Standard_Real& aStoredParam = anArr->Value( i );
985       if ( !isInserted )
986       {
987         if ( theParam > aStoredParam )
988         {
989           aResIndex++;
990         }
991         else
992         {
993           if (j<=n+1)
994             aNewArr[j-1] = theParam;
995           isInserted = true;
996           ++j;
997         }
998       }
999       if (j<=n+1)
1000         aNewArr[j-1] = aStoredParam;
1001     }
1002
1003     if ( !isInserted )
1004     {
1005       aResIndex = -1;
1006       aNewArr[aNewArr.size()-1] = theParam;
1007     }
1008     
1009     setParametersArray( aNewArr );
1010     delete anArr;
1011   }
1012   else
1013   {
1014     QVector<double> aNewArr( 1 );
1015     aNewArr[0] = theParam;
1016     setParametersArray( aNewArr );
1017   }
1018
1019   return aResIndex;
1020 }
1021
1022 void HYDROData_Stream::removeParameter( const int& theIndex )
1023 {
1024   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
1025   if ( aLabel.IsNull() )
1026     return;
1027
1028   Handle(TDataStd_RealArray) aParamsArray;
1029   if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
1030     return;
1031
1032   if ( aParamsArray->Length() == 1 )
1033   {
1034     removeParametersArray();
1035     return;
1036   }
1037
1038   QVector<double> aNewArr( aParamsArray->Upper() - 2 );
1039
1040   for ( int i = aParamsArray->Lower(), j = i, k = 0, n = aParamsArray->Upper(); i <= n; ++i, ++k )
1041   {
1042     const Standard_Real& aStoredParam = aParamsArray->Value( i );
1043     if ( k == theIndex )
1044       continue;
1045
1046     aNewArr[j-1] = aStoredParam;
1047     ++j;
1048   }
1049
1050   setParametersArray( aNewArr );
1051 }
1052
1053 bool HYDROData_Stream::GenerateBottomPolyline()
1054 {
1055   // Get the document
1056   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
1057   if ( aDocument.IsNull() ) {
1058     return false;
1059   }
1060
1061   // Collect bottom points ( one bottom point from each profile of the stream )
1062   HYDROData_Profile::ProfilePoints aBottomPoints;
1063   
1064   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
1065   for ( int i = 1, aNb = aSeqOfProfiles.Size(); i <= aNb; i++ ) {
1066     const Handle(HYDROData_Profile) aProfile = 
1067       Handle(HYDROData_Profile)::DownCast( aSeqOfProfiles.Value( i ) );
1068     if ( aProfile.IsNull() ) {
1069       continue;
1070     }
1071     
1072     aBottomPoints.Append( aProfile->GetBottomPoint() );
1073   }
1074
1075   int aNbBottomPoints = aBottomPoints.Size();
1076
1077   if ( aNbBottomPoints < 2 ) {
1078     return false;
1079   }
1080
1081   // Create bottom polyline object if the stream doesn't contain it yet
1082   Handle(HYDROData_Polyline3D) aBottom = GetBottomPolyline();
1083   if ( aBottom.IsNull() ) {
1084     aBottom = Handle(HYDROData_Polyline3D)::DownCast( aDocument->CreateObject( KIND_POLYLINE ) );  
1085     QString aBaseName = GetName() + "_bottom";
1086     QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName, QStringList(), true );
1087     aBottom->SetName( aName );
1088
1089     SetReferenceObject( aBottom, DataTag_BottomPolyline );
1090   }
1091   
1092   // Create 2D polyline if the bottom polyline doesn't contain it yet
1093   Handle(HYDROData_PolylineXY) aPolylineXY = aBottom->GetPolylineXY();
1094   if ( aPolylineXY.IsNull() ) {
1095     aPolylineXY = Handle(HYDROData_PolylineXY)::DownCast( aDocument->CreateObject( KIND_POLYLINEXY ) );
1096     QString aBaseName = GetName() + "_bottom_2d";
1097     QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName, QStringList(), true );
1098     aPolylineXY->SetName( aName );
1099     aBottom->SetPolylineXY( aPolylineXY, false );
1100   }
1101
1102   aPolylineXY->RemoveSections();
1103   aPolylineXY->AddSection( "", HYDROData_PolylineXY::SECTION_SPLINE, false );
1104   
1105   // Create profile if the bottom polyline doesn't contain it yet
1106   Handle(HYDROData_ProfileUZ) aProfileUZ = aBottom->GetProfileUZ();
1107   if ( aProfileUZ.IsNull() ) {
1108     Handle(HYDROData_Profile) aProfile = 
1109       Handle(HYDROData_Profile)::DownCast( aDocument->CreateObject( KIND_PROFILE ) );
1110     QString aBaseName = GetName() + "_bottom_profile";
1111     QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName, QStringList(), true );
1112     aProfile->SetName( aName );
1113     aProfileUZ = aProfile->GetProfileUZ( true );
1114     aBottom->SetProfileUZ( aProfileUZ );
1115   }
1116   
1117   aProfileUZ->RemoveSection( 0 );
1118
1119   aProfileUZ->CalculateAndAddPoints(aBottomPoints, aPolylineXY, true);
1120   
1121   return true;
1122 }
1123
1124 Handle(HYDROData_Polyline3D) HYDROData_Stream::GetBottomPolyline() const
1125 {
1126   return Handle(HYDROData_Polyline3D)::DownCast( 
1127            GetReferenceObject( DataTag_BottomPolyline ) );
1128 }
1129
1130 bool HYDROData_Stream::SetBottomPolyline( const Handle(HYDROData_Polyline3D)& theBottom )
1131 {
1132   if ( theBottom.IsNull() ) {
1133     return false;
1134   }
1135
1136   SetReferenceObject( theBottom, DataTag_BottomPolyline );
1137
1138   return true;
1139 }
1140
1141 bool HYDROData_Stream::Interpolate( HYDROData_IProfilesInterpolator* theInterpolator )
1142 {
1143   // Get the document
1144   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
1145   if ( aDocument.IsNull() ) {
1146     return false;
1147   }
1148   
1149   if ( theInterpolator->GetCalculatedProfilesNumber() < 1 ) {
1150     theInterpolator->Calculate();
1151   }
1152
1153   if ( theInterpolator->GetErrorCode() != OK ) {
1154     return false;
1155   }
1156
1157   bool isOK = true;
1158
1159   for ( int aProfileInd = 0; aProfileInd < theInterpolator->GetCalculatedProfilesNumber(); aProfileInd++ ) {
1160     // Get calculated point coordinates
1161     HYDROData_Profile::ProfilePoints aResultPoints = theInterpolator->GetResultProfilePoints( aProfileInd );
1162     if ( aResultPoints.IsEmpty() ) {
1163       isOK = false;
1164       continue;
1165     }
1166         
1167     // Create profile object
1168     Handle(HYDROData_Profile) aProfile = 
1169       Handle(HYDROData_Profile)::DownCast( aDocument->CreateObject( KIND_PROFILE ) );
1170     QString aBaseName = GetName() + "_interp_profile";
1171     QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName );
1172     aProfile->SetName( aName );
1173
1174     // Fill the profile with points
1175     aProfile->SetProfilePoints( aResultPoints );
1176
1177     // Add profile to the stream
1178     bool isAdded = AddProfile( aProfile );
1179     if ( !isAdded ) {
1180       aProfile->Remove();
1181     }
1182     else
1183       aProfile->Update();
1184   }
1185
1186   if ( isOK )
1187     Update();
1188
1189   return isOK;
1190 }
1191
1192 void HYDROData_Stream::CopyTo( const Handle(HYDROData_Entity)& theDestination,
1193                                bool isGenerateNewName ) const
1194 {
1195   // Get the document
1196   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
1197   if ( aDocument.IsNull() ) {
1198     return;
1199   }
1200
1201   // Call base method
1202   HYDROData_Entity::CopyTo( theDestination, isGenerateNewName );
1203
1204   Handle(HYDROData_Stream) aStreamCopy = 
1205     Handle(HYDROData_Stream)::DownCast( theDestination );
1206
1207   // Copy bottom polyline if exists
1208   if ( !aStreamCopy.IsNull() ) {
1209     const Handle(HYDROData_Polyline3D) aBottom = GetBottomPolyline();
1210     if ( !aBottom.IsNull() ) {
1211       aStreamCopy->ClearReferenceObjects( DataTag_BottomPolyline );
1212       aStreamCopy->GenerateBottomPolyline();
1213       const Handle(HYDROData_Polyline3D) aBottomCopy = aStreamCopy->GetBottomPolyline();
1214       if ( !aBottomCopy.IsNull() && !aBottomCopy->GetPolylineXY().IsNull() ) {
1215         aBottomCopy->GetPolylineXY()->Update();
1216         aBottomCopy->Update();
1217       }
1218     }
1219   }
1220 }
1221 void HYDROData_Stream::CreatePresentations( const Handle(TColgp_HArray1OfPnt)     theArrayOfFPnt,
1222                                             const Handle(TColgp_HArray1OfPnt)     theArrayOfLPnt,
1223                                             const Handle(TopTools_HArray1OfShape) theArrOfProfiles,
1224                                             PrsDefinition&                        thePrs )
1225 {
1226
1227   HYDROData_Bathymetry::AltitudePoints left;
1228   for (int i = theArrayOfLPnt->Lower(); i <= theArrayOfLPnt->Upper(); i++)
1229   {
1230     left.push_back(HYDROData_Bathymetry::AltitudePoint(theArrayOfLPnt->Value(i).X(), 
1231       theArrayOfLPnt->Value(i).Y(),
1232       theArrayOfLPnt->Value(i).Z()));
1233   }
1234
1235   HYDROData_Bathymetry::AltitudePoints right;
1236   for (int i = theArrayOfFPnt->Lower(); i <= theArrayOfFPnt->Upper(); i++)
1237   {
1238     right.push_back(HYDROData_Bathymetry::AltitudePoint(theArrayOfFPnt->Value(i).X(), 
1239       theArrayOfFPnt->Value(i).Y(),
1240       theArrayOfFPnt->Value(i).Z()));
1241   }
1242
1243   std::vector<HYDROData_Bathymetry::AltitudePoints> dummy;
1244   TopTools_IndexedMapOfOrientedShape ll = HYDROData_DTM::Create3DShape(left, right, dummy);
1245
1246   TopoDS_Shape LB, RB, IL, OL;
1247
1248   if (!ll.IsEmpty())
1249   {
1250     TopAbs_ShapeEnum ll1_sht = ll(1).ShapeType();
1251     TopAbs_ShapeEnum ll2_sht = ll(2).ShapeType();
1252     if ((ll1_sht == TopAbs_WIRE || ll1_sht == TopAbs_EDGE) &&
1253       (ll2_sht == TopAbs_WIRE || ll2_sht == TopAbs_EDGE))
1254     {
1255       LB = ll(1);
1256       RB = ll(2);
1257     }
1258   }
1259
1260   IL = TopoDS::Wire(theArrOfProfiles->Value(theArrOfProfiles->Lower())); //TODO check that
1261   OL = TopoDS::Wire(theArrOfProfiles->Value(theArrOfProfiles->Upper()));
1262
1263   //make new compound so it's shapes will be in known order to build correct projection
1264   BRep_Builder BB;
1265   TopoDS_Compound newCmp;
1266   BB.MakeCompound(newCmp);
1267   BB.Add(newCmp, LB);
1268   BB.Add(newCmp, IL);
1269   BB.Add(newCmp, OL);
1270   BB.Add(newCmp, RB);
1271
1272   thePrs.myPrs3D = newCmp;
1273
1274   TopTools_SequenceOfShape LS;
1275   //HYDROData_DTM::Get2dFaceFrom3dPres( newCmp, TopoDS::Face(thePrs.myPrs2D), &LS, ind );
1276   
1277   HYDROData_DTM::GetPlanarFaceFromBanks(TopoDS::Edge(LB), TopoDS::Edge(RB), TopoDS::Face(thePrs.myPrs2D), &LS);
1278
1279 #ifndef NDEBUG
1280   TopTools_IndexedMapOfShape EE;
1281   TopExp::MapShapes(thePrs.myPrs2D, TopAbs_EDGE, EE);
1282   int noncontNb = 0;
1283   for (int i = 1; i <= 4; i++)
1284   {
1285     TopoDS_Shape W = LS(i);
1286     TopTools_IndexedMapOfShape EW;
1287     TopExp::MapShapes(W, TopAbs_EDGE, EW);
1288     for (int k = 1; k <= EW.Extent(); k++)
1289       noncontNb += !EE.Contains(EW(k));
1290   }
1291   //noncontNb > 0 => some problem with edge history
1292   assert(noncontNb == 0);
1293 #endif
1294
1295   thePrs.myLeftBank = LS(1);  
1296   thePrs.myInlet = LS(2);  
1297   thePrs.myOutlet = LS(3);  
1298   thePrs.myRightBank = LS(4);
1299
1300 }