0026041: GeomLib_Tool::Parameter method fails
[occt.git] / src / GeomLib / GeomLib_Tool.cxx
1 // Created on: 2003-03-18
2 // Created by: Oleg FEDYAEV
3 // Copyright (c) 2003-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <GeomLib_Tool.ixx>
17
18 #include <Geom_Curve.hxx>
19 #include <Geom_Line.hxx>
20 #include <Geom_Circle.hxx>
21 #include <Geom_Ellipse.hxx>
22 #include <Geom_Parabola.hxx>
23 #include <Geom_Hyperbola.hxx>
24 #include <Geom_BSplineCurve.hxx>
25 #include <Geom_BezierCurve.hxx>
26 #include <Geom_TrimmedCurve.hxx>
27 #include <Geom_OffsetCurve.hxx>
28 #include <Geom_Surface.hxx>
29 #include <Geom_Plane.hxx>
30 #include <Geom_CylindricalSurface.hxx>
31 #include <Geom_ConicalSurface.hxx>
32 #include <Geom_SphericalSurface.hxx>
33 #include <Geom_ToroidalSurface.hxx>
34 #include <Geom_BSplineSurface.hxx>
35 #include <Geom_BezierSurface.hxx>
36 #include <Geom_RectangularTrimmedSurface.hxx>
37 #include <Geom_OffsetSurface.hxx> 
38 #include <Geom_SurfaceOfLinearExtrusion.hxx>
39 #include <Geom_SurfaceOfRevolution.hxx>
40 #include <gp_Pnt.hxx>
41 #include <gp_Pln.hxx>
42 #include <gp_Cylinder.hxx>
43 #include <gp_Cone.hxx>
44 #include <gp_Sphere.hxx>
45 #include <gp_Torus.hxx>
46 #include <gp_Lin.hxx>
47 #include <gp_Circ.hxx>
48 #include <gp_Elips.hxx>
49 #include <gp_Parab.hxx>
50 #include <gp_Hypr.hxx> 
51 #include <gp_Vec.hxx>
52 #include <GeomAdaptor_Curve.hxx>
53 #include <GeomAdaptor_Surface.hxx>
54 #include <ElSLib.hxx>
55 #include <ElCLib.hxx>
56 #include <Extrema_ExtPC.hxx>
57 #include <Extrema_ExtPS.hxx>
58 #include <Geom2d_Curve.hxx>
59 #include <Geom2d_Line.hxx>
60 #include <Geom2d_Circle.hxx>
61 #include <Geom2d_Ellipse.hxx>
62 #include <Geom2d_Parabola.hxx>
63 #include <Geom2d_Hyperbola.hxx>
64 #include <Geom2d_BSplineCurve.hxx>
65 #include <Geom2d_BezierCurve.hxx>
66 #include <Geom2d_TrimmedCurve.hxx>
67 #include <Geom2d_OffsetCurve.hxx>
68 #include <gp_Pnt2d.hxx>
69 #include <gp_Lin2d.hxx>
70 #include <gp_Circ2d.hxx>
71 #include <gp_Elips2d.hxx>
72 #include <gp_Parab2d.hxx>
73 #include <gp_Hypr2d.hxx>
74 #include <Geom2dAdaptor_Curve.hxx>
75 #include <ElCLib.hxx>
76 #include <Extrema_ExtPC2d.hxx>
77
78
79 // The functions Parameter(s) are used to compute parameter(s) of point
80 // on curves and surfaces. The main rule is that tested point must lied
81 // on curves or surfaces otherwise the resulted parameter(s) may be wrong.
82 // To make search process more common the tolerance value is used to define
83 // the proximity of point to curve or surface. It is clear that this tolerance
84 // value can't be too high to be not in conflict with previous rule.
85 static const Standard_Real MAXTOLERANCEGEOM = 1.e-4;
86 static const Standard_Real MAXTOLERANCEPARM = 1.e-3;
87 static const Standard_Real UNKNOWNVALUE = 1.e+100;
88 static const Standard_Real PARTOLERANCE = 1.e-9;
89
90 //=======================================================================
91 //function : Parameter
92 //purpose  : Get parameter on curve of given point
93 //           return FALSE if point is far from curve than tolerance
94 //           or computation fails
95 //=======================================================================
96
97 Standard_Boolean GeomLib_Tool::Parameter(const Handle(Geom_Curve)& Curve,
98                                          const gp_Pnt&             Point,
99                                          const Standard_Real       Tolerance,
100                                                Standard_Real&            U)
101 {
102   if( Curve.IsNull() ) return Standard_False;
103   //
104   U = 0.;
105   Standard_Real aTol = (Tolerance < MAXTOLERANCEGEOM) ? Tolerance : MAXTOLERANCEGEOM;
106   aTol *= aTol;
107   //
108   Handle(Standard_Type) KindOfCurve = Curve->DynamicType();
109
110   // process analitical curves
111   if( KindOfCurve == STANDARD_TYPE (Geom_Line) ||
112     KindOfCurve == STANDARD_TYPE (Geom_Circle) ||
113     KindOfCurve == STANDARD_TYPE (Geom_Ellipse) ||
114     KindOfCurve == STANDARD_TYPE (Geom_Parabola) ||
115     KindOfCurve == STANDARD_TYPE (Geom_Hyperbola) )
116   {
117     Standard_Real D = 0.;
118
119     if( KindOfCurve == STANDARD_TYPE (Geom_Line) )
120     {
121       Handle(Geom_Line) aGL = Handle(Geom_Line)::DownCast(Curve);
122       gp_Lin aLin = aGL->Lin();
123       D = aLin.SquareDistance(Point);
124       if(D > aTol)
125       {
126         return Standard_False;
127       }
128       U = ElCLib::Parameter(aLin,Point);
129     }
130     else if( KindOfCurve == STANDARD_TYPE (Geom_Circle) )
131     {
132       Handle(Geom_Circle) aGC = Handle(Geom_Circle)::DownCast(Curve);
133       gp_Circ aCirc = aGC->Circ();
134       D = aCirc.SquareDistance(Point);
135       if(D > aTol)
136       {
137         return Standard_False;
138       }
139       U = ElCLib::Parameter(aCirc,Point);
140     }
141     else if( KindOfCurve == STANDARD_TYPE (Geom_Ellipse) )
142     {
143       Handle(Geom_Ellipse) aGE = Handle(Geom_Ellipse)::DownCast(Curve);
144       gp_Elips anElips = aGE->Elips();
145       U = ElCLib::Parameter(anElips,Point);
146       D = Point.SquareDistance(aGE->Value(U));
147       if(D > aTol)
148       {
149         return Standard_False;
150       }
151     }
152     else if( KindOfCurve == STANDARD_TYPE (Geom_Parabola) )
153     { 
154       Handle(Geom_Parabola) aGP = Handle(Geom_Parabola)::DownCast(Curve);
155       gp_Parab aParab = aGP->Parab();
156       U = ElCLib::Parameter(aParab,Point);
157       D = Point.SquareDistance(aGP->Value(U));
158       if(D > aTol)
159       {
160         return Standard_False;
161       }
162     }
163     else if( KindOfCurve == STANDARD_TYPE (Geom_Hyperbola) )
164     {
165       Handle(Geom_Hyperbola) aGH = Handle(Geom_Hyperbola)::DownCast(Curve);
166       gp_Hypr aHypr = aGH->Hypr();
167       U = ElCLib::Parameter(aHypr,Point);
168       D = Point.SquareDistance(aGH->Value(U));
169       if(D > aTol)
170       {
171         return Standard_False;
172       }
173     }
174   }
175   // process parametrical curves
176   else if( KindOfCurve == STANDARD_TYPE (Geom_BSplineCurve) ||
177     KindOfCurve == STANDARD_TYPE (Geom_BezierCurve) ||
178     KindOfCurve == STANDARD_TYPE (Geom_TrimmedCurve) ||
179     KindOfCurve == STANDARD_TYPE (Geom_OffsetCurve) )
180   {
181     GeomAdaptor_Curve aGAC(Curve);
182     Extrema_ExtPC extrema(Point,aGAC);
183     if( !extrema.IsDone() ) return Standard_False;
184     Standard_Integer n = extrema.NbExt();
185     if( n <= 0 ) return Standard_False;
186     Standard_Integer i = 0, iMin = 0;
187     Standard_Real Dist2Min = 1.e+100;
188     for( i = 1; i <= n; i++ )
189     {
190       if (extrema.SquareDistance(i) < Dist2Min)
191       {
192         iMin = i;
193         Dist2Min = extrema.SquareDistance(i);
194       }
195     }
196     if( iMin != 0 && Dist2Min <= aTol ) U = (extrema.Point(iMin)).Parameter();
197   }
198   else { return Standard_False; }
199
200   return Standard_True;
201
202 }
203
204 //=======================================================================
205 //function : Parameters
206 //purpose  : Get parameters on surface of given point
207 //           return FALSE if point is far from surface than tolerance
208 //           or computation fails
209 //=======================================================================
210
211 Standard_Boolean GeomLib_Tool::Parameters(const Handle(Geom_Surface)& Surface,
212                                           const gp_Pnt&               Point,
213                                           const Standard_Real         Tolerance,
214                                                 Standard_Real&              U,
215                                                 Standard_Real&              V)
216 {
217   if( Surface.IsNull() ) return Standard_False;
218   //
219   U = 0.;
220   V = 0.;
221   Standard_Real aTol = (Tolerance < MAXTOLERANCEGEOM) ? Tolerance : MAXTOLERANCEGEOM;
222   aTol *= aTol;
223   //
224   Handle(Standard_Type) KindOfSurface = Surface->DynamicType();
225
226   // process analitical surfaces
227   if( KindOfSurface == STANDARD_TYPE (Geom_Plane) ||
228     KindOfSurface == STANDARD_TYPE (Geom_CylindricalSurface) ||
229     KindOfSurface == STANDARD_TYPE (Geom_ConicalSurface) ||
230     KindOfSurface == STANDARD_TYPE (Geom_SphericalSurface) ||
231     KindOfSurface == STANDARD_TYPE (Geom_ToroidalSurface) )
232   {
233     Standard_Real D = 0.;
234
235     if( KindOfSurface == STANDARD_TYPE (Geom_Plane) )
236     {
237       Handle(Geom_Plane) aGP = Handle(Geom_Plane)::DownCast(Surface);
238       gp_Pln aPlane = aGP->Pln(); 
239       D = aPlane.SquareDistance(Point);
240       if(D > aTol)
241       {
242         return Standard_False;
243       }
244       ElSLib::Parameters (aPlane,Point,U,V);
245     }
246     else if( KindOfSurface == STANDARD_TYPE (Geom_CylindricalSurface) )
247     {
248       Handle(Geom_CylindricalSurface) aGC = Handle(Geom_CylindricalSurface)::DownCast(Surface);
249       gp_Cylinder aCylinder = aGC->Cylinder();
250       ElSLib::Parameters(aCylinder,Point,U,V);
251       D = Point.SquareDistance(aGC->Value(U, V));
252       if(D > aTol)
253       {
254         return Standard_False;
255       }
256     }
257     else if( KindOfSurface == STANDARD_TYPE (Geom_ConicalSurface) )
258     {
259       Handle(Geom_ConicalSurface) aGC = Handle(Geom_ConicalSurface)::DownCast(Surface);
260       gp_Cone aCone = aGC->Cone();
261       ElSLib::Parameters(aCone,Point,U,V);
262       D = Point.SquareDistance(aGC->Value(U, V));
263       if(D > aTol)
264       {
265         return Standard_False;
266       }
267     }
268     else if( KindOfSurface == STANDARD_TYPE (Geom_SphericalSurface) )
269     {
270       Handle(Geom_SphericalSurface) aGS = Handle(Geom_SphericalSurface)::DownCast(Surface);
271       gp_Sphere aSphere = aGS->Sphere(); 
272       ElSLib::Parameters(aSphere,Point,U,V);
273       D = Point.SquareDistance(aGS->Value(U, V));
274       if(D > aTol)
275       {
276         return Standard_False;
277       }
278     }
279     else if( KindOfSurface == STANDARD_TYPE (Geom_ToroidalSurface) )
280     {
281       Handle(Geom_ToroidalSurface) aTS = Handle(Geom_ToroidalSurface)::DownCast(Surface);
282       gp_Torus aTorus = aTS->Torus();
283       ElSLib::Parameters(aTorus,Point,U,V);
284       D = Point.SquareDistance(aTS->Value(U, V));
285       if(D > aTol)
286       {
287         return Standard_False;
288       }
289     }
290     else return Standard_False;
291   }
292   // process parametrical surfaces
293   else if( KindOfSurface == STANDARD_TYPE (Geom_BSplineSurface) ||
294     KindOfSurface == STANDARD_TYPE (Geom_BezierSurface) ||
295     KindOfSurface == STANDARD_TYPE (Geom_RectangularTrimmedSurface) ||
296     KindOfSurface == STANDARD_TYPE (Geom_OffsetSurface) ||
297     KindOfSurface == STANDARD_TYPE (Geom_SurfaceOfLinearExtrusion) ||
298     KindOfSurface == STANDARD_TYPE (Geom_SurfaceOfRevolution) )
299   {
300     GeomAdaptor_Surface aGAS(Surface);
301     Standard_Real aTolU = PARTOLERANCE, aTolV = PARTOLERANCE;
302     Extrema_ExtPS extrema(Point,aGAS,aTolU,aTolV);
303     if( !extrema.IsDone() ) return Standard_False;
304     Standard_Integer n = extrema.NbExt();
305     if( n <= 0 ) return Standard_False;
306
307     Standard_Real Dist2Min = 1.e+100;
308     Standard_Integer i = 0, iMin = 0;
309     for( i = 1; i <= n; i++ )
310     {
311       if( extrema.SquareDistance(i) < Dist2Min )
312       {
313         Dist2Min = extrema.SquareDistance(i);
314         iMin = i;
315       }
316     }
317     if( iMin != 0 && Dist2Min <= aTol) extrema.Point(iMin).Parameter(U,V);
318     else return Standard_False;
319   }
320   else { return Standard_False; }
321
322   return Standard_True;
323
324 }
325
326 //=======================================================================
327 //function : Parameter
328 //purpose  : Get parameter on curve of given point
329 //           return FALSE if point is far from curve than tolerance
330 //           or computation fails
331 //=======================================================================
332
333 Standard_Boolean GeomLib_Tool::Parameter(const Handle(Geom2d_Curve)& Curve,
334                                          const gp_Pnt2d&             Point,
335                                          const Standard_Real         Tolerance,
336                                                Standard_Real&              U)
337 {
338   if( Curve.IsNull() ) return Standard_False;
339   //
340   U = 0.;
341   Standard_Real aTol = (Tolerance < MAXTOLERANCEGEOM) ? Tolerance : MAXTOLERANCEGEOM;
342   aTol *= aTol;
343
344   Handle(Standard_Type) KindOfCurve = Curve->DynamicType();
345
346   // process analytical curves
347   if( KindOfCurve == STANDARD_TYPE (Geom2d_Line) ||
348     KindOfCurve == STANDARD_TYPE (Geom2d_Circle) ||
349     KindOfCurve == STANDARD_TYPE (Geom2d_Ellipse) ||
350     KindOfCurve == STANDARD_TYPE (Geom2d_Parabola) ||
351     KindOfCurve == STANDARD_TYPE (Geom2d_Hyperbola) )
352   {
353     Standard_Real D = 0.;
354
355     if( KindOfCurve == STANDARD_TYPE (Geom2d_Line) )
356     {
357       Handle(Geom2d_Line) aGL = Handle(Geom2d_Line)::DownCast(Curve);
358       gp_Lin2d aLin = aGL->Lin2d();
359       D = aLin.SquareDistance(Point);
360       if(D > aTol)
361       {
362         return Standard_False;
363       }
364       U = ElCLib::Parameter(aLin,Point);
365     }
366     else if( KindOfCurve == STANDARD_TYPE (Geom2d_Circle) )
367     {
368       Handle(Geom2d_Circle) aGC = Handle(Geom2d_Circle)::DownCast(Curve);
369       gp_Circ2d aCirc = aGC->Circ2d();
370       D = aCirc.SquareDistance(Point);
371       if(D > aTol)
372       {
373         return Standard_False;
374       }   
375       U = ElCLib::Parameter(aCirc,Point);
376     }
377     else if( KindOfCurve == STANDARD_TYPE (Geom2d_Ellipse) )
378     {
379       Handle(Geom2d_Ellipse) aGE = Handle(Geom2d_Ellipse)::DownCast(Curve);
380       gp_Elips2d anElips = aGE->Elips2d();
381       U = ElCLib::Parameter(anElips,Point);
382       D = Point.SquareDistance(aGE->Value(U));
383       if(D > aTol)
384       {
385         return Standard_False;
386       }   
387     }
388     else if( KindOfCurve == STANDARD_TYPE (Geom2d_Parabola) )
389     {
390       Handle(Geom2d_Parabola) aGP = Handle(Geom2d_Parabola)::DownCast(Curve);
391       gp_Parab2d aParab = aGP->Parab2d();
392       U = ElCLib::Parameter(aParab,Point);
393       D = Point.SquareDistance(aGP->Value(U));
394       if(D > aTol)
395       {
396         return Standard_False;
397       }   
398     }
399     else if( KindOfCurve == STANDARD_TYPE (Geom2d_Hyperbola) )
400     {
401       Handle(Geom2d_Hyperbola) aGH = Handle(Geom2d_Hyperbola)::DownCast(Curve);
402       gp_Hypr2d aHypr = aGH->Hypr2d();
403       U = ElCLib::Parameter(aHypr,Point);
404       D = Point.SquareDistance(aGH->Value(U));
405       if(D > aTol)
406       {
407         return Standard_False;
408       }   
409     }
410     else return Standard_False;
411   }
412   // process parametrical curves
413   else if( KindOfCurve == STANDARD_TYPE (Geom2d_BSplineCurve) ||
414     KindOfCurve == STANDARD_TYPE (Geom2d_BezierCurve) ||
415     KindOfCurve == STANDARD_TYPE (Geom2d_TrimmedCurve) ||
416     KindOfCurve == STANDARD_TYPE (Geom2d_OffsetCurve) )
417   {
418     Geom2dAdaptor_Curve aGAC(Curve);
419     Extrema_ExtPC2d extrema(Point,aGAC);
420     if( !extrema.IsDone() ) return Standard_False;
421     Standard_Integer n = extrema.NbExt();
422     if( n <= 0 ) return Standard_False;
423     Standard_Integer i = 0, iMin = 0;
424     Standard_Real Dist2Min = 1.e+100;
425     for ( i = 1; i <= n; i++ )
426     {
427       if( extrema.SquareDistance(i) < Dist2Min )
428       {
429         Dist2Min = extrema.SquareDistance(i);
430         iMin = i;
431       }
432     }
433     if( iMin != 0 && Dist2Min <= aTol ) U = (extrema.Point(iMin)).Parameter();
434     else return Standard_False;
435   }
436   else { return Standard_False; }
437
438   return Standard_True;
439 }