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