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