]> SALOME platform Git repositories - modules/hydro.git/blob - src/HYDROData/HYDROData_ChannelAltitude.cxx
Salome HOME
Merge branch 'BR_H2018_3' into BR_2018_V8_5
[modules/hydro.git] / src / HYDROData / HYDROData_ChannelAltitude.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include "HYDROData_ChannelAltitude.h"
20
21 #include "HYDROData_Document.h"
22 #include "HYDROData_Object.h"
23 #include "HYDROData_Channel.h"
24 #include "HYDROData_Projection.h"
25 #include "HYDROData_Polyline3D.h"
26 #include "HYDROData_PolylineXY.h"
27 #include "HYDROData_ProfileUZ.h"
28 #include "HYDROData_Profile.h"
29
30 //#define _DEVDEBUG_
31 #include "HYDRO_trace.hxx"
32 #include <QString>
33
34 #include <BRepBuilderAPI_MakeVertex.hxx>
35 #include <BRepExtrema_DistShapeShape.hxx>
36
37 #include <Precision.hxx>
38 #include <TopAbs.hxx>
39 #include <TopExp.hxx>
40 #include <TopoDS.hxx>
41 #include <TopoDS_Shape.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Face.hxx>
44 #include <TopoDS_Vertex.hxx>
45 #include <TopoDS_Wire.hxx>
46 #include <TopExp_Explorer.hxx>
47 #include <TopAbs_ShapeEnum.hxx>
48 #include <BRep_Tool.hxx>
49 #include <BRepTools.hxx>
50 #include <Geom_Curve.hxx>
51
52 #include <gp_Trsf.hxx>
53 #include <gp_Pnt.hxx>
54 #include <gp_Vec.hxx>
55
56 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_ChannelAltitude, HYDROData_IAltitudeObject)
57
58 HYDROData_ChannelAltitude::HYDROData_ChannelAltitude()
59 : HYDROData_IAltitudeObject()
60 {
61 }
62
63 HYDROData_ChannelAltitude::~HYDROData_ChannelAltitude()
64 {
65 }
66
67 double HYDROData_ChannelAltitude::GetAltitudeForPoint( const gp_XY& thePoint,
68                                                        int theMethod) const
69 {
70   DEBTRACE("GetAltitudeForPoint p(" << thePoint.X() << ", " << thePoint.Y() << ")");
71   double aResAltitude = GetInvalidAltitude();
72
73   Handle(HYDROData_Channel) aChannel =
74   Handle(HYDROData_Channel)::DownCast(GetFatherObject());
75   if (aChannel.IsNull())
76     {
77       DEBTRACE("aChannel.IsNull()");
78       return aResAltitude;
79     }
80   DEBTRACE("aChannel: " << aChannel->GetName().toStdString());
81
82   Handle(HYDROData_Polyline3D) aGuideLine = aChannel->GetGuideLine();
83   if (aGuideLine.IsNull())
84     {
85       DEBTRACE("aGuideLine.IsNull()");
86       return aResAltitude;
87     }
88   //DEBTRACE("aGuideLine: " << aGuideLine->GetName().toStdString());
89
90   Handle(HYDROData_PolylineXY) aGuideXY = aGuideLine->GetPolylineXY();
91   if (aGuideXY.IsNull())
92     {
93       DEBTRACE("aGuideXY.IsNull()");
94       return aResAltitude;
95     }
96   //DEBTRACE("aGuideXY: " << aGuideXY->GetName().toStdString());
97
98   Handle(HYDROData_ProfileUZ) aGuideUZ = aGuideLine->GetProfileUZ();
99   if (aGuideUZ.IsNull())
100     {
101       aGuideUZ = aGuideLine->GetChildProfileUZ(); // profile obtained from bathymetry
102     }
103   if (aGuideUZ.IsNull())
104     {
105       DEBTRACE("aGuideUZ.IsNull()");
106       return aResAltitude;
107     }
108   //DEBTRACE("aGuideUZ: " << aGuideUZ->GetName().toStdString());
109
110   Handle (HYDROData_Profile) aProfile = aChannel->GetProfile();
111   if (aProfile.IsNull())
112     {
113       return aResAltitude;
114     }
115   //DEBTRACE("aProfile: " << aProfile->GetName().toStdString());
116
117   // --- See GEOMImpl_ProjectionDriver.cxx
118
119   gp_XY LP, RP;
120   aProfile->GetLeftPoint(LP);
121   aProfile->GetRightPoint(RP);
122
123   TopoDS_Shape aShape =  aGuideXY->GetShape();
124   gp_Pnt P1(thePoint.X(), thePoint.Y(), 0);
125   TopoDS_Shape aPoint = BRepBuilderAPI_MakeVertex(P1).Shape();
126
127   if (aPoint.IsNull() || aShape.IsNull())
128     {
129       DEBTRACE("aPoint.IsNull() || aShape.IsNull()");
130       return aResAltitude;
131     }
132
133   if (aShape.ShapeType() != TopAbs_EDGE && aShape.ShapeType() != TopAbs_WIRE)
134     {
135       DEBTRACE("Projection aborted : the shape is neither an edge nor a wire");
136       return aResAltitude;
137     }
138
139   // Perform projection.
140   BRepExtrema_DistShapeShape aDistShSh(aPoint, aShape, Extrema_ExtFlag_MIN);
141
142   if (aDistShSh.IsDone() == Standard_False)
143     {
144       DEBTRACE("Projection not done");
145       return aResAltitude;
146     }
147
148   Standard_Boolean hasValidSolution = Standard_False;
149   Standard_Integer aNbSolutions = aDistShSh.NbSolution();
150   Standard_Integer i;
151   double aParam = 0.;
152   Standard_Real aTolConf = BRep_Tool::Tolerance(TopoDS::Vertex(aPoint));
153   Standard_Real aTolAng = 1.e-4;
154
155   for (i = 1; i <= aNbSolutions; i++)
156     {
157       Standard_Boolean isValid = Standard_False;
158       BRepExtrema_SupportType aSupportType = aDistShSh.SupportTypeShape2(i);
159       TopoDS_Shape aSupportShape = aDistShSh.SupportOnShape2(i);
160
161       if (aSupportType == BRepExtrema_IsOnEdge)
162         {
163           // Minimal distance inside edge is really a projection.
164           isValid = Standard_True;
165           aDistShSh.ParOnEdgeS2(i, aParam);
166         }
167       else if (aSupportType == BRepExtrema_IsVertex)
168         {
169           TopExp_Explorer anExp(aShape, TopAbs_EDGE);
170
171           if (aDistShSh.Value() <= aTolConf)
172             {
173               // The point lies on the shape. This means this point
174               // is really a projection.
175               for (; anExp.More() && !isValid; anExp.Next())
176                 {
177                   TopoDS_Edge aCurEdge = TopoDS::Edge(anExp.Current());
178
179                   if (aCurEdge.IsNull() == Standard_False)
180                     {
181                       TopoDS_Vertex aVtx[2];
182
183                       TopExp::Vertices(aCurEdge, aVtx[0], aVtx[1]);
184
185                       for (int j = 0; j < 2; j++)
186                         {
187                           if (aSupportShape.IsSame(aVtx[j]))
188                             {
189                               // The current edge is a projection edge.
190                               isValid = Standard_True;
191                               aSupportShape = aCurEdge;
192                               aParam = BRep_Tool::Parameter(aVtx[j], aCurEdge);
193                               break;
194                             }
195                         }
196                     }
197                 }
198             }
199           else
200             {
201               // Minimal distance to vertex is not always a real projection.
202               gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aPoint));
203               gp_Pnt aPrjPnt = BRep_Tool::Pnt(TopoDS::Vertex(aSupportShape));
204               gp_Vec aDProjP(aPrjPnt, aPnt);
205
206               for (; anExp.More() && !isValid; anExp.Next())
207                 {
208                   TopoDS_Edge aCurEdge = TopoDS::Edge(anExp.Current());
209
210                   if (aCurEdge.IsNull() == Standard_False)
211                     {
212                       TopoDS_Vertex aVtx[2];
213
214                       TopExp::Vertices(aCurEdge, aVtx[0], aVtx[1]);
215
216                       for (int j = 0; j < 2; j++)
217                         {
218                           if (aSupportShape.IsSame(aVtx[j]))
219                             {
220                               // Check if the point is a projection to the current edge.
221                               Standard_Real anEdgePars[2];
222                               Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aCurEdge, anEdgePars[0], anEdgePars[1]);
223                               gp_Pnt aVal;
224                               gp_Vec aD1;
225
226                               aParam = BRep_Tool::Parameter(aVtx[j], aCurEdge);
227                               aCurve->D1(aParam, aVal, aD1);
228
229                               if (Abs(aD1.Dot(aDProjP)) <= aTolAng)
230                                 {
231                                   // The current edge is a projection edge.
232                                   isValid = Standard_True;
233                                   aSupportShape = aCurEdge;
234                                   break;
235                                 }
236                             }
237                         }
238                     }
239                 }
240             }
241         }
242
243       if (isValid)
244         {
245           if (hasValidSolution)
246             {
247               DEBTRACE("Projection aborted : multiple solutions");
248               return aResAltitude;
249             }
250
251           // Store the valid solution.
252           hasValidSolution = Standard_True;
253
254           // profile altitude at projection point
255           HYDROData_IPolyline::PointsList aProfilePoints = aGuideUZ->GetPoints();
256           if ( aProfilePoints.IsEmpty() )
257             {
258               DEBTRACE("empty profile UZ");
259               return aResAltitude;
260             }
261           double aDepth = HYDROData_ProfileUZ::GetDepthFromDistance( aProfilePoints, aParam );
262           //DEBTRACE("profile altitude: " << aDepth);
263
264           // Compute edge index.
265           TopExp_Explorer anExp(aShape, TopAbs_EDGE);
266           int anIndex = 0;
267           for (; anExp.More(); anExp.Next(), anIndex++)
268             {
269               if (aSupportShape.IsSame(anExp.Current()))
270                 {
271                   break;
272                 }
273             }
274
275           // get the XY distance from point to guideline
276           const gp_Pnt &aPntProj = aDistShSh.PointOnShape2(i);
277           //DEBTRACE("projection: (" << aPntProj.X() << ", " << aPntProj.Y() << ", " << aPntProj.Z() << ")");
278           gp_XY aProjXY = gp_XY(aPntProj.X(), aPntProj.Y());
279           aProjXY.Subtract(thePoint);
280           double distance = aProjXY.Modulus();
281           //DEBTRACE("distance to guideline " << distance);
282
283           gp_Vec2d aProjDir = aProjXY; 
284           gp_Vec2d aProfileDir(LP, RP);
285           double aSign = 1.0;
286           if( aProfileDir.Dot(aProjDir) < 0 )
287             aSign = -1.0;
288
289           distance *= aSign;
290
291           // get delta altitude on section (supposed symmetric) from guideline distance (aParam)
292           double delta = 0;
293           int i1 = 0;
294           gp_XY pt1 = gp_XY();
295           gp_XY pt2 = gp_XY();
296           HYDROData_ProfileUZ::PointsList aSectionPoints = aProfile->GetParametricPoints();
297           for ( int i = 1, aNbPoints = aSectionPoints.Size(); i <= aNbPoints; ++i )
298             {
299               const HYDROData_IPolyline::Point& aPolylinePoint = aSectionPoints.Value( i );
300               //DEBTRACE("  profile point: " << aPolylinePoint.X() << " " << aPolylinePoint.Y());
301               if (aPolylinePoint.X() < distance)
302                 {
303                   i1 = i;
304                   pt1 = aPolylinePoint;
305                 }
306               if (aPolylinePoint.X() >= distance)
307                 {
308                   pt2 = aPolylinePoint;
309                   break;
310                 }
311             }
312           if ((i1 == 0) && (distance > 0))
313             {
314               DEBTRACE("Projection aborted : non centered profile");
315               return aResAltitude;
316             }
317           if (i1 == aProfilePoints.Size()) // distance >= profile width
318             {
319               delta = pt1.Y();
320             }
321           else
322             {
323               delta = pt1.Y() + (pt2.Y() - pt1.Y())*(distance -pt1.X())/(pt2.X()-pt1.X());
324             }
325           aResAltitude = delta + aDepth;
326           DEBTRACE("distance XY: "<< aParam << " distance to guideline: " << distance << " final altitude: " << aResAltitude << " delta: " << delta);
327           return aResAltitude;
328         }
329     }
330
331   if (!hasValidSolution)
332     {
333       DEBTRACE("Projection aborted : no projection");
334       return aResAltitude;
335     }
336
337   return aResAltitude;
338 }
339
340
341
342