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