Salome HOME
Fix for the feature #6: Update of objects (T 1.2): For objects which need updating...
[modules/hydro.git] / src / HYDROData / HYDROData_Stream.cxx
1
2 #include "HYDROData_Stream.h"
3
4 #include "HYDROData_Document.h"
5 #include "HYDROData_PolylineXY.h"
6 #include "HYDROData_Profile.h"
7
8 #include <BRep_Builder.hxx>
9 #include <BRepBuilderAPI_MakeEdge.hxx>
10 #include <BRepBuilderAPI_MakeWire.hxx>
11 #include <BRepBuilderAPI_MakeFace.hxx>
12
13 #include <TopoDS.hxx>
14 #include <TopoDS_Wire.hxx>
15 #include <TopoDS_Shell.hxx>
16 #include <TopoDS_Face.hxx>
17
18 #include <QStringList>
19
20 #define PYTHON_STREAM_ID "KIND_STREAM"
21
22 IMPLEMENT_STANDARD_HANDLE(HYDROData_Stream,HYDROData_NaturalObject)
23 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Stream,HYDROData_NaturalObject)
24
25
26 HYDROData_Stream::HYDROData_Stream()
27 : HYDROData_NaturalObject()
28 {
29 }
30
31 HYDROData_Stream::~HYDROData_Stream()
32 {
33 }
34
35 QStringList HYDROData_Stream::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
36 {
37   QStringList aResList;
38
39   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
40   if ( aDocument.IsNull() )
41     return aResList;
42
43   QString aDocName = aDocument->GetDocPyName();
44   QString aStreamName = GetName();
45
46   aResList << QString( "%1 = %2.CreateObject( %3 );" )
47               .arg( aStreamName ).arg( aDocName ).arg( PYTHON_STREAM_ID );
48   aResList << QString( "%1.SetName( \"%2\" );" )
49               .arg( aStreamName ).arg( aStreamName );
50   aResList << QString( "" );
51
52   // TODO
53
54   return aResList;
55 }
56
57 HYDROData_SequenceOfObjects HYDROData_Stream::GetAllReferenceObjects() const
58 {
59   HYDROData_SequenceOfObjects aResSeq = HYDROData_Object::GetAllReferenceObjects();
60
61   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
62   if ( !aHydAxis.IsNull() )
63     aResSeq.Append( aHydAxis );
64
65   aResSeq.Append( GetProfiles() );
66
67   return aResSeq;
68 }
69
70 TopoDS_Shape HYDROData_Stream::GetTopShape() const
71 {
72   return getTopShape();
73 }
74
75 TopoDS_Shape HYDROData_Stream::GetShape3D() const
76 {
77   return getShape3D();
78 }
79
80 void HYDROData_Stream::Update()
81 {
82   HYDROData_NaturalObject::Update();
83
84   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
85   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
86   if ( aHydAxis.IsNull() || aRefProfiles.IsEmpty() )
87     return; 
88
89   TopoDS_Shell a2dShell;
90   BRep_Builder a2dShellBuilder;
91   a2dShellBuilder.MakeShell( a2dShell );
92
93   bool anIsFirst = true;
94   gp_Pnt aPrevFirstPoint, aPrevLastPoint;
95   
96   // Construct the top presentation
97   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
98   for ( ; anIter.More(); anIter.Next() )
99   {
100     Handle(HYDROData_Profile) aProfile =
101       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
102     if ( aProfile.IsNull() )
103       continue;
104
105     gp_XY aPnt1, aPnt2;
106     if ( !aProfile->GetFirstPoint( aPnt1 ) || !aProfile->GetLastPoint( aPnt2 ) )
107       continue;
108     
109     gp_Pnt aCurFirstPoint( aPnt1.X(), aPnt1.Y(), 0 );
110     gp_Pnt aCurLastPoint(  aPnt2.X(), aPnt2.Y(), 0 );
111
112     if ( anIsFirst )
113     {
114       aPrevFirstPoint = aCurFirstPoint;
115       aPrevLastPoint = aCurLastPoint;
116       anIsFirst = false;
117       continue;
118     }
119
120     BRepBuilderAPI_MakeEdge aFirstEdge( aPrevFirstPoint, aPrevLastPoint );
121     BRepBuilderAPI_MakeEdge aSecondEdge( aPrevLastPoint, aCurLastPoint );
122     BRepBuilderAPI_MakeEdge aThirdEdge( aCurLastPoint, aCurFirstPoint );
123     BRepBuilderAPI_MakeEdge aFourthEdge( aCurFirstPoint, aPrevFirstPoint );
124
125     BRepBuilderAPI_MakeWire aMakeWire( aFirstEdge.Edge(), aSecondEdge.Edge(), 
126                                        aThirdEdge.Edge(), aFourthEdge.Edge() );
127     
128     TopoDS_Wire aSectProfileWire = aMakeWire.Wire();
129     
130     BRepBuilderAPI_MakeFace aMakeFace( aSectProfileWire, Standard_True );
131     aMakeFace.Build();
132     if( aMakeFace.IsDone() )
133     {
134       a2dShellBuilder.Add( a2dShell, aMakeFace.Face() );
135     }
136
137     aPrevFirstPoint = aCurFirstPoint;
138     aPrevLastPoint = aCurLastPoint;
139   }
140
141   SetTopShape( a2dShell );
142
143   // Construct the 3D presentation
144   /// TODO
145 }
146
147 bool HYDROData_Stream::SetHydraulicAxis( const Handle(HYDROData_PolylineXY)& theAxis )
148 {
149   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
150
151   if ( theAxis.IsNull() )
152   {
153     RemoveHydraulicAxis();
154     return !aPrevAxis.IsNull();
155   }
156
157   if ( IsEqual( aPrevAxis, theAxis ) )
158     return false;
159
160   TopoDS_Wire aHydraulicWire = TopoDS::Wire( theAxis->GetShape() );
161   if ( aHydraulicWire.IsNull() )
162     return false; // The polyline must be a single wire
163
164   SetReferenceObject( theAxis, DataTag_HydraulicAxis );
165
166   // Update the order of profiles
167   updateProfilesOrder();
168
169   // Indicate model of the need to update the stream presentation
170   SetToUpdate( true );
171
172   return true;
173 }
174
175 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetHydraulicAxis() const
176 {
177   return Handle(HYDROData_PolylineXY)::DownCast( 
178            GetReferenceObject( DataTag_HydraulicAxis ) );
179 }
180
181 void HYDROData_Stream::RemoveHydraulicAxis()
182 {
183   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
184   if ( aPrevAxis.IsNull() )
185     return;
186
187   ClearReferenceObjects( DataTag_HydraulicAxis );
188
189   // We remove the reference profiles
190   RemoveProfiles();
191
192   // Indicate model of the need to update the stream presentation
193   SetToUpdate( true );
194 }
195
196 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_Profile)& theProfile ) const
197 {
198   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
199   if ( theProfile.IsNull() || aHydAxis.IsNull() )
200     return false; 
201
202   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
203   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
204   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
205     return false;
206
207   // TODO
208
209   return true;
210 }
211
212 bool HYDROData_Stream::AddProfile( const Handle(HYDROData_Profile)& theProfile )
213 {
214   if ( theProfile.IsNull() )
215     return false; 
216
217   if ( HasReference( theProfile, DataTag_Profile ) || !HasIntersection( theProfile ) )
218     return false; // Object is already in reference list or it has no intersection
219
220   insertProfileInToOrder( theProfile );
221   
222   // Indicate model of the need to update the stream presentation
223   SetToUpdate( true );
224
225   return true;
226 }
227
228 HYDROData_SequenceOfObjects HYDROData_Stream::GetProfiles() const
229 {
230   return GetReferenceObjects( DataTag_Profile );
231 }
232
233 bool HYDROData_Stream::RemoveProfile( const Handle(HYDROData_Profile)& theProfile )
234 {
235   if ( theProfile.IsNull() || !HasReference( theProfile, DataTag_Profile ) )
236     return false;
237
238   RemoveReferenceObject( theProfile->Label(), DataTag_Profile );
239
240   // Indicate model of the need to update the stream presentation
241   SetToUpdate( true );
242
243   return true;
244 }
245
246 void HYDROData_Stream::RemoveProfiles()
247 {
248   bool anIsToUpdate = IsMustBeUpdated() || NbReferenceObjects( DataTag_Profile ) > 0;
249
250   ClearReferenceObjects( DataTag_Profile );
251
252   // Indicate model of the need to update the stream presentation
253   SetToUpdate( anIsToUpdate );
254 }
255
256 void HYDROData_Stream::insertProfileInToOrder( const Handle(HYDROData_Profile)& theProfile )
257 {
258   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
259   if ( theProfile.IsNull() || aHydAxis.IsNull() )
260     return; 
261
262   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
263   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
264   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
265     return;
266
267   // TODO
268   AddReferenceObject( theProfile, DataTag_Profile ); // temporary for testing only
269 }
270
271 void HYDROData_Stream::updateProfilesOrder()
272 {
273   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
274   if ( aRefProfiles.IsEmpty() )
275     return;
276
277   // At first we remove all profiles from order
278   RemoveProfiles();
279
280   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
281   if ( aHydAxis.IsNull() )
282     return;
283
284   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
285   for ( ; anIter.More(); anIter.Next() )
286   {
287     Handle(HYDROData_Profile) aProfile =
288       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
289     if ( aProfile.IsNull() || !HasIntersection( aProfile ) )
290       continue;
291
292     insertProfileInToOrder( aProfile );
293   }
294 }
295