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