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