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