0024001: Stereographic rendering support
[occt.git] / src / Extrema / Extrema_ExtPElC.cxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
973c2be1 6// This library is free software; you can redistribute it and / or modify it
7// under the terms of the GNU Lesser General Public version 2.1 as published
8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
b311480e 14
7fd59977 15#include <Extrema_ExtPElC.ixx>
16#include <StdFail_NotDone.hxx>
17#include <math_DirectPolynomialRoots.hxx>
18#include <math_TrigonometricFunctionRoots.hxx>
19#include <ElCLib.hxx>
20#include <Standard_OutOfRange.hxx>
21#include <Standard_NotImplemented.hxx>
22#include <Precision.hxx>
23
42ff8f5b 24//=======================================================================
25//function : Extrema_ExtPElC
26//purpose :
27//=======================================================================
7fd59977 28Extrema_ExtPElC::Extrema_ExtPElC () { myDone = Standard_False; }
7fd59977 29
42ff8f5b 30//=======================================================================
31//function : Extrema_ExtPElC
32//purpose :
33//=======================================================================
7fd59977 34Extrema_ExtPElC::Extrema_ExtPElC (const gp_Pnt& P,
35 const gp_Lin& L,
36 const Standard_Real Tol,
37 const Standard_Real Uinf,
38 const Standard_Real Usup)
39{
40 Perform(P, L, Tol, Uinf, Usup);
41}
42ff8f5b 42//=======================================================================
43//function : Perform
44//purpose :
45//=======================================================================
7fd59977 46void Extrema_ExtPElC::Perform(const gp_Pnt& P,
47 const gp_Lin& L,
48 const Standard_Real Tol,
49 const Standard_Real Uinf,
50 const Standard_Real Usup)
51{
52 myDone = Standard_False;
53 myNbExt = 0;
42ff8f5b 54 gp_Vec V1 (L.Direction());
7fd59977 55 gp_Pnt OR = L.Location();
56 gp_Vec V(OR, P);
57 Standard_Real Mydist = V1.Dot(V);
58 if ((Mydist >= Uinf-Tol) &&
59 (Mydist <= Usup+Tol)){
60
61 gp_Pnt MyP = OR.Translated(Mydist*V1);
62 Extrema_POnCurv MyPOnCurve(Mydist, MyP);
63 mySqDist[0] = P.SquareDistance(MyP);
64 myPoint[0] = MyPOnCurve;
65 myIsMin[0] = Standard_True;
66 myNbExt = 1;
67 myDone = Standard_True;
68 }
69
70}
71
72
73
74Extrema_ExtPElC::Extrema_ExtPElC (const gp_Pnt& P,
75 const gp_Circ& C,
76 const Standard_Real Tol,
77 const Standard_Real Uinf,
78 const Standard_Real Usup)
79{
80 Perform(P, C, Tol, Uinf, Usup);
81}
82
83void Extrema_ExtPElC::Perform(const gp_Pnt& P,
84 const gp_Circ& C,
85 const Standard_Real Tol,
86 const Standard_Real Uinf,
87 const Standard_Real Usup)
88/*-----------------------------------------------------------------------------
0d969553
Y
89Function:
90 Find values of parameter u such as:
91 - dist(P,C(u)) pass by an extrema,
7fd59977 92 - Uinf <= u <= Usup.
93
0d969553
Y
94Method:
95 Pass 3 stages:
96 1- Projection of point P in the plane of the circle,
c6541a0c 97 2- Calculation of u solutions in [0.,2.*M_PI]:
0d969553
Y
98 Let Pp, the projected point and
99 O, the center of the circle;
100 2 cases:
101 - if Pp is mixed with 0, there is an infinite number of solutions;
7fd59977 102 IsDone() renvoie Standard_False.
0d969553
Y
103 - otherwise, 2 points are solutions for the complete circle:
104 . Us1 = angle(OPp,OX) corresponds to the minimum,
c6541a0c
D
105 . let Us2 = ( Us1 + M_PI if Us1 < M_PI,
106 ( Us1 - M_PI otherwise;
0d969553
Y
107 Us2 corresponds to the maximum.
108 3- Calculate the extrema in [Uinf,Usup].
7fd59977 109-----------------------------------------------------------------------------*/
110{
111 myDone = Standard_False;
112 myNbExt = 0;
113
0d969553 114// 1- Projection of the point P in the plane of circle -> Pp ...
7fd59977 115
116 gp_Pnt O = C.Location();
117 gp_Vec Axe (C.Axis().Direction());
118 gp_Vec Trsl = Axe.Multiplied(-(gp_Vec(O,P).Dot(Axe)));
119 gp_Pnt Pp = P.Translated(Trsl);
120
0d969553 121// 2- Calculate u solutions in [0.,2.*PI] ...
7fd59977 122
123 gp_Vec OPp (O,Pp);
124 if (OPp.Magnitude() < Tol) { return; }
125 Standard_Real Usol[2];
c6541a0c
D
126 Usol[0] = C.XAxis().Direction().AngleWithRef(OPp,Axe); // -M_PI<U1<M_PI
127 Usol[1] = Usol[0] + M_PI;
7fd59977 128
129 Standard_Real myuinf = Uinf;
7fd59977 130 //Standard_Real TolU = Tol*C.Radius();
131 Standard_Real TolU, aR;
132 aR=C.Radius();
133 TolU=Precision::Infinite();
134 if (aR > gp::Resolution()) {
135 TolU= Tol/aR;
136 }
42ff8f5b 137 //
c6541a0c
D
138 ElCLib::AdjustPeriodic(Uinf, Uinf+2*M_PI, TolU, myuinf, Usol[0]);
139 ElCLib::AdjustPeriodic(Uinf, Uinf+2*M_PI, TolU, myuinf, Usol[1]);
140 if (((Usol[0]-2*M_PI-Uinf) < TolU) && ((Usol[0]-2*M_PI-Uinf) > -TolU)) Usol[0] = Uinf;
141 if (((Usol[1]-2*M_PI-Uinf) < TolU) && ((Usol[1]-2*M_PI-Uinf) > -TolU)) Usol[1] = Uinf;
7fd59977 142
143
0d969553 144// 3- Calculate extrema in [Umin,Umax] ...
7fd59977 145
146 gp_Pnt Cu;
147 Standard_Real Us;
148 for (Standard_Integer NoSol = 0; NoSol <= 1; NoSol++) {
149 Us = Usol[NoSol];
150 if (((Uinf-Us) < TolU) && ((Us-Usup) < TolU)) {
151 Cu = ElCLib::Value(Us,C);
152 mySqDist[myNbExt] = Cu.SquareDistance(P);
153 myIsMin[myNbExt] = (NoSol == 0);
154 myPoint[myNbExt] = Extrema_POnCurv(Us,Cu);
155 myNbExt++;
156 }
157 }
158 myDone = Standard_True;
159}
160//=============================================================================
161
162Extrema_ExtPElC::Extrema_ExtPElC (const gp_Pnt& P,
163 const gp_Elips& C,
164 const Standard_Real Tol,
165 const Standard_Real Uinf,
166 const Standard_Real Usup)
167{
168 Perform(P, C, Tol, Uinf, Usup);
169}
170
171
172
173void Extrema_ExtPElC::Perform (const gp_Pnt& P,
174 const gp_Elips& C,
175 const Standard_Real Tol,
176 const Standard_Real Uinf,
177 const Standard_Real Usup)
178/*-----------------------------------------------------------------------------
0d969553
Y
179Function:
180 Find values of parameter u so that:
181 - dist(P,C(u)) passes by an extremum,
7fd59977 182 - Uinf <= u <= Usup.
183
0d969553
Y
184Method:
185 Takes 2 steps:
186 1- Projection of point P in the plane of the ellipse,
187 2- Calculation of the solutions:
188 Let Pp, the projected point; find values u so that:
7fd59977 189 (C(u)-Pp).C'(u) = 0. (1)
0d969553
Y
190 Let Cos = cos(u) and Sin = sin(u),
191 C(u) = (A*Cos,B*Sin) and Pp = (X,Y);
192 Then, (1) <=> (A*Cos-X,B*Sin-Y).(-A*Sin,B*Cos) = 0.
7fd59977 193 (B**2-A**2)*Cos*Sin - B*Y*Cos + A*X*Sin = 0.
0d969553 194 Use algorithm math_TrigonometricFunctionRoots to solve this equation.
7fd59977 195-----------------------------------------------------------------------------*/
196{
197 myDone = Standard_False;
198 myNbExt = 0;
199
0d969553 200// 1- Projection of point P in the plane of the ellipse -> Pp ...
7fd59977 201
202 gp_Pnt O = C.Location();
203 gp_Vec Axe (C.Axis().Direction());
204 gp_Vec Trsl = Axe.Multiplied(-(gp_Vec(O,P).Dot(Axe)));
205 gp_Pnt Pp = P.Translated(Trsl);
206
0d969553 207// 2- Calculation of solutions ...
7fd59977 208
209 Standard_Integer NoSol, NbSol;
210 Standard_Real A = C.MajorRadius();
211 Standard_Real B = C.MinorRadius();
212 gp_Vec OPp (O,Pp);
213 Standard_Real OPpMagn = OPp.Magnitude();
214 if (OPpMagn < Tol) { if (Abs(A-B) < Tol) { return; } }
215 Standard_Real X = OPp.Dot(gp_Vec(C.XAxis().Direction()));
216 Standard_Real Y = OPp.Dot(gp_Vec(C.YAxis().Direction()));
217 // Standard_Real Y = Sqrt(OPpMagn*OPpMagn-X*X);
218
219 Standard_Real ko2 = (B*B-A*A)/2., ko3 = -B*Y, ko4 = A*X;
220 if(Abs(ko3) < 1.e-16*Max(Abs(ko2), Abs(ko3))) ko3 = 0.0;
221
222// math_TrigonometricFunctionRoots Sol(0.,(B*B-A*A)/2.,-B*Y,A*X,0.,Uinf,Usup);
223 math_TrigonometricFunctionRoots Sol(0.,ko2, ko3, ko4, 0.,Uinf,Usup);
224
225 if (!Sol.IsDone()) { return; }
226 gp_Pnt Cu;
227 Standard_Real Us;
228 NbSol = Sol.NbSolutions();
229 for (NoSol = 1; NoSol <= NbSol; NoSol++) {
230 Us = Sol.Value(NoSol);
231 Cu = ElCLib::Value(Us,C);
232 mySqDist[myNbExt] = Cu.SquareDistance(P);
7fd59977 233 myPoint[myNbExt] = Extrema_POnCurv(Us,Cu);
a20400b3 234 Cu = ElCLib::Value(Us + 0.1, C);
235 myIsMin[myNbExt] = mySqDist[myNbExt] < Cu.SquareDistance(P);
7fd59977 236 myNbExt++;
237 }
238 myDone = Standard_True;
239}
240//=============================================================================
241
242Extrema_ExtPElC::Extrema_ExtPElC (const gp_Pnt& P,
243 const gp_Hypr& C,
244 const Standard_Real Tol,
245 const Standard_Real Uinf,
246 const Standard_Real Usup)
247{
248 Perform(P, C, Tol, Uinf, Usup);
249}
250
251
252void Extrema_ExtPElC::Perform(const gp_Pnt& P,
253 const gp_Hypr& C,
254 const Standard_Real Tol,
255 const Standard_Real Uinf,
256 const Standard_Real Usup)
257/*-----------------------------------------------------------------------------
0d969553
Y
258Function:
259 Find values of parameter u so that:
260 - dist(P,C(u)) passes by an extremum,
7fd59977 261 - Uinf <= u <= Usup.
262
0d969553
Y
263Method:
264 Takes 2 steps:
265 1- Projection of point P in the plane of the hyperbola,
266 2- Calculation of solutions:
267 Let Pp, le point projete; on recherche les valeurs u telles que:
7fd59977 268 (C(u)-Pp).C'(u) = 0. (1)
0d969553
Y
269 Let R and r be the radiuses of the hyperbola,
270 Chu = Cosh(u) and Shu = Sinh(u),
271 C(u) = (R*Chu,r*Shu) and Pp = (X,Y);
272 Then, (1) <=> (R*Chu-X,r*Shu-Y).(R*Shu,r*Chu) = 0.
7fd59977 273 (R**2+r**2)*Chu*Shu - X*R*Shu - Y*r*Chu = 0. (2)
0d969553
Y
274 Let v = e**u;
275 Then, by using Chu = (e**u+e**(-u))/2. and Sh = (e**u-e**(-u)))/2.
7fd59977 276 (2) <=> ((R**2+r**2)/4.) * (v**2-v**(-2)) -
277 ((X*R+Y*r)/2.) * v +
278 ((X*R-Y*r)/2.) * v**(-1) = 0.
279 (2)* v**2 <=> ((R**2+r**2)/4.) * v**4 -
280 ((X*R+Y*r)/2.) * v**3 +
281 ((X*R-Y*r)/2.) * v -
282 ((R**2+r**2)/4.) = 0.
0d969553 283 Use algorithm math_DirectPolynomialRoots to solve this equation by v.
7fd59977 284-----------------------------------------------------------------------------*/
285{
286 myDone = Standard_False;
287 myNbExt = 0;
288
0d969553 289// 1- Projection of point P in the plane of hyperbola -> Pp ...
7fd59977 290
291 gp_Pnt O = C.Location();
292 gp_Vec Axe (C.Axis().Direction());
293 gp_Vec Trsl = Axe.Multiplied(-(gp_Vec(O,P).Dot(Axe)));
294 gp_Pnt Pp = P.Translated(Trsl);
295
0d969553 296// 2- Calculation of solutions ...
7fd59977 297
298 Standard_Real Tol2 = Tol * Tol;
299 Standard_Real R = C.MajorRadius();
300 Standard_Real r = C.MinorRadius();
301 gp_Vec OPp (O,Pp);
7fd59977 302 Standard_Real X = OPp.Dot(gp_Vec(C.XAxis().Direction()));
303 Standard_Real Y = OPp.Dot(gp_Vec(C.YAxis().Direction()));
304
305 Standard_Real C1 = (R*R+r*r)/4.;
306 math_DirectPolynomialRoots Sol(C1,-(X*R+Y*r)/2.,0.,(X*R-Y*r)/2.,-C1);
307 if (!Sol.IsDone()) { return; }
308 gp_Pnt Cu;
309 Standard_Real Us, Vs;
310 Standard_Integer NbSol = Sol.NbSolutions();
311 Standard_Boolean DejaEnr;
312 Standard_Integer NoExt;
313 gp_Pnt TbExt[4];
314 for (Standard_Integer NoSol = 1; NoSol <= NbSol; NoSol++) {
315 Vs = Sol.Value(NoSol);
316 if (Vs > 0.) {
317 Us = Log(Vs);
318 if ((Us >= Uinf) && (Us <= Usup)) {
319 Cu = ElCLib::Value(Us,C);
320 DejaEnr = Standard_False;
321 for (NoExt = 0; NoExt < myNbExt; NoExt++) {
322 if (TbExt[NoExt].SquareDistance(Cu) < Tol2) {
323 DejaEnr = Standard_True;
324 break;
325 }
326 }
327 if (!DejaEnr) {
328 TbExt[myNbExt] = Cu;
329 mySqDist[myNbExt] = Cu.SquareDistance(P);
330 myIsMin[myNbExt] = mySqDist[myNbExt] < P.SquareDistance(ElCLib::Value(Us+1,C));
331 myPoint[myNbExt] = Extrema_POnCurv(Us,Cu);
332 myNbExt++;
333 }
334 } // if ((Us >= Uinf) && (Us <= Usup))
335 } // if (Vs > 0.)
336 } // for (Standard_Integer NoSol = 1; ...
337 myDone = Standard_True;
338}
339//=============================================================================
340
341Extrema_ExtPElC::Extrema_ExtPElC (const gp_Pnt& P,
342 const gp_Parab& C,
343 const Standard_Real Tol,
344 const Standard_Real Uinf,
345 const Standard_Real Usup)
346{
347 Perform(P, C, Tol, Uinf, Usup);
348}
349
350
351void Extrema_ExtPElC::Perform(const gp_Pnt& P,
352 const gp_Parab& C,
353// const Standard_Real Tol,
354 const Standard_Real ,
355 const Standard_Real Uinf,
356 const Standard_Real Usup)
357/*-----------------------------------------------------------------------------
0d969553
Y
358Function:
359 Find values of parameter u so that:
360 - dist(P,C(u)) pass by an extremum,
7fd59977 361 - Uinf <= u <= Usup.
362
0d969553
Y
363Method:
364 Takes 2 steps:
365 1- Projection of point P in the plane of the parabola,
366 2- Calculation of solutions:
367 Let Pp, the projected point; find values u so that:
7fd59977 368 (C(u)-Pp).C'(u) = 0. (1)
0d969553
Y
369 Let F the focus of the parabola,
370 C(u) = ((u*u)/(4.*F),u) and Pp = (X,Y);
7fd59977 371 Alors, (1) <=> ((u*u)/(4.*F)-X,u-Y).(u/(2.*F),1) = 0.
372 (1./(4.*F)) * U**3 + (2.*F-X) * U - 2*F*Y = 0.
0d969553 373 Use algorithm math_DirectPolynomialRoots to solve this equation by U.
7fd59977 374-----------------------------------------------------------------------------*/
375{
376 myDone = Standard_False;
377 myNbExt = 0;
378
0d969553 379// 1- Projection of point P in the plane of the parabola -> Pp ...
7fd59977 380
381 gp_Pnt O = C.Location();
382 gp_Vec Axe (C.Axis().Direction());
383 gp_Vec Trsl = Axe.Multiplied(-(gp_Vec(O,P).Dot(Axe)));
384 gp_Pnt Pp = P.Translated(Trsl);
385
0d969553 386// 2- Calculation of solutions ...
7fd59977 387
388 Standard_Real F = C.Focal();
389 gp_Vec OPp (O,Pp);
7fd59977 390 Standard_Real X = OPp.Dot(gp_Vec(C.XAxis().Direction()));
391// Standard_Real Y = Sqrt(OPpMagn*OPpMagn-X*X);
392 Standard_Real Y = OPp.Dot(gp_Vec(C.YAxis().Direction()));
393 math_DirectPolynomialRoots Sol(1./(4.*F),0.,2.*F-X,-2.*F*Y);
394 if (!Sol.IsDone()) { return; }
395 gp_Pnt Cu;
396 Standard_Real Us;
397 Standard_Integer NbSol = Sol.NbSolutions();
398 Standard_Boolean DejaEnr;
399 Standard_Integer NoExt;
400 gp_Pnt TbExt[3];
401 for (Standard_Integer NoSol = 1; NoSol <= NbSol; NoSol++) {
402 Us = Sol.Value(NoSol);
403 if ((Us >= Uinf) && (Us <= Usup)) {
404 Cu = ElCLib::Value(Us,C);
405 DejaEnr = Standard_False;
406 for (NoExt = 0; NoExt < myNbExt; NoExt++) {
08cd2f6b 407 if (TbExt[NoExt].SquareDistance(Cu) < Precision::SquareConfusion()) {
7fd59977 408 DejaEnr = Standard_True;
409 break;
410 }
411 }
412 if (!DejaEnr) {
413 TbExt[myNbExt] = Cu;
414 mySqDist[myNbExt] = Cu.SquareDistance(P);
415 myIsMin[myNbExt] = mySqDist[myNbExt] < P.SquareDistance(ElCLib::Value(Us+1,C));
416 myPoint[myNbExt] = Extrema_POnCurv(Us,Cu);
417 myNbExt++;
418 }
419 } // if ((Us >= Uinf) && (Us <= Usup))
420 } // for (Standard_Integer NoSol = 1; ...
421 myDone = Standard_True;
422}
423//=============================================================================
424
425Standard_Boolean Extrema_ExtPElC::IsDone () const { return myDone; }
426//=============================================================================
427
428Standard_Integer Extrema_ExtPElC::NbExt () const
429{
430 if (!IsDone()) { StdFail_NotDone::Raise(); }
431 return myNbExt;
432}
433//=============================================================================
434
435Standard_Real Extrema_ExtPElC::SquareDistance (const Standard_Integer N) const
436{
437 if ((N < 1) || (N > NbExt())) { Standard_OutOfRange::Raise(); }
438 return mySqDist[N-1];
439}
440//=============================================================================
441
442Standard_Boolean Extrema_ExtPElC::IsMin (const Standard_Integer N) const
443{
444 if ((N < 1) || (N > NbExt())) { Standard_OutOfRange::Raise(); }
445 return myIsMin[N-1];
446}
447//=============================================================================
448
5d99f2c8 449const Extrema_POnCurv& Extrema_ExtPElC::Point (const Standard_Integer N) const
7fd59977 450{
451 if ((N < 1) || (N > NbExt())) { Standard_OutOfRange::Raise(); }
452 return myPoint[N-1];
453}
454//=============================================================================