Salome HOME
Dump to python corrected.
[modules/hydro.git] / src / HYDROData / HYDROData_Region.cxx
1
2 #include "HYDROData_Region.h"
3
4 #include "HYDROData_CalculationCase.h"
5 #include "HYDROData_Document.h"
6 #include "HYDROData_Iterator.h"
7 #include "HYDROData_ShapesTool.h"
8 #include "HYDROData_Zone.h"
9
10 #include <TopoDS.hxx>
11 #include <TopoDS_Shape.hxx>
12 #include <TopoDS_Shell.hxx>
13 #include <TopoDS_Face.hxx>
14
15 #include <TopExp.hxx>
16
17 #include <TopTools_ListOfShape.hxx>
18 #include <TopTools_SequenceOfShape.hxx>
19 #include <TopTools_ListIteratorOfListOfShape.hxx>
20 #include <TopTools_IndexedMapOfShape.hxx>
21
22 #include <BRep_Builder.hxx>
23 #include <BRepAlgoAPI_Fuse.hxx>
24
25 #include <ShapeUpgrade_UnifySameDomain.hxx>
26
27 #include <QStringList>
28
29 //#define DEB_GET_REGION_SHAPE
30
31 IMPLEMENT_STANDARD_HANDLE(HYDROData_Region, HYDROData_Entity)
32 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Entity)
33
34
35 HYDROData_Region::HYDROData_Region()
36  : HYDROData_Entity()
37 {
38 }
39
40 HYDROData_Region::~HYDROData_Region()
41 {
42 }
43
44 QStringList HYDROData_Region::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
45 {
46   QStringList aResList = dumpObjectCreation( theTreatedObjects );
47   QString aRegionName = GetObjPyName();
48
49   HYDROData_SequenceOfObjects aZones = GetZones();
50   HYDROData_SequenceOfObjects::Iterator anIter( aZones );
51   for ( ; anIter.More(); anIter.Next() )
52   {
53     Handle(HYDROData_Zone) aRefZone =
54       Handle(HYDROData_Zone)::DownCast( anIter.Value() );
55     if ( !aRefZone.IsNull() )
56       setPythonReferenceObject( theTreatedObjects, aResList, aRefZone, "AddZone" );
57   }
58
59   aResList << QString( "" );
60   aResList << QString( "%1.Update();" ).arg( aRegionName );
61   aResList << QString( "" );
62
63   return aResList;
64 }
65
66 bool HYDROData_Region::CanBeUpdated() const
67 {
68   return false;
69 }
70
71 void HYDROData_Region::Remove()
72 {
73   Handle(HYDROData_CalculationCase) aFatherCalc = 
74     Handle(HYDROData_CalculationCase)::DownCast( GetFatherObject() );
75
76   HYDROData_Entity::Remove();
77
78   if ( !aFatherCalc.IsNull() )
79     aFatherCalc->UpdateRegionsOrder();
80 }
81
82 bool HYDROData_Region::CanRemove()
83 {
84   return false;
85 }
86
87 HYDROData_SequenceOfObjects HYDROData_Region::GetAllReferenceObjects() const
88 {
89   HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
90
91   HYDROData_SequenceOfObjects aSeqOfZones = GetZones();
92   aResSeq.Append( aSeqOfZones );
93
94   return aResSeq;
95 }
96
97 bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone )
98 {
99   if ( theZone.IsNull() )
100     return false;
101   
102   if ( HasReference( theZone, DataTag_Zone ) )
103     return false; // Object is already in reference list
104
105   // Move the zone from other region
106   Handle(HYDROData_Region) aFatherRegion = 
107     Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
108   if ( !aFatherRegion.IsNull() && aFatherRegion->Label() != myLab )
109   {
110     Handle(HYDROData_Zone) aNewZone = addNewZone();
111     theZone->CopyTo( aNewZone );
112
113     // To prevent changing of stored shape
114     aNewZone->SetShape( theZone->GetShape() );
115
116     aFatherRegion->RemoveZone( theZone );
117
118     theZone->SetLabel( aNewZone->Label() );
119   }
120   else
121   {
122     AddReferenceObject( theZone, DataTag_Zone );
123   }
124
125   return true;
126 }
127
128 HYDROData_SequenceOfObjects HYDROData_Region::GetZones() const
129 {
130   return GetReferenceObjects( DataTag_Zone );
131 }
132
133 void HYDROData_Region::RemoveZone( const Handle(HYDROData_Zone)& theZone )
134 {
135   if ( theZone.IsNull() )
136     return;
137
138   RemoveReferenceObject( theZone->Label(), DataTag_Zone );
139
140   // Remove zone from data model
141   Handle(HYDROData_Region) aFatherRegion = 
142     Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
143   if ( !aFatherRegion.IsNull() && aFatherRegion->Label() == myLab )
144     theZone->Remove();
145
146   // If the last zone has been removed from region we remove this region
147   HYDROData_SequenceOfObjects aRefZones = GetZones();
148   if ( aRefZones.IsEmpty() )
149     Remove();
150 }
151
152 void HYDROData_Region::RemoveZones()
153 {
154   ClearReferenceObjects( DataTag_Zone );
155   myLab.FindChild( DataTag_ChildZone ).ForgetAllAttributes( true );
156 }
157
158 Handle(HYDROData_Zone) HYDROData_Region::addNewZone()
159 {
160   TDF_Label aNewLab = myLab.FindChild( DataTag_ChildZone ).NewChild();
161
162   Handle(HYDROData_Zone) aNewZone =
163     Handle(HYDROData_Zone)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_ZONE ) );
164   AddZone( aNewZone );
165
166   return aNewZone;
167 }
168
169 void getUsedGroups( const TopoDS_Shape&                     theShape,
170                     HYDROData_ShapesGroup::SeqOfGroupsDefs& theOriGroups,
171                     HYDROData_ShapesGroup::SeqOfGroupsDefs& theUsedGroups )
172 {
173 #ifdef DEB_GET_REGION_SHAPE
174   HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Zone face edges:", theShape, TopAbs_EDGE );
175 #endif
176
177   TopTools_IndexedMapOfShape aMapOfSubShapes;
178   TopExp::MapShapes( theShape, TopAbs_EDGE, aMapOfSubShapes );
179
180   HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anIter( theOriGroups );
181   for ( ; anIter.More(); anIter.Next() )
182   {
183     HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anIter.ChangeValue();
184     if ( anOriGroupDef.Shapes.IsEmpty() )
185       continue;
186
187     for ( int i = 1; i <= anOriGroupDef.Shapes.Length(); ++i )
188     {
189       TopoDS_Shape aGroupEdge = anOriGroupDef.Shapes.Value( i );
190       
191       int aShapeIndex = aMapOfSubShapes.FindIndex( aGroupEdge );
192       if ( aShapeIndex <= 0 )
193         continue;
194
195       anOriGroupDef.Shapes.Remove( i );
196       --i;
197
198       bool anIsAdded = false;
199
200       HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( theUsedGroups );
201       for ( ; aUsedIter.More(); aUsedIter.Next() )
202       {
203         HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.ChangeValue();
204         if ( aUsedGroupDef.Name != anOriGroupDef.Name )
205           continue;
206
207         aUsedGroupDef.Shapes.Append( aGroupEdge );
208         anIsAdded = true;
209         break;
210       }
211
212       if ( !anIsAdded )
213       {
214         HYDROData_ShapesGroup::GroupDefinition aUsedGroupDef;
215         aUsedGroupDef.Name = anOriGroupDef.Name;
216         aUsedGroupDef.Shapes.Append( aGroupEdge );
217         theUsedGroups.Append( aUsedGroupDef );
218       }
219     }
220   }
221 }
222
223 TopoDS_Shape HYDROData_Region::GetShape( HYDROData_ShapesGroup::SeqOfGroupsDefs* theSeqOfGroups ) const
224 {
225   HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfGroups;
226   HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfUsedGroups;
227   if ( theSeqOfGroups )
228     aSeqOfGroups = *theSeqOfGroups;
229
230 #ifdef DEB_GET_REGION_SHAPE
231   HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfGroups );
232 #endif
233
234   TopoDS_Shape aResShape;
235
236   // Unite the region zones (each zone is a face) into one face (united face)
237   // If the zones can't be united into the single face - unite them into shell
238
239   // Collect the list of region faces
240   TopTools_ListOfShape aRegionFacesList;
241
242   HYDROData_SequenceOfObjects aZones = GetZones();
243   HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones );
244   for ( ; aZoneIter.More(); aZoneIter.Next() )
245   {
246     Handle(HYDROData_Zone) aZone =
247       Handle(HYDROData_Zone)::DownCast( aZoneIter.Value() );
248     if ( aZone.IsNull() )
249       continue;
250
251     TopoDS_Shape aZoneShape = aZone->GetShape();
252     if ( aZoneShape.IsNull() || aZoneShape.ShapeType() != TopAbs_FACE )
253       continue;
254
255     TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape );
256     aRegionFacesList.Append( aZoneFace );
257
258     getUsedGroups( aZoneFace, aSeqOfGroups, aSeqOfUsedGroups );
259   } // zones iterator
260   
261   if ( aRegionFacesList.IsEmpty() )
262     return aResShape;
263
264   // The unite region face
265   TopoDS_Face aRegionFace;
266
267   if ( aRegionFacesList.Extent() == 1 )
268   {
269     aRegionFace = TopoDS::Face( aRegionFacesList.First() );
270   }
271   else
272   {
273 #ifdef DEB_GET_REGION_SHAPE
274     HYDROData_ShapesGroup::GroupDefinition::Dump( std::cout, aSeqOfUsedGroups );
275 #endif
276
277     // Try to fuse all region faces into one common face
278     TopoDS_Shape aFuseShape;
279     TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
280     for ( ; aFaceIter.More(); aFaceIter.Next() )
281     {
282       if ( aFuseShape.IsNull() )
283       {
284         aFuseShape = aFaceIter.Value();
285         continue;
286       }
287
288       BRepAlgoAPI_Fuse aFuse( aFuseShape, aFaceIter.Value() );
289       if ( !aFuse.IsDone() )
290       {
291         aFuseShape.Nullify();
292         break;
293       }
294
295       aFuseShape = aFuse.Shape();
296       HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &aFuse );
297     } // faces iterator
298
299 #ifdef DEB_GET_REGION_SHAPE
300     HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Fused face edges:", aFuseShape, TopAbs_EDGE );
301 #endif
302
303     // Check the result of fuse operation
304     if ( !aFuseShape.IsNull() )
305     {
306       ShapeUpgrade_UnifySameDomain anUnifier( aFuseShape );
307       anUnifier.Build();
308
309       const TopoDS_Shape& anUnitedShape = anUnifier.Shape();
310
311       TopTools_SequenceOfShape aShapeFaces;
312       HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_FACE, aShapeFaces );
313       if ( aShapeFaces.Length() == 1 )
314       {
315         aRegionFace = TopoDS::Face( aShapeFaces.Value( 1 ) );
316
317 #ifdef DEB_GET_REGION_SHAPE
318         HYDROData_ShapesTool::DumpShapeSubShapes( std::cout, "Result face edges:", aRegionFace, TopAbs_EDGE );
319 #endif
320
321         HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfUsedGroups, &anUnifier );
322
323         // Update the sequence of groups
324         if ( theSeqOfGroups )
325         {
326           HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator aUsedIter( aSeqOfUsedGroups );
327           for ( ; aUsedIter.More(); aUsedIter.Next() )
328           {
329             const HYDROData_ShapesGroup::GroupDefinition& aUsedGroupDef = aUsedIter.Value();
330             if ( aUsedGroupDef.Shapes.IsEmpty() )
331               continue;
332
333             HYDROData_ShapesGroup::SeqOfGroupsDefs::Iterator anOriIter( aSeqOfGroups );
334             for ( ; anOriIter.More(); anOriIter.Next() )
335             {
336               HYDROData_ShapesGroup::GroupDefinition& anOriGroupDef = anOriIter.ChangeValue();
337               if ( anOriGroupDef.Name != aUsedGroupDef.Name )
338                 continue;
339
340               HYDROData_ShapesTool::AddShapes( anOriGroupDef.Shapes, aUsedGroupDef.Shapes );
341               break;
342             }
343           }
344
345           *theSeqOfGroups = aSeqOfGroups;
346         }
347       }
348     }
349   }
350
351   if ( !aRegionFace.IsNull() )
352   {
353     // result shape is a face
354     aResShape = aRegionFace;
355   }
356   else
357   {
358     // result shape is a shell
359     TopoDS_Shell aShell;
360     BRep_Builder aBuilder;
361     aBuilder.MakeShell( aShell );
362
363     TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
364     for ( ; aFaceIter.More(); aFaceIter.Next() )
365       aBuilder.Add( aShell, aFaceIter.Value() );
366
367     aResShape = aShell;
368   }
369   
370   return aResShape;
371 }