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