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