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