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