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