Salome HOME
4439850ae5daf0d4c47e70aec3ba5f8f3704229a
[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_ShapesGroup.h"
8 #include "HYDROData_Iterator.h"
9 #include "HYDROData_NaturalObject.h"
10 #include "HYDROData_PolylineXY.h"
11 #include "HYDROData_SplitToZonesTool.h"
12 #include "HYDROData_SplittedShapesGroup.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_SplittedShapesGroup) aGroup =
102         Handle(HYDROData_SplittedShapesGroup)::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_SplittedShapesGroup)> 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() || aSplitData.Shape.IsNull() )
248         continue;
249
250       QString anObjName = aSplitData.ObjectNames.first();
251       if ( anObjName.isEmpty() )
252         continue;
253
254       Handle(HYDROData_SplittedShapesGroup) aSplittedGroup;
255       if ( !aSplittedEdgesGroupsMap.contains( anObjName ) )
256       {
257         aSplittedGroup = addNewSplittedGroup();
258
259         QString aCalcGroupName = CALCULATION_GROUPS_PREF + anObjName;
260         aSplittedGroup->SetName( aCalcGroupName );
261
262         aSplittedEdgesGroupsMap.insert( anObjName, aSplittedGroup );
263       }
264       else
265       {
266         aSplittedGroup = aSplittedEdgesGroupsMap[ anObjName ];
267       }
268
269       if ( aSplittedGroup.IsNull() )
270         continue;
271
272       aSplittedGroup->AddShape( aSplitData.Shape );
273     }
274   }
275 }
276
277 bool HYDROData_CalculationCase::AddGeometryObject( const Handle(HYDROData_Object)& theObject )
278 {
279   if ( !HYDROData_Tool::IsGeometryObject( theObject ) )
280     return false; // Wrong type of object
281
282   if ( HasReference( theObject, DataTag_GeometryObject ) )
283     return false; // Object is already in reference list
284
285   AddReferenceObject( theObject, DataTag_GeometryObject );
286   
287   // Indicate model of the need to update splitting
288   SetToUpdate( true );
289
290   return true;
291 }
292
293 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetGeometryObjects() const
294 {
295   return GetReferenceObjects( DataTag_GeometryObject );
296 }
297
298 void HYDROData_CalculationCase::RemoveGeometryObject( const Handle(HYDROData_Object)& theObject )
299 {
300   if ( theObject.IsNull() )
301     return;
302
303   RemoveReferenceObject( theObject->Label(), DataTag_GeometryObject );
304
305   // Indicate model of the need to update splitting
306   SetToUpdate( true );
307 }
308
309 void HYDROData_CalculationCase::RemoveGeometryObjects()
310 {
311   ClearReferenceObjects( DataTag_GeometryObject );
312
313   // Indicate model of the need to update splitting
314   SetToUpdate( true );
315 }
316
317 bool HYDROData_CalculationCase::AddGeometryGroup( const Handle(HYDROData_ShapesGroup)& theGroup )
318 {
319   if ( theGroup.IsNull() )
320     return false;
321
322   if ( HasReference( theGroup, DataTag_GeometryGroup ) )
323     return false; // Object is already in reference list
324
325   AddReferenceObject( theGroup, DataTag_GeometryGroup );
326   
327   // Indicate model of the need to update splitting
328   SetToUpdate( true );
329
330   return true;
331 }
332
333 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetGeometryGroups() const
334 {
335   return GetReferenceObjects( DataTag_GeometryGroup );
336 }
337
338 void HYDROData_CalculationCase::RemoveGeometryGroup( const Handle(HYDROData_ShapesGroup)& theGroup )
339 {
340   if ( theGroup.IsNull() )
341     return;
342
343   RemoveReferenceObject( theGroup->Label(), DataTag_GeometryGroup );
344
345   // Indicate model of the need to update splitting
346   SetToUpdate( true );
347 }
348
349 void HYDROData_CalculationCase::RemoveGeometryGroups()
350 {
351   ClearReferenceObjects( DataTag_GeometryGroup );
352
353   // Indicate model of the need to update splitting
354   SetToUpdate( true );
355 }
356
357 void HYDROData_CalculationCase::SetBoundaryPolyline( const Handle(HYDROData_PolylineXY)& thePolyline )
358 {
359   Handle(HYDROData_PolylineXY) aPrevPolyline = GetBoundaryPolyline();
360
361   SetReferenceObject( thePolyline, DataTag_Polyline );
362
363   // Indicate model of the need to update zones splitting
364   SetToUpdate( !IsEqual( aPrevPolyline, thePolyline ) || IsMustBeUpdated() );
365 }
366
367 Handle(HYDROData_PolylineXY) HYDROData_CalculationCase::GetBoundaryPolyline() const
368 {
369   return Handle(HYDROData_PolylineXY)::DownCast( 
370            GetReferenceObject( DataTag_Polyline ) );
371 }
372
373 void HYDROData_CalculationCase::RemoveBoundaryPolyline()
374 {
375   Handle(HYDROData_PolylineXY) aPrevPolyline = GetBoundaryPolyline();
376
377   ClearReferenceObjects( DataTag_Polyline );
378
379   // Indicate model of the need to update zones splitting
380   SetToUpdate( !aPrevPolyline.IsNull() || IsMustBeUpdated() );
381 }
382
383 Handle(HYDROData_Region) HYDROData_CalculationCase::AddNewRegion( const Handle(HYDROData_Zone)& theZone )
384 {
385   Handle(HYDROData_Region) aNewRegion = addNewRegion();
386   if ( aNewRegion.IsNull() )
387     return aNewRegion;
388
389   // Generate new name for new region
390   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
391   if ( !aDocument.IsNull() )
392   {
393     QString aRegsPref = CALCULATION_REGIONS_PREF;
394
395     QString aNewRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
396     aNewRegion->SetName( aNewRegionName );
397   }
398
399   aNewRegion->AddZone( theZone );
400
401   return aNewRegion;
402 }
403
404 bool HYDROData_CalculationCase::AddRegion( const Handle(HYDROData_Region)& theRegion )
405 {
406   if ( theRegion.IsNull() )
407     return false;
408   
409   if ( HasReference( theRegion, DataTag_Region ) )
410     return false; // Object is already in reference list
411
412   // Move the region from other calculation
413   Handle(HYDROData_CalculationCase) aFatherCalc = 
414     Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
415   if ( !aFatherCalc.IsNull() && aFatherCalc->Label() != myLab )
416   {
417     Handle(HYDROData_Region) aNewRegion = addNewRegion();
418     theRegion->CopyTo( aNewRegion );
419
420     aFatherCalc->RemoveRegion( theRegion );
421
422     theRegion->SetLabel( aNewRegion->Label() );
423   }
424   else
425   {
426     AddReferenceObject( theRegion, DataTag_Region );
427   }
428
429   return true;
430 }
431
432 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetRegions() const
433 {
434   return GetReferenceObjects( DataTag_Region );
435 }
436
437 void HYDROData_CalculationCase::UpdateRegionsOrder()
438 {
439   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
440   if ( aDocument.IsNull() )
441     return;
442
443   HYDROData_SequenceOfObjects aRegions = GetRegions();
444
445   HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
446   for ( ; anIter.More(); anIter.Next() )
447   {
448     Handle(HYDROData_Region) aRegion =
449       Handle(HYDROData_Region)::DownCast( anIter.Value() );
450     if ( aRegion.IsNull() )
451       continue;
452
453     aRegion->SetName( "" );
454   }
455
456   QString aRegsPref = CALCULATION_REGIONS_PREF;
457
458   anIter.Init( aRegions );
459   for ( ; anIter.More(); anIter.Next() )
460   {
461     Handle(HYDROData_Region) aRegion =
462       Handle(HYDROData_Region)::DownCast( anIter.Value() );
463     if ( aRegion.IsNull() )
464       continue;
465
466     QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
467     aRegion->SetName( aRegionName );
468   }
469 }
470
471 void HYDROData_CalculationCase::RemoveRegion( const Handle(HYDROData_Region)& theRegion )
472 {
473   if ( theRegion.IsNull() )
474     return;
475
476   RemoveReferenceObject( theRegion->Label(), DataTag_Region );
477
478   // Remove region from data model
479   Handle(HYDROData_CalculationCase) aFatherCalc = 
480     Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
481   if ( !aFatherCalc.IsNull() && aFatherCalc->Label() == myLab )
482     theRegion->Remove();
483 }
484
485 void HYDROData_CalculationCase::RemoveRegions()
486 {
487   myLab.FindChild( DataTag_ChildRegion ).ForgetAllAttributes();
488 }
489
490 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetSplittedGroups() const
491 {
492   return GetReferenceObjects( DataTag_SplittedGroups );
493 }
494
495 void HYDROData_CalculationCase::RemoveSplittedGroups()
496 {
497   myLab.FindChild( DataTag_SplittedGroups ).ForgetAllAttributes();
498 }
499
500 TopoDS_Shell HYDROData_CalculationCase::GetShell()
501 {
502   TopoDS_Shell aShell;
503
504   TopTools_ListOfShape aFacesList;
505
506   // Make shell containing all region shapes
507   BRepBuilderAPI_Sewing aSewing( Precision::Confusion()*10.0 );
508
509   HYDROData_SequenceOfObjects aCaseRegions = GetRegions();
510   HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
511   for ( ; aRegionIter.More(); aRegionIter.Next() ) {
512     Handle(HYDROData_Region) aRegion =
513       Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
514     if( aRegion.IsNull() ) {
515       continue;
516     }
517
518     TopoDS_Shape aRegionShape = aRegion->GetShape();
519     if( !aRegionShape.IsNull() ) {
520       if ( aRegionShape.ShapeType() == TopAbs_FACE ) {
521         TopoDS_Face aFace = TopoDS::Face( aRegionShape );
522         if ( !aFace.IsNull() ) {
523           aFacesList.Append( aFace );
524           aSewing.Add( aFace );
525         }
526       } else {
527         TopExp_Explorer anExp( aRegionShape, TopAbs_FACE );
528         for ( ; anExp.More(); anExp.Next() ) {
529           TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
530           if ( !aFace.IsNull() ) {
531             aFacesList.Append( aFace );
532             aSewing.Add( aFace );
533           }
534         }
535       }
536     }
537   } // regions iterator
538   
539   aSewing.Perform();
540   TopoDS_Shape aSewedShape = aSewing.SewedShape();
541
542   if ( !aSewedShape.IsNull() )
543   {
544     if ( aSewedShape.ShapeType() == TopAbs_FACE && aCaseRegions.Length() ==1 ) {
545       // create shell from one face
546       BRep_Builder aBuilder;
547       aBuilder.MakeShell( aShell );
548       aBuilder.Add( aShell, aSewedShape);
549     } else {
550       TopExp_Explorer anExpShells( aSewedShape, TopAbs_SHELL );
551       Standard_Integer aNbOfShells = 0;
552       for ( ; anExpShells.More(); anExpShells.Next() ) {
553         aShell = TopoDS::Shell( anExpShells.Current() );
554         aNbOfShells++;
555       }
556
557       if ( aNbOfShells != 1 ) {
558         aShell.Nullify();
559         BRep_Builder aBuilder;
560         aBuilder.MakeShell( aShell );
561
562         TopExp_Explorer anExpFaces( aSewedShape, TopAbs_FACE );
563         for ( ; anExpFaces.More(); anExpFaces.Next() ) {
564           TopoDS_Face aFace = TopoDS::Face( anExpFaces.Current() );
565           if ( !aFace.IsNull() ) {
566             aBuilder.Add( aShell, aFace );
567           }
568         }
569       }
570     }
571   }
572
573   if ( !aShell.IsNull() ) {
574     TopTools_IndexedMapOfShape aMapOfFaces;
575     TopExp::MapShapes( aShell, TopAbs_FACE, aMapOfFaces );
576     if ( aMapOfFaces.Extent() != aFacesList.Extent() ) {
577       aShell.Nullify();
578       BRep_Builder aBuilder;
579       aBuilder.MakeShell( aShell );
580
581       TopTools_ListIteratorOfListOfShape anIter( aFacesList );
582       for ( ; anIter.More(); anIter.Next() ) {
583         TopoDS_Face aFace = TopoDS::Face( anIter.Value() );
584         aBuilder.Add( aShell, aFace );
585       }
586     }
587   }
588
589 /* TODO: old version
590   // Make shell
591   BRep_Builder aBuilder;
592   aBuilder.MakeShell( aShell );
593
594   // Make shell containing all region shapes
595   HYDROData_SequenceOfObjects aCaseRegions = GetRegions();
596   HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
597   for ( ; aRegionIter.More(); aRegionIter.Next() ) {
598     Handle(HYDROData_Region) aRegion =
599       Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
600     if( aRegion.IsNull() ) {
601       continue;
602     }
603
604     TopoDS_Shape aRegionShape = aRegion->GetShape();
605
606     // Add shape (face or shell) corresponding to the region into the shell
607     if( !aRegionShape.IsNull() ) {
608       if ( aRegionShape.ShapeType() == TopAbs_FACE ) {
609         aBuilder.Add( aShell, aRegionShape );
610       } else {
611         TopExp_Explorer anExp( aRegionShape, TopAbs_FACE );
612         for( ; anExp.More(); anExp.Next() ) {
613           TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
614           if( !aFace.IsNull() ) {
615             aBuilder.Add( aShell, aFace );
616           }
617         }
618       }
619     }
620   } // regions iterator
621 */
622
623   // Nullify shell if it is empty
624   if ( !aShell.IsNull() && !TopoDS_Iterator(aShell).More() ) {
625     aShell.Nullify();
626   }
627
628   return aShell;
629 }
630
631 double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY& thePoint ) const
632 {
633   double aResAltitude = HYDROData_Bathymetry::GetInvalidAltitude();
634
635   Handle(HYDROData_Zone) aZone = GetZoneFromPoint( thePoint );
636   if ( aZone.IsNull() )
637     return aResAltitude;
638
639   HYDROData_Zone::MergeBathymetriesType aZoneMergeType = aZone->GetMergeType();
640   if ( !aZone->IsMergingNeed() )
641   {
642     aZoneMergeType = HYDROData_Zone::Merge_UNKNOWN;
643   }
644   else if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
645   {
646     return aResAltitude;
647   }
648
649   if ( aZoneMergeType == HYDROData_Zone::Merge_Object )
650   {
651     Handle(HYDROData_Bathymetry) aMergeBathymetry = aZone->GetMergeBathymetry();
652     if ( !aMergeBathymetry.IsNull() )
653       aResAltitude = aMergeBathymetry->GetAltitudeForPoint( thePoint );
654   }
655   else
656   {
657     HYDROData_SequenceOfObjects aZoneObjects = aZone->GetGeometryObjects();
658     HYDROData_SequenceOfObjects::Iterator anIter( aZoneObjects );
659     for ( ; anIter.More(); anIter.Next() )
660     {
661       Handle(HYDROData_Object) aZoneObj =
662         Handle(HYDROData_Object)::DownCast( anIter.Value() );
663       if ( aZoneObj.IsNull() )
664         continue;
665
666       Handle(HYDROData_Bathymetry) anObjBathymetry = aZoneObj->GetBathymetry();
667       if ( anObjBathymetry.IsNull() )
668         continue;
669
670       double aPointAltitude = anObjBathymetry->GetAltitudeForPoint( thePoint );
671       if ( ValuesEquals( aPointAltitude, HYDROData_Bathymetry::GetInvalidAltitude() ) )
672         continue;
673
674       if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
675       {
676         aResAltitude = aPointAltitude;
677         break;
678       }
679       else if ( aZoneMergeType == HYDROData_Zone::Merge_ZMIN )
680       {
681         if ( ValuesEquals( aResAltitude, HYDROData_Bathymetry::GetInvalidAltitude() ) ||
682              aResAltitude > aPointAltitude )
683         {
684           aResAltitude = aPointAltitude;
685         }
686       }
687       else if ( aZoneMergeType == HYDROData_Zone::Merge_ZMAX )
688       {
689         if ( ValuesEquals( aResAltitude, HYDROData_Bathymetry::GetInvalidAltitude() ) ||
690              aResAltitude < aPointAltitude )
691         {
692           aResAltitude = aPointAltitude;
693         }
694       }
695     }
696   }
697
698   return aResAltitude;
699 }
700
701 Handle(HYDROData_Zone) HYDROData_CalculationCase::GetZoneFromPoint( const gp_XY& thePoint ) const
702 {
703   Handle(HYDROData_Zone) aResZone;
704
705   HYDROData_SequenceOfObjects aRegions = GetRegions();
706
707   HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
708   for ( ; anIter.More() && aResZone.IsNull(); anIter.Next() )
709   {
710     Handle(HYDROData_Region) aRegion =
711       Handle(HYDROData_Region)::DownCast( anIter.Value() );
712     if ( aRegion.IsNull() )
713       continue;
714
715     HYDROData_SequenceOfObjects aZones = aRegion->GetZones();
716     HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
717     for ( ; aZonesIter.More() && aResZone.IsNull(); aZonesIter.Next() )
718     {
719       Handle(HYDROData_Zone) aRegZone =
720         Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
721       if ( aRegZone.IsNull() )
722         continue;
723
724       PointClassification aPointRelation = GetPointClassification( thePoint, aRegZone );
725       if ( aPointRelation != POINT_OUT )
726         aResZone = aRegZone; // We found the desired zone
727     }
728   }
729
730   return aResZone;
731 }
732
733 HYDROData_CalculationCase::PointClassification HYDROData_CalculationCase::GetPointClassification(
734   const gp_XY&                  thePoint,
735   const Handle(HYDROData_Zone)& theZone ) const
736 {
737   PointClassification aRes = POINT_OUT;
738   if ( theZone.IsNull() )
739     return aRes;
740
741   TopoDS_Face aZoneFace = TopoDS::Face( theZone->GetShape() );
742   if ( aZoneFace.IsNull() )
743     return aRes;
744
745   BRepTopAdaptor_FClass2d aClassifier( aZoneFace, Precision::Confusion() );
746   TopAbs_State State = aClassifier.Perform( gp_Pnt2d(thePoint), Standard_False );
747   if (State == TopAbs_OUT)
748         aRes =  POINT_OUT;
749   else if(State == TopAbs_IN)
750     aRes =  POINT_IN;
751   else if(State == TopAbs_ON)
752     aRes =  POINT_ON;     
753   return aRes;
754 }
755
756 Handle(HYDROData_Region) HYDROData_CalculationCase::addNewRegion()
757 {
758   TDF_Label aNewLab = myLab.FindChild( DataTag_ChildRegion ).NewChild();
759
760   Handle(HYDROData_Region) aNewRegion =
761     Handle(HYDROData_Region)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_REGION ) );
762   AddRegion( aNewRegion );
763
764   return aNewRegion;
765 }
766
767 Handle(HYDROData_SplittedShapesGroup) HYDROData_CalculationCase::addNewSplittedGroup()
768 {
769   TDF_Label aNewLab = myLab.FindChild( DataTag_SplittedGroups ).NewChild();
770
771   Handle(HYDROData_SplittedShapesGroup) aNewGroup =
772     Handle(HYDROData_SplittedShapesGroup)::DownCast( 
773       HYDROData_Iterator::CreateObject( aNewLab, KIND_SPLITTED_GROUP ) );
774   AddReferenceObject( aNewGroup, DataTag_SplittedGroups );
775
776   return aNewGroup;
777 }
778
779 bool HYDROData_CalculationCase::Export( GEOM::GEOM_Gen_var theGeomEngine,
780                                         SALOMEDS::Study_ptr theStudy )
781 {
782   // Get faces
783   // TODO
784   TopTools_ListOfShape aFaces;
785
786   // Get groups
787   // TODO
788   HYDROData_SequenceOfObjects aSplittedGroups;
789
790   return Export( theGeomEngine, theStudy, aFaces, aSplittedGroups );
791 }
792
793 bool HYDROData_CalculationCase::Export( GEOM::GEOM_Gen_var theGeomEngine,
794                                         SALOMEDS::Study_ptr theStudy,
795                                         const TopTools_ListOfShape& theFaces,
796                                         const HYDROData_SequenceOfObjects& theSplittedGroups )
797 {
798   // Make shell from the faces
799   TopoDS_Shell aShell;
800   TopTools_ListOfShape aFacesList;
801
802   BRepBuilderAPI_Sewing aSewing( Precision::Confusion()*10.0 );
803
804   TopTools_ListIteratorOfListOfShape aFaceIter( theFaces );
805   for ( ; aFaceIter.More(); aFaceIter.Next() ) {
806     TopoDS_Shape aShape = aFaceIter.Value();
807     if ( !aShape.IsNull() && (aShape.ShapeType() == TopAbs_FACE) ) {
808       TopoDS_Face aFace = TopoDS::Face( aShape );
809       if ( !aFace.IsNull() ) {
810         aFacesList.Append( aFace );
811         aSewing.Add( aFace );
812       }
813     } else {
814       TopExp_Explorer anExp( aShape, TopAbs_FACE );
815       for ( ; anExp.More(); anExp.Next() ) {
816         TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
817         if ( !aFace.IsNull() ) {
818           aFacesList.Append( aFace );
819           aSewing.Add( aFace );
820         }
821       }
822     }
823   } // faces iterator
824   
825   aSewing.Perform();
826   TopoDS_Shape aSewedShape = aSewing.SewedShape();
827
828   if ( !aSewedShape.IsNull() ) {
829     if ( aSewedShape.ShapeType() == TopAbs_FACE && theFaces.Extent() ==1 ) {
830       // create shell from one face
831       BRep_Builder aBuilder;
832       aBuilder.MakeShell( aShell );
833       aBuilder.Add( aShell, aSewedShape);
834     } else {
835       TopExp_Explorer anExpShells( aSewedShape, TopAbs_SHELL );
836       Standard_Integer aNbOfShells = 0;
837       for ( ; anExpShells.More(); anExpShells.Next() ) {
838         aShell = TopoDS::Shell( anExpShells.Current() );
839         aNbOfShells++;
840       }
841
842       if ( aNbOfShells != 1 ) {
843         aShell.Nullify();
844         BRep_Builder aBuilder;
845         aBuilder.MakeShell( aShell );
846
847         TopExp_Explorer anExpFaces( aSewedShape, TopAbs_FACE );
848         for ( ; anExpFaces.More(); anExpFaces.Next() ) {
849           TopoDS_Face aFace = TopoDS::Face( anExpFaces.Current() );
850           if ( !aFace.IsNull() ) {
851             aBuilder.Add( aShell, aFace );
852           }
853         }
854       }
855     }
856   }
857
858   if ( !aShell.IsNull() ) {
859     TopTools_IndexedMapOfShape aMapOfFaces;
860     TopExp::MapShapes( aShell, TopAbs_FACE, aMapOfFaces );
861     if ( aMapOfFaces.Extent() != aFacesList.Extent() ) {
862       aShell.Nullify();
863       BRep_Builder aBuilder;
864       aBuilder.MakeShell( aShell );
865
866       TopTools_ListIteratorOfListOfShape anIter( aFacesList );
867       for ( ; anIter.More(); anIter.Next() ) {
868         TopoDS_Face aFace = TopoDS::Face( anIter.Value() );
869         aBuilder.Add( aShell, aFace );
870       }
871     }
872   }
873
874   // If the shell is empty - return false
875   if ( aShell.IsNull() || !TopoDS_Iterator(aShell).More() ) {
876     return false;
877   }
878
879   // Publish the shell
880   QString aName = EXPORT_NAME;
881   GEOM::GEOM_Object_ptr aPublishedObj = 
882     publishShapeInGEOM( theGeomEngine, theStudy, aShell, aName );
883
884   if ( aPublishedObj->_is_nil() ) {
885     return false;
886   }
887
888   // Create groups
889   GEOM::GEOM_IGroupOperations_var aGroupOp = 
890     theGeomEngine->GetIGroupOperations( theStudy->StudyId() );
891
892   GEOM::GEOM_Object_var aGroup = aGroupOp->CreateGroup( aPublishedObj, TopAbs_EDGE );
893   if ( !CORBA::is_nil(aGroup) && aGroupOp->IsDone() ) {
894     GEOM::ListOfLong_var anIndexes = new GEOM::ListOfLong;
895     aGroupOp->UnionIDs( aGroup, anIndexes );
896     if ( aGroupOp->IsDone() ) {
897       SALOMEDS::SObject_var aGroupSO = 
898         theGeomEngine->AddInStudy( theStudy, aGroup, qPrintable( aName ), aPublishedObj );
899     }
900   }
901
902   return true;
903 }
904
905 GEOM::GEOM_Object_ptr HYDROData_CalculationCase::publishShapeInGEOM( 
906   GEOM::GEOM_Gen_var theGeomEngine, SALOMEDS::Study_ptr theStudy,
907   const TopoDS_Shape& theShape, const QString& theName )
908 {
909   GEOM::GEOM_Object_var aGeomObj;
910
911   bool isNil = aGeomObj->_is_nil(); ///@MZN
912
913   if ( theGeomEngine->_is_nil() || theStudy->_is_nil() ||
914        theShape.IsNull() ) {
915     return aGeomObj._retn();
916   }
917
918   std::ostringstream aStreamShape;
919   // Write TopoDS_Shape in ASCII format to the stream
920   BRepTools::Write( theShape, aStreamShape );
921   // Returns the number of bytes that have been stored in the stream's buffer.
922   int aSize = aStreamShape.str().size();
923   // Allocate octect buffer of required size
924   CORBA::Octet* anOctetBuf = SALOMEDS::TMPFile::allocbuf( aSize );
925   // Copy ostrstream content to the octect buffer
926   memcpy( anOctetBuf, aStreamShape.str().c_str(), aSize );
927   // Create TMPFile
928   SALOMEDS::TMPFile_var aSeqFile = new SALOMEDS::TMPFile( aSize, aSize, anOctetBuf, 1 );
929
930   // Restore shape from the stream and get the GEOM object
931   GEOM::GEOM_IInsertOperations_var anInsOp = theGeomEngine->GetIInsertOperations( theStudy->StudyId() );
932   aGeomObj = anInsOp->RestoreShape( aSeqFile );
933   
934   // Puplish the GEOM object
935   if ( !aGeomObj->_is_nil() ) {
936     QString aName = GEOMBase::GetDefaultName( theName );
937
938     SALOMEDS::SObject_var aResultSO = 
939       theGeomEngine->PublishInStudy( theStudy, SALOMEDS::SObject::_nil(), 
940                                      aGeomObj, qPrintable( theName ) );
941     if ( aResultSO->_is_nil() ) {
942       aGeomObj = GEOM::GEOM_Object::_nil();
943     }
944   }
945
946   return aGeomObj._retn();
947  }