]> SALOME platform Git repositories - modules/hydro.git/blob - src/HYDROData/HYDROData_Region.cxx
Salome HOME
Common part of dump to python is moved to HYDROData_Entity.
[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
21 #include <BRep_Builder.hxx>
22 #include <BRepAlgoAPI_Fuse.hxx>
23
24 #include <ShapeUpgrade_UnifySameDomain.hxx>
25
26 #include <QStringList>
27
28 IMPLEMENT_STANDARD_HANDLE(HYDROData_Region, HYDROData_Entity)
29 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Entity)
30
31
32 HYDROData_Region::HYDROData_Region()
33  : HYDROData_Entity()
34 {
35 }
36
37 HYDROData_Region::~HYDROData_Region()
38 {
39 }
40
41 QStringList HYDROData_Region::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
42 {
43   QStringList aResList = HYDROData_Entity::DumpToPython( theTreatedObjects );
44   QString aRegionName = GetName();
45
46   HYDROData_SequenceOfObjects aZones = GetZones();
47   HYDROData_SequenceOfObjects::Iterator anIter( aZones );
48   for ( ; anIter.More(); anIter.Next() )
49   {
50     Handle(HYDROData_Zone) aRefZone =
51       Handle(HYDROData_Zone)::DownCast( anIter.Value() );
52     if ( !aRefZone.IsNull() )
53       setPythonReferenceObject( theTreatedObjects, aResList, aRefZone, "AddZone" );
54   }
55   aResList << QString( "" );
56
57   return aResList;
58 }
59
60 bool HYDROData_Region::CanBeUpdated() const
61 {
62   return false;
63 }
64
65 void HYDROData_Region::Remove()
66 {
67   Handle(HYDROData_CalculationCase) aFatherCalc = 
68     Handle(HYDROData_CalculationCase)::DownCast( GetFatherObject() );
69
70   HYDROData_Entity::Remove();
71
72   if ( !aFatherCalc.IsNull() )
73     aFatherCalc->UpdateRegionsOrder();
74 }
75
76 bool HYDROData_Region::CanRemove()
77 {
78   return false;
79 }
80
81 HYDROData_SequenceOfObjects HYDROData_Region::GetAllReferenceObjects() const
82 {
83   HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
84
85   HYDROData_SequenceOfObjects aSeqOfZones = GetZones();
86   aResSeq.Append( aSeqOfZones );
87
88   return aResSeq;
89 }
90
91 bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone )
92 {
93   if ( theZone.IsNull() )
94     return false;
95   
96   if ( HasReference( theZone, DataTag_Zone ) )
97     return false; // Object is already in reference list
98
99   // Move the zone from other region
100   Handle(HYDROData_Region) aFatherRegion = 
101     Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
102   if ( !aFatherRegion.IsNull() && aFatherRegion->Label() != myLab )
103   {
104     Handle(HYDROData_Zone) aNewZone = addNewZone();
105     theZone->CopyTo( aNewZone );
106
107     aFatherRegion->RemoveZone( theZone );
108
109     theZone->SetLabel( aNewZone->Label() );
110   }
111   else
112   {
113     AddReferenceObject( theZone, DataTag_Zone );
114   }
115
116   return true;
117 }
118
119 HYDROData_SequenceOfObjects HYDROData_Region::GetZones() const
120 {
121   return GetReferenceObjects( DataTag_Zone );
122 }
123
124 void HYDROData_Region::RemoveZone( const Handle(HYDROData_Zone)& theZone )
125 {
126   if ( theZone.IsNull() )
127     return;
128
129   RemoveReferenceObject( theZone->Label(), DataTag_Zone );
130
131   // Remove zone from data model
132   Handle(HYDROData_Region) aFatherRegion = 
133     Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
134   if ( !aFatherRegion.IsNull() && aFatherRegion->Label() == myLab )
135     theZone->Remove();
136
137   // If the last zone has been removed from region we remove this region
138   HYDROData_SequenceOfObjects aRefZones = GetZones();
139   if ( aRefZones.IsEmpty() )
140     Remove();
141 }
142
143 void HYDROData_Region::RemoveZones()
144 {
145   ClearReferenceObjects( DataTag_Zone );
146   myLab.FindChild( DataTag_ChildZone ).ForgetAllAttributes( true );
147 }
148
149 Handle(HYDROData_Zone) HYDROData_Region::addNewZone()
150 {
151   TDF_Label aNewLab = myLab.FindChild( DataTag_ChildZone ).NewChild();
152
153   Handle(HYDROData_Zone) aNewZone =
154     Handle(HYDROData_Zone)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_ZONE ) );
155   AddZone( aNewZone );
156
157   return aNewZone;
158 }
159
160 TopoDS_Shape HYDROData_Region::GetShape( HYDROData_ShapesGroup::SeqOfGroupsDefs* theSeqOfGroups ) const
161 {
162   HYDROData_ShapesGroup::SeqOfGroupsDefs aSeqOfGroups;
163   if ( theSeqOfGroups )
164     aSeqOfGroups = *theSeqOfGroups;
165
166   TopoDS_Shape aResShape;
167
168   // Unite the region zones (each zone is a face) into one face (united face)
169   // If the zones can't be united into the single face - unite them into shell
170
171   // Collect the list of region faces
172   TopTools_ListOfShape aRegionFacesList;
173
174   HYDROData_SequenceOfObjects aZones = GetZones();
175   HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones );
176   for ( ; aZoneIter.More(); aZoneIter.Next() )
177   {
178     Handle(HYDROData_Zone) aZone =
179       Handle(HYDROData_Zone)::DownCast( aZoneIter.Value() );
180     if ( aZone.IsNull() )
181       continue;
182
183     TopoDS_Shape aZoneShape = aZone->GetShape();
184     if ( aZoneShape.IsNull() || aZoneShape.ShapeType() != TopAbs_FACE )
185       continue;
186
187     TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape );
188     aRegionFacesList.Append( aZoneFace );
189   } // zones iterator
190   
191   if ( aRegionFacesList.IsEmpty() )
192     return aResShape;
193
194   // The unite region face
195   TopoDS_Face aRegionFace;
196
197   if ( aRegionFacesList.Extent() == 1 )
198   {
199     aRegionFace = TopoDS::Face( aRegionFacesList.First() );
200   }
201   else
202   {
203     // Try to fuse all region faces into one common face
204     TopoDS_Shape aFuseShape;
205     TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
206     for ( ; aFaceIter.More(); aFaceIter.Next() )
207     {
208       if ( aFuseShape.IsNull() )
209       {
210         aFuseShape = aFaceIter.Value();
211         continue;
212       }
213
214       BRepAlgoAPI_Fuse aFuse( aFuseShape, aFaceIter.Value() );
215       if ( !aFuse.IsDone() )
216       {
217         aFuseShape.Nullify();
218         break;
219       }
220
221       aFuseShape = aFuse.Shape();
222       HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfGroups, &aFuse );
223     } // faces iterator
224
225     // Check the result of fuse operation
226     if ( !aFuseShape.IsNull() )
227     {
228       ShapeUpgrade_UnifySameDomain anUnifier( aFuseShape );
229       anUnifier.Build();
230
231       const TopoDS_Shape& anUnitedShape = anUnifier.Shape();
232
233       TopTools_SequenceOfShape aShapeFaces;
234       HYDROData_ShapesTool::ExploreShapeToShapes( anUnitedShape, TopAbs_FACE, aShapeFaces );
235       if ( aShapeFaces.Length() == 1 )
236       {
237         aRegionFace = TopoDS::Face( aShapeFaces.Value( 1 ) );
238         HYDROData_ShapesGroup::GroupDefinition::Update( &aSeqOfGroups, &anUnifier );
239
240         // temporary commented because of needs of testing
241         //if ( theSeqOfGroups )
242           //*theSeqOfGroups = aSeqOfGroups;
243       }
244     }
245   }
246
247   if ( !aRegionFace.IsNull() )
248   {
249     // result shape is a face
250     aResShape = aRegionFace;
251   }
252   else
253   {
254     // result shape is a shell
255     TopoDS_Shell aShell;
256     BRep_Builder aBuilder;
257     aBuilder.MakeShell( aShell );
258
259     TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
260     for ( ; aFaceIter.More(); aFaceIter.Next() )
261       aBuilder.Add( aShell, aFaceIter.Value() );
262
263     aResShape = aShell;
264   }
265   
266   return aResShape;
267 }