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