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