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