Salome HOME
Merge branch 'BR_v14_rc' into BR_quadtree
[modules/hydro.git] / src / HYDROData / HYDROData_CalculationCase.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #ifdef WIN32
20   #pragma warning ( disable: 4251 )
21 #endif
22
23 #include "HYDROData_CalculationCase.h"
24 #include "HYDROData_ArtificialObject.h"
25 #include "HYDROData_IAltitudeObject.h"
26 #include "HYDROData_Document.h"
27 #include "HYDROData_ShapesGroup.h"
28 #include "HYDROData_Iterator.h"
29 #include "HYDROData_NaturalObject.h"
30 #include "HYDROData_PolylineXY.h"
31 #include "HYDROData_StricklerTable.h"
32 #include "HYDROData_LandCover.h"
33 #include "HYDROData_SplittedShapesGroup.h"
34 #include "HYDROData_Region.h"
35 #include "HYDROData_Tool.h"
36 #include "HYDROData_GeomTool.h"
37
38 #include <GEOMBase.h>
39
40 #include <QSet>
41
42 #include <TopoDS.hxx>
43 #include <TopoDS_Shell.hxx>
44 #include <TopoDS_Edge.hxx>
45
46 #include <BRep_Builder.hxx>
47 #include <BRepBuilderAPI_Sewing.hxx>
48 #include <BRepTopAdaptor_FClass2d.hxx>
49
50 #include <BRepTools.hxx>
51
52 #include <TopAbs.hxx>
53 #include <TopExp_Explorer.hxx>
54 #include <TopExp.hxx>
55 #include <TopTools_ListOfShape.hxx>
56 #include <TopTools_ListIteratorOfListOfShape.hxx>
57 #include <TDataStd_Integer.hxx>
58
59 //#define  DEB_CALCULATION 1
60 #ifdef DEB_CALCULATION
61 #include <BRepTools.hxx>
62 #include <TopLoc_Location.hxx>
63 #endif 
64 #define CALCULATION_REGIONS_PREF GetName() + "_Reg"
65 #define CALCULATION_ZONES_PREF GetName() + "_Zone"
66 #define CALCULATION_LANDCOVER_ZONES_PREF GetName() + "_LandCoverZone"
67 #define CALCULATION_GROUPS_PREF GetName() + "_"
68 //#define DEB_CLASS2D 1
69 #ifdef DEB_CLASS2D
70 #include <BRepBuilderAPI_MakeVertex.hxx>
71 #endif
72
73 #ifdef WIN32
74   #pragma warning ( default: 4251 )
75 #endif
76
77 #define EXPORT_NAME "HYDRO_" + GetName()
78
79 #include <SALOME_NamingService.hxx>
80 #include <SALOME_LifeCycleCORBA.hxx>
81
82 #define _DEVDEBUG_
83 #include "HYDRO_trace.hxx"
84
85 IMPLEMENT_STANDARD_HANDLE(HYDROData_CalculationCase, HYDROData_Entity)
86 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_CalculationCase, HYDROData_Entity)
87
88 HYDROData_CalculationCase::HYDROData_CalculationCase()
89 : HYDROData_Entity()
90 {
91 }
92
93 HYDROData_CalculationCase::~HYDROData_CalculationCase()
94 {
95 }
96
97 void HYDROData_CalculationCase::SetName( const QString& theName )
98 {
99   QString anOldCaseName = GetName();
100   if ( anOldCaseName != theName )
101   {
102     // Update names of regions and its zones
103     UpdateRegionsNames( GetRegions( false ), anOldCaseName, theName );
104     // Update names of land cover regions and its zones
105     UpdateRegionsNames( GetRegions( true ), anOldCaseName, theName );
106
107     HYDROData_SequenceOfObjects aGroups = GetSplittedGroups();
108
109     HYDROData_SequenceOfObjects::Iterator anIter;
110     anIter.Init( aGroups );
111     for ( ; anIter.More(); anIter.Next() )
112     {
113       Handle(HYDROData_SplittedShapesGroup) aGroup =
114         Handle(HYDROData_SplittedShapesGroup)::DownCast( anIter.Value() );
115       if ( aGroup.IsNull() )
116         continue;
117
118       HYDROData_Tool::UpdateChildObjectName( anOldCaseName, theName, aGroup );
119     }
120   }
121
122   HYDROData_Entity::SetName( theName );
123 }
124
125 QStringList HYDROData_CalculationCase::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
126 {
127   QStringList aResList = dumpObjectCreation( theTreatedObjects );
128   aResList.prepend( "# Calculation case" );
129
130   QString aCalculName = GetObjPyName();
131
132   AssignmentMode aMode = GetAssignmentMode();  
133   QString aModeStr = aMode==MANUAL ? "HYDROData_CalculationCase.MANUAL" : "HYDROData_CalculationCase.AUTOMATIC";
134   aResList << QString( "%0.SetAssignmentMode( %1 )" ).arg( aCalculName ).arg( aModeStr );
135
136   AssignmentMode aModeLC = GetAssignmentLandCoverMode();
137   QString aModeLCStr = aModeLC==MANUAL ? "HYDROData_CalculationCase.MANUAL" : "HYDROData_CalculationCase.AUTOMATIC";
138   aResList << QString( "%0.SetAssignmentLandCoverMode( %1 )" ).arg( aCalculName ).arg( aModeLCStr );
139
140   HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects();
141   HYDROData_SequenceOfObjects::Iterator anIter( aGeomObjects );
142   for ( ; anIter.More(); anIter.Next() )
143   {
144     Handle(HYDROData_Object) aRefGeomObj =
145       Handle(HYDROData_Object)::DownCast( anIter.Value() );
146     setPythonReferenceObject( theTreatedObjects, aResList, aRefGeomObj, "AddGeometryObject" );
147   }
148   aResList << QString( "" );
149
150   QString aGroupName = HYDROData_Tool::GenerateNameForPython( theTreatedObjects, "case_geom_group" );
151
152   HYDROData_SequenceOfObjects aGeomGroups = GetGeometryGroups();
153   anIter.Init( aGeomGroups );
154   for ( ; anIter.More(); anIter.Next() )
155   {
156     Handle(HYDROData_ShapesGroup) aGeomGroup =
157       Handle(HYDROData_ShapesGroup)::DownCast( anIter.Value() );
158     if ( aGeomGroup.IsNull() )
159       continue;
160
161     Handle(HYDROData_Object) aFatherGeom =
162       Handle(HYDROData_Object)::DownCast( aGeomGroup->GetFatherObject() );
163     if ( aFatherGeom.IsNull() )
164       continue;
165
166     int aGroupId = aFatherGeom->GetGroupId( aGeomGroup );
167     aResList << QString( "%1 = %2.GetGroup( %3 );" )
168               .arg( aGroupName ).arg( aFatherGeom->GetObjPyName() ).arg( aGroupId );
169
170     aResList << QString( "%1.AddGeometryGroup( %2 );" ).arg( aCalculName ).arg( aGroupName );
171   }
172
173   Handle(HYDROData_PolylineXY) aBoundaryPolyline = GetBoundaryPolyline();
174   setPythonReferenceObject( theTreatedObjects, aResList, aBoundaryPolyline, "SetBoundaryPolyline" );
175
176   if( aMode==AUTOMATIC )
177     DumpRulesToPython( aCalculName, aResList );
178   if( aModeLC==AUTOMATIC )
179     DumpLandCoverRulesToPython( aCalculName, aResList );
180
181   aResList << QString( "" );
182   aResList << "# Start the algorithm of the partition and assignment";
183   aResList << QString( "%1.Update();" ).arg( aCalculName );
184
185   if( aMode==MANUAL )
186   {
187     // Now we restore the
188     // - regions and zones order
189     DumpRegionsToPython( aResList, theTreatedObjects, GetRegions( false ) );   
190   }
191
192   if( aModeLC==MANUAL )
193   {
194     // Now we restore the
195     // - land cover regions and zones order
196     DumpRegionsToPython( aResList, theTreatedObjects, GetRegions( true ) );
197   }
198
199   // Export calculation case
200   aResList << QString( "" );
201   aResList << "# Export of the calculation case";
202   QString aStudyName = "theStudy";
203   QString anEntryVar = aCalculName + "_entry";
204   aResList << QString( "%1 = %2.Export( %3._get_StudyId() )" ).arg( anEntryVar ).arg( aCalculName ).arg( aStudyName );
205
206   // Get geometry object and print debug information
207   aResList << "";
208   aResList << "# Get geometry shape and print debug information";
209   aResList << "import GEOM";
210   aResList << QString( "print \"Entry:\", %1" ).arg( anEntryVar );
211   QString aGeomShapeName = aCalculName + "_geom";
212   aResList << QString( "%1 = salome.IDToObject( str( %2 ) )" ).arg( aGeomShapeName ).arg( anEntryVar );
213   aResList << QString( "print \"Geom shape:\", %1" ).arg( aGeomShapeName );
214   aResList << QString( "print \"Geom shape name:\", %1.GetName()" ).arg( aGeomShapeName );
215
216   DumpSampleMeshing( aResList, aStudyName, aGeomShapeName, aCalculName+"_mesh" );
217
218   aResList << QString( "" );
219   return aResList;
220 }
221
222 void HYDROData_CalculationCase::DumpSampleMeshing( QStringList& theResList,
223                                                    const QString& theStudyName,
224                                                    const QString& theGeomShapeName,
225                                                    const QString& theMeshName ) const
226 {
227   theResList << "";
228   theResList << "# Meshing";
229   theResList << "import SMESH, SALOMEDS";
230   theResList << "from salome.smesh import smeshBuilder";
231   theResList << "from salome.geom import geomBuilder";
232
233   theResList << QString( "smesh = smeshBuilder.New( %1 )" ).arg( theStudyName );
234   theResList << QString( "%1 = smesh.Mesh( %2 )" ).arg( theMeshName ).arg( theGeomShapeName );
235   theResList << QString( "MEFISTO_2D = %1.Triangle( algo=smeshBuilder.MEFISTO )" ).arg( theMeshName );
236   theResList << "Max_Element_Area_1 = MEFISTO_2D.MaxElementArea( 10 )";
237   theResList << QString( "Regular_1D = %1.Segment()" ).arg( theMeshName );
238   theResList << "Max_Size_1 = Regular_1D.MaxSize(10)";
239   theResList << QString( "isDone = %1.Compute()" ).arg( theMeshName );
240
241   theResList << "";
242   theResList << "# Set names of Mesh objects";
243   theResList << "smesh.SetName( MEFISTO_2D.GetAlgorithm(), 'MEFISTO_2D' )";
244   theResList << "smesh.SetName( Regular_1D.GetAlgorithm(), 'Regular_1D' )";
245   theResList << "smesh.SetName( Max_Size_1, 'Max Size_1' )";
246   theResList << "smesh.SetName( Max_Element_Area_1, 'Max. Element Area_1' )";
247   theResList << QString( "smesh.SetName( %1.GetMesh(), '%1' )" ).arg( theMeshName );
248
249   theResList << "";
250   theResList << "# Greate SMESH groups";
251   theResList << QString( "geompy = geomBuilder.New( %1 )" ).arg( theStudyName );
252   theResList << QString( "geom_groups = geompy.GetGroups( %1 )" ).arg( theGeomShapeName );
253   theResList << QString( "for group in geom_groups:" );
254   theResList << QString( "    smesh_group = %1.GroupOnGeom(group, group.GetName(), SMESH.EDGE)" )
255                 .arg( theMeshName );
256   theResList << QString( "    smesh.SetName(smesh_group, group.GetName())" );
257   theResList << QString( "    print \"SMESH group '%s': %s\" % (smesh_group.GetName(), smesh_group)" );
258 }
259
260 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetAllReferenceObjects() const
261 {
262   HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
263
264   Handle(HYDROData_PolylineXY) aBoundaryPolyline = GetBoundaryPolyline();
265   if ( !aBoundaryPolyline.IsNull() )
266     aResSeq.Append( aBoundaryPolyline );
267
268   // Regions
269   HYDROData_SequenceOfObjects aSeqOfRegions = GetRegions( false );
270   aResSeq.Append( aSeqOfRegions );
271
272   // Land cover regions
273   HYDROData_SequenceOfObjects aSeqOfLandCoverRegions = GetRegions( true );
274   aResSeq.Append( aSeqOfLandCoverRegions );
275
276   return aResSeq;
277 }
278
279 void HYDROData_CalculationCase::Update()
280 {
281   HYDROData_Entity::Update();
282   SetWarning();
283
284   // At first we remove previously created objects
285   RemoveRegions( false );
286   RemoveRegions( true );
287   RemoveSplittedGroups();
288
289   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
290   if ( aDocument.IsNull() )
291     return;
292
293   // Split to zones
294   HYDROData_SplitToZonesTool::SplitDataList aZonesList, anEdgesList;
295
296   Handle(HYDROData_PolylineXY) aBoundaryPolyline = GetBoundaryPolyline();
297   HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects();
298   if ( !aGeomObjects.IsEmpty() ) {
299     HYDROData_SequenceOfObjects aGeomGroups = GetGeometryGroups();
300
301     HYDROData_SplitToZonesTool::SplitDataList aSplitObjects =
302       HYDROData_SplitToZonesTool::Split( aGeomObjects, aGeomGroups, aBoundaryPolyline );
303     if ( !aSplitObjects.isEmpty() ) {
304       HYDROData_SplitToZonesTool::SplitDataListIterator anIter( aSplitObjects );
305       while( anIter.hasNext() ) {
306         const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next();
307         if ( aSplitData.Type == HYDROData_SplitToZonesTool::SplitData::Data_Zone )
308           aZonesList.append( aSplitData );
309         else if ( aSplitData.Type == HYDROData_SplitToZonesTool::SplitData::Data_Edge )
310           anEdgesList.append( aSplitData );
311       }
312     }
313   }
314
315   // Split to land cover zones
316   HYDROData_SplitToZonesTool::SplitDataList aLandCoverZonesList;
317
318   HYDROData_SequenceOfObjects aLandCovers = GetLandCovers();
319   if ( !aLandCovers.IsEmpty() ) {
320     HYDROData_SplitToZonesTool::SplitDataList aSplitLandCoverObjects =
321       HYDROData_SplitToZonesTool::Split( aLandCovers );
322     if ( !aSplitLandCoverObjects.isEmpty() ) {
323       HYDROData_SplitToZonesTool::SplitDataListIterator anIter( aSplitLandCoverObjects );
324       while( anIter.hasNext() ) {
325         const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next();
326         if ( aSplitData.Type == HYDROData_SplitToZonesTool::SplitData::Data_Zone )
327           aLandCoverZonesList.append( aSplitData );
328       }
329     }
330   }
331
332   switch( GetAssignmentMode() )
333   {
334   case MANUAL:
335     CreateRegionsDef( aDocument, aZonesList, false );    
336     break;
337   case AUTOMATIC:
338     CreateRegionsAuto( aDocument, aZonesList, false );    
339     break;
340   }
341
342   switch( GetAssignmentLandCoverMode() )
343   {
344   case MANUAL:
345     CreateRegionsDef( aDocument, aLandCoverZonesList, true );
346     break;
347   case AUTOMATIC:
348     CreateRegionsAuto( aDocument, aLandCoverZonesList, true );
349     break;
350   }
351
352   CreateEdgeGroupsDef( aDocument, anEdgesList );
353 }
354
355 void HYDROData_CalculationCase::CreateRegionsDef( const Handle(HYDROData_Document)& theDoc,
356                                                   const HYDROData_SplitToZonesTool::SplitDataList& theZones,
357                                                   const bool theLandCover )
358 {
359   // Create result regions for case, by default one zone for one region
360   QString aRegsPref = CALCULATION_REGIONS_PREF;
361   QString aZonesPref = theLandCover ? CALCULATION_LANDCOVER_ZONES_PREF : CALCULATION_ZONES_PREF;
362
363   HYDROData_SplitToZonesTool::SplitDataListIterator anIter( theZones );
364   while( anIter.hasNext() )
365   {
366     const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next();
367     // Create new region
368     Handle(HYDROData_Region) aRegion = addNewRegion( theDoc, aRegsPref, theLandCover );
369
370     // Add the zone for region
371     Handle(HYDROData_Zone) aRegionZone = aRegion->addNewZone( theDoc, aZonesPref, aSplitData.Face(), aSplitData.ObjectNames );
372   }
373 }
374
375 void HYDROData_CalculationCase::CreateRegionsAuto( const Handle(HYDROData_Document)& theDoc,
376                                                    const HYDROData_SplitToZonesTool::SplitDataList& theZones,
377                                                    const bool theLandCover )
378 {
379   QMap<QString, Handle(HYDROData_Region)> aRegionsMap; //object name to region
380   QMap<QString, QString> aRegionNameToObjNameMap;
381   QString aZonesPref = theLandCover ? CALCULATION_LANDCOVER_ZONES_PREF : CALCULATION_ZONES_PREF;
382   HYDROData_PriorityQueue aPr( this, theLandCover ? DataTag_CustomLandCoverRules : DataTag_CustomRules );
383
384   // 1. First we create a default region for each object included into the calculation case
385   HYDROData_SequenceOfObjects anObjects = theLandCover ? GetLandCovers() : GetGeometryObjects();
386   for( int i = anObjects.Lower(), n = anObjects.Upper(); i<=n; i++ )
387   {
388     Handle(HYDROData_Entity) anObj = anObjects.Value( i );
389     if( anObj.IsNull() )
390       continue;
391     QString anObjName = anObj->GetName();
392     QString aRegName = anObjName + "_reg";
393     Handle(HYDROData_Region) aRegion = addNewRegion( theDoc, aRegName, theLandCover, false );
394     aRegionsMap.insert( anObjName, aRegion );
395     aRegionNameToObjNameMap.insert( aRegName, anObjName );
396   }
397
398   // 2. Now for each zone it is necessary to determine the most priority object
399   //    and assign to zone to corresponding region
400   HYDROData_SplitToZonesTool::SplitDataListIterator anIter( theZones );
401   while( anIter.hasNext() )
402   {
403     const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next();
404     HYDROData_Zone::MergeType aMergeType;
405     Handle(HYDROData_Entity) aRegObj = aPr.GetMostPriorityObject( aSplitData.ObjectNames, aMergeType );
406     if( aRegObj.IsNull() )
407       continue;
408     Handle(HYDROData_Region) aRegion = aRegionsMap[aRegObj->GetName()];
409     if( aRegion.IsNull() )
410       continue;
411     Handle(HYDROData_Zone) aRegionZone = aRegion->addNewZone( theDoc, aZonesPref, aSplitData.Face(), aSplitData.ObjectNames );
412
413     if( aSplitData.ObjectNames.count() > 1 && aMergeType==HYDROData_Zone::Merge_UNKNOWN )
414     {
415       qDebug( "Error in algorithm: unresolved conflicts" );
416     }
417
418     Handle(HYDROData_Entity) aMergeEntity = aRegObj;
419     if ( !theLandCover ) {
420       Handle(HYDROData_Object) aMergeObject = Handle(HYDROData_Object)::DownCast( aMergeEntity );
421       if ( !aMergeObject.IsNull() ) {
422         aMergeEntity = aMergeObject->GetAltitudeObject();
423       }
424     }
425
426     switch( aMergeType )
427     {
428     case HYDROData_Zone::Merge_ZMIN:
429     case HYDROData_Zone::Merge_ZMAX:
430       aRegionZone->SetMergeType( aMergeType );
431       break;
432     case HYDROData_Zone::Merge_Object:
433       aRegionZone->SetMergeType( aMergeType );
434       aRegionZone->RemoveMergeObject();
435       aRegionZone->SetMergeObject( aMergeEntity );
436       break;
437     }
438   }
439
440   QStringList anObjectsWithEmptyRegions;
441   QMap<QString, Handle(HYDROData_Region)>::const_iterator
442     anIt = aRegionsMap.begin(), aLast = aRegionsMap.end();
443   for( ; anIt!=aLast; anIt++ )
444   {
445     Handle(HYDROData_Region) aRegion = anIt.value();
446     if( aRegion->GetZones().IsEmpty() )
447     {
448       QString aRegName = aRegion->GetName();
449       QString anObjName = aRegionNameToObjNameMap[aRegName];
450       anObjectsWithEmptyRegions.append( anObjName );
451     }
452   }
453   
454   if( !anObjectsWithEmptyRegions.empty() )
455   {
456     QString aData = anObjectsWithEmptyRegions.join( ", " );
457     SetWarning( WARN_EMPTY_REGIONS, aData );
458   }
459 }
460
461 void HYDROData_CalculationCase::CreateEdgeGroupsDef( const Handle(HYDROData_Document)& theDoc,
462                                                      const HYDROData_SplitToZonesTool::SplitDataList& theEdges )
463 {
464   QMap<QString,Handle(HYDROData_SplittedShapesGroup)> aSplittedEdgesGroupsMap;
465
466   HYDROData_SplitToZonesTool::SplitDataListIterator anIter( theEdges );
467   while( anIter.hasNext() )
468   {
469     const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next();
470     // Create new edges group
471     if ( aSplitData.ObjectNames.isEmpty() || aSplitData.Shape.IsNull() )
472       continue;
473
474     QString anObjName = aSplitData.ObjectNames.first();
475     if ( anObjName.isEmpty() )
476       continue;
477 #ifdef DEB_CALCULATION
478     QString aStr = aSplitData.ObjectNames.join(" "); 
479           cout << " CCase: Names = "<<aStr.toStdString() << " size = " <<aSplitData.ObjectNames.size() <<endl; 
480 #endif
481     Handle(HYDROData_SplittedShapesGroup) aSplittedGroup;
482     if ( !aSplittedEdgesGroupsMap.contains( anObjName ) )
483     {
484       aSplittedGroup = addNewSplittedGroup( CALCULATION_GROUPS_PREF + anObjName );
485       aSplittedEdgesGroupsMap.insert( anObjName, aSplittedGroup );
486     }
487     else
488     {
489       aSplittedGroup = aSplittedEdgesGroupsMap[ anObjName ];
490     }
491     if ( aSplittedGroup.IsNull() )
492       continue;
493
494     aSplittedGroup->AddShape( aSplitData.Shape );
495   }
496 }
497
498 bool HYDROData_CalculationCase::AddGeometryObject( const Handle(HYDROData_Object)& theObject )
499 {
500   if ( !HYDROData_Tool::IsGeometryObject( theObject ) )
501     return false; // Wrong type of object
502
503   if ( HasReference( theObject, DataTag_GeometryObject ) )
504     return false; // Object is already in reference list
505
506   AddReferenceObject( theObject, DataTag_GeometryObject );
507   
508   // Indicate model of the need to update splitting
509   SetToUpdate( true );
510
511   return true;
512 }
513
514 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetGeometryObjects() const
515 {
516   return GetReferenceObjects( DataTag_GeometryObject );
517 }
518
519 void HYDROData_CalculationCase::RemoveGeometryObject( const Handle(HYDROData_Object)& theObject )
520 {
521   if ( theObject.IsNull() )
522     return;
523
524   RemoveReferenceObject( theObject->Label(), DataTag_GeometryObject );
525
526   // Indicate model of the need to update splitting
527   SetToUpdate( true );
528 }
529
530 void HYDROData_CalculationCase::RemoveGeometryObjects()
531 {
532   ClearReferenceObjects( DataTag_GeometryObject );
533
534   // Indicate model of the need to update splitting
535   SetToUpdate( true );
536 }
537
538 bool HYDROData_CalculationCase::AddGeometryGroup( const Handle(HYDROData_ShapesGroup)& theGroup )
539 {
540   if ( theGroup.IsNull() )
541     return false;
542
543   if ( HasReference( theGroup, DataTag_GeometryGroup ) )
544     return false; // Object is already in reference list
545
546   AddReferenceObject( theGroup, DataTag_GeometryGroup );
547   
548   // Indicate model of the need to update splitting
549   SetToUpdate( true );
550
551   return true;
552 }
553
554 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetGeometryGroups() const
555 {
556   return GetReferenceObjects( DataTag_GeometryGroup );
557 }
558
559 void HYDROData_CalculationCase::RemoveGeometryGroup( const Handle(HYDROData_ShapesGroup)& theGroup )
560 {
561   if ( theGroup.IsNull() )
562     return;
563
564   RemoveReferenceObject( theGroup->Label(), DataTag_GeometryGroup );
565
566   // Indicate model of the need to update splitting
567   SetToUpdate( true );
568 }
569
570 void HYDROData_CalculationCase::RemoveGeometryGroups()
571 {
572   ClearReferenceObjects( DataTag_GeometryGroup );
573
574   // Indicate model of the need to update splitting
575   SetToUpdate( true );
576 }
577
578 void HYDROData_CalculationCase::SetBoundaryPolyline( const Handle(HYDROData_PolylineXY)& thePolyline )
579 {
580   Handle(HYDROData_PolylineXY) aPrevPolyline = GetBoundaryPolyline();
581
582   SetReferenceObject( thePolyline, DataTag_Polyline );
583
584   // Indicate model of the need to update zones splitting
585   SetToUpdate( !IsEqual( aPrevPolyline, thePolyline ) || IsMustBeUpdated() );
586 }
587
588 Handle(HYDROData_PolylineXY) HYDROData_CalculationCase::GetBoundaryPolyline() const
589 {
590   return Handle(HYDROData_PolylineXY)::DownCast( 
591            GetReferenceObject( DataTag_Polyline ) );
592 }
593
594 void HYDROData_CalculationCase::RemoveBoundaryPolyline()
595 {
596   Handle(HYDROData_PolylineXY) aPrevPolyline = GetBoundaryPolyline();
597
598   ClearReferenceObjects( DataTag_Polyline );
599
600   // Indicate model of the need to update zones splitting
601   SetToUpdate( !aPrevPolyline.IsNull() || IsMustBeUpdated() );
602 }
603
604 void HYDROData_CalculationCase::SetStricklerTable( const Handle(HYDROData_StricklerTable)& theStricklerTable )
605 {
606   Handle(HYDROData_StricklerTable) aPrevStricklerTable = GetStricklerTable();
607
608   SetReferenceObject( theStricklerTable, DataTag_StricklerTable );
609
610   // Indicate model of the need to update land covers partition
611   SetToUpdate( !IsEqual( aPrevStricklerTable, theStricklerTable ) || IsMustBeUpdated() );
612 }
613
614 Handle(HYDROData_StricklerTable) HYDROData_CalculationCase::GetStricklerTable() const
615 {
616   return Handle(HYDROData_StricklerTable)::DownCast( 
617            GetReferenceObject( DataTag_StricklerTable ) );
618 }
619
620 void HYDROData_CalculationCase::RemoveStricklerTable()
621 {
622   Handle(HYDROData_StricklerTable) aPrevStricklerTable = GetStricklerTable();
623
624   ClearReferenceObjects( DataTag_StricklerTable );
625
626   // Indicate model of the need to update land covers partition
627   SetToUpdate( !aPrevStricklerTable.IsNull() || IsMustBeUpdated() );
628 }
629
630 bool HYDROData_CalculationCase::AddLandCover( const Handle(HYDROData_LandCover)& theLandCover )
631 {
632   if ( HasReference( theLandCover, DataTag_LandCover ) )
633     return false; // Land cover is already in reference list
634
635   AddReferenceObject( theLandCover, DataTag_LandCover );
636   
637   // Indicate model of the need to update land covers partition
638   SetToUpdate( true );
639
640   return true;
641 }
642
643 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetLandCovers() const
644 {
645   return GetReferenceObjects( DataTag_LandCover );
646 }
647
648 void HYDROData_CalculationCase::RemoveLandCover( const Handle(HYDROData_LandCover)& theLandCover )
649 {
650   if ( theLandCover.IsNull() )
651     return;
652
653   RemoveReferenceObject( theLandCover->Label(), DataTag_LandCover );
654
655   // Indicate model of the need to update land cover partition
656   SetToUpdate( true );
657 }
658
659 void HYDROData_CalculationCase::RemoveLandCovers()
660 {
661   ClearReferenceObjects( DataTag_LandCover );
662
663   // Indicate model of the need to update land cover partition
664   SetToUpdate( true );
665 }
666
667 Handle(HYDROData_Region) HYDROData_CalculationCase::AddNewRegion( const Handle(HYDROData_Zone)& theZone,
668                                                                   const bool theLandCover )
669 {
670   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
671   Handle(HYDROData_Region) aNewRegion = addNewRegion( aDocument, CALCULATION_REGIONS_PREF, theLandCover );
672   if ( aNewRegion.IsNull() )
673     return aNewRegion;
674
675   aNewRegion->AddZone( theZone );
676
677   return aNewRegion;
678 }
679
680 bool HYDROData_CalculationCase::AddRegion( const Handle(HYDROData_Region)& theRegion,
681                                            const bool theLandCover )
682 {
683   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
684
685   if ( theRegion.IsNull() )
686     return false;
687   
688   HYDROData_CalculationCase::DataTag aDataTag = 
689     theLandCover ? DataTag_LandCoverRegion : DataTag_Region;
690
691   if ( HasReference( theRegion, aDataTag ) )
692     return false; // Object is already in reference list
693
694   // Move the region from other calculation
695   Handle(HYDROData_CalculationCase) aFatherCalc = 
696     Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
697   if ( !aFatherCalc.IsNull() && aFatherCalc->Label() != myLab )
698   {
699     Handle(HYDROData_Region) aNewRegion = addNewRegion( aDocument, CALCULATION_REGIONS_PREF, theLandCover );
700     theRegion->CopyTo( aNewRegion );
701
702     aFatherCalc->RemoveRegion( theRegion, theLandCover );
703
704     theRegion->SetLabel( aNewRegion->Label() );
705   }
706   else
707   {
708     AddReferenceObject( theRegion, aDataTag );
709   }
710
711   return true;
712 }
713
714 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetRegions( const bool theLandCover ) const
715 {
716   return GetReferenceObjects( theLandCover ? DataTag_LandCoverRegion : DataTag_Region );
717 }
718
719 void HYDROData_CalculationCase::UpdateRegionsOrder()
720 {
721   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
722   if ( aDocument.IsNull() )
723     return;
724
725   HYDROData_SequenceOfObjects aRegions = GetRegions( false );
726   HYDROData_SequenceOfObjects aRegionsLC = GetRegions( true );
727   aRegions.Append( aRegionsLC );
728
729   HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
730   for ( ; anIter.More(); anIter.Next() )
731   {
732     Handle(HYDROData_Region) aRegion =
733       Handle(HYDROData_Region)::DownCast( anIter.Value() );
734     if ( aRegion.IsNull() )
735       continue;
736
737     aRegion->SetName( "" );
738   }
739
740   QString aRegsPref = CALCULATION_REGIONS_PREF;
741
742   anIter.Init( aRegions );
743   for ( ; anIter.More(); anIter.Next() )
744   {
745     Handle(HYDROData_Region) aRegion =
746       Handle(HYDROData_Region)::DownCast( anIter.Value() );
747     if ( aRegion.IsNull() )
748       continue;
749
750     QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
751     aRegion->SetName( aRegionName );
752   }
753 }
754
755 void HYDROData_CalculationCase::RemoveRegion( const Handle(HYDROData_Region)& theRegion,
756                                               const bool theLandCover )
757 {
758   if ( theRegion.IsNull() )
759     return;
760
761   HYDROData_CalculationCase::DataTag aDataTag = 
762     theLandCover ? DataTag_LandCoverRegion : DataTag_Region;
763   RemoveReferenceObject( theRegion->Label(), aDataTag );
764
765   // Remove region from data model
766   Handle(HYDROData_CalculationCase) aFatherCalc = 
767     Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
768   if ( !aFatherCalc.IsNull() && aFatherCalc->Label() == myLab )
769     theRegion->Remove();
770 }
771
772 void HYDROData_CalculationCase::RemoveRegions( const bool theLandCover )
773 {
774   myLab.FindChild( theLandCover ? DataTag_ChildLandCoverRegion : DataTag_ChildRegion ).ForgetAllAttributes();
775 }
776
777 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetSplittedGroups() const
778 {
779   return GetReferenceObjects( DataTag_SplittedGroups );
780 }
781
782 void HYDROData_CalculationCase::RemoveSplittedGroups()
783 {
784   myLab.FindChild( DataTag_SplittedGroups ).ForgetAllAttributes();
785 }
786
787 double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY& thePoint ) const
788 {
789   Handle(HYDROData_Zone) aZone = GetZoneFromPoint( thePoint, false );
790   return GetAltitudeForPoint( thePoint, aZone );
791 }
792
793 double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY&                    thePoint,
794                                                        const Handle(HYDROData_Region)& theRegion ) const
795 {
796   double aResAltitude = HYDROData_IAltitudeObject::GetInvalidAltitude();
797
798   Handle(HYDROData_Zone) aZone = GetZoneFromPoint( thePoint, false );
799   if ( !aZone.IsNull() )
800   {
801     //DEBTRACE("GetAltitudeForPoint Region " << theRegion->GetName().toStdString() << " Zone " << aZone->GetName().toStdString());
802     Handle(HYDROData_Region) aRefRegion = Handle(HYDROData_Region)::DownCast( aZone->GetFatherObject() );
803     if ( IsEqual( aRefRegion, theRegion ) )
804       aResAltitude = GetAltitudeForPoint( thePoint, aZone );
805     else
806       {
807         DEBTRACE("GetAltitudeForPoint Region " << aRefRegion->GetName().toStdString() << " Zone " << aZone->GetName().toStdString() << " ---------------------------");
808         aResAltitude = GetAltitudeForPoint( thePoint, aZone );
809       }
810   }
811   else
812     {
813       DEBTRACE(" --- GetAltitudeForPoint No Zone ---");
814     }
815
816   return aResAltitude;
817 }
818
819 double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY&                  thePoint,
820                                                        const Handle(HYDROData_Zone)& theZone ) const
821 {
822   //DEBTRACE("GetAltitudeForPoint Zone " << theZone->GetName().toStdString());
823   double aResAltitude = HYDROData_IAltitudeObject::GetInvalidAltitude();
824   if ( theZone.IsNull() )
825     return aResAltitude;
826
827   HYDROData_Zone::MergeType aZoneMergeType = theZone->GetMergeType();
828   if ( !theZone->IsMergingNeed() )
829   {
830     aZoneMergeType = HYDROData_Zone::Merge_UNKNOWN;
831   }
832   else if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
833   {
834     return aResAltitude;
835   }
836
837   HYDROData_IInterpolator* aZoneInterpolator = theZone->GetInterpolator();
838   if ( aZoneMergeType == HYDROData_Zone::Merge_Object )
839   {
840     Handle(HYDROData_IAltitudeObject) aMergeAltitude = 
841       Handle(HYDROData_IAltitudeObject)::DownCast( theZone->GetMergeObject() );
842     if ( !aMergeAltitude.IsNull() )
843     {
844       if ( aZoneInterpolator != NULL )
845       {
846         aZoneInterpolator->SetAltitudeObject( aMergeAltitude );
847         aResAltitude = aZoneInterpolator->GetAltitudeForPoint( thePoint );
848       }
849       else
850         aResAltitude = aMergeAltitude->GetAltitudeForPoint( thePoint );
851     }
852   }
853   else
854   {
855     HYDROData_SequenceOfObjects aZoneObjects = theZone->GetObjects();
856     HYDROData_SequenceOfObjects::Iterator anIter( aZoneObjects );
857     for ( ; anIter.More(); anIter.Next() )
858     {
859       Handle(HYDROData_Object) aZoneObj =
860         Handle(HYDROData_Object)::DownCast( anIter.Value() );
861       if ( aZoneObj.IsNull() )
862         continue;
863
864       Handle(HYDROData_IAltitudeObject) anObjAltitude = aZoneObj->GetAltitudeObject();
865       if ( anObjAltitude.IsNull() )
866         continue;
867
868       double aPointAltitude = 0.0;
869       if ( aZoneInterpolator != NULL )
870       {
871         aZoneInterpolator->SetAltitudeObject( anObjAltitude );
872         aPointAltitude = aZoneInterpolator->GetAltitudeForPoint( thePoint );
873       }
874       else
875         aPointAltitude = anObjAltitude->GetAltitudeForPoint( thePoint );
876
877       if ( ValuesEquals( aPointAltitude, HYDROData_IAltitudeObject::GetInvalidAltitude() ) )
878         continue;
879
880       if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
881       {
882         aResAltitude = aPointAltitude;
883         break;
884       }
885       else if ( aZoneMergeType == HYDROData_Zone::Merge_ZMIN )
886       {
887         if ( ValuesEquals( aResAltitude, HYDROData_IAltitudeObject::GetInvalidAltitude() ) ||
888              aResAltitude > aPointAltitude )
889         {
890           aResAltitude = aPointAltitude;
891         }
892       }
893       else if ( aZoneMergeType == HYDROData_Zone::Merge_ZMAX )
894       {
895         if ( ValuesEquals( aResAltitude, HYDROData_IAltitudeObject::GetInvalidAltitude() ) ||
896              aResAltitude < aPointAltitude )
897         {
898           aResAltitude = aPointAltitude;
899         }
900       }
901     }
902   }
903
904   return aResAltitude;
905 }
906
907 NCollection_Sequence<double> HYDROData_CalculationCase::GetAltitudesForPoints( 
908   const NCollection_Sequence<gp_XY>& thePoints,
909   const Handle(HYDROData_Region)&    theRegion ) const
910 {
911   //DEBTRACE("HYDROData_CalculationCase::GetAltitudesForPoints " << theRegion->GetName().toStdString());
912   NCollection_Sequence<double> aResSeq;
913
914   for ( int i = 1, n = thePoints.Length(); i <= n; ++i )
915   {
916     const gp_XY& thePnt = thePoints.Value( i );
917     
918     double anAltitude = GetAltitudeForPoint( thePnt, theRegion );
919     aResSeq.Append( anAltitude );
920   }
921
922   return aResSeq;
923 }
924
925 NCollection_Sequence<double> HYDROData_CalculationCase::GetAltitudesForPoints( 
926   const NCollection_Sequence<gp_XY>& thePoints,
927   const Handle(HYDROData_Zone)&      theZone ) const
928 {
929   NCollection_Sequence<double> aResSeq;
930
931   for ( int i = 1, n = thePoints.Length(); i <= n; ++i )
932   {
933     const gp_XY& thePnt = thePoints.Value( i );
934     
935     double anAltitude = GetAltitudeForPoint( thePnt, theZone );
936     aResSeq.Append( anAltitude );
937   }
938
939   return aResSeq;
940 }
941
942 double HYDROData_CalculationCase::GetStricklerCoefficientForPoint( const gp_XY& thePoint ) const
943 {
944     double aCoeff = 0;
945     Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
946     if ( !aDocument.IsNull() )
947         aCoeff = aDocument->GetDefaultStricklerCoefficient();
948
949     Handle(HYDROData_LandCover) aLandCover;
950     Handle(HYDROData_Zone) aZone = GetZoneFromPoint( thePoint, Standard_True );
951     if ( !aZone.IsNull() )
952     {
953         HYDROData_SequenceOfObjects anObjList = aZone->GetObjects();
954         if ( anObjList.Length() == 1 )
955             aLandCover = Handle(HYDROData_LandCover)::DownCast( anObjList.First() );
956         else
957             aLandCover = Handle(HYDROData_LandCover)::DownCast( aZone->GetMergeObject() );
958     }
959
960     if ( !aLandCover.IsNull() )
961     {
962         QString aType = aLandCover->GetStricklerType();
963         Handle(HYDROData_StricklerTable) aTable = GetStricklerTable();
964         if ( !aTable.IsNull() )
965         {
966             if ( aTable->GetTypes().contains( aType ) )
967                 aCoeff = aTable->Get( aType, aCoeff );
968         }
969     }
970
971     return aCoeff;
972 }
973
974 Handle(HYDROData_Region) HYDROData_CalculationCase::GetRegionFromPoint( const gp_XY& thePoint,
975                                                                         const bool theLandCover ) const
976 {
977   Handle(HYDROData_Region) aResRegion;
978
979   Handle(HYDROData_Zone) aZone = GetZoneFromPoint( thePoint, theLandCover );
980   if ( !aZone.IsNull() )
981     aResRegion = Handle(HYDROData_Region)::DownCast( aZone->GetFatherObject() );
982
983   return aResRegion;
984 }
985
986 Handle(HYDROData_Zone) HYDROData_CalculationCase::GetZoneFromPoint( const gp_XY& thePoint,
987                                                                     const bool theLandCover ) const
988 {
989   Handle(HYDROData_Zone) aResZone;
990
991   HYDROData_SequenceOfObjects aRegions = GetRegions( theLandCover );
992
993   HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
994   for ( ; anIter.More() && aResZone.IsNull(); anIter.Next() )
995   {
996     Handle(HYDROData_Region) aRegion =
997       Handle(HYDROData_Region)::DownCast( anIter.Value() );
998     if ( aRegion.IsNull() )
999       continue;
1000
1001     HYDROData_SequenceOfObjects aZones = aRegion->GetZones();
1002     HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
1003     for ( ; aZonesIter.More() && aResZone.IsNull(); aZonesIter.Next() )
1004     {
1005       Handle(HYDROData_Zone) aRegZone =
1006         Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
1007       if ( aRegZone.IsNull() )
1008         continue;
1009
1010       PointClassification aPointRelation = GetPointClassification( thePoint, aRegZone );
1011       if ( aPointRelation != POINT_OUT )
1012         aResZone = aRegZone; // We found the desired zone
1013     }
1014   }
1015
1016   return aResZone;
1017 }
1018
1019 HYDROData_CalculationCase::PointClassification HYDROData_CalculationCase::GetPointClassification(
1020   const gp_XY&                  thePoint,
1021   const Handle(HYDROData_Zone)& theZone ) const
1022 {
1023   PointClassification aRes = POINT_OUT;
1024   if ( theZone.IsNull() )
1025     return aRes;
1026
1027   TopoDS_Face aZoneFace = TopoDS::Face( theZone->GetShape() );
1028   if ( aZoneFace.IsNull() )
1029     return aRes;
1030 #ifdef DEB_CLASS2D      
1031           TopoDS_Compound aCmp;
1032       BRep_Builder aBB;
1033       aBB.MakeCompound(aCmp);
1034           aBB.Add(aCmp, aZoneFace);
1035           gp_Pnt aPnt (thePoint.X(), thePoint.Y(), 0.);
1036           BRepBuilderAPI_MakeVertex aMk(aPnt);
1037           aBB.Add(aCmp, aMk.Vertex());
1038           BRepTools::Write(aCmp, "FCL2d.brep");
1039 #endif  
1040   TopAbs_State State = HYDROData_Tool::ComputePointState(thePoint, aZoneFace);
1041   if (State == TopAbs_OUT)
1042     aRes =  POINT_OUT;
1043   else if(State == TopAbs_IN)
1044     aRes =  POINT_IN;
1045   else if(State == TopAbs_ON)
1046     aRes =  POINT_ON;
1047   return aRes;
1048 }
1049
1050 Handle(HYDROData_Region) HYDROData_CalculationCase::addNewRegion( const Handle(HYDROData_Document)& theDoc,
1051                                                                   const QString& thePrefixOrName,
1052                                                                   const bool theLandCover,
1053                                                                   bool isPrefix )
1054 {
1055   TDF_Label aNewLab = myLab.FindChild( theLandCover ? DataTag_ChildLandCoverRegion : DataTag_ChildRegion ).NewChild();
1056   int aTag = aNewLab.Tag();
1057
1058   Handle(HYDROData_Region) aNewRegion =
1059     Handle(HYDROData_Region)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_REGION ) );
1060   AddRegion( aNewRegion, theLandCover );
1061
1062   QString aRegionName = isPrefix ? HYDROData_Tool::GenerateObjectName( theDoc, thePrefixOrName ) : thePrefixOrName;
1063   aNewRegion->SetName( aRegionName );
1064
1065   return aNewRegion;
1066 }
1067
1068 Handle(HYDROData_SplittedShapesGroup) HYDROData_CalculationCase::addNewSplittedGroup( const QString& theName )
1069 {
1070   TDF_Label aNewLab = myLab.FindChild( DataTag_SplittedGroups ).NewChild();
1071
1072   Handle(HYDROData_SplittedShapesGroup) aNewGroup =
1073     Handle(HYDROData_SplittedShapesGroup)::DownCast( 
1074       HYDROData_Iterator::CreateObject( aNewLab, KIND_SPLITTED_GROUP ) );
1075   AddReferenceObject( aNewGroup, DataTag_SplittedGroups );
1076
1077   aNewGroup->SetName( theName );
1078
1079   return aNewGroup;
1080 }
1081
1082 QString HYDROData_CalculationCase::Export( int theStudyId ) const
1083 {
1084   GEOM::GEOM_Gen_var aGEOMEngine = HYDROData_GeomTool::GetGeomGen();
1085   SALOMEDS::Study_var aDSStudy = HYDROData_GeomTool::GetStudyByID( theStudyId );
1086   
1087   QString aGeomObjEntry, anErrorMsg;
1088   bool isOK = Export( aGEOMEngine, aDSStudy, aGeomObjEntry, anErrorMsg );
1089   return isOK ? aGeomObjEntry : QString();
1090 }
1091
1092 bool HYDROData_CalculationCase::Export( GEOM::GEOM_Gen_var  theGeomEngine,
1093                                         SALOMEDS::Study_ptr theStudy,
1094                                         QString& theGeomObjEntry,
1095                                         QString& theErrorMsg ) const
1096 {
1097   HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfGroupsDefs;
1098
1099   // Get groups definitions
1100   HYDROData_SequenceOfObjects aSplittedGroups = GetSplittedGroups();
1101
1102   HYDROData_SequenceOfObjects::Iterator anIter( aSplittedGroups );
1103   for ( ; anIter.More(); anIter.Next() )
1104   {
1105     // Get shapes group
1106     Handle(HYDROData_ShapesGroup) aGroup =
1107       Handle(HYDROData_ShapesGroup)::DownCast( anIter.Value() );
1108     if ( aGroup.IsNull() )
1109       continue;
1110
1111     HYDROData_ShapesGroup::GroupDefinition aGroupDef;
1112
1113     aGroupDef.Name = aGroup->GetName().toLatin1().constData();
1114     aGroup->GetShapes( aGroupDef.Shapes );
1115
1116     aSeqOfGroupsDefs.Append( aGroupDef );
1117   }
1118   
1119   // Get faces
1120   bool isAllNotSubmersible = true;
1121   TopTools_ListOfShape aFaces;
1122   HYDROData_SequenceOfObjects aCaseRegions = GetRegions( false );
1123   HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
1124   for ( ; aRegionIter.More(); aRegionIter.Next() )
1125   {
1126     Handle(HYDROData_Region) aRegion =
1127       Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
1128     if( aRegion.IsNull() || !aRegion->IsSubmersible() )
1129       continue;
1130     
1131     if ( isAllNotSubmersible )
1132       isAllNotSubmersible = false;
1133
1134     TopoDS_Shape aRegionShape = aRegion->GetShape( &aSeqOfGroupsDefs );
1135     aFaces.Append( aRegionShape );
1136   }
1137
1138   bool aRes = false;
1139
1140   if ( aCaseRegions.IsEmpty() ) {
1141     theErrorMsg = QString("the list of regions is empty.");
1142   } else if ( isAllNotSubmersible ) {
1143     theErrorMsg = QString("there are no submersible regions.");
1144   } else {
1145     aRes = Export( theGeomEngine, theStudy, aFaces, aSeqOfGroupsDefs, theGeomObjEntry );;
1146   }
1147
1148   return aRes;
1149 }
1150
1151 bool HYDROData_CalculationCase::Export( GEOM::GEOM_Gen_var                            theGeomEngine,
1152                                         SALOMEDS::Study_ptr                           theStudy,
1153                                         const TopTools_ListOfShape&                   theFaces,
1154                                         const HYDROData_ShapesGroup::SeqOfGroupsDefs& theGroupsDefs,
1155                                         QString& theGeomObjEntry ) const
1156 {
1157   // Sew faces
1158   BRepBuilderAPI_Sewing aSewing( Precision::Confusion() * 10.0 );
1159   aSewing.SetNonManifoldMode( Standard_False );
1160 #ifdef DEB_CALCULATION
1161   TCollection_AsciiString aNam("Sh_");
1162   int i=1;
1163 #endif
1164   TopTools_ListIteratorOfListOfShape aFaceIter( theFaces );
1165   for ( ; aFaceIter.More(); aFaceIter.Next() )
1166   {
1167     TopoDS_Shape aShape = aFaceIter.Value();
1168     if ( aShape.IsNull() )
1169       continue;
1170
1171     if ( aShape.ShapeType() == TopAbs_FACE )
1172     {
1173       aSewing.Add( aShape );
1174 #ifdef DEB_CALCULATION
1175       TCollection_AsciiString aName = aNam + ++i + ".brep";
1176       BRepTools::Write(aShape ,aName.ToCString());
1177 #endif
1178     }
1179     else
1180     {
1181 #ifdef DEB_CALCULATION
1182       int j = 1;
1183 #endif
1184       TopExp_Explorer anExp( aShape, TopAbs_FACE );
1185       for (; anExp.More(); anExp.Next() ) {
1186         aSewing.Add( anExp.Current() );
1187 #ifdef DEB_CALCULATION
1188
1189         TCollection_AsciiString aName = aNam + i + "_" + ++j + ".brep";
1190         BRepTools::Write(anExp.Current() ,aName.ToCString());
1191 #endif
1192       }
1193     }
1194   } // faces iterator
1195   
1196   aSewing.Perform();
1197   TopoDS_Shape aSewedShape = aSewing.SewedShape();
1198
1199   // If the sewed shape is empty - return false
1200   if ( aSewedShape.IsNull() || !TopoDS_Iterator( aSewedShape ).More() )
1201     return false;
1202
1203 #ifdef DEB_CALCULATION
1204   BRepTools::Write(aSewedShape ,"Sew.brep");
1205 #endif
1206   // Publish the sewed shape
1207   QString aName = EXPORT_NAME;
1208   GEOM::GEOM_Object_ptr aMainShape = 
1209     HYDROData_GeomTool::publishShapeInGEOM( theGeomEngine, theStudy, aSewedShape, aName, theGeomObjEntry );
1210
1211   if ( aMainShape->_is_nil() )  
1212     return false;
1213
1214   if ( theGroupsDefs.IsEmpty() )
1215     return true;
1216
1217   // Create groups
1218   TopTools_IndexedMapOfShape aMapOfSubShapes;
1219   TopExp::MapShapes( aSewedShape, aMapOfSubShapes );
1220
1221   NCollection_DataMap< TCollection_AsciiString, NCollection_Sequence<int> > aGroupsData;
1222
1223   for ( int aGrId = 1, nbGroups = theGroupsDefs.Length(); aGrId <= nbGroups; ++aGrId )
1224   {
1225     const HYDROData_ShapesGroup::GroupDefinition& aGroupDef = theGroupsDefs.Value( aGrId );
1226
1227     NCollection_Sequence<int> aGroupIndexes;
1228     for( int i = 1, n = aGroupDef.Shapes.Length(); i <= n; i++ )
1229     {
1230       const TopoDS_Shape& aShape = aGroupDef.Shapes.Value( i );
1231 #ifdef DEB_CALCULATION
1232       cout << "\nOld shape(" << i << ") = " << aShape.TShape() <<endl;
1233 #endif
1234       
1235       TopoDS_Shape aModifiedShape = aShape;
1236       if ( aSewing.IsModified( aShape ) )
1237         aModifiedShape = aSewing.Modified( aShape );
1238       else if ( aSewing.IsModifiedSubShape( aShape ) )
1239         aModifiedShape = aSewing.ModifiedSubShape( aShape );
1240
1241 #ifdef DEB_CALCULATION
1242       const TopLoc_Location& aL1 = aShape.Location();
1243       const TopLoc_Location& aL2 = aModifiedShape.Location();
1244       cout << "\nNew shape(" << i << ") = " << aModifiedShape.TShape() << " Location is Equal = " << aL1.IsEqual(aL2)<<endl;
1245 #endif
1246
1247       int anIndex = aMapOfSubShapes.FindIndex(aModifiedShape);
1248       if ( anIndex > 0 ) {
1249         aGroupIndexes.Append( anIndex );
1250       } else {
1251 #ifdef DEB_CALCULATION    
1252         TCollection_AsciiString aNam("Lost_");
1253         if(!aMapOfSubShapes.Contains(aModifiedShape)) {
1254         for ( int anIndex = 1; anIndex <= aMapOfSubShapes.Extent(); anIndex++ )
1255         {
1256            const TopoDS_Shape& aS = aMapOfSubShapes.FindKey( anIndex );
1257            if ( aModifiedShape.IsPartner( aS ) )
1258            {
1259              cout <<"\nIndex in Map = " << anIndex << "TShape = " << aS.TShape() <<endl;
1260              TCollection_AsciiString aName = aNam + i + "_" + anIndex + ".brep";
1261              BRepTools::Write(aS ,aName.ToCString());
1262             break;
1263            }
1264          }
1265         }
1266 #endif
1267       }
1268     }
1269     if ( !aGroupIndexes.IsEmpty() )
1270       aGroupsData.Bind( aGroupDef.Name, aGroupIndexes );
1271   }
1272  
1273   if ( !aGroupsData.IsEmpty() )
1274   {
1275     GEOM::GEOM_IGroupOperations_var aGroupOp = 
1276       theGeomEngine->GetIGroupOperations( theStudy->StudyId() );  
1277
1278     NCollection_DataMap< TCollection_AsciiString, NCollection_Sequence<int> >::Iterator aMapIt( aGroupsData );
1279     for ( ; aMapIt.More(); aMapIt.Next() )
1280     {
1281       const TCollection_AsciiString& aGroupName = aMapIt.Key(); 
1282       const NCollection_Sequence<int>& aGroupIndexes = aMapIt.Value();
1283
1284       GEOM::GEOM_Object_var aGeomGroup = aGroupOp->CreateGroup( aMainShape, TopAbs_EDGE );
1285       if ( CORBA::is_nil( aGeomGroup ) || !aGroupOp->IsDone() )
1286         continue;
1287
1288       GEOM::ListOfLong_var aGeomIndexes = new GEOM::ListOfLong;
1289       aGeomIndexes->length( aGroupIndexes.Length() );
1290
1291       for( int i = 1, n = aGroupIndexes.Length(); i <= n; i++ )
1292         aGeomIndexes[ i - 1 ] = aGroupIndexes.Value( i );
1293
1294       aGroupOp->UnionIDs( aGeomGroup, aGeomIndexes );
1295       if ( aGroupOp->IsDone() )
1296       {
1297         SALOMEDS::SObject_var aGroupSO = 
1298           theGeomEngine->AddInStudy( theStudy, aGeomGroup, aGroupName.ToCString(), aMainShape );
1299       }
1300     }
1301   }
1302
1303   return true;
1304 }
1305
1306 void HYDROData_CalculationCase::ClearRules( HYDROData_CalculationCase::DataTag theDataTag,
1307                                             const bool theIsSetToUpdate )
1308 {
1309   TDF_Label aRulesLab = myLab.FindChild( theDataTag );
1310   HYDROData_PriorityQueue::ClearRules( aRulesLab );
1311
1312   // Indicate model of the need to update splitting
1313   if ( theIsSetToUpdate ) {
1314     SetToUpdate( true );
1315   }
1316 }
1317
1318 void HYDROData_CalculationCase::AddRule( const Handle(HYDROData_Entity)&    theObject1,
1319                                          HYDROData_PriorityType             thePriority,
1320                                          const Handle(HYDROData_Entity)&    theObject2,
1321                                          HYDROData_Zone::MergeType          theMergeType,
1322                                          HYDROData_CalculationCase::DataTag theDataTag )
1323 {
1324   TDF_Label aRulesLab = myLab.FindChild( theDataTag );
1325   HYDROData_PriorityQueue::AddRule( aRulesLab, theObject1, thePriority, theObject2, theMergeType );
1326
1327   // Indicate model of the need to update splitting
1328   SetToUpdate( true );
1329 }
1330
1331 QString HYDROData_CalculationCase::DumpRules() const
1332 {
1333   TDF_Label aRulesLab = myLab.FindChild( DataTag_CustomRules );
1334   return HYDROData_PriorityQueue::DumpRules( aRulesLab );
1335 }
1336
1337 QString HYDROData_CalculationCase::DumpLandCoverRules() const
1338 {
1339   TDF_Label aRulesLab = myLab.FindChild( DataTag_CustomLandCoverRules );
1340   return HYDROData_PriorityQueue::DumpRules( aRulesLab );
1341 }
1342
1343 void HYDROData_CalculationCase::SetAssignmentMode( AssignmentMode theMode )
1344 {
1345   TDF_Label aModeLab = myLab.FindChild( DataTag_AssignmentMode );
1346   TDataStd_Integer::Set( aModeLab, ( int ) theMode );
1347
1348   // Indicate model of the need to update splitting
1349   SetToUpdate( true );
1350 }
1351
1352 HYDROData_CalculationCase::AssignmentMode HYDROData_CalculationCase::GetAssignmentMode() const
1353 {
1354   Handle(TDataStd_Integer) aModeAttr;
1355   bool isOK = myLab.FindChild( DataTag_AssignmentMode ).FindAttribute( TDataStd_Integer::GetID(), aModeAttr );
1356   if( isOK )
1357     return ( AssignmentMode ) aModeAttr->Get();
1358   else
1359     return MANUAL;
1360 }
1361
1362 void HYDROData_CalculationCase::DumpRulesToPython( const QString& theCalcCaseName,
1363                                                    QStringList& theScript ) const
1364 {
1365   TDF_Label aRulesLab = myLab.FindChild( DataTag_CustomRules );
1366   HYDROData_PriorityQueue::DumpRulesToPython( aRulesLab, theCalcCaseName, theScript );
1367 }
1368
1369 void HYDROData_CalculationCase::DumpLandCoverRulesToPython( const QString& theCalcCaseName,
1370                                                             QStringList& theScript ) const
1371 {
1372   TDF_Label aRulesLab = myLab.FindChild( DataTag_CustomLandCoverRules );
1373   HYDROData_PriorityQueue::DumpRulesToPython( aRulesLab, theCalcCaseName, theScript );
1374 }
1375
1376 HYDROData_Warning HYDROData_CalculationCase::GetLastWarning() const
1377 {
1378   return myLastWarning;
1379 }
1380
1381 void HYDROData_CalculationCase::SetWarning( HYDROData_WarningType theType, const QString& theData )
1382 {
1383   myLastWarning.Type = theType;
1384   myLastWarning.Data = theData;
1385 }
1386
1387 void HYDROData_CalculationCase::UpdateRegionsNames( const HYDROData_SequenceOfObjects& theRegions,
1388                                                     const QString& theOldCaseName,
1389                                                     const QString& theName )
1390 {
1391   HYDROData_SequenceOfObjects::Iterator anIter( theRegions );
1392   for ( ; anIter.More(); anIter.Next() )
1393   {
1394     Handle(HYDROData_Region) aRegion =
1395       Handle(HYDROData_Region)::DownCast( anIter.Value() );
1396     if ( aRegion.IsNull() )
1397       continue;
1398
1399     HYDROData_Tool::UpdateChildObjectName( theOldCaseName, theName, aRegion );
1400
1401     HYDROData_SequenceOfObjects aZones = aRegion->GetZones();
1402     HYDROData_SequenceOfObjects::Iterator anIter( aZones );
1403     for ( ; anIter.More(); anIter.Next() )
1404     {
1405       Handle(HYDROData_Zone) aRegZone =
1406         Handle(HYDROData_Zone)::DownCast( anIter.Value() );
1407       if ( aRegZone.IsNull() )
1408         continue;
1409
1410       HYDROData_Tool::UpdateChildObjectName( theOldCaseName, theName, aRegZone );
1411     }
1412   }
1413 }
1414
1415 void HYDROData_CalculationCase::DumpRegionsToPython( QStringList& theResList,
1416                                                      MapOfTreatedObjects& theTreatedObjects,
1417                                                      const HYDROData_SequenceOfObjects& theRegions ) const
1418 {
1419   HYDROData_SequenceOfObjects::Iterator anIter;
1420   anIter.Init( theRegions );
1421   for ( ; anIter.More(); anIter.Next() )
1422   {
1423     Handle(HYDROData_Region) aRegion =
1424       Handle(HYDROData_Region)::DownCast( anIter.Value() );
1425     if ( aRegion.IsNull() )
1426       continue;
1427
1428     theTreatedObjects.insert( aRegion->GetName(), aRegion );
1429     QStringList aRegDump = aRegion->DumpToPython( theTreatedObjects );
1430     theResList << aRegDump;
1431   }
1432 }
1433
1434 bool HYDROData_CalculationCase::GetRule( int theIndex, 
1435                                          Handle(HYDROData_Entity)&           theObject1,
1436                                          HYDROData_PriorityType&             thePriority,
1437                                          Handle(HYDROData_Entity)&           theObject2,
1438                                          HYDROData_Zone::MergeType&          theMergeType,
1439                                          HYDROData_CalculationCase::DataTag& theDataTag) const
1440 {
1441   TDF_Label aRulesLab = myLab.FindChild( theDataTag );
1442   return HYDROData_PriorityQueue::GetRule( aRulesLab, theIndex,
1443     theObject1, thePriority, theObject2, theMergeType );
1444 }
1445
1446 void HYDROData_CalculationCase::SetAssignmentLandCoverMode( AssignmentMode theMode )
1447 {
1448   TDF_Label aModeLab = myLab.FindChild( DataTag_AssignmentLandCoverMode );
1449   TDataStd_Integer::Set( aModeLab, ( int ) theMode );
1450
1451   // Indicate model of the need to update land covers partition
1452   SetToUpdate( true );
1453 }
1454
1455 HYDROData_CalculationCase::AssignmentMode HYDROData_CalculationCase::GetAssignmentLandCoverMode() const
1456 {
1457   Handle(TDataStd_Integer) aModeAttr;
1458   bool isOK = myLab.FindChild( DataTag_AssignmentLandCoverMode ).FindAttribute( TDataStd_Integer::GetID(), aModeAttr );
1459   if( isOK )
1460     return ( AssignmentMode ) aModeAttr->Get();
1461   else
1462     return MANUAL;
1463 }