Salome HOME
The search of shapes in the map is corrected by workaround.
[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 ) const
637 {
638   HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfGroupsDefs;
639
640   // Get groups definitions
641   HYDROData_SequenceOfObjects aSplittedGroups = GetSplittedGroups();
642
643   HYDROData_SequenceOfObjects::Iterator anIter( aSplittedGroups );
644   for ( ; anIter.More(); anIter.Next() )
645   {
646     // Get shapes group
647     Handle(HYDROData_ShapesGroup) aGroup =
648       Handle(HYDROData_ShapesGroup)::DownCast( anIter.Value() );
649     if ( aGroup.IsNull() )
650       continue;
651
652     HYDROData_ShapesGroup::GroupDefinition aGroupDef;
653
654     aGroupDef.Name = aGroup->GetName().toLatin1().constData();
655     aGroup->GetShapes( aGroupDef.Shapes );
656
657     aSeqOfGroupsDefs.Append( aGroupDef );
658   }
659   
660   // Get faces
661   TopTools_ListOfShape aFaces;
662   HYDROData_SequenceOfObjects aCaseRegions = GetRegions();
663   HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
664   for ( ; aRegionIter.More(); aRegionIter.Next() )
665   {
666     Handle(HYDROData_Region) aRegion =
667       Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
668     if( aRegion.IsNull() )
669       continue;
670
671     TopoDS_Shape aRegionShape = aRegion->GetShape( &aSeqOfGroupsDefs );
672     aFaces.Append( aRegionShape );
673   }
674
675   return Export( theGeomEngine, theStudy, aFaces, aSeqOfGroupsDefs );
676 }
677
678 bool HYDROData_CalculationCase::Export( GEOM::GEOM_Gen_var                            theGeomEngine,
679                                         SALOMEDS::Study_ptr                           theStudy,
680                                         const TopTools_ListOfShape&                   theFaces,
681                                         const HYDROData_ShapesGroup::SeqOfGroupsDefs& theGroupsDefs ) const
682 {
683   // Sew faces
684   BRepBuilderAPI_Sewing aSewing( Precision::Confusion() * 10.0 );
685   aSewing.SetNonManifoldMode( Standard_True );
686
687   TopTools_ListIteratorOfListOfShape aFaceIter( theFaces );
688   for ( ; aFaceIter.More(); aFaceIter.Next() )
689   {
690     TopoDS_Shape aShape = aFaceIter.Value();
691     if ( aShape.IsNull() )
692       continue;
693
694     if ( aShape.ShapeType() == TopAbs_FACE )
695     {
696       aSewing.Add( aShape );
697     }
698     else
699     {
700       TopExp_Explorer anExp( aShape, TopAbs_FACE );
701       for ( ; anExp.More(); anExp.Next() )
702         aSewing.Add( anExp.Current() );
703     }
704   } // faces iterator
705   
706   aSewing.Perform();
707   TopoDS_Shape aSewedShape = aSewing.SewedShape();
708
709   // If the sewed shape is empty - return false
710   if ( aSewedShape.IsNull() || !TopoDS_Iterator( aSewedShape ).More() )
711     return false;
712
713   // Publish the sewed shape
714   QString aName = EXPORT_NAME;
715   GEOM::GEOM_Object_ptr aMainShape = 
716     publishShapeInGEOM( theGeomEngine, theStudy, aSewedShape, aName );
717
718   if ( aMainShape->_is_nil() )
719     return false;
720
721   if ( theGroupsDefs.IsEmpty() )
722     return true;
723
724   // Create groups
725   TopTools_IndexedMapOfShape aMapOfSubShapes;
726   TopExp::MapShapes( aSewedShape, aMapOfSubShapes );
727
728   NCollection_DataMap< TCollection_AsciiString, NCollection_Sequence<int> > aGroupsData;
729
730   for ( int aGrId = 1, nbGroups = theGroupsDefs.Length(); aGrId <= nbGroups; ++aGrId )
731   {
732     const HYDROData_ShapesGroup::GroupDefinition& aGroupDef = theGroupsDefs.Value( aGrId );
733
734     NCollection_Sequence<int> aGroupIndexes;
735     for( int i = 1, n = aGroupDef.Shapes.Length(); i <= n; i++ )
736     {
737       const TopoDS_Shape& aShape = aGroupDef.Shapes.Value( i );
738
739       const TopoDS_Shape& aModifiedShape = aSewing.Modified( aShape );
740       if ( aModifiedShape.IsNull() )
741         continue;
742
743       // Workaround for TopTools_IndexedMapOfShape::FindIndex()
744       for ( int anIndex = 1; anIndex <= aMapOfSubShapes.Extent(); anIndex++ )
745       {
746         if ( aModifiedShape.IsPartner( aMapOfSubShapes.FindKey( anIndex ) ) )
747         {
748           aGroupIndexes.Append( anIndex );
749           break;
750         }
751       }
752     }
753
754     if ( !aGroupIndexes.IsEmpty() )
755       aGroupsData.Bind( aGroupDef.Name, aGroupIndexes );
756   }
757   
758   if ( !aGroupsData.IsEmpty() )
759   {
760     GEOM::GEOM_IGroupOperations_var aGroupOp = 
761       theGeomEngine->GetIGroupOperations( theStudy->StudyId() );  
762
763     NCollection_DataMap< TCollection_AsciiString, NCollection_Sequence<int> >::Iterator aMapIt( aGroupsData );
764     for ( ; aMapIt.More(); aMapIt.Next() )
765     {
766       const TCollection_AsciiString& aGroupName = aMapIt.Key(); 
767       const NCollection_Sequence<int>& aGroupIndexes = aMapIt.Value();
768
769       GEOM::GEOM_Object_var aGeomGroup = aGroupOp->CreateGroup( aMainShape, TopAbs_EDGE );
770       if ( CORBA::is_nil( aGeomGroup ) || !aGroupOp->IsDone() )
771         continue;
772
773       GEOM::ListOfLong_var aGeomIndexes = new GEOM::ListOfLong;
774       aGeomIndexes->length( aGroupIndexes.Length() );
775
776       for( int i = 1, n = aGroupIndexes.Length(); i <= n; i++ )
777         aGeomIndexes[ i - 1 ] = aGroupIndexes.Value( i );
778
779       aGroupOp->UnionIDs( aGeomGroup, aGeomIndexes );
780       if ( aGroupOp->IsDone() )
781       {
782         SALOMEDS::SObject_var aGroupSO = 
783           theGeomEngine->AddInStudy( theStudy, aGeomGroup, aGroupName.ToCString(), aMainShape );
784       }
785     }
786   }
787
788   return true;
789 }
790
791 GEOM::GEOM_Object_ptr HYDROData_CalculationCase::publishShapeInGEOM( 
792   GEOM::GEOM_Gen_var theGeomEngine, SALOMEDS::Study_ptr theStudy,
793   const TopoDS_Shape& theShape, const QString& theName ) const
794 {
795   GEOM::GEOM_Object_var aGeomObj;
796
797   if ( theGeomEngine->_is_nil() || theStudy->_is_nil() ||
798        theShape.IsNull() ) {
799     return aGeomObj._retn();
800   }
801
802   std::ostringstream aStreamShape;
803   // Write TopoDS_Shape in ASCII format to the stream
804   BRepTools::Write( theShape, aStreamShape );
805   // Returns the number of bytes that have been stored in the stream's buffer.
806   int aSize = aStreamShape.str().size();
807   // Allocate octect buffer of required size
808   CORBA::Octet* anOctetBuf = SALOMEDS::TMPFile::allocbuf( aSize );
809   // Copy ostrstream content to the octect buffer
810   memcpy( anOctetBuf, aStreamShape.str().c_str(), aSize );
811   // Create TMPFile
812   SALOMEDS::TMPFile_var aSeqFile = new SALOMEDS::TMPFile( aSize, aSize, anOctetBuf, 1 );
813
814   // Restore shape from the stream and get the GEOM object
815   GEOM::GEOM_IInsertOperations_var anInsOp = theGeomEngine->GetIInsertOperations( theStudy->StudyId() );
816   aGeomObj = anInsOp->RestoreShape( aSeqFile );
817   
818   // Puplish the GEOM object
819   if ( !aGeomObj->_is_nil() ) {
820     QString aName = GEOMBase::GetDefaultName( theName );
821
822     SALOMEDS::SObject_var aResultSO = 
823       theGeomEngine->PublishInStudy( theStudy, SALOMEDS::SObject::_nil(), 
824                                      aGeomObj, qPrintable( aName ) );
825     if ( aResultSO->_is_nil() ) {
826       aGeomObj = GEOM::GEOM_Object::_nil();
827     }
828   }
829
830   return aGeomObj._retn();
831  }