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