Salome HOME
fd3917cc21566fda8e23c1f8d04bf44a255f53e6
[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_Profile.h"
27
28 #define _DEVDEBUG_
29 #include "HYDRO_trace.hxx"
30 #include <QString>
31
32 #include <BRepBuilderAPI_MakeVertex.hxx>
33 #include <BRepExtrema_DistShapeShape.hxx>
34
35 #include <Precision.hxx>
36 #include <TopAbs.hxx>
37 #include <TopExp.hxx>
38 #include <TopoDS.hxx>
39 #include <TopoDS_Shape.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Face.hxx>
42 #include <TopoDS_Vertex.hxx>
43 #include <TopoDS_Wire.hxx>
44 #include <TopExp_Explorer.hxx>
45 #include <TopAbs_ShapeEnum.hxx>
46 #include <BRep_Tool.hxx>
47 #include <BRepTools.hxx>
48 #include <Geom_Curve.hxx>
49
50 #include <gp_Trsf.hxx>
51 #include <gp_Pnt.hxx>
52 #include <gp_Vec.hxx>
53
54 IMPLEMENT_STANDARD_HANDLE(HYDROData_ChannelAltitude, HYDROData_IAltitudeObject)
55 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_ChannelAltitude, HYDROData_IAltitudeObject)
56
57 HYDROData_ChannelAltitude::HYDROData_ChannelAltitude()
58 : HYDROData_IAltitudeObject()
59 {
60 }
61
62 HYDROData_ChannelAltitude::~HYDROData_ChannelAltitude()
63 {
64 }
65
66 double HYDROData_ChannelAltitude::GetAltitudeForPoint( const gp_XY& thePoint ) const
67 {
68   DEBTRACE("HYDROData_ChannelAltitude::GetAltitudeForPoint");
69   double aResAltitude = GetInvalidAltitude();
70
71   Handle(HYDROData_Channel) aChannel =
72   Handle(HYDROData_Channel)::DownCast(GetFatherObject());
73   if (aChannel.IsNull())
74     {
75       DEBTRACE("aChannel.IsNull()");
76       return aResAltitude;
77     }
78   DEBTRACE("aChannel: " << aChannel->GetName().toStdString());
79   Handle(HYDROData_Polyline3D) aGuideLine = aChannel->GetGuideLine();
80   if (aGuideLine.IsNull())
81     {
82       DEBTRACE("aGuideLine.IsNull()");
83       return aResAltitude;
84     }
85   DEBTRACE("aGuideLine: " << aGuideLine->GetName().toStdString());
86   Handle (HYDROData_Profile) aProfile = aChannel->GetProfile();
87   if (aProfile.IsNull())
88     {
89       return aResAltitude;
90     }
91   DEBTRACE("aProfile: " << aProfile->GetName().toStdString());
92
93   // --- See GEOMImpl_ProjectionDriver.cxx
94
95   TopoDS_Shape aShape = aGuideLine->GetShape3D();
96   gp_Pnt P1(thePoint.X(), thePoint.Y(), 0); // plutot altitude moyenne
97   TopoDS_Shape aPoint = BRepBuilderAPI_MakeVertex(P1).Shape();
98
99   if (aPoint.IsNull() || aShape.IsNull())
100     {
101       DEBTRACE("aPoint.IsNull() || aShape.IsNull()");
102       return aResAltitude;
103     }
104
105   if (aShape.ShapeType() != TopAbs_EDGE && aShape.ShapeType() != TopAbs_WIRE)
106     {
107       DEBTRACE("Projection aborted : the shape is neither an edge nor a wire");
108       return aResAltitude;
109     }
110
111   // Perform projection.
112   BRepExtrema_DistShapeShape aDistShSh(aPoint, aShape, Extrema_ExtFlag_MIN);
113
114   if (aDistShSh.IsDone() == Standard_False)
115     {
116       DEBTRACE("Projection not done");
117       return aResAltitude;
118     }
119
120   Standard_Boolean hasValidSolution = Standard_False;
121   Standard_Integer aNbSolutions = aDistShSh.NbSolution();
122   Standard_Integer i;
123   double aParam = 0.;
124   Standard_Real aTolConf = BRep_Tool::Tolerance(TopoDS::Vertex(aPoint));
125   Standard_Real aTolAng = 1.e-4;
126
127   for (i = 1; i <= aNbSolutions; i++)
128     {
129       Standard_Boolean isValid = Standard_False;
130       BRepExtrema_SupportType aSupportType = aDistShSh.SupportTypeShape2(i);
131       TopoDS_Shape aSupportShape = aDistShSh.SupportOnShape2(i);
132
133       if (aSupportType == BRepExtrema_IsOnEdge)
134         {
135           // Minimal distance inside edge is really a projection.
136           isValid = Standard_True;
137           aDistShSh.ParOnEdgeS2(i, aParam);
138         }
139       else if (aSupportType == BRepExtrema_IsVertex)
140         {
141           TopExp_Explorer anExp(aShape, TopAbs_EDGE);
142
143           if (aDistShSh.Value() <= aTolConf)
144             {
145               // The point lies on the shape. This means this point
146               // is really a projection.
147               for (; anExp.More() && !isValid; anExp.Next())
148                 {
149                   TopoDS_Edge aCurEdge = TopoDS::Edge(anExp.Current());
150
151                   if (aCurEdge.IsNull() == Standard_False)
152                     {
153                       TopoDS_Vertex aVtx[2];
154
155                       TopExp::Vertices(aCurEdge, aVtx[0], aVtx[1]);
156
157                       for (int j = 0; j < 2; j++)
158                         {
159                           if (aSupportShape.IsSame(aVtx[j]))
160                             {
161                               // The current edge is a projection edge.
162                               isValid = Standard_True;
163                               aSupportShape = aCurEdge;
164                               aParam = BRep_Tool::Parameter(aVtx[j], aCurEdge);
165                               break;
166                             }
167                         }
168                     }
169                 }
170             }
171           else
172             {
173               // Minimal distance to vertex is not always a real projection.
174               gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aPoint));
175               gp_Pnt aPrjPnt = BRep_Tool::Pnt(TopoDS::Vertex(aSupportShape));
176               gp_Vec aDProjP(aPrjPnt, aPnt);
177
178               for (; anExp.More() && !isValid; anExp.Next())
179                 {
180                   TopoDS_Edge aCurEdge = TopoDS::Edge(anExp.Current());
181
182                   if (aCurEdge.IsNull() == Standard_False)
183                     {
184                       TopoDS_Vertex aVtx[2];
185
186                       TopExp::Vertices(aCurEdge, aVtx[0], aVtx[1]);
187
188                       for (int j = 0; j < 2; j++)
189                         {
190                           if (aSupportShape.IsSame(aVtx[j]))
191                             {
192                               // Check if the point is a projection to the current edge.
193                               Standard_Real anEdgePars[2];
194                               Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aCurEdge, anEdgePars[0], anEdgePars[1]);
195                               gp_Pnt aVal;
196                               gp_Vec aD1;
197
198                               aParam = BRep_Tool::Parameter(aVtx[j], aCurEdge);
199                               aCurve->D1(aParam, aVal, aD1);
200
201                               if (Abs(aD1.Dot(aDProjP)) <= aTolAng)
202                                 {
203                                   // The current edge is a projection edge.
204                                   isValid = Standard_True;
205                                   aSupportShape = aCurEdge;
206                                   break;
207                                 }
208                             }
209                         }
210                     }
211                 }
212             }
213         }
214
215       if (isValid)
216         {
217           if (hasValidSolution)
218             {
219               DEBTRACE("Projection aborted : multiple solutions");
220               return aResAltitude;
221             }
222
223           // Store the valid solution.
224           hasValidSolution = Standard_True;
225
226           // Normalize parameter.
227           TopoDS_Edge aSupportEdge = TopoDS::Edge(aSupportShape);
228           Standard_Real aF, aL;
229
230           BRep_Tool::Range(aSupportEdge, aF, aL);
231
232           if (Abs(aL - aF) <= aTolConf)
233             {
234               DEBTRACE("Projection aborted : degenerated projection edge");
235               return aResAltitude;
236             }
237
238 //          aParam = (aParam - aF) / (aL - aF);
239 //          aProj.SetU(aParam);
240 //
241 //          // Compute edge index.
242 //          TopExp_Explorer anExp(aShape, TopAbs_EDGE);
243 //          int anIndex = 0;
244 //
245 //          for (; anExp.More(); anExp.Next(), anIndex++)
246 //            {
247 //              if (aSupportShape.IsSame(anExp.Current()))
248 //                {
249 //                  aProj.SetIndex(anIndex);
250 //                  break;
251 //                }
252 //            }
253 //
254 //          if (!anExp.More())
255 //            {
256 //              DEBTRACE("Projection aborted : Can't define edge index");
257 //              return aResAltitude;
258 //            }
259
260           // Construct a projection vertex.
261           const gp_Pnt &aPntProj = aDistShSh.PointOnShape2(i);
262           TopoDS_Shape aProj = BRepBuilderAPI_MakeVertex(aPntProj).Shape();
263           DEBTRACE("projection: (" << aPntProj.X() << ", " << aPntProj.Y() << ", " << aPntProj.Z() << ")");
264           return aPntProj.Z();
265           //aFunction->SetValue(aProj);
266         }
267     }
268
269   if (!hasValidSolution)
270     {
271       DEBTRACE("Projection aborted : no projection");
272       return aResAltitude;
273     }
274
275   return aResAltitude;
276 }
277
278
279
280