Salome HOME
Creat\Edit stream operation.
[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 TopoDS_Shape HYDROData_Stream::GetTopShape() const
58 {
59   return getTopShape();
60 }
61
62 TopoDS_Shape HYDROData_Stream::GetShape3D() const
63 {
64   return getShape3D();
65 }
66
67 void HYDROData_Stream::Update()
68 {
69   removeTopShape();
70   removeShape3D();
71
72   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
73   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
74   if ( aHydAxis.IsNull() || aRefProfiles.IsEmpty() )
75     return; 
76
77   TopoDS_Shell a2dShell;
78   BRep_Builder a2dShellBuilder;
79   a2dShellBuilder.MakeShell( a2dShell );
80
81   bool anIsFirst = true;
82   gp_Pnt aPrevFirstPoint, aPrevLastPoint;
83   
84   // Construct the top presentation
85   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
86   for ( ; anIter.More(); anIter.Next() )
87   {
88     Handle(HYDROData_Profile) aProfile =
89       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
90     if ( aProfile.IsNull() )
91       continue;
92
93     gp_XY aPnt1, aPnt2;
94     if ( !aProfile->GetFirstPoint( aPnt1 ) || !aProfile->GetLastPoint( aPnt2 ) )
95       continue;
96     
97     gp_Pnt aCurFirstPoint( aPnt1.X(), aPnt1.Y(), 0 );
98     gp_Pnt aCurLastPoint(  aPnt2.X(), aPnt2.Y(), 0 );
99
100     if ( anIsFirst )
101     {
102       aPrevFirstPoint = aCurFirstPoint;
103       aPrevLastPoint = aCurLastPoint;
104       anIsFirst = false;
105       continue;
106     }
107
108     BRepBuilderAPI_MakeEdge aFirstEdge( aPrevFirstPoint, aPrevLastPoint );
109     BRepBuilderAPI_MakeEdge aSecondEdge( aPrevLastPoint, aCurLastPoint );
110     BRepBuilderAPI_MakeEdge aThirdEdge( aCurLastPoint, aCurFirstPoint );
111     BRepBuilderAPI_MakeEdge aFourthEdge( aCurFirstPoint, aPrevFirstPoint );
112
113     BRepBuilderAPI_MakeWire aMakeWire( aFirstEdge.Edge(), aSecondEdge.Edge(), 
114                                        aThirdEdge.Edge(), aFourthEdge.Edge() );
115     
116     TopoDS_Wire aSectProfileWire = aMakeWire.Wire();
117     
118     BRepBuilderAPI_MakeFace aMakeFace( aSectProfileWire, Standard_True );
119     aMakeFace.Build();
120     if( aMakeFace.IsDone() )
121     {
122       a2dShellBuilder.Add( a2dShell, aMakeFace.Face() );
123     }
124
125     aPrevFirstPoint = aCurFirstPoint;
126     aPrevLastPoint = aCurLastPoint;
127   }
128
129   SetTopShape( a2dShell );
130
131   // Construct the 3D presentation
132   /// TODO
133 }
134
135 bool HYDROData_Stream::SetHydraulicAxis( const Handle(HYDROData_PolylineXY)& theAxis )
136 {
137   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
138
139   if ( theAxis.IsNull() )
140   {
141     RemoveHydraulicAxis();
142     return !aPrevAxis.IsNull();
143   }
144
145   if ( IsEqual( aPrevAxis, theAxis ) )
146     return false;
147
148   TopoDS_Wire aHydraulicWire = TopoDS::Wire( theAxis->GetShape() );
149   if ( aHydraulicWire.IsNull() )
150     return false; // The polyline must be a single wire
151
152   SetReferenceObject( theAxis, DataTag_HydraulicAxis );
153
154   // Update the order of profiles
155   updateProfilesOrder();
156
157   // Indicate model of the need to update the stream presentation
158   SetToUpdate( true );
159
160   return true;
161 }
162
163 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetHydraulicAxis() const
164 {
165   return Handle(HYDROData_PolylineXY)::DownCast( 
166            GetReferenceObject( DataTag_HydraulicAxis ) );
167 }
168
169 void HYDROData_Stream::RemoveHydraulicAxis()
170 {
171   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
172   if ( aPrevAxis.IsNull() )
173     return;
174
175   ClearReferenceObjects( DataTag_HydraulicAxis );
176
177   // We remove the reference profiles
178   RemoveProfiles();
179
180   // Indicate model of the need to update the stream presentation
181   SetToUpdate( true );
182 }
183
184 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_Profile)& theProfile ) const
185 {
186   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
187   if ( theProfile.IsNull() || aHydAxis.IsNull() )
188     return false; 
189
190   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
191   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
192   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
193     return false;
194
195   // TODO
196
197   return true;
198 }
199
200 bool HYDROData_Stream::AddProfile( const Handle(HYDROData_Profile)& theProfile )
201 {
202   if ( theProfile.IsNull() )
203     return false; 
204
205   if ( HasReference( theProfile, DataTag_Profile ) || !HasIntersection( theProfile ) )
206     return false; // Object is already in reference list or it has no intersection
207
208   insertProfileInToOrder( theProfile );
209   
210   // Indicate model of the need to update the stream presentation
211   SetToUpdate( true );
212
213   return true;
214 }
215
216 HYDROData_SequenceOfObjects HYDROData_Stream::GetProfiles() const
217 {
218   return GetReferenceObjects( DataTag_Profile );
219 }
220
221 bool HYDROData_Stream::RemoveProfile( const Handle(HYDROData_Profile)& theProfile )
222 {
223   if ( theProfile.IsNull() || !HasReference( theProfile, DataTag_Profile ) )
224     return false;
225
226   RemoveReferenceObject( theProfile->Label(), DataTag_Profile );
227
228   // Indicate model of the need to update the stream presentation
229   SetToUpdate( true );
230
231   return true;
232 }
233
234 void HYDROData_Stream::RemoveProfiles()
235 {
236   bool anIsToUpdate = IsMustBeUpdated() || NbReferenceObjects( DataTag_Profile ) > 0;
237
238   ClearReferenceObjects( DataTag_Profile );
239
240   // Indicate model of the need to update the stream presentation
241   SetToUpdate( anIsToUpdate );
242 }
243
244 void HYDROData_Stream::insertProfileInToOrder( const Handle(HYDROData_Profile)& theProfile )
245 {
246   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
247   if ( theProfile.IsNull() || aHydAxis.IsNull() )
248     return; 
249
250   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
251   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
252   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
253     return;
254
255   // TODO
256   AddReferenceObject( theProfile, DataTag_Profile ); // temporary for testing only
257 }
258
259 void HYDROData_Stream::updateProfilesOrder()
260 {
261   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
262   if ( aRefProfiles.IsEmpty() )
263     return;
264
265   // At first we remove all profiles from order
266   RemoveProfiles();
267
268   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
269   if ( aHydAxis.IsNull() )
270     return;
271
272   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
273   for ( ; anIter.More(); anIter.Next() )
274   {
275     Handle(HYDROData_Profile) aProfile =
276       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
277     if ( aProfile.IsNull() || !HasIntersection( aProfile ) )
278       continue;
279
280     insertProfileInToOrder( aProfile );
281   }
282 }
283