Salome HOME
Names of module actions corrected (Bug #107).
[modules/hydro.git] / src / HYDROData / HYDROData_CalculationCase.cxx
1
2 #include "HYDROData_CalculationCase.h"
3
4 #include "HYDROData_ArtificialObject.h"
5 #include "HYDROData_Document.h"
6 #include "HYDROData_Iterator.h"
7 #include "HYDROData_NaturalObject.h"
8 #include "HYDROData_Polyline.h"
9 #include "HYDROData_SplitToZonesTool.h"
10 #include "HYDROData_Region.h"
11 #include "HYDROData_Tool.h"
12 #include "HYDROData_Zone.h"
13
14 #include <TopoDS.hxx>
15 #include <TopoDS_Shell.hxx>
16 #include <BRep_Builder.hxx>
17 #include <BRepBuilderAPI_Sewing.hxx>
18 #include <TopExp_Explorer.hxx>
19
20 #define CALCULATION_REGIONS_PREF GetName() + "_Reg"
21 #define CALCULATION_ZONES_PREF GetName() + "_Zone"
22
23 #define PYTHON_CALCULATION_ID "KIND_CALCULATION"
24
25 IMPLEMENT_STANDARD_HANDLE(HYDROData_CalculationCase, HYDROData_Entity)
26 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_CalculationCase, HYDROData_Entity)
27
28 HYDROData_CalculationCase::HYDROData_CalculationCase()
29 : HYDROData_Entity()
30 {
31 }
32
33 HYDROData_CalculationCase::~HYDROData_CalculationCase()
34 {
35 }
36
37 QStringList HYDROData_CalculationCase::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
38 {
39   QStringList aResList;
40
41   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
42   if ( aDocument.IsNull() )
43     return aResList;
44                              
45   QString aDocName = aDocument->GetDocPyName();
46   QString aCalculName = GetName();
47
48   aResList << QString( "%1 = %2.CreateObject( %3 );" )
49               .arg( aCalculName ).arg( aDocName ).arg( PYTHON_CALCULATION_ID );
50   aResList << QString( "%1.SetName( \"%2\" );" )
51               .arg( aCalculName ).arg( aCalculName );
52   aResList << QString( "" );
53
54   HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects();
55   HYDROData_SequenceOfObjects::Iterator anIter( aGeomObjects );
56   for ( ; anIter.More(); anIter.Next() )
57   {
58     Handle(HYDROData_Object) aRefGeomObj =
59       Handle(HYDROData_Object)::DownCast( anIter.Value() );
60     if ( !aRefGeomObj.IsNull() )
61       setPythonReferenceObject( theTreatedObjects, aResList, aRefGeomObj, "AddGeometryObject" );
62   }
63   aResList << QString( "" );
64
65   aResList << QString( "%1.SplitGeometryObjects();" ).arg( aCalculName );
66   aResList << QString( "" );
67
68   // Now we restore the regions and zones order
69   HYDROData_SequenceOfObjects aRegions = GetRegions();
70   anIter.Init( aRegions );
71   for ( ; anIter.More(); anIter.Next() )
72   {
73     Handle(HYDROData_Region) aRegion =
74       Handle(HYDROData_Region)::DownCast( anIter.Value() );
75     if ( aRegion.IsNull() )
76       continue;
77
78     QString aRegionName = aRegion->GetName();
79     // TODO
80   }
81
82   return aResList;
83 }
84
85 void HYDROData_CalculationCase::SplitGeometryObjects()
86 {
87   // At first we remove previously created regions
88   RemoveRegions();
89
90   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
91   if ( aDocument.IsNull() )
92     return;
93
94   Handle(HYDROData_Polyline) aBoundaryPolyline = GetBoundaryPolyline();
95   HYDROData_SequenceOfObjects aGeomObjects = GetGeometryObjects();
96   if ( aGeomObjects.IsEmpty() )
97     return;
98
99   HYDROData_SplitToZonesTool::SplitDataList aSplitedZones =
100     HYDROData_SplitToZonesTool::SplitToZones( aGeomObjects, aBoundaryPolyline );
101   if ( aSplitedZones.isEmpty() )
102     return;
103
104   QString aRegsPref = CALCULATION_REGIONS_PREF;
105   QString aZonesPref = CALCULATION_ZONES_PREF;
106
107   // Create result regions for case, by default one zone for one region
108   HYDROData_SplitToZonesTool::SplitDataListIterator anIter( aSplitedZones );
109   while( anIter.hasNext() )
110   {
111     const HYDROData_SplitToZonesTool::SplitData& aSplitData = anIter.next();
112
113     // Create new region
114     Handle(HYDROData_Region) aRegion = addNewRegion();
115
116     QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
117     aRegion->SetName( aRegionName );
118
119     // Add the zone for region
120     Handle(HYDROData_Zone) aRegionZone = aRegion->addNewZone();
121
122     QString aZoneName = HYDROData_Tool::GenerateObjectName( aDocument, aZonesPref );
123     aRegionZone->SetName( aZoneName );
124
125     aRegionZone->SetShape( aSplitData.Face() );
126
127     // Add the reference object for zone
128     for ( int i = 0, n = aSplitData.ObjectNames.length(); i < n; ++i )
129     {
130       const QString& anObjName = aSplitData.ObjectNames.at( i );
131       
132       Handle(HYDROData_Object) aRefObject = Handle(HYDROData_Object)::DownCast(
133         HYDROData_Tool::FindObjectByName( aDocument, anObjName ) );
134       if ( aRefObject.IsNull() )
135         continue;
136
137       aRegionZone->AddGeometryObject( aRefObject );
138     }
139   }
140
141   // The splitted data is up to date
142   SetToUpdate( false );
143 }
144
145 bool HYDROData_CalculationCase::AddGeometryObject( const Handle(HYDROData_Object)& theObject )
146 {
147   if ( !HYDROData_Tool::IsGeometryObject( theObject ) )
148     return false; // Wrong type of object
149
150   if ( HasReference( theObject, DataTag_GeometryObject ) )
151     return false; // Object is already in reference list
152
153   AddReferenceObject( theObject, DataTag_GeometryObject );
154   
155   // Indicate model of the need to update zones splitting
156   SetToUpdate( true );
157
158   return true;
159 }
160
161 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetGeometryObjects() const
162 {
163   return GetReferenceObjects( DataTag_GeometryObject );
164 }
165
166 void HYDROData_CalculationCase::RemoveGeometryObject( const Handle(HYDROData_Object)& theObject )
167 {
168   if ( theObject.IsNull() )
169     return;
170
171   RemoveReferenceObject( theObject->Label(), DataTag_GeometryObject );
172
173   // Indicate model of the need to update zones splitting
174   SetToUpdate( true );
175 }
176
177 void HYDROData_CalculationCase::RemoveGeometryObjects()
178 {
179   ClearReferenceObjects( DataTag_GeometryObject );
180
181   // Indicate model of the need to update zones splitting
182   SetToUpdate( true );
183 }
184
185 void HYDROData_CalculationCase::SetBoundaryPolyline( const Handle(HYDROData_Polyline)& thePolyline )
186 {
187   Handle(HYDROData_Polyline) aPrevPolyline = GetBoundaryPolyline();
188
189   SetReferenceObject( thePolyline, DataTag_Polyline );
190
191   // Indicate model of the need to update zones splitting
192   SetToUpdate( !IsEqual( aPrevPolyline, thePolyline ) || IsMustBeUpdated() );
193 }
194
195 Handle(HYDROData_Polyline) HYDROData_CalculationCase::GetBoundaryPolyline() const
196 {
197   return Handle(HYDROData_Polyline)::DownCast( 
198            GetReferenceObject( DataTag_Polyline ) );
199 }
200
201 void HYDROData_CalculationCase::RemoveBoundaryPolyline()
202 {
203   Handle(HYDROData_Polyline) aPrevPolyline = GetBoundaryPolyline();
204
205   ClearReferenceObjects( DataTag_Polyline );
206
207   // Indicate model of the need to update zones splitting
208   SetToUpdate( !aPrevPolyline.IsNull() || IsMustBeUpdated() );
209 }
210
211 Handle(HYDROData_Region) HYDROData_CalculationCase::AddNewRegion( const Handle(HYDROData_Zone)& theZone )
212 {
213   Handle(HYDROData_Region) aNewRegion = addNewRegion();
214   if ( aNewRegion.IsNull() )
215     return aNewRegion;
216
217   // Generate new name for new region
218   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
219   if ( !aDocument.IsNull() )
220   {
221     QString aRegsPref = CALCULATION_REGIONS_PREF;
222
223     QString aNewRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
224     aNewRegion->SetName( aNewRegionName );
225   }
226
227   aNewRegion->AddZone( theZone );
228
229   return aNewRegion;
230 }
231
232 bool HYDROData_CalculationCase::AddRegion( const Handle(HYDROData_Region)& theRegion )
233 {
234   if ( theRegion.IsNull() )
235     return false;
236   
237   if ( HasReference( theRegion, DataTag_Region ) )
238     return false; // Object is already in reference list
239
240   // Move the region from other calculation
241   Handle(HYDROData_CalculationCase) aFatherCalc = 
242     Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
243   if ( !aFatherCalc.IsNull() && aFatherCalc->Label() != myLab )
244   {
245     Handle(HYDROData_Region) aNewRegion = addNewRegion();
246     theRegion->CopyTo( aNewRegion );
247
248     aFatherCalc->RemoveRegion( theRegion );
249
250     theRegion->SetLabel( aNewRegion->Label() );
251   }
252   else
253   {
254     AddReferenceObject( theRegion, DataTag_Region );
255   }
256
257   return true;
258 }
259
260 HYDROData_SequenceOfObjects HYDROData_CalculationCase::GetRegions() const
261 {
262   return GetReferenceObjects( DataTag_Region );
263 }
264
265 void HYDROData_CalculationCase::UpdateRegionsOrder()
266 {
267   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
268   if ( aDocument.IsNull() )
269     return;
270
271   HYDROData_SequenceOfObjects aRegions = GetRegions();
272
273   HYDROData_SequenceOfObjects::Iterator anIter( aRegions );
274   for ( ; anIter.More(); anIter.Next() )
275   {
276     Handle(HYDROData_Region) aRegion =
277       Handle(HYDROData_Region)::DownCast( anIter.Value() );
278     if ( aRegion.IsNull() )
279       continue;
280
281     aRegion->SetName( "" );
282   }
283
284   QString aRegsPref = CALCULATION_REGIONS_PREF;
285
286   anIter.Init( aRegions );
287   for ( ; anIter.More(); anIter.Next() )
288   {
289     Handle(HYDROData_Region) aRegion =
290       Handle(HYDROData_Region)::DownCast( anIter.Value() );
291     if ( aRegion.IsNull() )
292       continue;
293
294     QString aRegionName = HYDROData_Tool::GenerateObjectName( aDocument, aRegsPref );
295     aRegion->SetName( aRegionName );
296   }
297 }
298
299 void HYDROData_CalculationCase::RemoveRegion( const Handle(HYDROData_Region)& theRegion )
300 {
301   if ( theRegion.IsNull() )
302     return;
303
304   RemoveReferenceObject( theRegion->Label(), DataTag_Region );
305
306   // Remove region from data model
307   Handle(HYDROData_CalculationCase) aFatherCalc = 
308     Handle(HYDROData_CalculationCase)::DownCast( theRegion->GetFatherObject() );
309   if ( !aFatherCalc.IsNull() && aFatherCalc->Label() == myLab )
310     theRegion->Remove();
311 }
312
313 void HYDROData_CalculationCase::RemoveRegions()
314 {
315   ClearReferenceObjects( DataTag_Region );
316   myLab.FindChild( DataTag_ChildRegion ).ForgetAllAttributes( true );
317 }
318
319 Handle(HYDROData_Region) HYDROData_CalculationCase::addNewRegion()
320 {
321   TDF_Label aNewLab = myLab.FindChild( DataTag_ChildRegion ).NewChild();
322
323   Handle(HYDROData_Region) aNewRegion =
324     Handle(HYDROData_Region)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_REGION ) );
325   AddRegion( aNewRegion );
326
327   return aNewRegion;
328 }
329
330 TopoDS_Shell HYDROData_CalculationCase::GetShell()
331 {
332   TopoDS_Shell aShell;
333
334   // Make shell containing all region shapes
335   BRepBuilderAPI_Sewing aSewing( Precision::Confusion()*10.0 );
336
337   HYDROData_SequenceOfObjects aCaseRegions = GetRegions();
338   HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
339   for ( ; aRegionIter.More(); aRegionIter.Next() ) {
340     Handle(HYDROData_Region) aRegion =
341       Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
342     if( aRegion.IsNull() ) {
343       continue;
344     }
345
346     TopoDS_Shape aRegionShape = aRegion->GetShape();
347     if( !aRegionShape.IsNull() ) {
348       aSewing.Add( aRegionShape );
349     }
350   } // regions iterator
351   
352   aSewing.Perform();
353   TopoDS_Shape aSewedShape = aSewing.SewedShape();
354
355   if ( aSewedShape.ShapeType() == TopAbs_FACE && aCaseRegions.Length() ==1 ) {
356     // create shell from one face
357     BRep_Builder aBuilder;
358     aBuilder.MakeShell( aShell );
359     aBuilder.Add( aShell, aSewedShape);
360   } else {
361     TopExp_Explorer anExpShells( aSewedShape, TopAbs_SHELL );
362     Standard_Integer aNbOfShells = 0;
363     for ( ; anExpShells.More(); anExpShells.Next() ) {
364       aShell = TopoDS::Shell( anExpShells.Current() );
365       aNbOfShells++;
366     }
367
368     if ( aNbOfShells != 1 ) {
369       aShell.Nullify();
370       BRep_Builder aBuilder;
371       aBuilder.MakeShell( aShell );
372
373       TopExp_Explorer anExpFaces( aSewedShape, TopAbs_FACE );
374       for ( ; anExpFaces.More(); anExpFaces.Next() ) {
375         TopoDS_Face aFace = TopoDS::Face( anExpFaces.Current() );
376         if ( !aFace.IsNull() ) {
377           aBuilder.Add( aShell, aFace );
378         }
379       }
380     }
381   }
382
383 /* TODO: old version
384   // Make shell
385   BRep_Builder aBuilder;
386   aBuilder.MakeShell( aShell );
387
388   // Make shell containing all region shapes
389   HYDROData_SequenceOfObjects aCaseRegions = GetRegions();
390   HYDROData_SequenceOfObjects::Iterator aRegionIter( aCaseRegions );
391   for ( ; aRegionIter.More(); aRegionIter.Next() ) {
392     Handle(HYDROData_Region) aRegion =
393       Handle(HYDROData_Region)::DownCast( aRegionIter.Value() );
394     if( aRegion.IsNull() ) {
395       continue;
396     }
397
398     TopoDS_Shape aRegionShape = aRegion->GetShape();
399
400     // Add shape (face or shell) corresponding to the region into the shell
401     if( !aRegionShape.IsNull() ) {
402       if ( aRegionShape.ShapeType() == TopAbs_FACE ) {
403         aBuilder.Add( aShell, aRegionShape );
404       } else {
405         TopExp_Explorer anExp( aRegionShape, TopAbs_FACE );
406         for( ; anExp.More(); anExp.Next() ) {
407           TopoDS_Face aFace = TopoDS::Face( anExp.Current() );
408           if( !aFace.IsNull() ) {
409             aBuilder.Add( aShell, aFace );
410           }
411         }
412       }
413     }
414   } // regions iterator
415 */
416
417   // Nullify shell if it is empty
418   if ( !aShell.IsNull() && !TopoDS_Iterator(aShell).More() ) {
419     aShell.Nullify();
420   }
421
422   return aShell;
423 }
424
425