Salome HOME
f8d25eb746999b52c0aaa5e42442cedb827d18a9
[modules/hydro.git] / src / HYDROData / HYDROData_CalculationCase.cxx
1
2 #include "HYDROData_CalculationCase.h"
3
4 #include "HYDROData_ArtificialObject.h"
5 #include "HYDROData_Bathymetry.h"
6 #include "HYDROData_Document.h"
7 #include "HYDROData_EdgesGroup.h"
8 #include "HYDROData_Iterator.h"
9 #include "HYDROData_NaturalObject.h"
10 #include "HYDROData_PolylineXY.h"
11 #include "HYDROData_SplitToZonesTool.h"
12 #include "HYDROData_SplittedEdgesGroup.h"
13 #include "HYDROData_Region.h"
14 #include "HYDROData_Tool.h"
15 #include "HYDROData_Zone.h"
16
17 #include <GEOMBase.h>
18
19 #include <TopoDS.hxx>
20 #include <TopoDS_Shell.hxx>
21 #include <TopoDS_Edge.hxx>
22
23 #include <BRep_Builder.hxx>
24 #include <BRepBuilderAPI_Sewing.hxx>
25 #include <BRepTopAdaptor_FClass2d.hxx>
26
27 #include <BRepTools.hxx>
28
29 #include <TopAbs.hxx>
30 #include <TopExp_Explorer.hxx>
31 #include <TopExp.hxx>
32 #include <TopTools_ListOfShape.hxx>
33 #include <TopTools_ListIteratorOfListOfShape.hxx>
34
35
36 #define CALCULATION_REGIONS_PREF GetName() + "_Reg"
37 #define CALCULATION_ZONES_PREF GetName() + "_Zone"
38 #define CALCULATION_GROUPS_PREF GetName() + "_"
39
40 #define PYTHON_CALCULATION_ID "KIND_CALCULATION"
41
42 #define EXPORT_NAME "HYDRO_" + GetName()
43
44 IMPLEMENT_STANDARD_HANDLE(HYDROData_CalculationCase, HYDROData_Entity)
45 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_CalculationCase, HYDROData_Entity)
46
47 HYDROData_CalculationCase::HYDROData_CalculationCase()
48 : HYDROData_Entity()
49 {
50 }
51
52 HYDROData_CalculationCase::~HYDROData_CalculationCase()
53 {
54 }
55
56 void HYDROData_CalculationCase::SetName( const QString& theName )
57 {
58   QString anOldCaseName = GetName();
59   if ( anOldCaseName != theName )
60   {
61     HYDROData_SequenceOfObjects aRegions = GetRegions();
62
63     HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
64     for ( ; anIter.More(); anIter.Next() )
65     {
66       Handle(HYDROData_Region) aRegion =
67         Handle(HYDROData_Region)::DownCast( anIter.Value() );
68       if ( aRegion.IsNull() )
69         continue;
70
71       QString aRegionName = aRegion->GetName();
72       if ( aRegionName.startsWith( anOldCaseName ) )
73       {
74         aRegionName.replace( anOldCaseName, theName );
75         aRegion->SetName( aRegionName );
76       }
77
78       HYDROData_SequenceOfObjects aZones = aRegion->GetZones();
79       HYDROData_SequenceOfObjects::Iterator anIter( aZones );
80       for ( ; anIter.More(); anIter.Next() )
81       {
82         Handle(HYDROData_Zone) aRegZone =
83           Handle(HYDROData_Zone)::DownCast( anIter.Value() );
84         if ( aRegZone.IsNull() )
85           continue;
86
87         QString aRegionZoneName = aRegZone->GetName();
88         if ( aRegionZoneName.startsWith( anOldCaseName ) )
89         {
90           aRegionZoneName.replace( anOldCaseName, theName );
91           aRegZone->SetName( aRegionZoneName );
92         }
93       }
94     }
95
96     HYDROData_SequenceOfObjects aGroups = GetGeometryGroups();
97
98     anIter.Init( aGroups );
99     for ( ; anIter.More(); anIter.Next() )
100     {
101       Handle(HYDROData_SplittedEdgesGroup) aGroup =
102         Handle(HYDROData_SplittedEdgesGroup)::DownCast( anIter.Value() );
103       if ( aGroup.IsNull() )
104         continue;
105
106       QString aGroupName = aGroup->GetName();
107       if ( aGroupName.startsWith( anOldCaseName ) )
108       {
109         aGroupName.replace( anOldCaseName, theName );
110         aGroup->SetName( aGroupName );
111       }
112     }
113   }
114
115   HYDROData_Entity::SetName( theName );
116 }
117
118 QStringList HYDROData_CalculationCase::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
119 {
120   QStringList aResList;
121
122   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
123   if ( aDocument.IsNull() )
124     return aResList;
125                              
126   QString aDocName = aDocument->GetDocPyName();
127   QString aCalculName = GetName();
128
129   aResList << QString( "%1 = %2.CreateObject( %3 );" )
130               .arg( aCalculName ).arg( aDocName ).arg( PYTHON_CALCULATION_ID );
131   aResList << QString( "%1.SetName( \"%2\" );" )
132               .arg( aCalculName ).arg( aCalculName );
133   aResList << QString( "" );
134
135   HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects();
136   HYDROData_SequenceOfObjects::Iterator anIter( aGeomObjects );
137   for ( ; anIter.More(); anIter.Next() )
138   {
139     Handle(HYDROData_Object) aRefGeomObj =
140       Handle(HYDROData_Object)::DownCast( anIter.Value() );
141     if ( !aRefGeomObj.IsNull() )
142       setPythonReferenceObject( theTreatedObjects, aResList, aRefGeomObj, "AddGeometryObject" );
143   }
144   aResList << QString( "" );
145
146   aResList << QString( "%1.SplitGeometryObjects();" ).arg( aCalculName );
147   aResList << QString( "" );
148
149   // Now we restore the regions and zones order
150   HYDROData_SequenceOfObjects aRegions = GetRegions();
151   anIter.Init( aRegions );
152   for ( ; anIter.More(); anIter.Next() )
153   {
154     Handle(HYDROData_Region) aRegion =
155       Handle(HYDROData_Region)::DownCast( anIter.Value() );
156     if ( aRegion.IsNull() )
157       continue;
158
159     QString aRegionName = aRegion->GetName();
160     // TODO
161   }
162
163   return aResList;
164 }
165
166 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetAllReferenceObjects() const
167 {
168   HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
169
170   Handle(HYDROData_PolylineXY) aBoundaryPolyline = GetBoundaryPolyline();
171   if ( !aBoundaryPolyline.IsNull() )
172     aResSeq.Append( aBoundaryPolyline );
173
174   HYDROData_SequenceOfObjects aSeqOfRegions = GetRegions();
175   aResSeq.Append( aSeqOfRegions );
176
177   return aResSeq;
178 }
179
180 void HYDROData_CalculationCase::Update()
181 {
182   HYDROData_Entity::Update();
183
184   // At first we remove previously created objects
185   RemoveRegions();
186   RemoveSplittedGroups();
187
188   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
189   if ( aDocument.IsNull() )
190     return;
191
192   Handle(HYDROData_PolylineXY) aBoundaryPolyline = GetBoundaryPolyline();
193   HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects();
194   if ( aGeomObjects.IsEmpty() )
195     return;
196
197   HYDROData_SequenceOfObjects aGeomGroups = GetGeometryGroups();
198
199   HYDROData_SplitToZonesTool::SplitDataList aSplitedObjects =
200     HYDROData_SplitToZonesTool::Split( aGeomObjects, aGeomGroups, aBoundaryPolyline );
201   if ( aSplitedObjects.isEmpty() )
202     return;
203
204   QString aRegsPref = CALCULATION_REGIONS_PREF;
205   QString aZonesPref = CALCULATION_ZONES_PREF;
206
207   QMap<QString,Handle(HYDROData_SplittedEdgesGroup)> aSplittedEdgesGroupsMap;
208
209   // Create result regions for case, by default one zone for one region
210   HYDROData_SplitToZonesTool::SplitDataListIterator anIter( aSplitedObjects );
211   while( anIter.hasNext() )
212   {
213     const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next();
214
215     if ( aSplitData.Type == HYDROData_SplitToZonesTool::SplitData::Data_Zone )
216     {
217       // Create new region
218       Handle(HYDROData_Region) aRegion = addNewRegion();
219
220       QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
221       aRegion->SetName( aRegionName );
222
223       // Add the zone for region
224       Handle(HYDROData_Zone) aRegionZone = aRegion->addNewZone();
225
226       QString aZoneName = HYDROData_Tool::GenerateObjectName( aDocument, aZonesPref );
227       aRegionZone->SetName( aZoneName );
228
229       aRegionZone->SetShape( aSplitData.Face() );
230
231       // Add the reference object for zone
232       for ( int i = 0, n = aSplitData.ObjectNames.length(); i < n; ++i )
233       {
234         const QString& anObjName = aSplitData.ObjectNames.at( i );
235         
236         Handle(HYDROData_Object) aRefObject = Handle(HYDROData_Object)::DownCast(
237           HYDROData_Tool::FindObjectByName( aDocument, anObjName ) );
238         if ( aRefObject.IsNull() )
239           continue;
240
241         aRegionZone->AddGeometryObject( aRefObject );
242       }
243     }
244     else if ( aSplitData.Type == HYDROData_SplitToZonesTool::SplitData::Data_Edge )
245     {
246       // Create new edges group
247       if ( aSplitData.ObjectNames.isEmpty() || 
248            aSplitData.Shape.IsNull() || aSplitData.Shape.ShapeType() != TopAbs_EDGE )
249         continue;
250
251       QString anObjName = aSplitData.ObjectNames.first();
252       if ( anObjName.isEmpty() )
253         continue;
254
255       Handle(HYDROData_SplittedEdgesGroup) aSplittedGroup;
256       if ( !aSplittedEdgesGroupsMap.contains( anObjName ) )
257       {
258         aSplittedGroup = addNewSplittedGroup();
259
260         QString aCalcGroupName = CALCULATION_GROUPS_PREF + anObjName;
261         aSplittedGroup->SetName( aCalcGroupName );
262
263         aSplittedEdgesGroupsMap.insert( anObjName, aSplittedGroup );
264       }
265       else
266       {
267         aSplittedGroup = aSplittedEdgesGroupsMap[ anObjName ];
268       }
269
270       if ( aSplittedGroup.IsNull() )
271         continue;
272
273       TopoDS_Edge anEdge = TopoDS::Edge( aSplitData.Shape );
274       aSplittedGroup->AddEdge( anEdge );
275     }
276   }
277 }
278
279 bool HYDROData_CalculationCase::AddGeometryObject( const Handle(HYDROData_Object)& theObject )
280 {
281   if ( !HYDROData_Tool::IsGeometryObject( theObject ) )
282     return false; // Wrong type of object
283
284   if ( HasReference( theObject, DataTag_GeometryObject ) )
285     return false; // Object is already in reference list
286
287   AddReferenceObject( theObject, DataTag_GeometryObject );
288   
289   // Indicate model of the need to update splitting
290   SetToUpdate( true );
291
292   return true;
293 }
294
295 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetGeometryObjects() const
296 {
297   return GetReferenceObjects( DataTag_GeometryObject );
298 }
299
300 void HYDROData_CalculationCase::RemoveGeometryObject( const Handle(HYDROData_Object)& theObject )
301 {
302   if ( theObject.IsNull() )
303     return;
304
305   RemoveReferenceObject( theObject->Label(), DataTag_GeometryObject );
306
307   // Indicate model of the need to update splitting
308   SetToUpdate( true );
309 }
310
311 void HYDROData_CalculationCase::RemoveGeometryObjects()
312 {
313   ClearReferenceObjects( DataTag_GeometryObject );
314
315   // Indicate model of the need to update splitting
316   SetToUpdate( true );
317 }
318
319 bool HYDROData_CalculationCase::AddGeometryGroup( const Handle(HYDROData_EdgesGroup)& theGroup )
320 {
321   if ( theGroup.IsNull() )
322     return false;
323
324   if ( HasReference( theGroup, DataTag_GeometryGroup ) )
325     return false; // Object is already in reference list
326
327   AddReferenceObject( theGroup, DataTag_GeometryGroup );
328   
329   // Indicate model of the need to update splitting
330   SetToUpdate( true );
331
332   return true;
333 }
334
335 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetGeometryGroups() const
336 {
337   return GetReferenceObjects( DataTag_GeometryGroup );
338 }
339
340 void HYDROData_CalculationCase::RemoveGeometryGroup( const Handle(HYDROData_EdgesGroup)& theGroup )
341 {
342   if ( theGroup.IsNull() )
343     return;
344
345   RemoveReferenceObject( theGroup->Label(), DataTag_GeometryGroup );
346
347   // Indicate model of the need to update splitting
348   SetToUpdate( true );
349 }
350
351 void HYDROData_CalculationCase::RemoveGeometryGroups()
352 {
353   ClearReferenceObjects( DataTag_GeometryGroup );
354
355   // Indicate model of the need to update splitting
356   SetToUpdate( true );
357 }
358
359 void HYDROData_CalculationCase::SetBoundaryPolyline( const Handle(HYDROData_PolylineXY)& thePolyline )
360 {
361   Handle(HYDROData_PolylineXY) aPrevPolyline = GetBoundaryPolyline();
362
363   SetReferenceObject( thePolyline, DataTag_Polyline );
364
365   // Indicate model of the need to update zones splitting
366   SetToUpdate( !IsEqual( aPrevPolyline, thePolyline ) || IsMustBeUpdated() );
367 }
368
369 Handle(HYDROData_PolylineXY) HYDROData_CalculationCase::GetBoundaryPolyline() const
370 {
371   return Handle(HYDROData_PolylineXY)::DownCast( 
372            GetReferenceObject( DataTag_Polyline ) );
373 }
374
375 void HYDROData_CalculationCase::RemoveBoundaryPolyline()
376 {
377   Handle(HYDROData_PolylineXY) aPrevPolyline = GetBoundaryPolyline();
378
379   ClearReferenceObjects( DataTag_Polyline );
380
381   // Indicate model of the need to update zones splitting
382   SetToUpdate( !aPrevPolyline.IsNull() || IsMustBeUpdated() );
383 }
384
385 Handle(HYDROData_Region) HYDROData_CalculationCase::AddNewRegion( const Handle(HYDROData_Zone)& theZone )
386 {
387   Handle(HYDROData_Region) aNewRegion = addNewRegion();
388   if ( aNewRegion.IsNull() )
389     return aNewRegion;
390
391   // Generate new name for new region
392   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
393   if ( !aDocument.IsNull() )
394   {
395     QString aRegsPref = CALCULATION_REGIONS_PREF;
396
397     QString aNewRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
398     aNewRegion->SetName( aNewRegionName );
399   }
400
401   aNewRegion->AddZone( theZone );
402
403   return aNewRegion;
404 }
405
406 bool HYDROData_CalculationCase::AddRegion( const Handle(HYDROData_Region)& theRegion )
407 {
408   if ( theRegion.IsNull() )
409     return false;
410   
411   if ( HasReference( theRegion, DataTag_Region ) )
412     return false; // Object is already in reference list
413
414   // Move the region from other calculation
415   Handle(HYDROData_CalculationCase) aFatherCalc = 
416     Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
417   if ( !aFatherCalc.IsNull() && aFatherCalc->Label() != myLab )
418   {
419     Handle(HYDROData_Region) aNewRegion = addNewRegion();
420     theRegion->CopyTo( aNewRegion );
421
422     aFatherCalc->RemoveRegion( theRegion );
423
424     theRegion->SetLabel( aNewRegion->Label() );
425   }
426   else
427   {
428     AddReferenceObject( theRegion, DataTag_Region );
429   }
430
431   return true;
432 }
433
434 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetRegions() const
435 {
436   return GetReferenceObjects( DataTag_Region );
437 }
438
439 void HYDROData_CalculationCase::UpdateRegionsOrder()
440 {
441   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
442   if ( aDocument.IsNull() )
443     return;
444
445   HYDROData_SequenceOfObjects aRegions = GetRegions();
446
447   HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
448   for ( ; anIter.More(); anIter.Next() )
449   {
450     Handle(HYDROData_Region) aRegion =
451       Handle(HYDROData_Region)::DownCast( anIter.Value() );
452     if ( aRegion.IsNull() )
453       continue;
454
455     aRegion->SetName( "" );
456   }
457
458   QString aRegsPref = CALCULATION_REGIONS_PREF;
459
460   anIter.Init( aRegions );
461   for ( ; anIter.More(); anIter.Next() )
462   {
463     Handle(HYDROData_Region) aRegion =
464       Handle(HYDROData_Region)::DownCast( anIter.Value() );
465     if ( aRegion.IsNull() )
466       continue;
467
468     QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
469     aRegion->SetName( aRegionName );
470   }
471 }
472
473 void HYDROData_CalculationCase::RemoveRegion( const Handle(HYDROData_Region)& theRegion )
474 {
475   if ( theRegion.IsNull() )
476     return;
477
478   RemoveReferenceObject( theRegion->Label(), DataTag_Region );
479
480   // Remove region from data model
481   Handle(HYDROData_CalculationCase) aFatherCalc = 
482     Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
483   if ( !aFatherCalc.IsNull() && aFatherCalc->Label() == myLab )
484     theRegion->Remove();
485 }
486
487 void HYDROData_CalculationCase::RemoveRegions()
488 {
489   myLab.FindChild( DataTag_ChildRegion ).ForgetAllAttributes();
490 }
491
492 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetSplittedGroups() const
493 {
494   return GetReferenceObjects( DataTag_SplittedGroups );
495 }
496
497 void HYDROData_CalculationCase::RemoveSplittedGroups()
498 {
499   myLab.FindChild( DataTag_SplittedGroups ).ForgetAllAttributes();
500 }
501
502 TopoDS_Shell HYDROData_CalculationCase::GetShell()
503 {
504   TopoDS_Shell aShell;
505
506   TopTools_ListOfShape aFacesList;
507
508   // Make shell containing all region shapes
509   BRepBuilderAPI_Sewing aSewing( Precision::Confusion()*10.0 );
510
511   HYDROData_SequenceOfObjects aCaseRegions = GetRegions();
512   HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
513   for ( ; aRegionIter.More(); aRegionIter.Next() ) {
514     Handle(HYDROData_Region) aRegion =
515       Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
516     if( aRegion.IsNull() ) {
517       continue;
518     }
519
520     TopoDS_Shape aRegionShape = aRegion->GetShape();
521     if( !aRegionShape.IsNull() ) {
522       if ( aRegionShape.ShapeType() == TopAbs_FACE ) {
523         TopoDS_Face aFace = TopoDS::Face( aRegionShape );
524         if ( !aFace.IsNull() ) {
525           aFacesList.Append( aFace );
526           aSewing.Add( aFace );
527         }
528       } else {
529         TopExp_Explorer anExp( aRegionShape, TopAbs_FACE );
530         for ( ; anExp.More(); anExp.Next() ) {
531           TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
532           if ( !aFace.IsNull() ) {
533             aFacesList.Append( aFace );
534             aSewing.Add( aFace );
535           }
536         }
537       }
538     }
539   } // regions iterator
540   
541   aSewing.Perform();
542   TopoDS_Shape aSewedShape = aSewing.SewedShape();
543
544   if ( !aSewedShape.IsNull() )
545   {
546     if ( aSewedShape.ShapeType() == TopAbs_FACE && aCaseRegions.Length() ==1 ) {
547       // create shell from one face
548       BRep_Builder aBuilder;
549       aBuilder.MakeShell( aShell );
550       aBuilder.Add( aShell, aSewedShape);
551     } else {
552       TopExp_Explorer anExpShells( aSewedShape, TopAbs_SHELL );
553       Standard_Integer aNbOfShells = 0;
554       for ( ; anExpShells.More(); anExpShells.Next() ) {
555         aShell = TopoDS::Shell( anExpShells.Current() );
556         aNbOfShells++;
557       }
558
559       if ( aNbOfShells != 1 ) {
560         aShell.Nullify();
561         BRep_Builder aBuilder;
562         aBuilder.MakeShell( aShell );
563
564         TopExp_Explorer anExpFaces( aSewedShape, TopAbs_FACE );
565         for ( ; anExpFaces.More(); anExpFaces.Next() ) {
566           TopoDS_Face aFace = TopoDS::Face( anExpFaces.Current() );
567           if ( !aFace.IsNull() ) {
568             aBuilder.Add( aShell, aFace );
569           }
570         }
571       }
572     }
573   }
574
575   if ( !aShell.IsNull() ) {
576     TopTools_IndexedMapOfShape aMapOfFaces;
577     TopExp::MapShapes( aShell, TopAbs_FACE, aMapOfFaces );
578     if ( aMapOfFaces.Extent() != aFacesList.Extent() ) {
579       aShell.Nullify();
580       BRep_Builder aBuilder;
581       aBuilder.MakeShell( aShell );
582
583       TopTools_ListIteratorOfListOfShape anIter( aFacesList );
584       for ( ; anIter.More(); anIter.Next() ) {
585         TopoDS_Face aFace = TopoDS::Face( anIter.Value() );
586         aBuilder.Add( aShell, aFace );
587       }
588     }
589   }
590
591 /* TODO: old version
592   // Make shell
593   BRep_Builder aBuilder;
594   aBuilder.MakeShell( aShell );
595
596   // Make shell containing all region shapes
597   HYDROData_SequenceOfObjects aCaseRegions = GetRegions();
598   HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
599   for ( ; aRegionIter.More(); aRegionIter.Next() ) {
600     Handle(HYDROData_Region) aRegion =
601       Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
602     if( aRegion.IsNull() ) {
603       continue;
604     }
605
606     TopoDS_Shape aRegionShape = aRegion->GetShape();
607
608     // Add shape (face or shell) corresponding to the region into the shell
609     if( !aRegionShape.IsNull() ) {
610       if ( aRegionShape.ShapeType() == TopAbs_FACE ) {
611         aBuilder.Add( aShell, aRegionShape );
612       } else {
613         TopExp_Explorer anExp( aRegionShape, TopAbs_FACE );
614         for( ; anExp.More(); anExp.Next() ) {
615           TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
616           if( !aFace.IsNull() ) {
617             aBuilder.Add( aShell, aFace );
618           }
619         }
620       }
621     }
622   } // regions iterator
623 */
624
625   // Nullify shell if it is empty
626   if ( !aShell.IsNull() && !TopoDS_Iterator(aShell).More() ) {
627     aShell.Nullify();
628   }
629
630   return aShell;
631 }
632
633 double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY& thePoint ) const
634 {
635   double aResAltitude = HYDROData_Bathymetry::GetInvalidAltitude();
636
637   Handle(HYDROData_Zone) aZone = GetZoneFromPoint( thePoint );
638   if ( aZone.IsNull() )
639     return aResAltitude;
640
641   HYDROData_Zone::MergeBathymetriesType aZoneMergeType = aZone->GetMergeType();
642   if ( !aZone->IsMergingNeed() )
643   {
644     aZoneMergeType = HYDROData_Zone::Merge_UNKNOWN;
645   }
646   else if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
647   {
648     return aResAltitude;
649   }
650
651   if ( aZoneMergeType == HYDROData_Zone::Merge_Object )
652   {
653     Handle(HYDROData_Bathymetry) aMergeBathymetry = aZone->GetMergeBathymetry();
654     if ( !aMergeBathymetry.IsNull() )
655       aResAltitude = aMergeBathymetry->GetAltitudeForPoint( thePoint );
656   }
657   else
658   {
659     HYDROData_SequenceOfObjects aZoneObjects = aZone->GetGeometryObjects();
660     HYDROData_SequenceOfObjects::Iterator anIter( aZoneObjects );
661     for ( ; anIter.More(); anIter.Next() )
662     {
663       Handle(HYDROData_Object) aZoneObj =
664         Handle(HYDROData_Object)::DownCast( anIter.Value() );
665       if ( aZoneObj.IsNull() )
666         continue;
667
668       Handle(HYDROData_Bathymetry) anObjBathymetry = aZoneObj->GetBathymetry();
669       if ( anObjBathymetry.IsNull() )
670         continue;
671
672       double aPointAltitude = anObjBathymetry->GetAltitudeForPoint( thePoint );
673       if ( ValuesEquals( aPointAltitude, HYDROData_Bathymetry::GetInvalidAltitude() ) )
674         continue;
675
676       if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
677       {
678         aResAltitude = aPointAltitude;
679         break;
680       }
681       else if ( aZoneMergeType == HYDROData_Zone::Merge_ZMIN )
682       {
683         if ( ValuesEquals( aResAltitude, HYDROData_Bathymetry::GetInvalidAltitude() ) ||
684              aResAltitude > aPointAltitude )
685         {
686           aResAltitude = aPointAltitude;
687         }
688       }
689       else if ( aZoneMergeType == HYDROData_Zone::Merge_ZMAX )
690       {
691         if ( ValuesEquals( aResAltitude, HYDROData_Bathymetry::GetInvalidAltitude() ) ||
692              aResAltitude < aPointAltitude )
693         {
694           aResAltitude = aPointAltitude;
695         }
696       }
697     }
698   }
699
700   return aResAltitude;
701 }
702
703 Handle(HYDROData_Zone) HYDROData_CalculationCase::GetZoneFromPoint( const gp_XY& thePoint ) const
704 {
705   Handle(HYDROData_Zone) aResZone;
706
707   HYDROData_SequenceOfObjects aRegions = GetRegions();
708
709   HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
710   for ( ; anIter.More() && aResZone.IsNull(); anIter.Next() )
711   {
712     Handle(HYDROData_Region) aRegion =
713       Handle(HYDROData_Region)::DownCast( anIter.Value() );
714     if ( aRegion.IsNull() )
715       continue;
716
717     HYDROData_SequenceOfObjects aZones = aRegion->GetZones();
718     HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
719     for ( ; aZonesIter.More() && aResZone.IsNull(); aZonesIter.Next() )
720     {
721       Handle(HYDROData_Zone) aRegZone =
722         Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
723       if ( aRegZone.IsNull() )
724         continue;
725
726       PointClassification aPointRelation = GetPointClassification( thePoint, aRegZone );
727       if ( aPointRelation != POINT_OUT )
728         aResZone = aRegZone; // We found the desired zone
729     }
730   }
731
732   return aResZone;
733 }
734
735 HYDROData_CalculationCase::PointClassification HYDROData_CalculationCase::GetPointClassification(
736   const gp_XY&                  thePoint,
737   const Handle(HYDROData_Zone)& theZone ) const
738 {
739   PointClassification aRes = POINT_OUT;
740   if ( theZone.IsNull() )
741     return aRes;
742
743   TopoDS_Face aZoneFace = TopoDS::Face( theZone->GetShape() );
744   if ( aZoneFace.IsNull() )
745     return aRes;
746
747   BRepTopAdaptor_FClass2d aClassifier( aZoneFace, Precision::Confusion() );
748   TopAbs_State State = aClassifier.Perform( gp_Pnt2d(thePoint), Standard_False );
749   if (State == TopAbs_OUT)
750         aRes =  POINT_OUT;
751   else if(State == TopAbs_IN)
752     aRes =  POINT_IN;
753   else if(State == TopAbs_ON)
754     aRes =  POINT_ON;     
755   return aRes;
756 }
757
758 Handle(HYDROData_Region) HYDROData_CalculationCase::addNewRegion()
759 {
760   TDF_Label aNewLab = myLab.FindChild( DataTag_ChildRegion ).NewChild();
761
762   Handle(HYDROData_Region) aNewRegion =
763     Handle(HYDROData_Region)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_REGION ) );
764   AddRegion( aNewRegion );
765
766   return aNewRegion;
767 }
768
769 Handle(HYDROData_SplittedEdgesGroup) HYDROData_CalculationCase::addNewSplittedGroup()
770 {
771   TDF_Label aNewLab = myLab.FindChild( DataTag_SplittedGroups ).NewChild();
772
773   Handle(HYDROData_SplittedEdgesGroup) aNewGroup =
774     Handle(HYDROData_SplittedEdgesGroup)::DownCast( 
775       HYDROData_Iterator::CreateObject( aNewLab, KIND_SPLITTED_GROUP ) );
776   AddReferenceObject( aNewGroup, DataTag_SplittedGroups );
777
778   return aNewGroup;
779 }
780
781 bool HYDROData_CalculationCase::Export( GEOM::GEOM_Gen_var theGeomEngine,
782                                         SALOMEDS::Study_ptr theStudy )
783 {
784   // Get faces
785   // TODO
786   TopTools_ListOfShape aFaces;
787
788   // Get groups
789   // TODO
790   HYDROData_SequenceOfObjects aSplittedGroups;
791
792   return Export( theGeomEngine, theStudy, aFaces, aSplittedGroups );
793 }
794
795 bool HYDROData_CalculationCase::Export( GEOM::GEOM_Gen_var theGeomEngine,
796                                         SALOMEDS::Study_ptr theStudy,
797                                         const TopTools_ListOfShape& theFaces,
798                                         const HYDROData_SequenceOfObjects& theSplittedGroups )
799 {
800   // Make shell from the faces
801   TopoDS_Shell aShell;
802   TopTools_ListOfShape aFacesList;
803
804   BRepBuilderAPI_Sewing aSewing( Precision::Confusion()*10.0 );
805
806   TopTools_ListIteratorOfListOfShape aFaceIter( theFaces );
807   for ( ; aFaceIter.More(); aFaceIter.Next() ) {
808     TopoDS_Shape aShape = aFaceIter.Value();
809     if ( !aShape.IsNull() && (aShape.ShapeType() == TopAbs_FACE) ) {
810       TopoDS_Face aFace = TopoDS::Face( aShape );
811       if ( !aFace.IsNull() ) {
812         aFacesList.Append( aFace );
813         aSewing.Add( aFace );
814       }
815     } else {
816       TopExp_Explorer anExp( aShape, TopAbs_FACE );
817       for ( ; anExp.More(); anExp.Next() ) {
818         TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
819         if ( !aFace.IsNull() ) {
820           aFacesList.Append( aFace );
821           aSewing.Add( aFace );
822         }
823       }
824     }
825   } // faces iterator
826   
827   aSewing.Perform();
828   TopoDS_Shape aSewedShape = aSewing.SewedShape();
829
830   if ( !aSewedShape.IsNull() ) {
831     if ( aSewedShape.ShapeType() == TopAbs_FACE && theFaces.Extent() ==1 ) {
832       // create shell from one face
833       BRep_Builder aBuilder;
834       aBuilder.MakeShell( aShell );
835       aBuilder.Add( aShell, aSewedShape);
836     } else {
837       TopExp_Explorer anExpShells( aSewedShape, TopAbs_SHELL );
838       Standard_Integer aNbOfShells = 0;
839       for ( ; anExpShells.More(); anExpShells.Next() ) {
840         aShell = TopoDS::Shell( anExpShells.Current() );
841         aNbOfShells++;
842       }
843
844       if ( aNbOfShells != 1 ) {
845         aShell.Nullify();
846         BRep_Builder aBuilder;
847         aBuilder.MakeShell( aShell );
848
849         TopExp_Explorer anExpFaces( aSewedShape, TopAbs_FACE );
850         for ( ; anExpFaces.More(); anExpFaces.Next() ) {
851           TopoDS_Face aFace = TopoDS::Face( anExpFaces.Current() );
852           if ( !aFace.IsNull() ) {
853             aBuilder.Add( aShell, aFace );
854           }
855         }
856       }
857     }
858   }
859
860   if ( !aShell.IsNull() ) {
861     TopTools_IndexedMapOfShape aMapOfFaces;
862     TopExp::MapShapes( aShell, TopAbs_FACE, aMapOfFaces );
863     if ( aMapOfFaces.Extent() != aFacesList.Extent() ) {
864       aShell.Nullify();
865       BRep_Builder aBuilder;
866       aBuilder.MakeShell( aShell );
867
868       TopTools_ListIteratorOfListOfShape anIter( aFacesList );
869       for ( ; anIter.More(); anIter.Next() ) {
870         TopoDS_Face aFace = TopoDS::Face( anIter.Value() );
871         aBuilder.Add( aShell, aFace );
872       }
873     }
874   }
875
876   // If the shell is empty - return false
877   if ( aShell.IsNull() || !TopoDS_Iterator(aShell).More() ) {
878     return false;
879   }
880
881   // Publish the shell
882   QString aName = EXPORT_NAME;
883   GEOM::GEOM_Object_ptr aPublishedObj = 
884     publishShapeInGEOM( theGeomEngine, theStudy, aShell, aName );
885
886   if ( aPublishedObj->_is_nil() ) {
887     return false;
888   }
889
890   // Create groups
891   GEOM::GEOM_IGroupOperations_var aGroupOp = 
892     theGeomEngine->GetIGroupOperations( theStudy->StudyId() );
893
894   GEOM::GEOM_Object_var aGroup = aGroupOp->CreateGroup( aPublishedObj, TopAbs_EDGE );
895   if ( !CORBA::is_nil(aGroup) && aGroupOp->IsDone() ) {
896     GEOM::ListOfLong_var anIndexes = new GEOM::ListOfLong;
897     aGroupOp->UnionIDs( aGroup, anIndexes );
898     if ( aGroupOp->IsDone() ) {
899       SALOMEDS::SObject_var aGroupSO = 
900         theGeomEngine->AddInStudy( theStudy, aGroup, qPrintable( aName ), aPublishedObj );
901     }
902   }
903
904   return true;
905 }
906
907 GEOM::GEOM_Object_ptr HYDROData_CalculationCase::publishShapeInGEOM( 
908   GEOM::GEOM_Gen_var theGeomEngine, SALOMEDS::Study_ptr theStudy,
909   const TopoDS_Shape& theShape, const QString& theName )
910 {
911   GEOM::GEOM_Object_var aGeomObj;
912
913   bool isNil = aGeomObj->_is_nil(); ///@MZN
914
915   if ( theGeomEngine->_is_nil() || theStudy->_is_nil() ||
916        theShape.IsNull() ) {
917     return aGeomObj._retn();
918   }
919
920   std::ostringstream aStreamShape;
921   // Write TopoDS_Shape in ASCII format to the stream
922   BRepTools::Write( theShape, aStreamShape );
923   // Returns the number of bytes that have been stored in the stream's buffer.
924   int aSize = aStreamShape.str().size();
925   // Allocate octect buffer of required size
926   CORBA::Octet* anOctetBuf = SALOMEDS::TMPFile::allocbuf( aSize );
927   // Copy ostrstream content to the octect buffer
928   memcpy( anOctetBuf, aStreamShape.str().c_str(), aSize );
929   // Create TMPFile
930   SALOMEDS::TMPFile_var aSeqFile = new SALOMEDS::TMPFile( aSize, aSize, anOctetBuf, 1 );
931
932   // Restore shape from the stream and get the GEOM object
933   GEOM::GEOM_IInsertOperations_var anInsOp = theGeomEngine->GetIInsertOperations( theStudy->StudyId() );
934   aGeomObj = anInsOp->RestoreShape( aSeqFile );
935   
936   // Puplish the GEOM object
937   if ( !aGeomObj->_is_nil() ) {
938     QString aName = GEOMBase::GetDefaultName( theName );
939
940     SALOMEDS::SObject_var aResultSO = 
941       theGeomEngine->PublishInStudy( theStudy, SALOMEDS::SObject::_nil(), 
942                                      aGeomObj, qPrintable( theName ) );
943     if ( aResultSO->_is_nil() ) {
944       aGeomObj = GEOM::GEOM_Object::_nil();
945     }
946   }
947
948   return aGeomObj._retn();
949  }