]> SALOME platform Git repositories - modules/hydro.git/blob - src/HYDROData/HYDROData_CalculationCase.cxx
Salome HOME
15.01.2014. Fix for bug of GroupDef edges.
[modules/hydro.git] / src / HYDROData / HYDROData_CalculationCase.cxx
1
2 #include "HYDROData_CalculationCase.h"
3
4 #include "HYDROData_ArtificialObject.h"
5 #include "HYDROData_IAltitudeObject.h"
6 #include "HYDROData_Document.h"
7 #include "HYDROData_ShapesGroup.h"
8 #include "HYDROData_Iterator.h"
9 #include "HYDROData_NaturalObject.h"
10 #include "HYDROData_PolylineXY.h"
11 #include "HYDROData_SplitToZonesTool.h"
12 #include "HYDROData_SplittedShapesGroup.h"
13 #include "HYDROData_Region.h"
14 #include "HYDROData_Tool.h"
15 #include "HYDROData_Zone.h"
16
17 #include <GEOMBase.h>
18
19 #include <QSet>
20
21 #include <TopoDS.hxx>
22 #include <TopoDS_Shell.hxx>
23 #include <TopoDS_Edge.hxx>
24
25 #include <BRep_Builder.hxx>
26 #include <BRepBuilderAPI_Sewing.hxx>
27 #include <BRepTopAdaptor_FClass2d.hxx>
28
29 #include <BRepTools.hxx>
30
31 #include <TopAbs.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <TopExp.hxx>
34 #include <TopTools_ListOfShape.hxx>
35 #include <TopTools_ListIteratorOfListOfShape.hxx>
36
37 //#define  DEB_CALCULATION 1
38 #ifdef DEB_CALCULATION
39 #include <BRepTools.hxx>
40 #include <TopLoc_Location.hxx>
41 #endif 
42 #define CALCULATION_REGIONS_PREF GetName() + "_Reg"
43 #define CALCULATION_ZONES_PREF GetName() + "_Zone"
44 #define CALCULATION_GROUPS_PREF GetName() + "_"
45
46 #define EXPORT_NAME "HYDRO_" + GetName()
47
48 IMPLEMENT_STANDARD_HANDLE(HYDROData_CalculationCase, HYDROData_Entity)
49 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_CalculationCase, HYDROData_Entity)
50
51 HYDROData_CalculationCase::HYDROData_CalculationCase()
52 : HYDROData_Entity()
53 {
54 }
55
56 HYDROData_CalculationCase::~HYDROData_CalculationCase()
57 {
58 }
59
60 void HYDROData_CalculationCase::SetName( const QString& theName )
61 {
62   QString anOldCaseName = GetName();
63   if ( anOldCaseName != theName )
64   {
65     HYDROData_SequenceOfObjects aRegions = GetRegions();
66
67     HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
68     for ( ; anIter.More(); anIter.Next() )
69     {
70       Handle(HYDROData_Region) aRegion =
71         Handle(HYDROData_Region)::DownCast( anIter.Value() );
72       if ( aRegion.IsNull() )
73         continue;
74
75       HYDROData_Tool::UpdateChildObjectName( anOldCaseName, theName, aRegion );
76
77       HYDROData_SequenceOfObjects aZones = aRegion->GetZones();
78       HYDROData_SequenceOfObjects::Iterator anIter( aZones );
79       for ( ; anIter.More(); anIter.Next() )
80       {
81         Handle(HYDROData_Zone) aRegZone =
82           Handle(HYDROData_Zone)::DownCast( anIter.Value() );
83         if ( aRegZone.IsNull() )
84           continue;
85
86         HYDROData_Tool::UpdateChildObjectName( anOldCaseName, theName, aRegZone );
87       }
88     }
89
90     HYDROData_SequenceOfObjects aGroups = GetGeometryGroups();
91
92     anIter.Init( aGroups );
93     for ( ; anIter.More(); anIter.Next() )
94     {
95       Handle(HYDROData_SplittedShapesGroup) aGroup =
96         Handle(HYDROData_SplittedShapesGroup)::DownCast( anIter.Value() );
97       if ( aGroup.IsNull() )
98         continue;
99
100       HYDROData_Tool::UpdateChildObjectName( anOldCaseName, theName, aGroup );
101     }
102   }
103
104   HYDROData_Entity::SetName( theName );
105 }
106
107 QStringList HYDROData_CalculationCase::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
108 {
109   QStringList aResList = dumpObjectCreation( theTreatedObjects );
110   QString aCalculName = GetName();
111
112   HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects();
113   HYDROData_SequenceOfObjects::Iterator anIter( aGeomObjects );
114   for ( ; anIter.More(); anIter.Next() )
115   {
116     Handle(HYDROData_Object) aRefGeomObj =
117       Handle(HYDROData_Object)::DownCast( anIter.Value() );
118     if ( !aRefGeomObj.IsNull() )
119       setPythonReferenceObject( theTreatedObjects, aResList, aRefGeomObj, "AddGeometryObject" );
120   }
121   aResList << QString( "" );
122
123   aResList << QString( "%1.SplitGeometryObjects();" ).arg( aCalculName );
124   aResList << QString( "" );
125
126   // Now we restore the regions and zones order
127   HYDROData_SequenceOfObjects aRegions = GetRegions();
128   anIter.Init( aRegions );
129   for ( ; anIter.More(); anIter.Next() )
130   {
131     Handle(HYDROData_Region) aRegion =
132       Handle(HYDROData_Region)::DownCast( anIter.Value() );
133     if ( aRegion.IsNull() )
134       continue;
135
136     QString aRegionName = aRegion->GetName();
137     // TODO
138   }
139
140   return aResList;
141 }
142
143 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetAllReferenceObjects() const
144 {
145   HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
146
147   Handle(HYDROData_PolylineXY) aBoundaryPolyline = GetBoundaryPolyline();
148   if ( !aBoundaryPolyline.IsNull() )
149     aResSeq.Append( aBoundaryPolyline );
150
151   HYDROData_SequenceOfObjects aSeqOfRegions = GetRegions();
152   aResSeq.Append( aSeqOfRegions );
153
154   return aResSeq;
155 }
156
157 void HYDROData_CalculationCase::Update()
158 {
159   HYDROData_Entity::Update();
160
161   // At first we remove previously created objects
162   RemoveRegions();
163   RemoveSplittedGroups();
164
165   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
166   if ( aDocument.IsNull() )
167     return;
168
169   Handle(HYDROData_PolylineXY) aBoundaryPolyline = GetBoundaryPolyline();
170   HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects();
171   if ( aGeomObjects.IsEmpty() )
172     return;
173
174   HYDROData_SequenceOfObjects aGeomGroups = GetGeometryGroups();
175
176   HYDROData_SplitToZonesTool::SplitDataList aSplitedObjects =
177     HYDROData_SplitToZonesTool::Split( aGeomObjects, aGeomGroups, aBoundaryPolyline );
178   if ( aSplitedObjects.isEmpty() )
179     return;
180
181   QString aRegsPref = CALCULATION_REGIONS_PREF;
182   QString aZonesPref = CALCULATION_ZONES_PREF;
183
184   QMap<QString,Handle(HYDROData_SplittedShapesGroup)> aSplittedEdgesGroupsMap;
185
186   // Create result regions for case, by default one zone for one region
187   HYDROData_SplitToZonesTool::SplitDataListIterator anIter( aSplitedObjects );
188   while( anIter.hasNext() )
189   {
190     const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next();
191
192     if ( aSplitData.Type == HYDROData_SplitToZonesTool::SplitData::Data_Zone )
193     {
194       // Create new region
195       Handle(HYDROData_Region) aRegion = addNewRegion();
196
197       QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
198       aRegion->SetName( aRegionName );
199
200       // Add the zone for region
201       Handle(HYDROData_Zone) aRegionZone = aRegion->addNewZone();
202
203       QString aZoneName = HYDROData_Tool::GenerateObjectName( aDocument, aZonesPref );
204       aRegionZone->SetName( aZoneName );
205
206       aRegionZone->SetShape( aSplitData.Face() );
207
208       // Add the reference object for zone
209       for ( int i = 0, n = aSplitData.ObjectNames.length(); i < n; ++i )
210       {
211         const QString& anObjName = aSplitData.ObjectNames.at( i );
212         
213         Handle(HYDROData_Object) aRefObject = Handle(HYDROData_Object)::DownCast(
214           HYDROData_Tool::FindObjectByName( aDocument, anObjName ) );
215         if ( aRefObject.IsNull() )
216           continue;
217
218         aRegionZone->AddGeometryObject( aRefObject );
219       }
220     }
221     else if ( aSplitData.Type == HYDROData_SplitToZonesTool::SplitData::Data_Edge )
222     {
223       // Create new edges group
224       if ( aSplitData.ObjectNames.isEmpty() || aSplitData.Shape.IsNull() )
225         continue;
226
227       QString anObjName = aSplitData.ObjectNames.first();
228       if ( anObjName.isEmpty() )
229         continue;
230
231       Handle(HYDROData_SplittedShapesGroup) aSplittedGroup;
232       if ( !aSplittedEdgesGroupsMap.contains( anObjName ) )
233       {
234         aSplittedGroup = addNewSplittedGroup();
235
236         QString aCalcGroupName = CALCULATION_GROUPS_PREF + anObjName;
237         aSplittedGroup->SetName( aCalcGroupName );
238
239         aSplittedEdgesGroupsMap.insert( anObjName, aSplittedGroup );
240       }
241       else
242       {
243         aSplittedGroup = aSplittedEdgesGroupsMap[ anObjName ];
244       }
245
246       if ( aSplittedGroup.IsNull() )
247         continue;
248
249       aSplittedGroup->AddShape( aSplitData.Shape );
250     }
251   }
252 }
253
254 bool HYDROData_CalculationCase::AddGeometryObject( const Handle(HYDROData_Object)& theObject )
255 {
256   if ( !HYDROData_Tool::IsGeometryObject( theObject ) )
257     return false; // Wrong type of object
258
259   if ( HasReference( theObject, DataTag_GeometryObject ) )
260     return false; // Object is already in reference list
261
262   AddReferenceObject( theObject, DataTag_GeometryObject );
263   
264   // Indicate model of the need to update splitting
265   SetToUpdate( true );
266
267   return true;
268 }
269
270 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetGeometryObjects() const
271 {
272   return GetReferenceObjects( DataTag_GeometryObject );
273 }
274
275 void HYDROData_CalculationCase::RemoveGeometryObject( const Handle(HYDROData_Object)& theObject )
276 {
277   if ( theObject.IsNull() )
278     return;
279
280   RemoveReferenceObject( theObject->Label(), DataTag_GeometryObject );
281
282   // Indicate model of the need to update splitting
283   SetToUpdate( true );
284 }
285
286 void HYDROData_CalculationCase::RemoveGeometryObjects()
287 {
288   ClearReferenceObjects( DataTag_GeometryObject );
289
290   // Indicate model of the need to update splitting
291   SetToUpdate( true );
292 }
293
294 bool HYDROData_CalculationCase::AddGeometryGroup( const Handle(HYDROData_ShapesGroup)& theGroup )
295 {
296   if ( theGroup.IsNull() )
297     return false;
298
299   if ( HasReference( theGroup, DataTag_GeometryGroup ) )
300     return false; // Object is already in reference list
301
302   AddReferenceObject( theGroup, DataTag_GeometryGroup );
303   
304   // Indicate model of the need to update splitting
305   SetToUpdate( true );
306
307   return true;
308 }
309
310 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetGeometryGroups() const
311 {
312   return GetReferenceObjects( DataTag_GeometryGroup );
313 }
314
315 void HYDROData_CalculationCase::RemoveGeometryGroup( const Handle(HYDROData_ShapesGroup)& theGroup )
316 {
317   if ( theGroup.IsNull() )
318     return;
319
320   RemoveReferenceObject( theGroup->Label(), DataTag_GeometryGroup );
321
322   // Indicate model of the need to update splitting
323   SetToUpdate( true );
324 }
325
326 void HYDROData_CalculationCase::RemoveGeometryGroups()
327 {
328   ClearReferenceObjects( DataTag_GeometryGroup );
329
330   // Indicate model of the need to update splitting
331   SetToUpdate( true );
332 }
333
334 void HYDROData_CalculationCase::SetBoundaryPolyline( const Handle(HYDROData_PolylineXY)& thePolyline )
335 {
336   Handle(HYDROData_PolylineXY) aPrevPolyline = GetBoundaryPolyline();
337
338   SetReferenceObject( thePolyline, DataTag_Polyline );
339
340   // Indicate model of the need to update zones splitting
341   SetToUpdate( !IsEqual( aPrevPolyline, thePolyline ) || IsMustBeUpdated() );
342 }
343
344 Handle(HYDROData_PolylineXY) HYDROData_CalculationCase::GetBoundaryPolyline() const
345 {
346   return Handle(HYDROData_PolylineXY)::DownCast( 
347            GetReferenceObject( DataTag_Polyline ) );
348 }
349
350 void HYDROData_CalculationCase::RemoveBoundaryPolyline()
351 {
352   Handle(HYDROData_PolylineXY) aPrevPolyline = GetBoundaryPolyline();
353
354   ClearReferenceObjects( DataTag_Polyline );
355
356   // Indicate model of the need to update zones splitting
357   SetToUpdate( !aPrevPolyline.IsNull() || IsMustBeUpdated() );
358 }
359
360 Handle(HYDROData_Region) HYDROData_CalculationCase::AddNewRegion( const Handle(HYDROData_Zone)& theZone )
361 {
362   Handle(HYDROData_Region) aNewRegion = addNewRegion();
363   if ( aNewRegion.IsNull() )
364     return aNewRegion;
365
366   // Generate new name for new region
367   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
368   if ( !aDocument.IsNull() )
369   {
370     QString aRegsPref = CALCULATION_REGIONS_PREF;
371
372     QString aNewRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
373     aNewRegion->SetName( aNewRegionName );
374   }
375
376   aNewRegion->AddZone( theZone );
377
378   return aNewRegion;
379 }
380
381 bool HYDROData_CalculationCase::AddRegion( const Handle(HYDROData_Region)& theRegion )
382 {
383   if ( theRegion.IsNull() )
384     return false;
385   
386   if ( HasReference( theRegion, DataTag_Region ) )
387     return false; // Object is already in reference list
388
389   // Move the region from other calculation
390   Handle(HYDROData_CalculationCase) aFatherCalc = 
391     Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
392   if ( !aFatherCalc.IsNull() && aFatherCalc->Label() != myLab )
393   {
394     Handle(HYDROData_Region) aNewRegion = addNewRegion();
395     theRegion->CopyTo( aNewRegion );
396
397     aFatherCalc->RemoveRegion( theRegion );
398
399     theRegion->SetLabel( aNewRegion->Label() );
400   }
401   else
402   {
403     AddReferenceObject( theRegion, DataTag_Region );
404   }
405
406   return true;
407 }
408
409 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetRegions() const
410 {
411   return GetReferenceObjects( DataTag_Region );
412 }
413
414 void HYDROData_CalculationCase::UpdateRegionsOrder()
415 {
416   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
417   if ( aDocument.IsNull() )
418     return;
419
420   HYDROData_SequenceOfObjects aRegions = GetRegions();
421
422   HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
423   for ( ; anIter.More(); anIter.Next() )
424   {
425     Handle(HYDROData_Region) aRegion =
426       Handle(HYDROData_Region)::DownCast( anIter.Value() );
427     if ( aRegion.IsNull() )
428       continue;
429
430     aRegion->SetName( "" );
431   }
432
433   QString aRegsPref = CALCULATION_REGIONS_PREF;
434
435   anIter.Init( aRegions );
436   for ( ; anIter.More(); anIter.Next() )
437   {
438     Handle(HYDROData_Region) aRegion =
439       Handle(HYDROData_Region)::DownCast( anIter.Value() );
440     if ( aRegion.IsNull() )
441       continue;
442
443     QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
444     aRegion->SetName( aRegionName );
445   }
446 }
447
448 void HYDROData_CalculationCase::RemoveRegion( const Handle(HYDROData_Region)& theRegion )
449 {
450   if ( theRegion.IsNull() )
451     return;
452
453   RemoveReferenceObject( theRegion->Label(), DataTag_Region );
454
455   // Remove region from data model
456   Handle(HYDROData_CalculationCase) aFatherCalc = 
457     Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
458   if ( !aFatherCalc.IsNull() && aFatherCalc->Label() == myLab )
459     theRegion->Remove();
460 }
461
462 void HYDROData_CalculationCase::RemoveRegions()
463 {
464   myLab.FindChild( DataTag_ChildRegion ).ForgetAllAttributes();
465 }
466
467 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetSplittedGroups() const
468 {
469   return GetReferenceObjects( DataTag_SplittedGroups );
470 }
471
472 void HYDROData_CalculationCase::RemoveSplittedGroups()
473 {
474   myLab.FindChild( DataTag_SplittedGroups ).ForgetAllAttributes();
475 }
476
477 double HYDROData_CalculationCase::GetAltitudeForPoint( const gp_XY& thePoint ) const
478 {
479   double aResAltitude = HYDROData_IAltitudeObject::GetInvalidAltitude();
480
481   Handle(HYDROData_Zone) aZone = GetZoneFromPoint( thePoint );
482   if ( aZone.IsNull() )
483     return aResAltitude;
484
485   HYDROData_Zone::MergeAltitudesType aZoneMergeType = aZone->GetMergeType();
486   if ( !aZone->IsMergingNeed() )
487   {
488     aZoneMergeType = HYDROData_Zone::Merge_UNKNOWN;
489   }
490   else if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
491   {
492     return aResAltitude;
493   }
494
495   if ( aZoneMergeType == HYDROData_Zone::Merge_Object )
496   {
497     Handle(HYDROData_IAltitudeObject) aMergeAltitude = aZone->GetMergeAltitude();
498     if ( !aMergeAltitude.IsNull() )
499       aResAltitude = aMergeAltitude->GetAltitudeForPoint( thePoint );
500   }
501   else
502   {
503     HYDROData_SequenceOfObjects aZoneObjects = aZone->GetGeometryObjects();
504     HYDROData_SequenceOfObjects::Iterator anIter( aZoneObjects );
505     for ( ; anIter.More(); anIter.Next() )
506     {
507       Handle(HYDROData_Object) aZoneObj =
508         Handle(HYDROData_Object)::DownCast( anIter.Value() );
509       if ( aZoneObj.IsNull() )
510         continue;
511
512       Handle(HYDROData_IAltitudeObject) anObjAltitude = aZoneObj->GetAltitudeObject();
513       if ( anObjAltitude.IsNull() )
514         continue;
515
516       double aPointAltitude = anObjAltitude->GetAltitudeForPoint( thePoint );
517       if ( ValuesEquals( aPointAltitude, HYDROData_IAltitudeObject::GetInvalidAltitude() ) )
518         continue;
519
520       if ( aZoneMergeType == HYDROData_Zone::Merge_UNKNOWN )
521       {
522         aResAltitude = aPointAltitude;
523         break;
524       }
525       else if ( aZoneMergeType == HYDROData_Zone::Merge_ZMIN )
526       {
527         if ( ValuesEquals( aResAltitude, HYDROData_IAltitudeObject::GetInvalidAltitude() ) ||
528              aResAltitude > aPointAltitude )
529         {
530           aResAltitude = aPointAltitude;
531         }
532       }
533       else if ( aZoneMergeType == HYDROData_Zone::Merge_ZMAX )
534       {
535         if ( ValuesEquals( aResAltitude, HYDROData_IAltitudeObject::GetInvalidAltitude() ) ||
536              aResAltitude < aPointAltitude )
537         {
538           aResAltitude = aPointAltitude;
539         }
540       }
541     }
542   }
543
544   return aResAltitude;
545 }
546
547 Handle(HYDROData_Zone) HYDROData_CalculationCase::GetZoneFromPoint( const gp_XY& thePoint ) const
548 {
549   Handle(HYDROData_Zone) aResZone;
550
551   HYDROData_SequenceOfObjects aRegions = GetRegions();
552
553   HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
554   for ( ; anIter.More() && aResZone.IsNull(); anIter.Next() )
555   {
556     Handle(HYDROData_Region) aRegion =
557       Handle(HYDROData_Region)::DownCast( anIter.Value() );
558     if ( aRegion.IsNull() )
559       continue;
560
561     HYDROData_SequenceOfObjects aZones = aRegion->GetZones();
562     HYDROData_SequenceOfObjects::Iterator aZonesIter( aZones );
563     for ( ; aZonesIter.More() && aResZone.IsNull(); aZonesIter.Next() )
564     {
565       Handle(HYDROData_Zone) aRegZone =
566         Handle(HYDROData_Zone)::DownCast( aZonesIter.Value() );
567       if ( aRegZone.IsNull() )
568         continue;
569
570       PointClassification aPointRelation = GetPointClassification( thePoint, aRegZone );
571       if ( aPointRelation != POINT_OUT )
572         aResZone = aRegZone; // We found the desired zone
573     }
574   }
575
576   return aResZone;
577 }
578
579 HYDROData_CalculationCase::PointClassification HYDROData_CalculationCase::GetPointClassification(
580   const gp_XY&                  thePoint,
581   const Handle(HYDROData_Zone)& theZone ) const
582 {
583   PointClassification aRes = POINT_OUT;
584   if ( theZone.IsNull() )
585     return aRes;
586
587   TopoDS_Face aZoneFace = TopoDS::Face( theZone->GetShape() );
588   if ( aZoneFace.IsNull() )
589     return aRes;
590
591   BRepTopAdaptor_FClass2d aClassifier( aZoneFace, Precision::Confusion() );
592   TopAbs_State State = aClassifier.Perform( gp_Pnt2d(thePoint), Standard_False );
593   if (State == TopAbs_OUT)
594         aRes =  POINT_OUT;
595   else if(State == TopAbs_IN)
596     aRes =  POINT_IN;
597   else if(State == TopAbs_ON)
598     aRes =  POINT_ON;     
599   return aRes;
600 }
601
602 Handle(HYDROData_Region) HYDROData_CalculationCase::addNewRegion()
603 {
604   TDF_Label aNewLab = myLab.FindChild( DataTag_ChildRegion ).NewChild();
605
606   Handle(HYDROData_Region) aNewRegion =
607     Handle(HYDROData_Region)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_REGION ) );
608   AddRegion( aNewRegion );
609
610   return aNewRegion;
611 }
612
613 Handle(HYDROData_SplittedShapesGroup) HYDROData_CalculationCase::addNewSplittedGroup()
614 {
615   TDF_Label aNewLab = myLab.FindChild( DataTag_SplittedGroups ).NewChild();
616
617   Handle(HYDROData_SplittedShapesGroup) aNewGroup =
618     Handle(HYDROData_SplittedShapesGroup)::DownCast( 
619       HYDROData_Iterator::CreateObject( aNewLab, KIND_SPLITTED_GROUP ) );
620   AddReferenceObject( aNewGroup, DataTag_SplittedGroups );
621
622   return aNewGroup;
623 }
624
625 bool HYDROData_CalculationCase::Export( GEOM::GEOM_Gen_var  theGeomEngine,
626                                         SALOMEDS::Study_ptr theStudy ) const
627 {
628   HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfGroupsDefs;
629
630   // Get groups definitions
631   HYDROData_SequenceOfObjects aSplittedGroups = GetSplittedGroups();
632
633   HYDROData_SequenceOfObjects::Iterator anIter( aSplittedGroups );
634   for ( ; anIter.More(); anIter.Next() )
635   {
636     // Get shapes group
637     Handle(HYDROData_ShapesGroup) aGroup =
638       Handle(HYDROData_ShapesGroup)::DownCast( anIter.Value() );
639     if ( aGroup.IsNull() )
640       continue;
641
642     HYDROData_ShapesGroup::GroupDefinition aGroupDef;
643
644     aGroupDef.Name = aGroup->GetName().toLatin1().constData();
645     aGroup->GetShapes( aGroupDef.Shapes );
646
647     aSeqOfGroupsDefs.Append( aGroupDef );
648   }
649   
650   // Get faces
651   TopTools_ListOfShape aFaces;
652   HYDROData_SequenceOfObjects aCaseRegions = GetRegions();
653   HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
654   for ( ; aRegionIter.More(); aRegionIter.Next() )
655   {
656     Handle(HYDROData_Region) aRegion =
657       Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
658     if( aRegion.IsNull() )
659       continue;
660
661     TopoDS_Shape aRegionShape = aRegion->GetShape( &aSeqOfGroupsDefs );
662     aFaces.Append( aRegionShape );
663   }
664
665   return Export( theGeomEngine, theStudy, aFaces, aSeqOfGroupsDefs );
666 }
667
668 bool HYDROData_CalculationCase::Export( GEOM::GEOM_Gen_var                            theGeomEngine,
669                                         SALOMEDS::Study_ptr                           theStudy,
670                                         const TopTools_ListOfShape&                   theFaces,
671                                         const HYDROData_ShapesGroup::SeqOfGroupsDefs& theGroupsDefs ) const
672 {
673   // Sew faces
674   BRepBuilderAPI_Sewing aSewing( Precision::Confusion() * 10.0 );
675   aSewing.SetNonManifoldMode( Standard_False );
676 #ifdef DEB_CALCULATION
677   TCollection_AsciiString aNam("Sh_");
678   int i=1;
679 #endif
680   TopTools_ListIteratorOfListOfShape aFaceIter( theFaces );
681   for ( ; aFaceIter.More(); aFaceIter.Next() )
682   {
683     TopoDS_Shape aShape = aFaceIter.Value();
684     if ( aShape.IsNull() )
685       continue;
686
687     if ( aShape.ShapeType() == TopAbs_FACE )
688     {
689       aSewing.Add( aShape );
690 #ifdef DEB_CALCULATION
691           TCollection_AsciiString aName = aNam + ++i + ".brep";
692           BRepTools::Write(aShape ,aName.ToCString());
693 #endif
694     }
695     else
696     {
697 #ifdef DEB_CALCULATION
698           int j = 1;
699 #endif
700       TopExp_Explorer anExp( aShape, TopAbs_FACE );
701           for (; anExp.More(); anExp.Next() ) {
702         aSewing.Add( anExp.Current() );
703 #ifdef DEB_CALCULATION
704
705         TCollection_AsciiString aName = aNam + i + "_" + ++j + ".brep";
706                 BRepTools::Write(anExp.Current() ,aName.ToCString());
707 #endif
708           }
709     }
710   } // faces iterator
711   
712   aSewing.Perform();
713   TopoDS_Shape aSewedShape = aSewing.SewedShape();
714
715   // If the sewed shape is empty - return false
716   if ( aSewedShape.IsNull() || !TopoDS_Iterator( aSewedShape ).More() )
717     return false;
718
719 #ifdef DEB_CALCULATION
720   BRepTools::Write(aSewedShape ,"Sew.brep");
721 #endif
722   // Publish the sewed shape
723   QString aName = EXPORT_NAME;
724   GEOM::GEOM_Object_ptr aMainShape = 
725     publishShapeInGEOM( theGeomEngine, theStudy, aSewedShape, aName );
726
727   if ( aMainShape->_is_nil() )  
728     return false;
729
730   if ( theGroupsDefs.IsEmpty() )
731     return true;
732
733   // Create groups
734   TopTools_IndexedMapOfShape aMapOfSubShapes;
735   TopExp::MapShapes( aSewedShape, aMapOfSubShapes );
736
737   NCollection_DataMap< TCollection_AsciiString, NCollection_Sequence<int> > aGroupsData;
738
739   for ( int aGrId = 1, nbGroups = theGroupsDefs.Length(); aGrId <= nbGroups; ++aGrId )
740   {
741     const HYDROData_ShapesGroup::GroupDefinition& aGroupDef = theGroupsDefs.Value( aGrId );
742
743     NCollection_Sequence<int> aGroupIndexes;
744     for( int i = 1, n = aGroupDef.Shapes.Length(); i <= n; i++ )
745         {
746       const TopoDS_Shape& aShape = aGroupDef.Shapes.Value( i );
747 #ifdef DEB_CALCULATION
748       cout << "\nOld shape(" << i << ") = " << aShape.TShape() <<endl;
749 #endif
750       const TopoDS_Shape& aModifiedShape = aSewing.Modified( aShape );
751       if ( aModifiedShape.IsNull() )
752         continue;
753
754 #ifdef DEB_CALCULATION
755           const TopLoc_Location& aL1 = aShape.Location();
756           const TopLoc_Location& aL2 = aModifiedShape.Location();
757           cout << "\nNew shape(" << i << ") = " << aModifiedShape.TShape() << " Location is Equal = " << aL1.IsEqual(aL2)<<endl;
758 #endif
759
760       // Workaround for TopTools_IndexedMapOfShape::FindIndex()
761       /*for ( int anIndex = 1; anIndex <= aMapOfSubShapes.Extent(); anIndex++ )
762       {
763         if ( aModifiedShape.IsPartner( aMapOfSubShapes.FindKey( anIndex ) ) )
764         {
765           aGroupIndexes.Append( anIndex );
766           break;
767         }
768       }
769     */
770           int anIndex = aMapOfSubShapes.FindIndex(aModifiedShape);
771           if(anIndex > 0) {
772                 aGroupIndexes.Append( anIndex );
773         //break;
774           } else {
775 #ifdef DEB_CALCULATION  
776           TCollection_AsciiString aNam("Lost_");
777           if(!aMapOfSubShapes.Contains(aModifiedShape)) {
778        for ( int anIndex = 1; anIndex <= aMapOfSubShapes.Extent(); anIndex++ )
779        {
780              const TopoDS_Shape& aS = aMapOfSubShapes.FindKey( anIndex );
781          if ( aModifiedShape.IsPartner( aS ) )
782                  {
783                    cout <<"\nIndex in Map = " << anIndex << "TShape = " << aS.TShape() <<endl;
784                    TCollection_AsciiString aName = aNam + i + "_" + anIndex + ".brep";
785                    BRepTools::Write(aS ,aName.ToCString());
786           break;
787                  }
788            }
789           }
790 #endif
791         }
792         }
793     if ( !aGroupIndexes.IsEmpty() )
794       aGroupsData.Bind( aGroupDef.Name, aGroupIndexes );
795   }
796  
797   if ( !aGroupsData.IsEmpty() )
798   {
799     GEOM::GEOM_IGroupOperations_var aGroupOp = 
800       theGeomEngine->GetIGroupOperations( theStudy->StudyId() );  
801
802     NCollection_DataMap< TCollection_AsciiString, NCollection_Sequence<int> >::Iterator aMapIt( aGroupsData );
803     for ( ; aMapIt.More(); aMapIt.Next() )
804     {
805       const TCollection_AsciiString& aGroupName = aMapIt.Key(); 
806       const NCollection_Sequence<int>& aGroupIndexes = aMapIt.Value();
807
808       GEOM::GEOM_Object_var aGeomGroup = aGroupOp->CreateGroup( aMainShape, TopAbs_EDGE );
809       if ( CORBA::is_nil( aGeomGroup ) || !aGroupOp->IsDone() )
810         continue;
811
812       GEOM::ListOfLong_var aGeomIndexes = new GEOM::ListOfLong;
813       aGeomIndexes->length( aGroupIndexes.Length() );
814
815       for( int i = 1, n = aGroupIndexes.Length(); i <= n; i++ )
816         aGeomIndexes[ i - 1 ] = aGroupIndexes.Value( i );
817
818       aGroupOp->UnionIDs( aGeomGroup, aGeomIndexes );
819       if ( aGroupOp->IsDone() )
820       {
821         SALOMEDS::SObject_var aGroupSO = 
822           theGeomEngine->AddInStudy( theStudy, aGeomGroup, aGroupName.ToCString(), aMainShape );
823       }
824     }
825   }
826
827   return true;
828 }
829
830 GEOM::GEOM_Object_ptr HYDROData_CalculationCase::publishShapeInGEOM( 
831   GEOM::GEOM_Gen_var theGeomEngine, SALOMEDS::Study_ptr theStudy,
832   const TopoDS_Shape& theShape, const QString& theName ) const
833 {
834   GEOM::GEOM_Object_var aGeomObj;
835
836   if ( theGeomEngine->_is_nil() || theStudy->_is_nil() ||
837        theShape.IsNull() ) {
838     return aGeomObj._retn();
839   }
840
841   std::ostringstream aStreamShape;
842   // Write TopoDS_Shape in ASCII format to the stream
843   BRepTools::Write( theShape, aStreamShape );
844   // Returns the number of bytes that have been stored in the stream's buffer.
845   int aSize = aStreamShape.str().size();
846   // Allocate octect buffer of required size
847   CORBA::Octet* anOctetBuf = SALOMEDS::TMPFile::allocbuf( aSize );
848   // Copy ostrstream content to the octect buffer
849   memcpy( anOctetBuf, aStreamShape.str().c_str(), aSize );
850   // Create TMPFile
851   SALOMEDS::TMPFile_var aSeqFile = new SALOMEDS::TMPFile( aSize, aSize, anOctetBuf, 1 );
852
853   // Restore shape from the stream and get the GEOM object
854   GEOM::GEOM_IInsertOperations_var anInsOp = theGeomEngine->GetIInsertOperations( theStudy->StudyId() );
855   aGeomObj = anInsOp->RestoreShape( aSeqFile );
856   
857   // Puplish the GEOM object
858   if ( !aGeomObj->_is_nil() ) {
859     QString aName = GEOMBase::GetDefaultName( theName );
860
861     SALOMEDS::SObject_var aResultSO = 
862       theGeomEngine->PublishInStudy( theStudy, SALOMEDS::SObject::_nil(), 
863                                      aGeomObj, qPrintable( aName ) );
864     if ( aResultSO->_is_nil() ) {
865       aGeomObj = GEOM::GEOM_Object::_nil();
866     }
867   }
868
869   return aGeomObj._retn();
870  }