]> SALOME platform Git repositories - modules/hydro.git/blob - src/HYDROData/HYDROData_ChannelAltitude.cxx
Salome HOME
1b1111c45350801030b209a93c823d6a9410f187
[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_HANDLE(HYDROData_ChannelAltitude, HYDROData_IAltitudeObject)
57 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_ChannelAltitude, HYDROData_IAltitudeObject)
58
59 HYDROData_ChannelAltitude::HYDROData_ChannelAltitude()
60 : HYDROData_IAltitudeObject()
61 {
62 }
63
64 HYDROData_ChannelAltitude::~HYDROData_ChannelAltitude()
65 {
66 }
67
68 double HYDROData_ChannelAltitude::GetAltitudeForPoint( const gp_XY& thePoint ) const
69 {
70   DEBTRACE("HYDROData_ChannelAltitude::GetAltitudeForPoint");
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 //  TopoDS_Shape aShape = aGuideLine->GetShape3D();
120 //  double middleZ = -9999;
121 //  aGuideLine->GetMiddleZ(middleZ); // use the middle Z value of the 3d line to help the projection.
122 //  if (middleZ < -9000)
123 //    {
124 //      DEBTRACE("the middle Z value of the 3d line is incorrect");
125 //    }
126 //  gp_Pnt P1(thePoint.X(), thePoint.Y(), middleZ);
127
128   TopoDS_Shape aShape =  aGuideXY->GetShape();
129   gp_Pnt P1(thePoint.X(), thePoint.Y(), 0);
130   TopoDS_Shape aPoint = BRepBuilderAPI_MakeVertex(P1).Shape();
131
132   if (aPoint.IsNull() || aShape.IsNull())
133     {
134       DEBTRACE("aPoint.IsNull() || aShape.IsNull()");
135       return aResAltitude;
136     }
137
138   if (aShape.ShapeType() != TopAbs_EDGE && aShape.ShapeType() != TopAbs_WIRE)
139     {
140       DEBTRACE("Projection aborted : the shape is neither an edge nor a wire");
141       return aResAltitude;
142     }
143
144   // Perform projection.
145   BRepExtrema_DistShapeShape aDistShSh(aPoint, aShape, Extrema_ExtFlag_MIN);
146
147   if (aDistShSh.IsDone() == Standard_False)
148     {
149       DEBTRACE("Projection not done");
150       return aResAltitude;
151     }
152
153   Standard_Boolean hasValidSolution = Standard_False;
154   Standard_Integer aNbSolutions = aDistShSh.NbSolution();
155   Standard_Integer i;
156   double aParam = 0.;
157   Standard_Real aTolConf = BRep_Tool::Tolerance(TopoDS::Vertex(aPoint));
158   Standard_Real aTolAng = 1.e-4;
159
160   for (i = 1; i <= aNbSolutions; i++)
161     {
162       Standard_Boolean isValid = Standard_False;
163       BRepExtrema_SupportType aSupportType = aDistShSh.SupportTypeShape2(i);
164       TopoDS_Shape aSupportShape = aDistShSh.SupportOnShape2(i);
165
166       if (aSupportType == BRepExtrema_IsOnEdge)
167         {
168           // Minimal distance inside edge is really a projection.
169           isValid = Standard_True;
170           aDistShSh.ParOnEdgeS2(i, aParam);
171         }
172       else if (aSupportType == BRepExtrema_IsVertex)
173         {
174           TopExp_Explorer anExp(aShape, TopAbs_EDGE);
175
176           if (aDistShSh.Value() <= aTolConf)
177             {
178               // The point lies on the shape. This means this point
179               // is really a projection.
180               for (; anExp.More() && !isValid; anExp.Next())
181                 {
182                   TopoDS_Edge aCurEdge = TopoDS::Edge(anExp.Current());
183
184                   if (aCurEdge.IsNull() == Standard_False)
185                     {
186                       TopoDS_Vertex aVtx[2];
187
188                       TopExp::Vertices(aCurEdge, aVtx[0], aVtx[1]);
189
190                       for (int j = 0; j < 2; j++)
191                         {
192                           if (aSupportShape.IsSame(aVtx[j]))
193                             {
194                               // The current edge is a projection edge.
195                               isValid = Standard_True;
196                               aSupportShape = aCurEdge;
197                               aParam = BRep_Tool::Parameter(aVtx[j], aCurEdge);
198                               break;
199                             }
200                         }
201                     }
202                 }
203             }
204           else
205             {
206               // Minimal distance to vertex is not always a real projection.
207               gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aPoint));
208               gp_Pnt aPrjPnt = BRep_Tool::Pnt(TopoDS::Vertex(aSupportShape));
209               gp_Vec aDProjP(aPrjPnt, aPnt);
210
211               for (; anExp.More() && !isValid; anExp.Next())
212                 {
213                   TopoDS_Edge aCurEdge = TopoDS::Edge(anExp.Current());
214
215                   if (aCurEdge.IsNull() == Standard_False)
216                     {
217                       TopoDS_Vertex aVtx[2];
218
219                       TopExp::Vertices(aCurEdge, aVtx[0], aVtx[1]);
220
221                       for (int j = 0; j < 2; j++)
222                         {
223                           if (aSupportShape.IsSame(aVtx[j]))
224                             {
225                               // Check if the point is a projection to the current edge.
226                               Standard_Real anEdgePars[2];
227                               Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aCurEdge, anEdgePars[0], anEdgePars[1]);
228                               gp_Pnt aVal;
229                               gp_Vec aD1;
230
231                               aParam = BRep_Tool::Parameter(aVtx[j], aCurEdge);
232                               aCurve->D1(aParam, aVal, aD1);
233
234                               if (Abs(aD1.Dot(aDProjP)) <= aTolAng)
235                                 {
236                                   // The current edge is a projection edge.
237                                   isValid = Standard_True;
238                                   aSupportShape = aCurEdge;
239                                   break;
240                                 }
241                             }
242                         }
243                     }
244                 }
245             }
246         }
247
248       if (isValid)
249         {
250           if (hasValidSolution)
251             {
252               DEBTRACE("Projection aborted : multiple solutions");
253               return aResAltitude;
254             }
255
256           // Store the valid solution.
257           hasValidSolution = Standard_True;
258
259           // Normalize parameter.
260           TopoDS_Edge aSupportEdge = TopoDS::Edge(aSupportShape);
261           Standard_Real aF, aL;
262           BRep_Tool::Range(aSupportEdge, aF, aL);
263           if (Abs(aL - aF) <= aTolConf)
264             {
265               DEBTRACE("Projection aborted : degenerated projection edge");
266               return aResAltitude;
267             }
268           aParam = (aParam - aF)/(aL - aF);
269
270           // Compute edge index.
271           TopExp_Explorer anExp(aShape, TopAbs_EDGE);
272           int anIndex = 0;
273           for (; anExp.More(); anExp.Next(), anIndex++)
274             {
275               if (aSupportShape.IsSame(anExp.Current()))
276                 {
277                   break;
278                 }
279             }
280
281           // Construct a projection vertex.
282           const gp_Pnt &aPntProj = aDistShSh.PointOnShape2(i);
283 //          TopoDS_Shape aProj = BRepBuilderAPI_MakeVertex(aPntProj).Shape();
284           DEBTRACE("projection: (" << aPntProj.X() << ", " << aPntProj.Y() << ", " << aPntProj.Z() << ")");
285           gp_XY aProjXY = gp_XY(aPntProj.X(), aPntProj.Y());
286           aProjXY.Subtract(thePoint);
287           double distance = aProjXY.Modulus();
288           DEBTRACE("distance " << distance);
289           int i1 = 0;
290           gp_XY pt1 = gp_XY();
291           gp_XY pt2 = gp_XY();
292           HYDROData_ProfileUZ::PointsList aProfilePoints = aProfile->GetParametricPoints();
293           for ( int i = 1, aNbPoints = aProfilePoints.Size(); i <= aNbPoints; ++i )
294             {
295               const HYDROData_IPolyline::Point& aPolylinePoint = aProfilePoints.Value( i );
296               DEBTRACE("  profile point: " << aPolylinePoint.X() << " " << aPolylinePoint.Y());
297               if (aPolylinePoint.X() < distance)
298                 {
299                   i1 = i;
300                   pt1 = aPolylinePoint;
301                 }
302               if (aPolylinePoint.X() >= distance)
303                 {
304                   pt2 = aPolylinePoint;
305                   break;
306                 }
307             }
308           if ((i1 == 0) && (distance > 0))
309             {
310               DEBTRACE("Projection aborted : non centered profile");
311               return aResAltitude;
312             }
313
314           // get the point with the same param on altitude profile
315           double zRef = 0; //aPntProj.Z();
316           TopoDS_Shape aShapeUZ =  aGuideUZ->GetShape();
317           if (!aShapeUZ.IsNull())
318             {
319               TopExp_Explorer anExpUZ(aShapeUZ, TopAbs_EDGE);
320               TopoDS_Edge anEdgeUZ;
321               int anI = 0;
322               for (; anExpUZ.More(); anExpUZ.Next(), anI++)
323                 {
324                   if (anI == anIndex)
325                     {
326                       anEdgeUZ = TopoDS::Edge(anExpUZ.Current());
327                       break;
328                     }
329                 }
330               if (!anEdgeUZ.IsNull())
331                 {
332                   double anEdgePars[2];
333                   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdgeUZ, anEdgePars[0], anEdgePars[1]);
334                   gp_Pnt aVal;
335                   aCurve->D0(aParam, aVal);
336                   DEBTRACE("altitude point: " << aVal.X() << " "<< aVal.Y() << " "<< aVal.Z());
337                   zRef = aVal.Y();
338                 }
339               else zRef = 20;
340             }
341           else zRef = 20;
342
343           // distance on section to get altitude
344           if (i1 == aProfilePoints.Size()) // distance >= profile width
345             {
346               aResAltitude = zRef + pt1.Y();
347             }
348           else
349             {
350               double z = pt1.Y() + (pt2.Y() - pt1.Y())*(distance -pt1.X())/(pt2.X()-pt1.X());
351               aResAltitude = zRef + z;
352             }
353           DEBTRACE("altitude: " << aResAltitude << " delta: " << aResAltitude - zRef);
354           return aResAltitude;
355         }
356     }
357
358   if (!hasValidSolution)
359     {
360       DEBTRACE("Projection aborted : no projection");
361       return aResAltitude;
362     }
363
364   return aResAltitude;
365 }
366
367
368
369