Salome HOME
patch for correct compilation on Linux
[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 #include <TopoDS_Edge.hxx>
18 #include <TopoDS_Vertex.hxx>
19 #include <TopExp.hxx>
20 #include <TopExp_Explorer.hxx>
21 #include <BRepProj_Projection.hxx>
22 #include <BRepExtrema_ExtCC.hxx>
23 #include <gp_Ax1.hxx>
24 #include <gp_Ax2.hxx>
25 #include <gp_Ax3.hxx>
26 #include <gp_Vec.hxx>
27 #include <gp_Pnt.hxx>
28 #include <gp_Pln.hxx>
29 #include <gp.hxx>
30 #include <Precision.hxx>
31 #include <QStringList>
32
33 #define PYTHON_STREAM_ID "KIND_STREAM"
34
35 IMPLEMENT_STANDARD_HANDLE(HYDROData_Stream,HYDROData_NaturalObject)
36 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Stream,HYDROData_NaturalObject)
37
38
39 HYDROData_Stream::HYDROData_Stream()
40 : HYDROData_NaturalObject()
41 {
42 }
43
44 HYDROData_Stream::~HYDROData_Stream()
45 {
46 }
47
48 QStringList HYDROData_Stream::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
49 {
50   QStringList aResList;
51
52   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
53   if ( aDocument.IsNull() )
54     return aResList;
55
56   QString aDocName = aDocument->GetDocPyName();
57   QString aStreamName = GetName();
58
59   aResList << QString( "%1 = %2.CreateObject( %3 );" )
60               .arg( aStreamName ).arg( aDocName ).arg( PYTHON_STREAM_ID );
61   aResList << QString( "%1.SetName( \"%2\" );" )
62               .arg( aStreamName ).arg( aStreamName );
63   aResList << QString( "" );
64
65   // TODO
66
67   return aResList;
68 }
69
70 HYDROData_SequenceOfObjects HYDROData_Stream::GetAllReferenceObjects() const
71 {
72   HYDROData_SequenceOfObjects aResSeq = HYDROData_Object::GetAllReferenceObjects();
73
74   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
75   if ( !aHydAxis.IsNull() )
76     aResSeq.Append( aHydAxis );
77
78   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
79   aResSeq.Append( aSeqOfProfiles );
80
81   return aResSeq;
82 }
83
84 TopoDS_Shape HYDROData_Stream::GetTopShape() const
85 {
86   return getTopShape();
87 }
88
89 TopoDS_Shape HYDROData_Stream::GetShape3D() const
90 {
91   return getShape3D();
92 }
93
94 void HYDROData_Stream::Update()
95 {
96   HYDROData_NaturalObject::Update();
97
98   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
99   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
100   if ( aHydAxis.IsNull() || aRefProfiles.IsEmpty() )
101     return; 
102
103   TopoDS_Shell a2dShell;
104   BRep_Builder a2dShellBuilder;
105   a2dShellBuilder.MakeShell( a2dShell );
106
107   bool anIsFirst = true;
108   gp_Pnt aPrevFirstPoint, aPrevLastPoint;
109   
110   // Construct the top presentation
111   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
112   for ( ; anIter.More(); anIter.Next() )
113   {
114     Handle(HYDROData_Profile) aProfile =
115       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
116     if ( aProfile.IsNull() )
117       continue;
118
119     gp_XY aPnt1, aPnt2;
120     if ( !aProfile->GetFirstPoint( aPnt1 ) || !aProfile->GetLastPoint( aPnt2 ) )
121       continue;
122     
123     gp_Pnt aCurFirstPoint( aPnt1.X(), aPnt1.Y(), 0 );
124     gp_Pnt aCurLastPoint(  aPnt2.X(), aPnt2.Y(), 0 );
125
126     if ( anIsFirst )
127     {
128       aPrevFirstPoint = aCurFirstPoint;
129       aPrevLastPoint = aCurLastPoint;
130       anIsFirst = false;
131       continue;
132     }
133
134     BRepBuilderAPI_MakeEdge aFirstEdge( aPrevFirstPoint, aPrevLastPoint );
135     BRepBuilderAPI_MakeEdge aSecondEdge( aPrevLastPoint, aCurLastPoint );
136     BRepBuilderAPI_MakeEdge aThirdEdge( aCurLastPoint, aCurFirstPoint );
137     BRepBuilderAPI_MakeEdge aFourthEdge( aCurFirstPoint, aPrevFirstPoint );
138
139     BRepBuilderAPI_MakeWire aMakeWire( aFirstEdge.Edge(), aSecondEdge.Edge(), 
140                                        aThirdEdge.Edge(), aFourthEdge.Edge() );
141     
142     TopoDS_Wire aSectProfileWire = aMakeWire.Wire();
143     
144     BRepBuilderAPI_MakeFace aMakeFace( aSectProfileWire, Standard_True );
145     aMakeFace.Build();
146     if( aMakeFace.IsDone() )
147     {
148       a2dShellBuilder.Add( a2dShell, aMakeFace.Face() );
149     }
150
151     aPrevFirstPoint = aCurFirstPoint;
152     aPrevLastPoint = aCurLastPoint;
153   }
154
155   SetTopShape( a2dShell );
156
157   // Construct the 3D presentation
158   /// TODO
159 }
160
161 bool HYDROData_Stream::SetHydraulicAxis( const Handle(HYDROData_PolylineXY)& theAxis )
162 {
163   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
164
165   if ( theAxis.IsNull() )
166   {
167     RemoveHydraulicAxis();
168     return !aPrevAxis.IsNull();
169   }
170
171   if ( IsEqual( aPrevAxis, theAxis ) )
172     return false;
173
174   TopoDS_Wire aHydraulicWire = TopoDS::Wire( theAxis->GetShape() );
175   if ( aHydraulicWire.IsNull() )
176     return false; // The polyline must be a single wire
177
178   SetReferenceObject( theAxis, DataTag_HydraulicAxis );
179
180   // Update the order of profiles
181   updateProfilesOrder();
182
183   // Indicate model of the need to update the stream presentation
184   SetToUpdate( true );
185
186   return true;
187 }
188
189 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetHydraulicAxis() const
190 {
191   return Handle(HYDROData_PolylineXY)::DownCast( 
192            GetReferenceObject( DataTag_HydraulicAxis ) );
193 }
194
195 void HYDROData_Stream::RemoveHydraulicAxis()
196 {
197   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
198   if ( aPrevAxis.IsNull() )
199     return;
200
201   ClearReferenceObjects( DataTag_HydraulicAxis );
202
203   // We remove the reference profiles
204   RemoveProfiles();
205
206   // Indicate model of the need to update the stream presentation
207   SetToUpdate( true );
208 }
209
210 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_Profile)& theProfile, const TopoDS_Face& thePlane,
211                                                                            Standard_Real& outPar ) const
212 {
213   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
214   if ( theProfile.IsNull() || aHydAxis.IsNull() )
215     return false; 
216
217   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() ); //guide line
218   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
219   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
220     return false;
221
222   // TODO
223   return true; // temporary
224   BRepProj_Projection aProjector (aProfileWire, thePlane, gp::OZ().Direction());
225   if(!aProjector.IsDone())
226     return false;
227   TopoDS_Shape aPrjProfile = aProjector.Shape();
228   if(aPrjProfile.IsNull())
229     return false;
230   TopoDS_Vertex aV1, aV2;
231   if(aPrjProfile.ShapeType() == TopAbs_EDGE)
232           TopExp::Vertices(TopoDS::Edge(aPrjProfile), aV1, aV2);          
233   else if(aPrjProfile.ShapeType() == TopAbs_WIRE)  
234           TopExp::Vertices(TopoDS::Wire(aPrjProfile), aV1, aV2);          
235   else if(aPrjProfile.ShapeType() == TopAbs_COMPOUND){
236     TopExp_Explorer anExp(aPrjProfile, TopAbs_WIRE);
237         if(anExp.More()) {
238                 TopExp::Vertices(TopoDS::Wire(anExp.Current()), aV1, aV2);        
239         } else {
240           anExp.Init(aPrjProfile, TopAbs_EDGE);
241           if(anExp.More()) {
242                 TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV1, aV2);        
243           }
244         }
245   }
246   if(aV1.IsNull() || aV2.IsNull())
247         return false;
248   gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
249   gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
250   aPnt1.SetZ(0.0);
251   aPnt2.SetZ(0.0);
252   BRepBuilderAPI_MakeEdge aMk(aPnt1, aPnt2); 
253   if(!aMk.IsDone())
254     return false;
255   const TopoDS_Edge& anEdg2 = aMk.Edge();//Section edge
256   Standard_Integer aNum(0);
257   
258   TopExp_Explorer anExplo(aHydraulicWire, TopAbs_EDGE);
259   for(;anExplo.More();anExplo.Next()) aNum++;
260   // check for self-intersection
261   const Standard_Real SquareTolerance = Precision::Confusion()*Precision::Confusion();
262   Standard_Boolean hasInt(false);
263   Standard_Real aSqDist(DBL_MAX);
264   Standard_Integer anIndx(0);
265   BRepExtrema_ExtCC aCC;
266   aCC.Initialize(anEdg2);
267   outPar = 0.0;
268   anExplo.Init(aHydraulicWire, TopAbs_EDGE);
269   for(Standard_Integer j=1;anExplo.More();anExplo.Next(),j++) {
270         const TopoDS_Edge& anEdg1 = TopoDS::Edge(anExplo.Current());
271         if(anEdg1.IsNull())
272           continue;     
273         aCC.Perform(anEdg1);
274     if(aCC.IsDone()) {
275     for(Standard_Integer i=1; i<= aCC.NbExt();i++)
276       if(aCC.SquareDistance(i) < aSqDist) {
277         aSqDist = aCC.SquareDistance(i);
278         anIndx = i;
279                 hasInt = true;          
280           }  
281         }
282         if(hasInt) {    
283       if(aSqDist <= SquareTolerance) {
284         const gp_Pnt& aPnt = aCC.PointOnE1(anIndx);
285         if(aNum > 1) {
286           TopExp::Vertices(anEdg1, aV1, aV2, Standard_True);
287                   outPar += BRep_Tool::Pnt(aV1).Distance(aPnt);
288             } else {
289           Standard_Real aPar = aCC.ParameterOnE1(anIndx);
290                   outPar = aPar;
291             }
292             break;
293           } else {
294         if(aNum > 1) {
295           TopExp::Vertices(anEdg1, aV1, aV2);
296               outPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
297             }
298           }
299         }
300   }
301   return true;
302 }
303
304 bool HYDROData_Stream::AddProfile( const Handle(HYDROData_Profile)& theProfile )
305 {
306   if ( theProfile.IsNull() )
307     return false; 
308   gp_Ax2 aX2(gp::XOY());
309   gp_Ax3 aX3(aX2);
310   gp_Pln aPln(aX3);
311   BRepBuilderAPI_MakeFace aMkr(aPln);
312   if(!aMkr.IsDone())
313         return false;
314   const TopoDS_Face& aPlane = TopoDS::Face(aMkr.Shape());
315   Standard_Real aPar(.0);
316   if ( HasReference( theProfile, DataTag_Profile ) || !HasIntersection( theProfile, aPlane, aPar ) )
317     return false; // Object is already in reference list or it has no intersection
318
319   insertProfileInToOrder( theProfile );
320   
321   // Indicate model of the need to update the stream presentation
322   SetToUpdate( true );
323
324   return true;
325 }
326
327 HYDROData_SequenceOfObjects HYDROData_Stream::GetProfiles() const
328 {
329   return GetReferenceObjects( DataTag_Profile );
330 }
331
332 bool HYDROData_Stream::RemoveProfile( const Handle(HYDROData_Profile)& theProfile )
333 {
334   if ( theProfile.IsNull() || !HasReference( theProfile, DataTag_Profile ) )
335     return false;
336
337   RemoveReferenceObject( theProfile->Label(), DataTag_Profile );
338
339   // Indicate model of the need to update the stream presentation
340   SetToUpdate( true );
341
342   return true;
343 }
344
345 void HYDROData_Stream::RemoveProfiles()
346 {
347   bool anIsToUpdate = IsMustBeUpdated() || NbReferenceObjects( DataTag_Profile ) > 0;
348
349   ClearReferenceObjects( DataTag_Profile );
350
351   // Indicate model of the need to update the stream presentation
352   SetToUpdate( anIsToUpdate );
353 }
354
355 void HYDROData_Stream::insertProfileInToOrder( const Handle(HYDROData_Profile)& theProfile )
356 {
357   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
358   if ( theProfile.IsNull() || aHydAxis.IsNull() )
359     return; 
360
361   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
362   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
363   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
364     return;
365
366   // TODO
367   AddReferenceObject( theProfile, DataTag_Profile ); // temporary for testing only
368 }
369
370 void HYDROData_Stream::updateProfilesOrder()
371 {
372   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
373   if ( aRefProfiles.IsEmpty() )
374     return;
375
376   // At first we remove all profiles from order
377   RemoveProfiles();
378
379   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
380   if ( aHydAxis.IsNull() )
381     return;
382   gp_Ax2 aX2(gp::XOY());
383   gp_Ax3 aX3(aX2);
384   gp_Pln aPln(aX3);
385   BRepBuilderAPI_MakeFace aMkr(aPln);
386   if(!aMkr.IsDone())
387         return;
388   const TopoDS_Face& aPlane = TopoDS::Face(aMkr.Shape());
389   Standard_Real aPar(.0);
390   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
391   for ( ; anIter.More(); anIter.Next() )
392   {
393     Handle(HYDROData_Profile) aProfile =
394       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
395     if ( aProfile.IsNull() || !HasIntersection( aProfile, aPlane, aPar ) )
396       continue;
397
398     insertProfileInToOrder( aProfile );
399   }
400 }
401