Salome HOME
Import profiles protection (Bug #203).
[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_Zone.h"
8
9 #include <TopoDS.hxx>
10 #include <TopoDS_Shape.hxx>
11 #include <TopoDS_Shell.hxx>
12 #include <TopoDS_Face.hxx>
13 #include <TopTools_ListOfShape.hxx>
14 #include <TopTools_ListIteratorOfListOfShape.hxx>
15 #include <TopTools_IndexedMapOfShape.hxx>
16 #include <TopExp.hxx>
17 #include <BRep_Builder.hxx>
18 #include <BRepAlgoAPI_Fuse.hxx>
19 #include <ShapeUpgrade_UnifySameDomain.hxx>
20
21 #include <QStringList>
22
23 #define PYTHON_REGION_ID "KIND_REGION"
24
25 IMPLEMENT_STANDARD_HANDLE(HYDROData_Region, HYDROData_Entity)
26 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Entity)
27
28
29 HYDROData_Region::HYDROData_Region()
30  : HYDROData_Entity()
31 {
32 }
33
34 HYDROData_Region::~HYDROData_Region()
35 {
36 }
37
38 QStringList HYDROData_Region::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
39 {
40   QStringList aResList;
41
42   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
43   if ( aDocument.IsNull() )
44     return aResList;
45
46   QString aDocName = aDocument->GetDocPyName();
47   QString aRegionName = GetName();
48
49   aResList << QString( "%1 = %2.CreateObject( %3 );" )
50               .arg( aRegionName ).arg( aDocName ).arg( PYTHON_REGION_ID );
51   aResList << QString( "%1.SetName( \"%2\" );" )
52               .arg( aRegionName ).arg( aRegionName );
53   aResList << QString( "" );
54
55   HYDROData_SequenceOfObjects aZones = GetZones();
56   HYDROData_SequenceOfObjects::Iterator anIter( aZones );
57   for ( ; anIter.More(); anIter.Next() )
58   {
59     Handle(HYDROData_Zone) aRefZone =
60       Handle(HYDROData_Zone)::DownCast( anIter.Value() );
61     if ( !aRefZone.IsNull() )
62       setPythonReferenceObject( theTreatedObjects, aResList, aRefZone, "AddZone" );
63   }
64   aResList << QString( "" );
65
66   return aResList;
67 }
68
69 bool HYDROData_Region::CanBeUpdated() const
70 {
71   return false;
72 }
73
74 void HYDROData_Region::Remove()
75 {
76   Handle(HYDROData_CalculationCase) aFatherCalc = 
77     Handle(HYDROData_CalculationCase)::DownCast( GetFatherObject() );
78
79   HYDROData_Entity::Remove();
80
81   if ( !aFatherCalc.IsNull() )
82     aFatherCalc->UpdateRegionsOrder();
83 }
84
85 bool HYDROData_Region::CanRemove()
86 {
87   return false;
88 }
89
90 HYDROData_SequenceOfObjects HYDROData_Region::GetAllReferenceObjects() const
91 {
92   HYDROData_SequenceOfObjects aResSeq = HYDROData_Entity::GetAllReferenceObjects();
93
94   HYDROData_SequenceOfObjects aSeqOfZones = GetZones();
95   aResSeq.Append( aSeqOfZones );
96
97   return aResSeq;
98 }
99
100 bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone )
101 {
102   if ( theZone.IsNull() )
103     return false;
104   
105   if ( HasReference( theZone, DataTag_Zone ) )
106     return false; // Object is already in reference list
107
108   // Move the zone from other region
109   Handle(HYDROData_Region) aFatherRegion = 
110     Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
111   if ( !aFatherRegion.IsNull() && aFatherRegion->Label() != myLab )
112   {
113     Handle(HYDROData_Zone) aNewZone = addNewZone();
114     theZone->CopyTo( aNewZone );
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 TopoDS_Shape HYDROData_Region::GetShape() const
170 {
171   TopoDS_Shape aResShape;
172
173   // Unite the region zones (each zone is a face) into one face (united face)
174   // If the zones can't be united into the single face - unite them into shell
175
176   // Collect the list of region faces
177   TopTools_ListOfShape aRegionFacesList;
178
179   HYDROData_SequenceOfObjects aZones = GetZones();
180   HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones );
181   for ( ; aZoneIter.More(); aZoneIter.Next() ) {
182     Handle(HYDROData_Zone) aZone =
183       Handle(HYDROData_Zone)::DownCast( aZoneIter.Value() );
184   
185     if ( aZone.IsNull() ) {
186       continue;
187     }
188
189     TopoDS_Face aFace = TopoDS::Face( aZone->GetShape() );
190     if ( !aFace.IsNull() ) {
191       aRegionFacesList.Append( aFace );
192     }
193   } // zones iterator
194   
195   // Check number of faces
196   int aNbFaces = aRegionFacesList.Extent();
197   if ( aNbFaces > 0 ) {
198     // The unite region face
199     TopoDS_Face aRegionFace;
200   
201     if ( aNbFaces == 1 ) {
202       aRegionFace = TopoDS::Face( aRegionFacesList.First() );
203     } else {
204       // Fuse faces into one
205       TopoDS_Shape aFuseShape;
206       TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
207       for ( ; aFaceIter.More(); aFaceIter.Next() ) {
208         if ( aFuseShape.IsNull() ) {
209           aFuseShape = aFaceIter.Value();
210         } else {
211           BRepAlgoAPI_Fuse aFuse(aFuseShape, aFaceIter.Value());
212           if ( !aFuse.IsDone() ) {
213             aFuseShape.Nullify();
214             break;
215           }
216           aFuseShape = aFuse.Shape();
217         }
218       } // faces iterator
219
220       // Check the result of fuse operation
221       if ( !aFuseShape.IsNull() ) {
222         ShapeUpgrade_UnifySameDomain anUnifier( aFuseShape );
223         anUnifier.Build();
224         TopoDS_Shape anUnitedShape = anUnifier.Shape();
225
226         TopTools_IndexedMapOfShape aMapOfFaces;
227         TopExp::MapShapes( anUnitedShape, TopAbs_FACE, aMapOfFaces );
228         if ( aMapOfFaces.Extent() == 1 ) {
229           aRegionFace = TopoDS::Face( aMapOfFaces(1) );
230         }
231       }
232     }
233
234     if ( !aRegionFace.IsNull() ) { // result shape is a face
235       aResShape = aRegionFace;
236     } else { // result shape is a shell
237       TopoDS_Shell aShell;
238       BRep_Builder aBuilder;
239       aBuilder.MakeShell( aShell );
240
241       TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
242       for ( ; aFaceIter.More(); aFaceIter.Next() ) {
243         aBuilder.Add( aShell, aFaceIter.Value() );
244       }
245
246       aResShape = aShell;
247     }
248   }
249   
250   return aResShape;
251 }