4 #include <Extrema_ExtElC.ixx>
5 #include <StdFail_InfiniteSolutions.hxx>
6 #include <StdFail_NotDone.hxx>
8 #include <math_TrigonometricFunctionRoots.hxx>
9 #include <math_DirectPolynomialRoots.hxx>
10 #include <Standard_OutOfRange.hxx>
11 #include <Standard_NotImplemented.hxx>
12 #include <Precision.hxx>
13 #include <Extrema_ExtPElC.hxx>
14 #include <IntAna_QuadQuadGeo.hxx>
15 #include <Extrema_ExtPElC.hxx>
26 //======================================================================
27 //== Classe Interne (Donne des racines classees d un polynome trigo)
28 //== Code duplique avec IntAna_IntQuadQuad.cxx (lbr le 26 mars 98)
29 //== Solution fiable aux problemes de coefficients proches de 0
30 //== avec essai de rattrapage si coeff<1.e-10 (jct le 27 avril 98)
31 //======================================================================
32 static const Standard_Real PIpPI=Standard_PI+Standard_PI;
34 class ExtremaExtElC_TrigonometricRoots {
36 Standard_Real Roots[4];
37 Standard_Boolean done;
38 Standard_Integer NbRoots;
39 Standard_Boolean infinite_roots;
41 ExtremaExtElC_TrigonometricRoots(const Standard_Real CC
42 ,const Standard_Real SC
43 ,const Standard_Real C
44 ,const Standard_Real S
45 ,const Standard_Real Cte
46 ,const Standard_Real Binf
47 ,const Standard_Real Bsup);
49 Standard_Boolean IsDone() { return(done); }
51 Standard_Boolean IsARoot(Standard_Real u) {
52 for(Standard_Integer i=0 ; i<NbRoots; i++) {
53 if(Abs(u - Roots[i])<=RealEpsilon()) return(Standard_True);
54 if(Abs(u - Roots[i]-PIpPI)<=RealEpsilon()) return(Standard_True);
56 return(Standard_False);
59 Standard_Integer NbSolutions() {
60 if(!done) StdFail_NotDone::Raise();
63 Standard_Boolean InfiniteRoots() {
64 if(!done) StdFail_NotDone::Raise();
65 return(infinite_roots);
67 Standard_Real Value(const Standard_Integer& n) {
68 if((!done)||(n>NbRoots)) StdFail_NotDone::Raise();
72 //----------------------------------------------------------------------
73 ExtremaExtElC_TrigonometricRoots::ExtremaExtElC_TrigonometricRoots(const Standard_Real CC
74 ,const Standard_Real SC
75 ,const Standard_Real C
76 ,const Standard_Real S
77 ,const Standard_Real Cte
78 ,const Standard_Real Binf
79 ,const Standard_Real Bsup) {
82 Standard_Integer nbessai = 1;
83 Standard_Real cc = CC, sc = SC, c = C, s = S, cte = Cte;
85 while (nbessai<=2 && !done) {
86 //-- F= AA*CN*CN+2*BB*CN*SN+CC*CN+DD*SN+EE;
87 math_TrigonometricFunctionRoots MTFR(cc,sc,c,s,cte,Binf,Bsup);
90 if(MTFR.InfiniteRoots()) {
91 infinite_roots=Standard_True;
94 NbRoots=MTFR.NbSolutions();
95 for( i=0;i<NbRoots;i++) {
96 Roots[i]=MTFR.Value(i+1);
97 if(Roots[i]<0.0) Roots[i]+=PI+PI;
98 if(Roots[i]>(PI+PI)) Roots[i]-=PI+PI;
100 Standard_Boolean Triee;
103 //-- La recherche directe donne n importe quoi.
104 // modified by OCC Tue Oct 3 18:41:27 2006.BEGIN
105 Standard_Real aMaxCoef = Max(CC,SC);
106 aMaxCoef = Max(aMaxCoef,C);
107 aMaxCoef = Max(aMaxCoef,S);
108 aMaxCoef = Max(aMaxCoef,Cte);
109 const Standard_Real aPrecision = Max(1.e-8,1.e-12*aMaxCoef);
110 // modified by OCC Tue Oct 3 18:41:33 2006.END
112 Standard_Integer SvNbRoots=NbRoots;
113 for(i=0;i<SvNbRoots;i++) {
115 Standard_Real co=cos(Roots[i]);
116 Standard_Real si=sin(Roots[i]);
117 y=co*(CC*co + (SC+SC)*si + C) + S*si + Cte;
118 // modified by OCC Tue Oct 3 18:43:00 2006
119 if(Abs(y)>aPrecision) {
121 printf("\n**IntAna_IntQuadQuad** Solution : %g ( %g cos2 + 2 %g cos sin + %g cos + %g sin + %g) = %g\n",
122 Roots[i],CC,SC,C,S,Cte,y);
131 for(i=1,j=0;i<SvNbRoots;i++,j++) {
132 if(Roots[i]<Roots[j]) {
133 Triee=Standard_False;
134 Standard_Real t=Roots[i]; Roots[i]=Roots[j]; Roots[j]=t;
139 infinite_roots=Standard_False;
140 if(NbRoots==0) { //--!!!!! Detection du cas Pol = Cte ( 1e-50 ) !!!!
141 if((Abs(CC) + Abs(SC) + Abs(C) + Abs(S)) < 1e-10) {
142 if(Abs(Cte) < 1e-10) {
143 infinite_roots=Standard_True;
150 // on essaie en mettant les tres petits coeff. a ZERO
151 if (Abs(CC)<1e-10) cc = 0.0;
152 if (Abs(SC)<1e-10) sc = 0.0;
153 if (Abs(C)<1e-10) c = 0.0;
154 if (Abs(S)<1e-10) s = 0.0;
155 if (Abs(Cte)<1e-10) cte = 0.0;
161 //=============================================================================
163 Extrema_ExtElC::Extrema_ExtElC () { myDone = Standard_False; }
164 //=============================================================================
166 Extrema_ExtElC::Extrema_ExtElC (const gp_Lin& C1, const gp_Lin& C2,
169 // Recherche de la distance minimale entre 2 droites.
172 // Soit D1 et D2, les 2 directions des droites C1 et C2.
173 // 2 cas sont consideres:
174 // 1- si Angle(D1,D2) < AngTol, les droites sont paralleles.
175 // La distance est la distance entre un point quelconque de C1 et la droite
177 // 2- si Angle(D1,D2) > AngTol:
178 // Soit P1=C1(u1) et P2=C2(u2) les 2 points solutions:
179 // Alors, ( P1P2.D1 = 0. (1)
180 // ( P1P2.D2 = 0. (2)
181 // Soit O1 et O2 les origines de C1 et C2;
182 // Alors, (1) <=> (O1P2-u1*D1).D1 = 0. car O1P1 = u1*D1
183 // <=> u1 = O1P2.D1 car D1.D1 = 1.
184 // (2) <=> (P1O2+u2*D2).D2 = 0. car O2P2 = u2*D2
185 // <=> u2 = O2P1.D2 car D2.D2 = 1.
186 // <=> u2 = (O2O1+O1P1).D2
187 // <=> u2 = O2O1.D2+((O1P2.T1)T1).T2) car O1P1 = u1*T1 = (O1P2.T1)T1
188 // <=> u2 = O2O1.D2+(((O1O2+O2P2).D1)D1).D2)
189 // <=> u2 = O2O1.D2+((O1O2.D1)D1).D2)+(O2P2.D1)(D1.D2)
190 // <=> u2 = ((O1O2.D1)D1-O1O2).D2 + u2*(D2.D1)(D1.D2)
191 // <=> u2 = (((O1O2.D1)D1-O1O2).D2) / 1.-(D1.D2)**2
193 myDone = Standard_False;
196 gp_Dir D1 = C1.Position().Direction();
197 gp_Dir D2 = C2.Position().Direction();
198 // MSV 16/01/2000: avoid "divide by zero"
199 Standard_Real D1DotD2 = D1.Dot(D2);
200 Standard_Real aSin = 1.-D1DotD2*D1DotD2;
201 if (aSin < gp::Resolution() ||
202 D1.IsParallel(D2, Precision::Angular())) {
203 myIsPar = Standard_True;
204 mySqDist[0] = C2.SquareDistance(C1.Location());
205 mySqDist[1] = mySqDist[0];
208 myIsPar = Standard_False;
209 gp_Pnt O1 = C1.Location();
210 gp_Pnt O2 = C2.Location();
212 Standard_Real U2 = (D1.XYZ()*(O1O2.Dot(D1))-(O1O2.XYZ())).Dot(D2.XYZ());
213 if( Precision::IsInfinite(U2) ) {
214 myIsPar = Standard_True;
215 mySqDist[0] = C2.SquareDistance(C1.Location());
216 mySqDist[1] = mySqDist[0];
220 if( Precision::IsInfinite(U2) ) {
221 myIsPar = Standard_True;
222 mySqDist[0] = C2.SquareDistance(C1.Location());
223 mySqDist[1] = mySqDist[0];
226 gp_Pnt P2(ElCLib::Value(U2,C2));
227 Standard_Real U1 = (gp_Vec(O1,P2)).Dot(D1);
228 if( Precision::IsInfinite(U1) ) {
229 myIsPar = Standard_True;
230 mySqDist[0] = C2.SquareDistance(C1.Location());
231 mySqDist[1] = mySqDist[0];
234 gp_Pnt P1(ElCLib::Value(U1,C1));
235 mySqDist[myNbExt] = P1.SquareDistance(P2);
236 myPoint[myNbExt][0] = Extrema_POnCurv(U1,P1);
237 myPoint[myNbExt][1] = Extrema_POnCurv(U2,P2);
243 myDone = Standard_True;
245 //=============================================================================
247 Extrema_ExtElC::Extrema_ExtElC (const gp_Lin& C1, const gp_Circ& C2,
249 /*-----------------------------------------------------------------------------
251 Recherche des distances extremales entre la droite C1 et le cercle C2.
254 Soit P1=C1(u1) et P2=C2(u2) deux points solutions
255 D la direction de la droite C1
256 T la tangente au point P2;
257 Alors, ( P1P2.D = 0. (1)
259 Soit O1 et O2 les origines de C1 et C2;
260 Alors, (1) <=> (O1P2-u1*D).D = 0. car O1P1 = u1*D
261 <=> u1 = O1P2.D car D.D = 1.
262 (2) <=> P1O2.T = 0. car O2P2.T = 0.
263 <=> ((P2O1.D)D+O1O2).T = 0. car P1O1 = -u1*D = (P2O1.D)D
264 <=> (((P2O2+O2O1).D)D+O1O2).T = 0.
265 <=> ((P2O2.D)(D.T)+((O2O1.D)D-O2O1).T = 0.
266 On se place dans le repere du cercle; soit:
267 Cos = Cos(u2) et Sin = Sin(u2),
271 V (Vx,Vy,Vz) = (O2O1.D)D-O2O1;
272 Alors, on obtient l'equation en Cos et Sin suivante:
273 -(2*R*R*Dx*Dy) * Cos**2 + A1
274 R*R*(Dx**2-Dy**2) * Cos*Sin + 2* A2
278 On utilise l'algorithme math_TrigonometricFunctionRoots pour resoudre
280 -----------------------------------------------------------------------------*/
282 myIsPar = Standard_False;
283 myDone = Standard_False;
286 // Calcul de T1 dans le repere du cercle ...
287 gp_Dir D = C1.Direction();
290 x2 = C2.XAxis().Direction();
291 y2 = C2.YAxis().Direction();
292 z2 = C2.Axis().Direction();
293 Standard_Real Dx = D.Dot(x2);
294 Standard_Real Dy = D.Dot(y2);
295 Standard_Real Dz = D.Dot(z2);
296 D.SetCoord(Dx,Dy,Dz);
298 // Calcul de V dans le repere du cercle:
299 gp_Pnt O1 = C1.Location();
300 gp_Pnt O2 = C2.Location();
302 O2O1.SetCoord(O2O1.Dot(x2), O2O1.Dot(y2), O2O1.Dot(z2));
303 gp_XYZ Vxyz = (D.XYZ()*(O2O1.Dot(D)))-O2O1.XYZ();
305 // Calcul des coefficients de l equation en Cos et Sin ...
306 Standard_Real R = C2.Radius();
307 Standard_Real A5 = R*R*Dx*Dy;
308 Standard_Real A1 = -2.*A5;
309 Standard_Real A2 = R*R*(Dx*Dx-Dy*Dy)/2.0;
310 Standard_Real A3 = R*Vxyz.Y();
311 Standard_Real A4 = -R*Vxyz.X();
312 // Standard_Real TolU = Tol * R;
315 if(fabs(A5) <= 1.e-12) A5 = 0.;
316 if(fabs(A1) <= 1.e-12) A1 = 0.;
317 if(fabs(A2) <= 1.e-12) A2 = 0.;
318 if(fabs(A3) <= 1.e-12) A3 = 0.;
319 if(fabs(A4) <= 1.e-12) A4 = 0.;
322 ExtremaExtElC_TrigonometricRoots Sol(A1,A2,A3,A4,A5,0.,PI+PI);
323 if (!Sol.IsDone()) { return; }
324 if (Sol.InfiniteRoots()) {
325 myIsPar = Standard_True;
327 myDone = Standard_True;
330 // Stockage des solutions ...
333 Standard_Integer NbSol = Sol.NbSolutions();
334 for (Standard_Integer NoSol = 1; NoSol <= NbSol; NoSol++) {
335 U2 = Sol.Value(NoSol);
336 P2 = ElCLib::Value(U2,C2);
337 U1 = (gp_Vec(O1,P2)).Dot(D1);
338 P1 = ElCLib::Value(U1,C1);
339 mySqDist[myNbExt] = P1.SquareDistance(P2);
340 myPoint[myNbExt][0] = Extrema_POnCurv(U1,P1);
341 myPoint[myNbExt][1] = Extrema_POnCurv(U2,P2);
344 myDone = Standard_True;
349 Extrema_ExtElC::Extrema_ExtElC (const gp_Lin& C1, const gp_Elips& C2)
351 /*-----------------------------------------------------------------------------
353 Recherche des distances extremales entre la droite C1 et l ellipse C2.
356 Soit P1=C1(u1) et P2=C2(u2) deux points solutions
357 D la direction de la droite C1
358 T la tangente au point P2;
359 Alors, ( P1P2.D = 0. (1)
361 Soit O1 et O2 les origines de C1 et C2;
362 Alors, (1) <=> (O1P2-u1*D).D = 0. car O1P1 = u1*D
363 <=> u1 = O1P2.D car D.D = 1.
364 (2) <=> P1O2.T = 0. car O2P2.T = 0.
365 <=> ((P2O1.D)D+O1O2).T = 0. car P1O1 = -u1*D = (P2O1.D)D
366 <=> (((P2O2+O2O1).D)D+O1O2).T = 0.
367 <=> ((P2O2.D)(D.T)+((O2O1.D)D-O2O1).T = 0.
368 On se place dans le repere de l ellipse; soit:
369 Cos = Cos(u2) et Sin = Sin(u2),
370 P2 (MajR*Cos,MinR*Sin,0.),
371 T (-MajR*Sin,MinR*Cos,0.),
373 V (Vx,Vy,Vz) = (O2O1.D)D-O2O1;
374 Alors, on obtient l'equation en Cos et Sin suivante:
375 -(2*MajR*MinR*Dx*Dy) * Cos**2 +
376 (MajR*MajR*Dx**2-MinR*MinR*Dy**2) * Cos*Sin +
380 On utilise l'algorithme math_TrigonometricFunctionRoots pour resoudre
382 -----------------------------------------------------------------------------*/
383 myIsPar = Standard_False;
384 myDone = Standard_False;
387 // Calcul de T1 dans le repere de l'ellipse ...
388 gp_Dir D = C1.Direction();
391 x2 = C2.XAxis().Direction();
392 y2 = C2.YAxis().Direction();
393 z2 = C2.Axis().Direction();
394 Standard_Real Dx = D.Dot(x2);
395 Standard_Real Dy = D.Dot(y2);
396 Standard_Real Dz = D.Dot(z2);
397 D.SetCoord(Dx,Dy,Dz);
400 gp_Pnt O1 = C1.Location();
401 gp_Pnt O2 = C2.Location();
403 O2O1.SetCoord(O2O1.Dot(x2), O2O1.Dot(y2), O2O1.Dot(z2));
404 gp_XYZ Vxyz = (D.XYZ()*(O2O1.Dot(D)))-O2O1.XYZ();
406 // Calcul des coefficients de l equation en Cos et Sin ...
407 Standard_Real MajR = C2.MajorRadius();
408 Standard_Real MinR = C2.MinorRadius();
409 Standard_Real A5 = MajR*MinR*Dx*Dy;
410 Standard_Real A1 = -2.*A5;
411 Standard_Real R2 = MajR*MajR;
412 Standard_Real r2 = MinR*MinR;
413 Standard_Real A2 =(R2*Dx*Dx -r2*Dy*Dy -R2 +r2)/2.0;
414 Standard_Real A3 = MinR*Vxyz.Y();
415 Standard_Real A4 = -MajR*Vxyz.X();
417 ExtremaExtElC_TrigonometricRoots Sol(A1,A2,A3,A4,A5,0.,PI+PI);
418 if (!Sol.IsDone()) { return; }
420 // Stockage des solutions ...
423 Standard_Integer NbSol = Sol.NbSolutions();
424 for (Standard_Integer NoSol = 1; NoSol <= NbSol; NoSol++) {
425 U2 = Sol.Value(NoSol);
426 P2 = ElCLib::Value(U2,C2);
427 U1 = (gp_Vec(O1,P2)).Dot(D1);
428 P1 = ElCLib::Value(U1,C1);
429 mySqDist[myNbExt] = P1.SquareDistance(P2);
430 myPoint[myNbExt][0] = Extrema_POnCurv(U1,P1);
431 myPoint[myNbExt][1] = Extrema_POnCurv(U2,P2);
434 myDone = Standard_True;
436 //=============================================================================
438 Extrema_ExtElC::Extrema_ExtElC (const gp_Lin& C1, const gp_Hypr& C2)
440 /*-----------------------------------------------------------------------------
442 Recherche des distances extremales entre la droite C1 et l'hyperbole C2.
445 Soit P1=C1(u1) et P2=C2(u2) deux points solutions
446 D la direction de la droite C1
447 T la tangente au point P2;
448 Alors, ( P1P2.D = 0. (1)
450 Soit O1 et O2 les origines de C1 et C2;
451 Alors, (1) <=> (O1P2-u1*D).D = 0. car O1P1 = u1*D
452 <=> u1 = O1P2.D car D.D = 1.
453 (2) <=> (P1O2 + O2P2).T= 0.
454 <=> ((P2O1.D)D+O1O2 + O2P2).T = 0. car P1O1 = -u1*D = (P2O1.D)D
455 <=> (((P2O2+O2O1).D)D+O1O2 + O2P2).T = 0.
456 <=> (P2O2.D)(D.T)+((O2O1.D)D-O2O1).T + O2P2.T= 0.
457 On se place dans le repere de l'hyperbole; soit:
458 en ecrivant P (R* Chu, r* Shu, 0.0)
459 et Chu = (v**2 + 1)/(2*v) ,
460 Shu = (V**2 - 1)/(2*v)
464 V (Vx,Vy,Vz) = (O2O1.D)D-O2O1;
466 Alors, on obtient l'equation en v suivante:
467 (-2*R*r*Dx*Dy - R*R*Dx*Dx-r*r*Dy*Dy + R*R + r*r) * v**4 +
468 (2*R*Vx + 2*r*Vy) * v**3 +
469 (-2*R*Vx + 2*r*Vy) * v +
470 (-2*R*r*Dx*Dy - (R*R*Dx*Dx-r*r*Dy*Dy + R*R + r*r)) = 0
473 On utilise l'algorithme math_DirectPolynomialRoots pour resoudre
475 -----------------------------------------------------------------------------*/
476 myIsPar = Standard_False;
477 myDone = Standard_False;
480 // Calcul de T1 dans le repere de l'hyperbole ...
481 gp_Dir D = C1.Direction();
484 x2 = C2.XAxis().Direction();
485 y2 = C2.YAxis().Direction();
486 z2 = C2.Axis().Direction();
487 Standard_Real Dx = D.Dot(x2);
488 Standard_Real Dy = D.Dot(y2);
489 Standard_Real Dz = D.Dot(z2);
490 D.SetCoord(Dx,Dy,Dz);
493 gp_Pnt O1 = C1.Location();
494 gp_Pnt O2 = C2.Location();
496 O2O1.SetCoord(O2O1.Dot(x2), O2O1.Dot(y2), O2O1.Dot(z2));
497 gp_XYZ Vxyz = (D.XYZ()*(O2O1.Dot(D)))-O2O1.XYZ();
498 Standard_Real Vx = Vxyz.X();
499 Standard_Real Vy = Vxyz.Y();
501 // Calcul des coefficients de l equation en v
502 Standard_Real R = C2.MajorRadius();
503 Standard_Real r = C2.MinorRadius();
504 Standard_Real a = -2*R*r*Dx*Dy;
505 Standard_Real b = -R*R*Dx*Dx - r*r*Dy*Dy + R*R + r*r;
506 Standard_Real A1 = a + b;
507 Standard_Real A2 = 2*R*Vx + 2*r*Vy;
508 Standard_Real A4 = -2*R*Vx + 2*r*Vy;
509 Standard_Real A5 = a - b;
511 math_DirectPolynomialRoots Sol(A1,A2,0.0,A4, A5);
512 if (!Sol.IsDone()) { return; }
514 // Stockage des solutions ...
516 Standard_Real U1,U2, v;
517 Standard_Integer NbSol = Sol.NbSolutions();
518 for (Standard_Integer NoSol = 1; NoSol <= NbSol; NoSol++) {
519 v = Sol.Value(NoSol);
522 P2 = ElCLib::Value(U2,C2);
523 U1 = (gp_Vec(O1,P2)).Dot(D1);
524 P1 = ElCLib::Value(U1,C1);
525 mySqDist[myNbExt] = P1.SquareDistance(P2);
526 myPoint[myNbExt][0] = Extrema_POnCurv(U1,P1);
527 myPoint[myNbExt][1] = Extrema_POnCurv(U2,P2);
531 myDone = Standard_True;
533 //=============================================================================
535 Extrema_ExtElC::Extrema_ExtElC (const gp_Lin& C1, const gp_Parab& C2)
537 /*-----------------------------------------------------------------------------
539 Recherche des distances extremales entre la droite C1 et la parabole C2.
542 Soit P1=C1(u1) et P2=C2(u2) deux points solutions
543 D la direction de la droite C1
544 T la tangente au point P2;
545 Alors, ( P1P2.D = 0. (1)
547 Soit O1 et O2 les origines de C1 et C2;
548 Alors, (1) <=> (O1P2-u1*D).D = 0. car O1P1 = u1*D
549 <=> u1 = O1P2.D car D.D = 1.
550 (2) <=> (P1O2 + O2P2).T= 0.
551 <=> ((P2O1.D)D+O1O2 + O2P2).T = 0. car P1O1 = -u1*D = (P2O1.D)D
552 <=> (((P2O2+O2O1).D)D+O1O2 + O2P2).T = 0.
553 <=> (P2O2.D)(D.T)+((O2O1.D)D-O2O1).T + O2P2.T = 0.
554 On se place dans le repere de la parabole; soit:
558 V (Vx,Vy,Vz) = (O2O1.D)D-O2O1;
560 Alors, on obtient l'equation en y suivante:
561 ((1-Dx*Dx)/(2*p*p)) * y*y*y + A1
562 (-3*Dx*Dy/(2*p)) * y*y + A2
563 (1-Dy*Dy + Vx/p) * y + A3
566 On utilise l'algorithme math_DirectPolynomialRoots pour resoudre
568 -----------------------------------------------------------------------------*/
569 myIsPar = Standard_False;
570 myDone = Standard_False;
573 // Calcul de T1 dans le repere de la parabole ...
574 gp_Dir D = C1.Direction();
577 x2 = C2.XAxis().Direction();
578 y2 = C2.YAxis().Direction();
579 z2 = C2.Axis().Direction();
580 Standard_Real Dx = D.Dot(x2);
581 Standard_Real Dy = D.Dot(y2);
582 Standard_Real Dz = D.Dot(z2);
583 D.SetCoord(Dx,Dy,Dz);
586 gp_Pnt O1 = C1.Location();
587 gp_Pnt O2 = C2.Location();
589 O2O1.SetCoord(O2O1.Dot(x2), O2O1.Dot(y2), O2O1.Dot(z2));
590 gp_XYZ Vxyz = (D.XYZ()*(O2O1.Dot(D)))-O2O1.XYZ();
592 // Calcul des coefficients de l equation en y
593 Standard_Real P = C2.Parameter();
594 Standard_Real A1 = (1-Dx*Dx)/(2.0*P*P);
595 Standard_Real A2 = (-3.0*Dx*Dy/(2.0*P));
596 Standard_Real A3 = (1 - Dy*Dy + Vxyz.X()/P);
597 Standard_Real A4 = Vxyz.Y();
599 math_DirectPolynomialRoots Sol(A1,A2,A3,A4);
600 if (!Sol.IsDone()) { return; }
602 // Stockage des solutions ...
605 Standard_Integer NbSol = Sol.NbSolutions();
606 for (Standard_Integer NoSol = 1; NoSol <= NbSol; NoSol++) {
607 U2 = Sol.Value(NoSol);
608 P2 = ElCLib::Value(U2,C2);
609 U1 = (gp_Vec(O1,P2)).Dot(D1);
610 P1 = ElCLib::Value(U1,C1);
611 mySqDist[myNbExt] = P1.SquareDistance(P2);
612 myPoint[myNbExt][0] = Extrema_POnCurv(U1,P1);
613 myPoint[myNbExt][1] = Extrema_POnCurv(U2,P2);
616 myDone = Standard_True;
618 //=============================================================================
619 Extrema_ExtElC::Extrema_ExtElC (const gp_Circ&, const gp_Elips&)
621 Standard_NotImplemented::Raise();
623 //=============================================================================
625 Extrema_ExtElC::Extrema_ExtElC (const gp_Circ&, const gp_Hypr&)
627 Standard_NotImplemented::Raise();
629 //=============================================================================
631 Extrema_ExtElC::Extrema_ExtElC (const gp_Circ&, const gp_Parab&)
633 Standard_NotImplemented::Raise();
635 //=============================================================================
637 Extrema_ExtElC::Extrema_ExtElC (const gp_Elips&, const gp_Elips&)
639 Standard_NotImplemented::Raise();
641 //=============================================================================
643 Extrema_ExtElC::Extrema_ExtElC (const gp_Elips&, const gp_Hypr&)
645 Standard_NotImplemented::Raise();
647 //=============================================================================
649 Extrema_ExtElC::Extrema_ExtElC (const gp_Elips&, const gp_Parab&)
651 Standard_NotImplemented::Raise();
653 //=============================================================================
655 Extrema_ExtElC::Extrema_ExtElC (const gp_Hypr&, const gp_Hypr&)
657 Standard_NotImplemented::Raise();
659 //=============================================================================
661 Extrema_ExtElC::Extrema_ExtElC (const gp_Hypr&, const gp_Parab&)
663 Standard_NotImplemented::Raise();
665 //=============================================================================
667 Extrema_ExtElC::Extrema_ExtElC (const gp_Parab&, const gp_Parab&)
669 Standard_NotImplemented::Raise();
671 //=============================================================================
673 Standard_Boolean Extrema_ExtElC::IsDone () const { return myDone; }
674 //=============================================================================
676 Standard_Boolean Extrema_ExtElC::IsParallel () const
678 if (!IsDone()) { StdFail_NotDone::Raise(); }
681 //=============================================================================
683 Standard_Integer Extrema_ExtElC::NbExt () const
685 if (IsParallel()) { StdFail_InfiniteSolutions::Raise(); }
688 //=============================================================================
690 Standard_Real Extrema_ExtElC::SquareDistance (const Standard_Integer N) const
692 if (!myDone) { StdFail_NotDone::Raise(); }
694 if (N < 1 || N > 2) { Standard_OutOfRange::Raise(); }
697 if (N < 1 || N > NbExt()) { Standard_OutOfRange::Raise(); }
699 return mySqDist[N-1];
701 //=============================================================================
703 void Extrema_ExtElC::Points (const Standard_Integer N,
704 Extrema_POnCurv& P1, Extrema_POnCurv& P2) const
706 if (N < 1 || N > NbExt()) { Standard_OutOfRange::Raise(); }
707 P1 = myPoint[N-1][0];
708 P2 = myPoint[N-1][1];
710 //=============================================================================
711 //=============================================================================
713 //modified by NIZNHY-PKV Fri Nov 21 10:48:46 2008f
714 //=======================================================================
715 //function : Extrema_ExtElC
717 //=======================================================================
718 Extrema_ExtElC::Extrema_ExtElC (const gp_Circ& C1, const gp_Circ& C2)
720 Standard_Boolean bIsSamePlane, bIsSameAxe;
721 Standard_Real aTolD, aTolD2, aTolA, aD2, aDC2;
725 myIsPar = Standard_False;
726 myDone = Standard_False;
729 aTolA=Precision::Angular();
730 aTolD=Precision::Confusion();
734 aDc1=C1.Axis().Direction();
737 aDc2=C2.Axis().Direction();
738 gp_Pln aPlc1(aPc1, aDc1);
740 aD2=aPlc1.SquareDistance(aPc2);
741 bIsSamePlane=aDc1.IsParallel(aDc2, aTolA) && aD2<aTolD2;
746 aDC2=aPc1.SquareDistance(aPc2);
747 bIsSameAxe=aDC2<aTolD2;
750 myIsPar = Standard_True;
751 Standard_Real dR = C1.Radius() - C2.Radius();
752 Standard_Real dC = C1.Location().Distance(C2.Location());
753 mySqDist[0] = dR*dR + dC*dC;
754 dR = C1.Radius() + C2.Radius();
755 mySqDist[1] = dR*dR + dC*dC;
756 myDone = Standard_True;
759 Standard_Boolean bIn, bOut;
760 Standard_Integer j1, j2;
761 Standard_Real aR1, aR2, aD12, aT11, aT12, aT21, aT22;
763 gp_Pnt aP11, aP12, aP21, aP22;
765 myDone = Standard_True;
781 aR1=aC1.Radius(); // max radius
782 aR2=aC2.Radius(); // min radius
787 aD12=aPc1.Distance(aPc2);
788 gp_Vec aVec12(aPc1, aPc2);
789 gp_Dir aDir12(aVec12);
791 // 1. Four common solutions
794 aP11.SetXYZ(aPc1.XYZ()-aR1*aDir12.XYZ());
795 aP12.SetXYZ(aPc1.XYZ()+aR1*aDir12.XYZ());
796 aP21.SetXYZ(aPc2.XYZ()-aR2*aDir12.XYZ());
797 aP22.SetXYZ(aPc2.XYZ()+aR2*aDir12.XYZ());
799 aT11=ElCLib::Parameter(aC1, aP11);
800 aT12=ElCLib::Parameter(aC1, aP12);
801 aT21=ElCLib::Parameter(aC2, aP21);
802 aT22=ElCLib::Parameter(aC2, aP22);
805 myPoint[0][j1].SetValues(aT11, aP11);
806 myPoint[0][j2].SetValues(aT21, aP21);
807 mySqDist[0]=aP11.SquareDistance(aP21);
809 myPoint[1][j1].SetValues(aT11, aP11);
810 myPoint[1][j2].SetValues(aT22, aP22);
811 mySqDist[1]=aP11.SquareDistance(aP22);
814 myPoint[2][j1].SetValues(aT12, aP12);
815 myPoint[2][j2].SetValues(aT21, aP21);
816 mySqDist[2]=aP12.SquareDistance(aP21);
819 myPoint[3][j1].SetValues(aT12, aP12);
820 myPoint[3][j2].SetValues(aT22, aP22);
821 mySqDist[3]=aP12.SquareDistance(aP22);
823 // 2. Check for intersections
824 bOut=aD12>(aR1+aR2+aTolD);
825 bIn =aD12<(aR1-aR2-aTolD);
827 Standard_Boolean bNbExt6;
828 Standard_Real aAlpha, aBeta, aT[2], aVal, aDist2;
829 gp_Pnt aPt, aPL1, aPL2;
832 aAlpha=0.5*(aR1*aR1-aR2*aR2+aD12*aD12)/aD12;
833 aVal=aR1*aR1-aAlpha*aAlpha;
834 if (aVal<0.) {// see pkv/900/L4 for details
838 //aBeta=Sqrt(aR1*aR1-aAlpha*aAlpha);
840 aPt.SetXYZ(aPc1.XYZ()+aAlpha*aDir12.XYZ());
843 aPL1.SetXYZ(aPt.XYZ()+aBeta*aDLt.XYZ());
844 aPL2.SetXYZ(aPt.XYZ()-aBeta*aDLt.XYZ());
846 aDist2=aPL1.SquareDistance(aPL2);
847 bNbExt6=aDist2>aTolD2;
849 myNbExt=5;// just in case. see pkv/900/L4 for details
850 aT[j1]=ElCLib::Parameter(aC1, aPL1);
851 aT[j2]=ElCLib::Parameter(aC2, aPL1);
852 myPoint[4][j1].SetValues(aT[j1], aPL1);
853 myPoint[4][j2].SetValues(aT[j2], aPL1);
858 aT[j1]=ElCLib::Parameter(aC1, aPL2);
859 aT[j2]=ElCLib::Parameter(aC2, aPL2);
860 myPoint[5][j1].SetValues(aT[j1], aPL2);
861 myPoint[5][j2].SetValues(aT[j2], aPL2);
865 }// if (!bOut || !bIn) {
868 //modified by NIZNHY-PKV Fri Nov 21 10:48:56 2008t