Salome HOME
Move color tags to the base geometrical object class.
[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 <TopExp_Explorer.hxx>
16 #include <ShapeUpgrade_UnifySameDomain.hxx>
17 #include <BRep_Builder.hxx>
18 #include <BRepAlgoAPI_Fuse.hxx>
19
20 #include <QStringList>
21
22 #define PYTHON_REGION_ID "KIND_REGION"
23
24 IMPLEMENT_STANDARD_HANDLE(HYDROData_Region, HYDROData_Entity)
25 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Region, HYDROData_Entity)
26
27
28 HYDROData_Region::HYDROData_Region()
29  : HYDROData_Entity()
30 {
31 }
32
33 HYDROData_Region::~HYDROData_Region()
34 {
35 }
36
37 QStringList HYDROData_Region::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
38 {
39   QStringList aResList;
40
41   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
42   if ( aDocument.IsNull() )
43     return aResList;
44
45   QString aDocName = aDocument->GetDocPyName();
46   QString aRegionName = GetName();
47
48   aResList << QString( "%1 = %2.CreateObject( %3 );" )
49               .arg( aRegionName ).arg( aDocName ).arg( PYTHON_REGION_ID );
50   aResList << QString( "%1.SetName( \"%2\" );" )
51               .arg( aRegionName ).arg( aRegionName );
52   aResList << QString( "" );
53
54   HYDROData_SequenceOfObjects aZones = GetZones();
55   HYDROData_SequenceOfObjects::Iterator anIter( aZones );
56   for ( ; anIter.More(); anIter.Next() )
57   {
58     Handle(HYDROData_Zone) aRefZone =
59       Handle(HYDROData_Zone)::DownCast( anIter.Value() );
60     if ( !aRefZone.IsNull() )
61       setPythonReferenceObject( theTreatedObjects, aResList, aRefZone, "AddZone" );
62   }
63   aResList << QString( "" );
64
65   return aResList;
66 }
67
68 void HYDROData_Region::Remove()
69 {
70   Handle(HYDROData_CalculationCase) aFatherCalc = 
71     Handle(HYDROData_CalculationCase)::DownCast( GetFatherObject() );
72
73   HYDROData_Entity::Remove();
74
75   if ( !aFatherCalc.IsNull() )
76     aFatherCalc->UpdateRegionsOrder();
77 }
78
79 bool HYDROData_Region::AddZone( const Handle(HYDROData_Zone)& theZone )
80 {
81   if ( theZone.IsNull() )
82     return false;
83   
84   if ( HasReference( theZone, DataTag_Zone ) )
85     return false; // Object is already in reference list
86
87   // Move the zone from other region
88   Handle(HYDROData_Region) aFatherRegion = 
89     Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
90   if ( !aFatherRegion.IsNull() && aFatherRegion->Label() != myLab )
91   {
92     Handle(HYDROData_Zone) aNewZone = addNewZone();
93     theZone->CopyTo( aNewZone );
94
95     aFatherRegion->RemoveZone( theZone );
96
97     theZone->SetLabel( aNewZone->Label() );
98   }
99   else
100   {
101     AddReferenceObject( theZone, DataTag_Zone );
102   }
103
104   return true;
105 }
106
107 HYDROData_SequenceOfObjects HYDROData_Region::GetZones() const
108 {
109   return GetReferenceObjects( DataTag_Zone );
110 }
111
112 void HYDROData_Region::RemoveZone( const Handle(HYDROData_Zone)& theZone )
113 {
114   if ( theZone.IsNull() )
115     return;
116
117   RemoveReferenceObject( theZone->Label(), DataTag_Zone );
118
119   // Remove zone from data model
120   Handle(HYDROData_Region) aFatherRegion = 
121     Handle(HYDROData_Region)::DownCast( theZone->GetFatherObject() );
122   if ( !aFatherRegion.IsNull() && aFatherRegion->Label() == myLab )
123     theZone->Remove();
124
125   // If the last zone has been removed from region we remove this region
126   HYDROData_SequenceOfObjects aRefZones = GetZones();
127   if ( aRefZones.IsEmpty() )
128     Remove();
129 }
130
131 void HYDROData_Region::RemoveZones()
132 {
133   ClearReferenceObjects( DataTag_Zone );
134   myLab.FindChild( DataTag_ChildZone ).ForgetAllAttributes( true );
135 }
136
137 Handle(HYDROData_Zone) HYDROData_Region::addNewZone()
138 {
139   TDF_Label aNewLab = myLab.FindChild( DataTag_ChildZone ).NewChild();
140
141   Handle(HYDROData_Zone) aNewZone =
142     Handle(HYDROData_Zone)::DownCast( HYDROData_Iterator::CreateObject( aNewLab, KIND_ZONE ) );
143   AddZone( aNewZone );
144
145   return aNewZone;
146 }
147
148 TopoDS_Shape HYDROData_Region::GetShape() const
149 {
150   TopoDS_Shape aResShape;
151
152   // Unite the region zones (each zone is a face) into one face (united face)
153   // If the zones can't be united into the single face - unite them into shell
154
155   // Collect the list of region faces
156   TopTools_ListOfShape aRegionFacesList;
157
158   HYDROData_SequenceOfObjects aZones = GetZones();
159   HYDROData_SequenceOfObjects::Iterator aZoneIter( aZones );
160   for ( ; aZoneIter.More(); aZoneIter.Next() ) {
161     Handle(HYDROData_Zone) aZone =
162       Handle(HYDROData_Zone)::DownCast( aZoneIter.Value() );
163   
164     if ( aZone.IsNull() ) {
165       continue;
166     }
167
168     TopoDS_Face aFace = TopoDS::Face( aZone->GetShape() );
169     if ( !aFace.IsNull() ) {
170       aRegionFacesList.Append( aFace );
171     }
172   } // zones iterator
173   
174   // Check number of faces
175   int aNbFaces = aRegionFacesList.Extent();
176   if ( aNbFaces > 0 ) {
177     // The unite region face
178     TopoDS_Face aRegionFace;
179   
180     if ( aNbFaces == 1 ) {
181       aRegionFace = TopoDS::Face( aRegionFacesList.First() );
182     } else {
183       // Fuse faces into one
184       TopoDS_Shape aFuseShape;
185       TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
186       for ( ; aFaceIter.More(); aFaceIter.Next() ) {
187         if ( aFuseShape.IsNull() ) {
188           aFuseShape = aFaceIter.Value();
189         } else {
190           BRepAlgoAPI_Fuse aFuse(aFuseShape, aFaceIter.Value());
191           if ( !aFuse.IsDone() ) {
192             aFuseShape.Nullify();
193             break;
194           }
195           aFuseShape = aFuse.Shape();
196         }
197       } // faces iterator
198
199       if ( !aFuseShape.IsNull() ) {
200         ShapeUpgrade_UnifySameDomain anUnifier( aFuseShape );
201         anUnifier.UnifyFacesAndEdges();
202         anUnifier.Build();
203         TopoDS_Shape anUnitedShape = anUnifier.Shape();
204
205         TopExp_Explorer anExp( anUnitedShape, TopAbs_FACE );
206         if ( anExp.More() ) {
207           aRegionFace = TopoDS::Face( anExp.Current() );
208           anExp.Next();
209           if ( anExp.More() ) {
210             aRegionFace.Nullify();
211           }
212         }
213       }
214     }
215
216     if ( !aRegionFace.IsNull() ) { // result shape is a face
217       aResShape = aRegionFace;
218     } else { // result shape is a shell
219       TopoDS_Shell aShell;
220       BRep_Builder aBuilder;
221       aBuilder.MakeShell( aShell );
222
223       TopTools_ListIteratorOfListOfShape aFaceIter( aRegionFacesList );
224       for ( ; aFaceIter.More(); aFaceIter.Next() ) {
225         aBuilder.Add( aShell, aFaceIter.Value() );
226       }
227
228       aResShape = aShell;
229     }
230   }
231   
232   return aResShape;
233 }