1 // Created on: 1992-08-06
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 //----------------------------------------------------------------------
18 //-- Purposse: Geometric Intersection between two Natural Quadric
19 //-- If the intersection is not a conic,
20 //-- analytical methods must be called.
21 //----------------------------------------------------------------------
23 #define No_Standard_RangeError
24 #define No_Standard_OutOfRange
27 #include <IntAna_QuadQuadGeo.ixx>
29 #include <IntAna_IntConicQuad.hxx>
30 #include <StdFail_NotDone.hxx>
31 #include <Standard_DomainError.hxx>
32 #include <Standard_OutOfRange.hxx>
33 #include <math_DirectPolynomialRoots.hxx>
43 #include <gp_Pnt2d.hxx>
44 #include <gp_Vec2d.hxx>
45 #include <gp_Dir2d.hxx>
49 gp_Ax2 DirToAx2(const gp_Pnt& P,const gp_Dir& D);
51 void RefineDir(gp_Dir& aDir);
53 //=======================================================================
55 //purpose : O p e r a t i o n s D i v e r s e s s u r d e s A x 1
56 //=======================================================================
59 AxeOperator(const gp_Ax1& A1,const gp_Ax1& A2);
61 void Distance(Standard_Real& dist,
62 Standard_Real& Param1,
63 Standard_Real& Param2);
65 gp_Pnt PtIntersect() {
68 Standard_Boolean Coplanar(void) {
71 Standard_Boolean Same(void) {
72 return theparallel && (thedistance<myEPSILON_DISTANCE);
74 Standard_Real Distance(void) {
77 Standard_Boolean Intersect(void) {
78 return (thecoplanar && (!theparallel));
80 Standard_Boolean Parallel(void) {
83 Standard_Boolean Normal(void) {
88 Standard_Real Det33(const Standard_Real a11,
89 const Standard_Real a12,
90 const Standard_Real a13,
91 const Standard_Real a21,
92 const Standard_Real a22,
93 const Standard_Real a23,
94 const Standard_Real a31,
95 const Standard_Real a32,
96 const Standard_Real a33) {
97 Standard_Real theReturn =
98 a11*(a22*a33-a32*a23) - a21*(a12*a33-a32*a13) + a31*(a12*a23-a22*a13) ;
106 Standard_Real thedistance;
107 Standard_Boolean theparallel;
108 Standard_Boolean thecoplanar;
109 Standard_Boolean thenormal;
111 Standard_Real myEPSILON_DISTANCE;
112 Standard_Real myEPSILON_AXES_PARA;
115 //=======================================================================
116 //function : AxeOperator::AxeOperator
118 //=======================================================================
119 AxeOperator::AxeOperator(const gp_Ax1& A1,const gp_Ax1& A2)
121 myEPSILON_DISTANCE=0.00000000000001;
122 myEPSILON_AXES_PARA=0.000000000001;
125 //---------------------------------------------------------------------
126 gp_Dir V1=Axe1.Direction();
127 gp_Dir V2=Axe2.Direction();
128 gp_Pnt P1=Axe1.Location();
129 gp_Pnt P2=Axe2.Location();
133 thecoplanar= Standard_False;
134 thenormal = Standard_False;
136 //--- check if the two axis are parallel
137 theparallel=V1.IsParallel(V2, myEPSILON_AXES_PARA);
138 //--- Distance between the two axis
139 gp_XYZ perp(A1.Direction().XYZ().Crossed(A2.Direction().XYZ()));
142 thedistance = L1.Distance(A2.Location());
145 thedistance = Abs(gp_Vec(perp.Normalized()).Dot(gp_Vec(Axe1.Location(),
148 //--- check if Axis are Coplanar
150 if(thedistance<myEPSILON_DISTANCE) {
151 D33=Det33(V1.X(),V1.Y(),V1.Z()
152 ,V2.X(),V2.Y(),V2.Z()
153 ,P1.X()-P2.X(),P1.Y()-P2.Y(),P1.Z()-P2.Z());
154 if(Abs(D33)<=myEPSILON_DISTANCE) {
155 thecoplanar=Standard_True;
159 thecoplanar=Standard_True;
160 thenormal=(V1.Dot(V2)==0.0)? Standard_True : Standard_False;
162 //--- check if the two axis are concurrent
163 if(thecoplanar && (!theparallel)) {
164 Standard_Real smx=P2.X() - P1.X();
165 Standard_Real smy=P2.Y() - P1.Y();
166 Standard_Real smz=P2.Z() - P1.Z();
167 Standard_Real Det1,Det2,Det3,A;
168 Det1=V1.Y() * V2.X() - V1.X() * V2.Y();
169 Det2=V1.Z() * V2.Y() - V1.Y() * V2.Z();
170 Det3=V1.Z() * V2.X() - V1.X() * V2.Z();
172 if((Det1!=0.0) && ((Abs(Det1) >= Abs(Det2))&&(Abs(Det1) >= Abs(Det3)))) {
173 A=(smy * V2.X() - smx * V2.Y())/Det1;
176 && ((Abs(Det2) >= Abs(Det1))
177 &&(Abs(Det2) >= Abs(Det3)))) {
178 A=(smz * V2.Y() - smy * V2.Z())/Det2;
181 A=(smz * V2.X() - smx * V2.Z())/Det3;
183 ptintersect.SetCoord( P1.X() + A * V1.X()
185 ,P1.Z() + A * V1.Z());
188 ptintersect.SetCoord(0,0,0); //-- Pour eviter des FPE
191 //=======================================================================
192 //function : Distance
194 //=======================================================================
195 void AxeOperator::Distance(Standard_Real& dist,
196 Standard_Real& Param1,
197 Standard_Real& Param2)
199 gp_Vec O1O2(Axe1.Location(),Axe2.Location());
200 gp_Dir U1 = Axe1.Direction(); //-- juste pour voir.
201 gp_Dir U2 = Axe2.Direction();
203 gp_Dir N = U1.Crossed(U2);
204 Standard_Real D = Det33(U1.X(),U2.X(),N.X(),
206 U1.Z(),U2.Z(),N.Z());
208 dist = Det33(U1.X(),U2.X(),O1O2.X(),
209 U1.Y(),U2.Y(),O1O2.Y(),
210 U1.Z(),U2.Z(),O1O2.Z()) / D;
211 Param1 = Det33(O1O2.X(),U2.X(),N.X(),
212 O1O2.Y(),U2.Y(),N.Y(),
213 O1O2.Z(),U2.Z(),N.Z()) / (-D);
214 //------------------------------------------------------------
215 //-- On resout P1 * Dir1 + P2 * Dir2 + d * N = O1O2
216 //-- soit : Segment perpendiculaire : O1+P1 D1
218 Param2 = Det33(U1.X(),O1O2.X(),N.X(),
219 U1.Y(),O1O2.Y(),N.Y(),
220 U1.Z(),O1O2.Z(),N.Z()) / (D);
223 //=======================================================================
224 //function : DirToAx2
225 //purpose : returns a gp_Ax2 where D is the main direction
226 //=======================================================================
227 gp_Ax2 DirToAx2(const gp_Pnt& P,const gp_Dir& D)
229 Standard_Real x=D.X(); Standard_Real ax=Abs(x);
230 Standard_Real y=D.Y(); Standard_Real ay=Abs(y);
231 Standard_Real z=D.Z(); Standard_Real az=Abs(z);
232 if( (ax==0.0) || ((ax<ay) && (ax<az)) ) {
233 return(gp_Ax2(P,D,gp_Dir(gp_Vec(0.0,-z,y))));
235 else if( (ay==0.0) || ((ay<ax) && (ay<az)) ) {
236 return(gp_Ax2(P,D,gp_Dir(gp_Vec(-z,0.0,x))));
239 return(gp_Ax2(P,D,gp_Dir(gp_Vec(-y,x,0.0))));
242 //=======================================================================
243 //function : IntAna_QuadQuadGeo
244 //purpose : Empty constructor
245 //=======================================================================
246 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(void)
247 : done(Standard_False),
249 typeres(IntAna_Empty),
260 myCommonGen(Standard_False),
265 //=======================================================================
266 //function : InitTolerances
268 //=======================================================================
269 void IntAna_QuadQuadGeo::InitTolerances()
271 myEPSILON_DISTANCE = 0.00000000000001;
272 myEPSILON_ANGLE_CONE = 0.000000000001;
273 myEPSILON_MINI_CIRCLE_RADIUS = 0.000000001;
274 myEPSILON_CYLINDER_DELTA_RADIUS = 0.0000000000001;
275 myEPSILON_CYLINDER_DELTA_DISTANCE= 0.0000001;
276 myEPSILON_AXES_PARA = 0.000000000001;
278 //=======================================================================
279 //function : IntAna_QuadQuadGeo
281 //=======================================================================
282 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Pln& P1,
284 const Standard_Real TolAng,
285 const Standard_Real Tol)
286 : done(Standard_False),
288 typeres(IntAna_Empty),
299 myCommonGen(Standard_False),
303 Perform(P1,P2,TolAng,Tol);
305 //=======================================================================
308 //=======================================================================
309 void IntAna_QuadQuadGeo::Perform (const gp_Pln& P1,
311 const Standard_Real TolAng,
312 const Standard_Real Tol)
314 Standard_Real A1, B1, C1, D1, A2, B2, C2, D2, dist1, dist2, aMVD;
319 P1.Coefficients(A1,B1,C1,D1);
320 P2.Coefficients(A2,B2,C2,D2);
322 gp_Vec aVN1(A1,B1,C1);
323 gp_Vec aVN2(A2,B2,C2);
324 gp_Vec vd(aVN1.Crossed(aVN2));
326 const gp_Pnt& aLocP1=P1.Location();
327 const gp_Pnt& aLocP2=P2.Location();
329 dist1=A2*aLocP1.X() + B2*aLocP1.Y() + C2*aLocP1.Z() + D2;
330 dist2=A1*aLocP2.X() + B1*aLocP2.Y() + C1*aLocP2.Z() + D1;
334 // normalles are collinear - planes are same or parallel
335 typeres = (Abs(dist1) <= Tol && Abs(dist2) <= Tol) ? IntAna_Same
339 Standard_Real denom, denom2, ddenom, par1, par2;
340 Standard_Real X1, Y1, Z1, X2, Y2, Z2, aEps;
343 denom=A1*A2 + B1*B2 + C1*C2;
344 denom2 = denom*denom;
345 ddenom = 1. - denom2;
347 denom = ( Abs(ddenom) <= aEps ) ? aEps : ddenom;
352 gp_Vec inter1(aVN1.Crossed(vd));
353 gp_Vec inter2(aVN2.Crossed(vd));
355 X1=aLocP1.X() + par1*inter1.X();
356 Y1=aLocP1.Y() + par1*inter1.Y();
357 Z1=aLocP1.Z() + par1*inter1.Z();
358 X2=aLocP2.X() + par2*inter2.X();
359 Y2=aLocP2.Y() + par2*inter2.Y();
360 Z2=aLocP2.Z() + par2*inter2.Z();
362 pt1=gp_Pnt((X1+X2)*0.5, (Y1+Y2)*0.5, (Z1+Z2)*0.5);
364 typeres = IntAna_Line;
367 //-------------------------------------------------------
368 // When the value of the angle between the planes is small
369 // the origin of intersection line is computed with error
370 // [ ~0.0001 ] that can not br considered as small one
372 // for {A~=2.e-6, dist1=4.2e-5, dist2==1.e-4} =>
373 // {denom=3.4e-12, par1=12550297.6, par2=32605552.9, etc}
375 // the origin should be refined if it is possible
377 Standard_Real aTreshAng, aTreshDist;
379 aTreshAng=2.e-6; // 1.e-4 deg
382 if (aMVD < aTreshAng) {
383 Standard_Real aDist1, aDist2;
385 aDist1=A1*pt1.X() + B1*pt1.Y() + C1*pt1.Z() + D1;
386 aDist2=A2*pt1.X() + B2*pt1.Y() + C2*pt1.Z() + D2;
388 if (fabs(aDist1)>aTreshDist || fabs(aDist2)>aTreshDist) {
389 Standard_Boolean bIsDone, bIsParallel;
390 IntAna_IntConicQuad aICQ;
394 gp_Lin aL1(pt1, aDN1);
396 aICQ.Perform(aL1, P1, TolAng, Tol);
397 bIsDone=aICQ.IsDone();
402 const gp_Pnt& aPnt1=aICQ.Point(1);
403 //----------------------------------
405 gp_Dir aDL2(dir1.Crossed(aDN1));
406 gp_Lin aL2(aPnt1, aDL2);
408 aICQ.Perform(aL2, P2, TolAng, Tol);
409 bIsDone=aICQ.IsDone();
414 bIsParallel=aICQ.IsParallel();
419 const gp_Pnt& aPnt2=aICQ.Point(1);
427 //=======================================================================
428 //function : IntAna_QuadQuadGeo
429 //purpose : Pln Cylinder
430 //=======================================================================
431 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo( const gp_Pln& P
432 ,const gp_Cylinder& Cl
433 ,const Standard_Real Tolang
434 ,const Standard_Real Tol
435 ,const Standard_Real H)
436 : done(Standard_False),
438 typeres(IntAna_Empty),
449 myCommonGen(Standard_False),
453 Perform(P,Cl,Tolang,Tol,H);
455 //=======================================================================
458 //=======================================================================
459 void IntAna_QuadQuadGeo::Perform( const gp_Pln& P
460 ,const gp_Cylinder& Cl
461 ,const Standard_Real Tolang
462 ,const Standard_Real Tol
463 ,const Standard_Real H)
465 done = Standard_False;
466 Standard_Real dist,radius;
467 Standard_Real A,B,C,D;
469 Standard_Real sint,cost,h;
470 gp_XYZ axex,axey,omega;
474 radius = Cl.Radius();
476 gp_Lin axec(Cl.Axis());
477 gp_XYZ normp(P.Axis().Direction().XYZ());
479 P.Coefficients(A,B,C,D);
480 axec.Location().Coord(X,Y,Z);
481 // la distance axe/plan est evaluee a l origine de l axe.
482 dist = A*X + B*Y + C*Z + D;
484 Standard_Real tolang = Tolang;
485 Standard_Boolean newparams = Standard_False;
487 gp_Vec ldv( axec.Direction() );
489 Standard_Real dA = Abs( ldv.Angle( npv ) );
492 Standard_Real dang = Abs( ldv.Angle( npv ) ) - M_PI/2.;
493 Standard_Real dangle = Abs( dang );
494 if( dangle > Tolang )
496 Standard_Real sinda = Abs( Sin( dangle ) );
497 Standard_Real dif = Abs( sinda - Tol );
501 newparams = Standard_True;
507 IntAna_IntConicQuad inter(axec,P,tolang,Tol,H);
509 if (inter.IsParallel()) {
510 // Le resultat de l intersection Plan-Cylindre est de type droite.
511 // il y a 1 ou 2 droites
513 typeres = IntAna_Line;
514 omega.SetCoord(X-dist*A,Y-dist*B,Z-dist*C);
516 if (Abs(Abs(dist)-radius) < Tol)
523 gp_XYZ omegaXYZ(X,Y,Z);
524 gp_XYZ omegaXYZtrnsl( omegaXYZ + 100.*axec.Direction().XYZ() );
525 Standard_Real Xt,Yt,Zt,distt;
526 omegaXYZtrnsl.Coord(Xt,Yt,Zt);
527 distt = A*Xt + B*Yt + C*Zt + D;
528 gp_XYZ omega1(omegaXYZtrnsl.X()-distt*A,
529 omegaXYZtrnsl.Y()-distt*B,
530 omegaXYZtrnsl.Z()-distt*C );
532 ppt1.SetXYZ( omega1 );
533 gp_Vec vv1(pt1,ppt1);
538 dir1 = axec.Direction();
540 else if (Abs(dist) < radius)
543 h = Sqrt(radius*radius - dist*dist);
544 axey = axec.Direction().XYZ().Crossed(normp); // axey est normalise
546 pt1.SetXYZ(omega - h*axey);
547 pt2.SetXYZ(omega + h*axey);
551 gp_XYZ omegaXYZ(X,Y,Z);
552 gp_XYZ omegaXYZtrnsl( omegaXYZ + 100.*axec.Direction().XYZ() );
553 Standard_Real Xt,Yt,Zt,distt,ht;
554 omegaXYZtrnsl.Coord(Xt,Yt,Zt);
555 distt = A*Xt + B*Yt + C*Zt + D;
556 // ht = Sqrt(radius*radius - distt*distt);
557 Standard_Real anSqrtArg = radius*radius - distt*distt;
558 ht = (anSqrtArg > 0.) ? Sqrt(anSqrtArg) : 0.;
560 gp_XYZ omega1( omegaXYZtrnsl.X()-distt*A,
561 omegaXYZtrnsl.Y()-distt*B,
562 omegaXYZtrnsl.Z()-distt*C );
564 ppt1.SetXYZ( omega1 - ht*axey);
565 ppt2.SetXYZ( omega1 + ht*axey);
566 gp_Vec vv1(pt1,ppt1);
567 gp_Vec vv2(pt2,ppt2);
575 dir1 = axec.Direction();
576 dir2 = axec.Direction();
581 // debug JAG : le nbint = 0 doit etre remplace par typeres = IntAna_Empty
582 // et ne pas etre seulement supprime...
585 typeres = IntAna_Empty;
588 else { // Il y a un point d intersection. C est le centre du cercle
589 // ou de l ellipse solution.
592 axey = normp.Crossed(axec.Direction().XYZ());
593 sint = axey.Modulus();
595 pt1 = inter.Point(1);
597 if (sint < Tol/radius) {
599 // on construit un cercle avec comme axes X et Y ceux du cylindre
600 typeres = IntAna_Circle;
602 dir1 = axec.Direction(); // axe Z
603 dir2 = Cl.Position().XDirection();
608 // on construit un ellipse
609 typeres = IntAna_Ellipse;
610 cost = Abs(axec.Direction().XYZ().Dot(normp));
611 axex = axey.Crossed(normp);
613 dir1.SetXYZ(normp); //Modif ds ce bloc
616 param1 = radius/cost;
621 done = Standard_True;
623 //=======================================================================
624 //function : IntAna_QuadQuadGeo
626 //=======================================================================
627 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Pln& P,
629 const Standard_Real Tolang,
630 const Standard_Real Tol)
631 : done(Standard_False),
633 typeres(IntAna_Empty),
644 myCommonGen(Standard_False),
648 Perform(P,Co,Tolang,Tol);
650 //=======================================================================
653 //=======================================================================
654 void IntAna_QuadQuadGeo::Perform(const gp_Pln& P,
656 const Standard_Real Tolang,
657 const Standard_Real Tol)
660 done = Standard_False;
663 Standard_Real A,B,C,D;
665 Standard_Real dist,sint,cost,sina,cosa,angl,costa;
669 gp_Lin axec(Co.Axis());
670 P.Coefficients(A,B,C,D);
671 gp_Pnt apex(Co.Apex());
674 dist = A*X + B*Y + C*Z + D; // distance signee sommet du cone/ Plan
676 gp_XYZ normp = P.Axis().Direction().XYZ();
677 if(P.Direct()==Standard_False) { //-- lbr le 14 jan 97
681 axey = normp.Crossed(Co.Axis().Direction().XYZ());
682 axex = axey.Crossed(normp);
685 angl = Co.SemiAngle();
688 sina = Abs(Sin(angl));
691 // Angle entre la normale au plan et l axe du cone, ramene entre 0. et PI/2.
693 sint = axey.Modulus();
694 cost = Abs(Co.Axis().Direction().XYZ().Dot(normp));
696 // Le calcul de costa permet de determiner si le plan contient
697 // un generatrice du cone : on calcul Sin((PI/2. - t) - angl)
699 costa = cost*cosa - sint*sina; // sin((PI/2 -t)-angl)=cos(t+angl)
700 // avec t ramene entre 0 et pi/2.
702 if (Abs(dist) < Tol) {
703 // on considere que le plan contient le sommet du cone.
704 // les solutions possibles sont donc : 1 point, 1 droite, 2 droites
705 // selon l inclinaison du plan.
707 if (Abs(costa) < Tolang) { // plan parallele a la generatrice
708 typeres = IntAna_Line;
710 gp_XYZ ptonaxe(apex.XYZ() + 10.*(Co.Axis().Direction().XYZ()));
711 // point sur l axe du cone cote z positif
713 dist = A*ptonaxe.X() + B*ptonaxe.Y() + C*ptonaxe.Z() + D;
714 ptonaxe = ptonaxe - dist*normp;
716 dir1.SetXYZ(ptonaxe - pt1.XYZ());
718 else if (cost < sina) { // plan "interieur" au cone
719 typeres = IntAna_Line;
723 dh = Sqrt(sina*sina-cost*cost)/cosa;
724 dir1.SetXYZ(axex + dh*axey);
725 dir2.SetXYZ(axex - dh*axey);
727 else { // plan "exterieur" au cone
728 typeres = IntAna_Point;
734 // Solutions possibles : cercle, ellipse, parabole, hyperbole selon
735 // l inclinaison du plan.
736 Standard_Real deltacenter, distance;
739 // Le plan contient la direction de l axe du cone. La solution est
741 typeres = IntAna_Hyperbola;
743 pt1.SetXYZ(apex.XYZ()-dist*normp);
747 param1 = param2 = Abs(dist/Tan(angl));
748 param1bis = param2bis = Abs(dist);
752 IntAna_IntConicQuad inter(axec,P,Tolang); // on a necessairement 1 point.
754 gp_Pnt center(inter.Point(1));
756 // En fonction de la position de l intersection par rapport au sommet
757 // du cone, on change l axe x en -x et y en -y. Le parametre du sommet
758 // sur axec est negatif (voir definition du cone)
760 distance = apex.Distance(center);
762 if (inter.ParamOnConic(1) + Co.RefRadius()/Tan(angl) < 0.) {
767 if (Abs(costa) < Tolang) { // plan parallele a une generatrice
768 typeres = IntAna_Parabola;
770 deltacenter = distance/2./cosa;
772 pt1.SetXYZ(center.XYZ()-deltacenter*axex);
775 param1 = deltacenter*sina*sina;
777 else if (sint < Tolang) { // plan perpendiculaire a l axe
778 typeres = IntAna_Circle;
781 dir1 = Co.Position().Direction();
782 dir2 = Co.Position().XDirection();
783 param1 = apex.Distance(center)*Abs(Tan(angl));
785 else if (cost < sina ) {
786 typeres = IntAna_Hyperbola;
790 deltacenter = sint*sina*sina*distance/(sina*sina - cost*cost);
791 pt1.SetXYZ(center.XYZ() - deltacenter*axex);
795 param1 = param2 = cost*sina*cosa*distance /(sina*sina-cost*cost);
796 param1bis = param2bis = cost*sina*distance / Sqrt(sina*sina-cost*cost);
799 else { // on a alors cost > sina
800 typeres = IntAna_Ellipse;
802 Standard_Real radius = cost*sina*cosa*distance/(cost*cost-sina*sina);
803 deltacenter = sint*sina*sina*distance/(cost*cost-sina*sina);
805 pt1.SetXYZ(center.XYZ() + deltacenter*axex);
809 param1bis = cost*sina*distance/ Sqrt(cost*cost - sina*sina);
814 //-- On a du mal a gerer plus loin (Value ProjLib, Params ... )
815 //-- des hyperboles trop bizarres
816 //-- On retourne False -> Traitement par biparametree
817 static Standard_Real EllipseLimit = 1.0E+9; //OCC513(apo) 1000000
818 static Standard_Real HyperbolaLimit = 2.0E+6; //OCC537(apo) 50000
819 if(typeres==IntAna_Ellipse && nbint>=1) {
820 if(Abs(param1) > EllipseLimit || Abs(param1bis) > EllipseLimit) {
825 if(typeres==IntAna_Hyperbola && nbint>=2) {
826 if(Abs(param2) > HyperbolaLimit || Abs(param2bis) > HyperbolaLimit) {
827 done = Standard_False;
831 if(typeres==IntAna_Hyperbola && nbint>=1) {
832 if(Abs(param1) > HyperbolaLimit || Abs(param1bis) > HyperbolaLimit) {
838 done = Standard_True;
841 //=======================================================================
842 //function : IntAna_QuadQuadGeo
843 //purpose : Pln Sphere
844 //=======================================================================
845 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Pln& P,
847 : done(Standard_False),
849 typeres(IntAna_Empty),
860 myCommonGen(Standard_False),
866 //=======================================================================
869 //=======================================================================
870 void IntAna_QuadQuadGeo::Perform( const gp_Pln& P
874 done = Standard_False;
875 Standard_Real A,B,C,D,dist, radius;
879 // debug JAG : on met typeres = IntAna_Empty par defaut...
880 typeres = IntAna_Empty;
882 P.Coefficients(A,B,C,D);
883 S.Location().Coord(X,Y,Z);
886 dist = A * X + B * Y + C * Z + D;
888 if (Abs( Abs(dist) - radius) < Epsilon(radius)) {
889 // on a une seule solution : le point projection du centre de la sphere
892 typeres = IntAna_Point;
893 pt1.SetCoord(X - dist*A, Y - dist*B, Z - dist*C);
895 else if (Abs(dist) < radius) {
896 // on a un cercle solution
898 typeres = IntAna_Circle;
899 pt1.SetCoord(X - dist*A, Y - dist*B, Z - dist*C);
900 dir1 = P.Axis().Direction();
901 if(P.Direct()==Standard_False) dir1.Reverse();
902 dir2 = P.Position().XDirection();
903 param1 = Sqrt(radius*radius - dist*dist);
905 param2bis=0.0; //-- pour eviter param2bis not used ....
906 done = Standard_True;
909 //=======================================================================
910 //function : IntAna_QuadQuadGeo
911 //purpose : Cylinder - Cylinder
912 //=======================================================================
913 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cylinder& Cyl1,
914 const gp_Cylinder& Cyl2,
915 const Standard_Real Tol)
916 : done(Standard_False),
918 typeres(IntAna_Empty),
929 myCommonGen(Standard_False),
933 Perform(Cyl1,Cyl2,Tol);
935 //=======================================================================
938 //=======================================================================
939 void IntAna_QuadQuadGeo::Perform(const gp_Cylinder& Cyl1,
940 const gp_Cylinder& Cyl2,
941 const Standard_Real Tol)
944 //---------------------------- Parallel axes -------------------------
945 AxeOperator A1A2(Cyl1.Axis(),Cyl2.Axis());
946 Standard_Real R1=Cyl1.Radius();
947 Standard_Real R2=Cyl2.Radius();
948 Standard_Real RmR, RmR_Relative;
949 RmR=(R1>R2)? (R1-R2) : (R2-R1);
952 Rmax=(R1>R2)? R1 : R2;
953 RmR_Relative=RmR/Rmax;
956 Standard_Real DistA1A2=A1A2.Distance();
968 typeres=IntAna_Empty;
972 { //-- DistA1A2 > Tol
973 gp_Pnt P1=Cyl1.Location();
974 gp_Pnt P2t=Cyl2.Location();
976 //-- P2t is projected on the plane (P1,DirCylX,DirCylY)
977 gp_Dir DirCyl = Cyl1.Position().Direction();
978 Standard_Real ProjP2OnDirCyl1=gp_Vec(DirCyl).Dot(gp_Vec(P1,P2t));
980 //P2 is a projection the location of the 2nd cylinder on the base
981 //of the 1st cylinder
982 P2.SetCoord(P2t.X() - ProjP2OnDirCyl1*DirCyl.X(),
983 P2t.Y() - ProjP2OnDirCyl1*DirCyl.Y(),
984 P2t.Z() - ProjP2OnDirCyl1*DirCyl.Z());
986 Standard_Real R1pR2=R1+R2;
987 if(DistA1A2>(R1pR2+Tol))
989 typeres=IntAna_Empty;
992 else if((R1pR2 - DistA1A2) <= RealSmall())
994 //-- 1 Tangent line -------------------------------------OK
999 Standard_Real R1_R1pR2=R1/R1pR2;
1000 pt1.SetCoord( P1.X() + R1_R1pR2 * (P2.X()-P1.X()),
1001 P1.Y() + R1_R1pR2 * (P2.Y()-P1.Y()),
1002 P1.Z() + R1_R1pR2 * (P2.Z()-P1.Z()));
1004 else if(DistA1A2>RmR)
1006 //-- 2 lines ---------------------------------------------OK
1007 typeres=IntAna_Line;
1012 const Standard_Real aR1R1 = R1*R1;
1025 Two cylinders have axes collinear. Therefore, problem can be reformulated as
1026 to find intersection point of two circles (the bases of the cylinders) on
1027 the plane: 1st circle has center P1 and radius R1 (the radius of the
1028 1st cylinder) and 2nd circle has center P2 and radius R2 (the radius of the
1029 2nd cylinder). The plane is the base of the 1st cylinder. Points A and B
1030 are intersection point of these circles. Distance P1P2 is equal to DistA1A2.
1031 O1 is the intersection point of P1P2 and AB segments.
1033 At that, if distance AB < Tol we consider that the circles are tangent and
1034 has only one intersection point.
1036 AB = 2*R1*sin(angle AP1P2).
1038 AB^2 < Tol^2 => 4*R1*R1*sin(angle AP1P2)^2 < Tol*Tol.
1042 //Cosine and Square of Sine of the A-P1-P2 angle
1043 const Standard_Real aCos = 0.5*(aR1R1-R2*R2+DistA1A2*DistA1A2)/(R1*DistA1A2);
1044 const Standard_Real aSin2 = 1-aCos*aCos;
1046 const Standard_Boolean isTangent =((4.0*aR1R1*aSin2) < Tol*Tol);
1048 //Normalized vector P1P2
1049 const gp_Vec DirA1A2((P2.XYZ() - P1.XYZ())/DistA1A2);
1053 //Intercept the segment from P1 point along P1P2 direction
1054 //and having |P1O1| length
1056 pt1.SetXYZ(P1.XYZ() + DirA1A2.XYZ()*R1*aCos);
1060 //Sine of the A-P1-P2 angle (if aSin2 < 0 then isTangent == TRUE =>
1061 //go to another branch)
1062 const Standard_Real aSin = sqrt(aSin2);
1064 //1. Rotate P1P2 to the angle A-P1-P2 relative to P1
1065 //(clockwise and anticlockwise for getting
1066 //two intersection points).
1067 //2. Intercept the segment from P1 along direction,
1068 //determined in the preview paragraph and having R1 length
1069 const gp_Dir &aXDir = Cyl1.Position().XDirection(),
1070 &aYDir = Cyl1.Position().YDirection();
1071 const gp_Vec aR1Xdir = R1*aXDir.XYZ(),
1072 aR1Ydir = R1*aYDir.XYZ();
1074 //Source 2D-coordinates of the P1P2 vector normalized
1075 //in coordinate system, based on the X- and Y-directions
1076 //of the 1st cylinder in the plane of the 1st cylinder base
1077 //(P1 is the origin of the coordinate system).
1078 const Standard_Real aDx = DirA1A2.Dot(aXDir),
1079 aDy = DirA1A2.Dot(aYDir);
1081 //New coordinate (after rotation) of the P1P2 vector normalized.
1082 Standard_Real aNewDx = aDx*aCos - aDy*aSin,
1083 aNewDy = aDy*aCos + aDx*aSin;
1084 pt1.SetXYZ(P1.XYZ() + aNewDx*aR1Xdir.XYZ() + aNewDy*aR1Ydir.XYZ());
1086 aNewDx = aDx*aCos + aDy*aSin;
1087 aNewDy = aDy*aCos - aDx*aSin;
1088 pt2.SetXYZ(P1.XYZ() + aNewDx*aR1Xdir.XYZ() + aNewDy*aR1Ydir.XYZ());
1091 else if(DistA1A2>(RmR-Tol))
1093 //-- 1 Tangent ------------------------------------------OK
1094 typeres=IntAna_Line;
1097 Standard_Real R1_RmR=R1/RmR;
1102 pt1.SetCoord( P1.X() + R1_RmR * (P2.X()-P1.X()),
1103 P1.Y() + R1_RmR * (P2.Y()-P1.Y()),
1104 P1.Z() + R1_RmR * (P2.Z()-P1.Z()));
1108 typeres=IntAna_Empty;
1112 else { //-- No Parallel Axis ---------------------------------OK
1113 if((RmR_Relative<=myEPSILON_CYLINDER_DELTA_RADIUS)
1114 && (DistA1A2 <= myEPSILON_CYLINDER_DELTA_DISTANCE))
1116 //-- PI/2 between the two axis and Intersection
1117 //-- and identical radius
1118 typeres=IntAna_Ellipse;
1120 gp_Dir DirCyl1=Cyl1.Position().Direction();
1121 gp_Dir DirCyl2=Cyl2.Position().Direction();
1122 pt1=pt2=A1A2.PtIntersect();
1124 Standard_Real A=DirCyl1.Angle(DirCyl2);
1126 B=Abs(Sin(0.5*(M_PI-A)));
1129 if(A==0.0 || B==0.0)
1131 typeres=IntAna_Same;
1135 gp_Vec dircyl1(DirCyl1);gp_Vec dircyl2(DirCyl2);
1136 dir1 = gp_Dir(dircyl1.Added(dircyl2));
1137 dir2 = gp_Dir(dircyl1.Subtracted(dircyl2));
1139 param2 = Cyl1.Radius() / A;
1140 param1 = Cyl1.Radius() / B;
1141 param2bis= param1bis = Cyl1.Radius();
1142 if(param1 < param1bis)
1149 if(param2 < param2bis)
1158 if(Abs(DistA1A2-Cyl1.Radius()-Cyl2.Radius())<Tol)
1160 typeres = IntAna_Point;
1161 Standard_Real d,p1,p2;
1163 gp_Dir D1 = Cyl1.Axis().Direction();
1164 gp_Dir D2 = Cyl2.Axis().Direction();
1165 A1A2.Distance(d,p1,p2);
1166 gp_Pnt P = Cyl1.Axis().Location();
1167 gp_Pnt P1(P.X() - p1*D1.X(),
1171 P = Cyl2.Axis().Location();
1173 gp_Pnt P2(P.X() - p2*D2.X(),
1181 pt1.SetCoord(P1.X() + p1*D1.X(),
1183 P1.Z() + p1*D1.Z());
1188 typeres=IntAna_NoGeometricSolution;
1193 //=======================================================================
1194 //function : IntAna_QuadQuadGeo
1195 //purpose : Cylinder - Cone
1196 //=======================================================================
1197 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cylinder& Cyl,
1199 const Standard_Real Tol)
1200 : done(Standard_False),
1202 typeres(IntAna_Empty),
1213 myCommonGen(Standard_False),
1217 Perform(Cyl,Con,Tol);
1219 //=======================================================================
1220 //function : Perform
1222 //=======================================================================
1223 void IntAna_QuadQuadGeo::Perform(const gp_Cylinder& Cyl,
1225 const Standard_Real )
1228 AxeOperator A1A2(Cyl.Axis(),Con.Axis());
1230 gp_Pnt Pt=Con.Apex();
1231 Standard_Real dist=Cyl.Radius()/(Tan(Con.SemiAngle()));
1232 gp_Dir dir=Cyl.Position().Direction();
1233 pt1.SetCoord( Pt.X() + dist*dir.X()
1234 ,Pt.Y() + dist*dir.Y()
1235 ,Pt.Z() + dist*dir.Z());
1236 pt2.SetCoord( Pt.X() - dist*dir.X()
1237 ,Pt.Y() - dist*dir.Y()
1238 ,Pt.Z() - dist*dir.Z());
1240 param1=param2=Cyl.Radius();
1242 typeres=IntAna_Circle;
1246 typeres=IntAna_NoGeometricSolution;
1249 //=======================================================================
1251 //purpose : Cylinder - Sphere
1252 //=======================================================================
1253 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cylinder& Cyl,
1254 const gp_Sphere& Sph,
1255 const Standard_Real Tol)
1256 : done(Standard_False),
1258 typeres(IntAna_Empty),
1269 myCommonGen(Standard_False),
1273 Perform(Cyl,Sph,Tol);
1275 //=======================================================================
1276 //function : Perform
1278 //=======================================================================
1279 void IntAna_QuadQuadGeo::Perform( const gp_Cylinder& Cyl
1280 ,const gp_Sphere& Sph
1281 ,const Standard_Real)
1284 gp_Pnt Pt=Sph.Location();
1285 AxeOperator A1A2(Cyl.Axis(),Sph.Position().Axis());
1286 if((A1A2.Intersect() && Pt.Distance(A1A2.PtIntersect())==0.0 )
1288 if(Sph.Radius() < Cyl.Radius()) {
1289 typeres = IntAna_Empty;
1292 Standard_Real dist=Sqrt( Sph.Radius() * Sph.Radius() - Cyl.Radius() * Cyl.Radius() );
1293 gp_Dir dir=Cyl.Position().Direction();
1295 typeres=IntAna_Circle;
1296 pt1.SetCoord( Pt.X() + dist*dir.X()
1297 ,Pt.Y() + dist*dir.Y()
1298 ,Pt.Z() + dist*dir.Z());
1300 param1 = Cyl.Radius();
1301 if(dist>RealEpsilon()) {
1302 pt2.SetCoord( Pt.X() - dist*dir.X()
1303 ,Pt.Y() - dist*dir.Y()
1304 ,Pt.Z() - dist*dir.Z());
1305 param2=Cyl.Radius();
1311 typeres=IntAna_NoGeometricSolution;
1315 //=======================================================================
1316 //function : IntAna_QuadQuadGeo
1317 //purpose : Cone - Cone
1318 //=======================================================================
1319 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cone& Con1,
1320 const gp_Cone& Con2,
1321 const Standard_Real Tol)
1322 : done(Standard_False),
1324 typeres(IntAna_Empty),
1335 myCommonGen(Standard_False),
1339 Perform(Con1,Con2,Tol);
1342 //=======================================================================
1343 //function : Perform
1345 //=======================================================================
1346 void IntAna_QuadQuadGeo::Perform(const gp_Cone& Con1,
1347 const gp_Cone& Con2,
1348 const Standard_Real Tol)
1352 Standard_Real tg1, tg2, aDA1A2, aTol2;
1353 gp_Pnt aPApex1, aPApex2;
1355 Standard_Real TOL_APEX_CONF = 1.e-10;
1358 tg1=Tan(Con1.SemiAngle());
1359 tg2=Tan(Con2.SemiAngle());
1361 if((tg1 * tg2) < 0.) {
1366 aPApex1=Con1.Apex();
1367 aPApex2=Con2.Apex();
1368 aDA1A2=aPApex1.SquareDistance(aPApex2);
1370 AxeOperator A1A2(Con1.Axis(),Con2.Axis());
1376 gp_Pnt P=Con1.Apex();
1377 gp_Dir D=Con1.Position().Direction();
1378 Standard_Real d=gp_Vec(D).Dot(gp_Vec(P,Con2.Apex()));
1380 if(Abs(tg1-tg2)>myEPSILON_ANGLE_CONE) {
1381 if (fabs(d) < TOL_APEX_CONF) {
1382 typeres = IntAna_Point;
1387 x=(d*tg2)/(tg1+tg2);
1388 pt1.SetCoord( P.X() + x*D.X()
1393 x=(d*tg2)/(tg2-tg1);
1394 pt2.SetCoord( P.X() + x*D.X()
1400 typeres=IntAna_Circle;
1403 if (fabs(d) < TOL_APEX_CONF) {
1404 typeres=IntAna_Same;
1407 typeres=IntAna_Circle;
1410 pt1.SetCoord( P.X() + x*D.X()
1413 param1 = Abs(x * tg1);
1417 } //-- fin A1A2.Same
1419 else if((Abs(tg1-tg2)<myEPSILON_ANGLE_CONE) && (A1A2.Parallel())) {
1420 //-- voir AnVer12mai98
1421 Standard_Real DistA1A2=A1A2.Distance();
1422 gp_Dir DA1=Con1.Position().Direction();
1423 gp_Vec O1O2(Con1.Apex(),Con2.Apex());
1424 gp_Dir O1O2n(O1O2); // normalization of the vector before projection
1425 Standard_Real O1O2_DA1=gp_Vec(DA1).Dot(gp_Vec(O1O2n));
1427 gp_Vec O1_Proj_A2(O1O2n.X()-O1O2_DA1*DA1.X(),
1428 O1O2n.Y()-O1O2_DA1*DA1.Y(),
1429 O1O2n.Z()-O1O2_DA1*DA1.Z());
1430 gp_Dir DB1=gp_Dir(O1_Proj_A2);
1432 Standard_Real yO1O2=O1O2.Dot(gp_Vec(DA1));
1433 Standard_Real ABSTG1 = Abs(tg1);
1434 Standard_Real X2 = (DistA1A2/ABSTG1 - yO1O2)*0.5;
1435 Standard_Real X1 = X2+yO1O2;
1437 gp_Pnt P1(Con1.Apex().X() + X1*( DA1.X() + ABSTG1*DB1.X()),
1438 Con1.Apex().Y() + X1*( DA1.Y() + ABSTG1*DB1.Y()),
1439 Con1.Apex().Z() + X1*( DA1.Z() + ABSTG1*DB1.Z()));
1441 gp_Pnt MO1O2(0.5*(Con1.Apex().X()+Con2.Apex().X()),
1442 0.5*(Con1.Apex().Y()+Con2.Apex().Y()),
1443 0.5*(Con1.Apex().Z()+Con2.Apex().Z()));
1444 gp_Vec P1MO1O2(P1,MO1O2);
1446 gp_Dir DA1_X_DB1=DA1.Crossed(DB1);
1447 gp_Dir OrthoPln = DA1_X_DB1.Crossed(gp_Dir(P1MO1O2));
1449 IntAna_QuadQuadGeo INTER_QUAD_PLN(gp_Pln(P1,OrthoPln),Con1,Tol,Tol);
1450 if(INTER_QUAD_PLN.IsDone()) {
1451 switch(INTER_QUAD_PLN.TypeInter()) {
1452 case IntAna_Ellipse: {
1453 typeres=IntAna_Ellipse;
1454 gp_Elips E=INTER_QUAD_PLN.Ellipse(1);
1456 dir1 = E.Position().Direction();
1457 dir2 = E.Position().XDirection();
1458 param1 = E.MajorRadius();
1459 param1bis = E.MinorRadius();
1463 case IntAna_Circle: {
1464 typeres=IntAna_Circle;
1465 gp_Circ C=INTER_QUAD_PLN.Circle(1);
1467 dir1 = C.Position().XDirection();
1468 dir2 = C.Position().YDirection();
1469 param1 = C.Radius();
1473 case IntAna_Hyperbola: {
1474 typeres=IntAna_Hyperbola;
1475 gp_Hypr H=INTER_QUAD_PLN.Hyperbola(1);
1476 pt1 = pt2 = H.Location();
1477 dir1 = H.Position().Direction();
1478 dir2 = H.Position().XDirection();
1479 param1 = param2 = H.MajorRadius();
1480 param1bis = param2bis = H.MinorRadius();
1485 typeres=IntAna_Line;
1486 gp_Lin H=INTER_QUAD_PLN.Line(1);
1487 pt1 = pt2 = H.Location();
1488 dir1 = dir2 = H.Position().Direction();
1489 param1 = param2 = 0.0;
1490 param1bis = param2bis = 0.0;
1495 typeres=IntAna_NoGeometricSolution;
1498 }// else if((Abs(tg1-tg2)<EPSILON_ANGLE_CONE) && (A1A2.Parallel()))
1500 else if (aDA1A2<aTol2) {
1502 // When apices are coinsided there can be 3 possible cases
1503 // 3.1 - empty solution (iRet=0)
1504 // 3.2 - one line when cone1 touches cone2 (iRet=1)
1505 // 3.3 - two lines when cone1 intersects cone2 (iRet=2)
1507 Standard_Integer iRet;
1508 Standard_Real aGamma, aBeta1, aBeta2;
1509 Standard_Real aD1, aR1, aTgBeta1, aTgBeta2, aHalfPI;
1510 Standard_Real aCosGamma, aSinGamma, aDx, aR2, aRD2, aD2;
1511 gp_Pnt2d aP0, aPA1, aP1, aPA2;
1515 // Preliminary analysis. Determination of iRet
1520 aPA1.SetCoord(aD1, 0.);
1521 aP0.SetCoord(0., 0.);
1525 aGamma=aAx1.Angle(aAx2);
1526 if (aGamma>aHalfPI){
1529 aCosGamma=Cos(aGamma);
1530 aSinGamma=Sin(aGamma);
1532 aBeta1=Con1.SemiAngle();
1533 aTgBeta1=Tan(aBeta1);
1534 aTgBeta1=Abs(aTgBeta1);
1536 aBeta2=Con2.SemiAngle();
1537 aTgBeta2=Tan(aBeta2);
1538 aTgBeta2=Abs(aTgBeta2);
1541 aP1.SetCoord(aD1, aR1);
1544 aVAx2.SetCoord(aCosGamma, aSinGamma);
1545 gp_Dir2d aDAx2(aVAx2);
1546 gp_Lin2d aLAx2(aP0, aDAx2);
1548 gp_Vec2d aV(aP0, aP1);
1550 aPA2=aP0.Translated(aDx*aDAx2);
1553 aDx=aPA2.Distance(aP0);
1557 aRD2=aPA2.Distance(aP1);
1559 if (aRD2>(aR2+Tol)) {
1561 typeres=IntAna_Empty; //nothing
1565 iRet=1; //touch case => 1 line
1566 if (aRD2<(aR2-Tol)) {
1567 iRet=2;//intersection => couple of lines
1570 // Finding the solution in 3D
1573 gp_Pnt aQApex1, aQA1, aQA2, aQX, aQX1, aQX2;
1574 gp_Dir aD3Ax1, aD3Ax2;
1576 IntAna_QuadQuadGeo aIntr;
1578 aQApex1=Con1.Apex();
1579 aD3Ax1=aAx1.Direction();
1580 aQA1.SetCoord(aQApex1.X()+aD1*aD3Ax1.X(),
1581 aQApex1.Y()+aD1*aD3Ax1.Y(),
1582 aQApex1.Z()+aD1*aD3Ax1.Z());
1584 aDx=aD3Ax1.Dot(aAx2.Direction());
1588 aD3Ax2=aAx2.Direction();
1590 aD2=aD1*sqrt((1.+aTgBeta1*aTgBeta1)/(1.+aTgBeta2*aTgBeta2));
1592 aQA2.SetCoord(aQApex1.X()+aD2*aD3Ax2.X(),
1593 aQApex1.Y()+aD2*aD3Ax2.Y(),
1594 aQApex1.Z()+aD2*aD3Ax2.Z());
1596 gp_Pln aPln1(aQA1, aD3Ax1);
1597 gp_Pln aPln2(aQA2, aD3Ax2);
1599 aIntr.Perform(aPln1, aPln2, Tol, Tol);
1600 if (!aIntr.IsDone() || 0 == aIntr.NbSolutions()) {
1601 iRet=-1; // just in case. it must not be so
1602 typeres=IntAna_NoGeometricSolution;
1607 const gp_Dir& aDLin=aLin.Direction();
1608 gp_Vec aVLin(aDLin);
1609 gp_Pnt aOrig=aLin.Location();
1610 gp_Vec aVr(aQA1, aOrig);
1612 aQX=aOrig.Translated(aDx*aVLin);
1616 typeres=IntAna_Line;
1627 gp_Vec aVX(aQApex1, aQX);
1634 aDa=aQA1.Distance(aQX);
1635 aDx=sqrt(aR1*aR1-aDa*aDa);
1636 aQX1=aQX.Translated(aDx*aVLin);
1637 aQX2=aQX.Translated(-aDx*aVLin);
1641 gp_Vec aVX1(aQApex1, aQX1);
1643 gp_Vec aVX2(aQApex1, aQX2);
1646 } //else if (aDA1A2<aTol2) {
1647 //Case when cones have common generatrix
1648 else if(A1A2.Intersect()) {
1649 //Check if apex of one cone belongs another one
1650 Standard_Real u, v, tol2 = Tol*Tol;
1651 ElSLib::Parameters(Con2, aPApex1, u, v);
1652 gp_Pnt p = ElSLib::Value(u, v, Con2);
1653 if(aPApex1.SquareDistance(p) > tol2) {
1654 typeres=IntAna_NoGeometricSolution;
1658 ElSLib::Parameters(Con1, aPApex2, u, v);
1659 p = ElSLib::Value(u, v, Con1);
1660 if(aPApex2.SquareDistance(p) > tol2) {
1661 typeres=IntAna_NoGeometricSolution;
1665 //Cones have a common generatrix passing through apexes
1666 myCommonGen = Standard_True;
1668 //common generatrix of cones
1669 gp_Lin aGen(aPApex1, gp_Dir(gp_Vec(aPApex1, aPApex2)));
1671 //Intersection point of axes
1672 gp_Pnt aPAxeInt = A1A2.PtIntersect();
1674 //Characteristic point of intersection curve
1675 u = ElCLib::Parameter(aGen, aPAxeInt);
1676 myPChar = ElCLib::Value(u, aGen);
1679 //Other generatrixes of cones laying in maximal plane
1680 gp_Lin aGen1 = aGen.Rotated(Con1.Axis(), M_PI);
1681 gp_Lin aGen2 = aGen.Rotated(Con2.Axis(), M_PI);
1683 //Intersection point of generatrixes
1684 gp_Dir aN; //solution plane normal
1685 gp_Dir aD1 = aGen1.Direction();
1687 gp_Dir aD2(aD1.Crossed(aGen.Direction()));
1689 if(aD1.IsParallel(aGen2.Direction(), Precision::Angular())) {
1690 aN = aD1.Crossed(aD2);
1692 else if(aGen1.SquareDistance(aGen2) > tol2) {
1693 //Something wrong ???
1694 typeres=IntAna_NoGeometricSolution;
1698 gp_Dir D1 = aGen1.Position().Direction();
1699 gp_Dir D2 = aGen2.Position().Direction();
1700 gp_Pnt O1 = aGen1.Location();
1701 gp_Pnt O2 = aGen2.Location();
1702 Standard_Real D1DotD2 = D1.Dot(D2);
1703 Standard_Real aSin = 1.-D1DotD2*D1DotD2;
1704 gp_Vec O1O2 (O1,O2);
1705 Standard_Real U2 = (D1.XYZ()*(O1O2.Dot(D1))-(O1O2.XYZ())).Dot(D2.XYZ());
1707 gp_Pnt aPGint(ElCLib::Value(U2, aGen2));
1709 aD1 = gp_Dir(gp_Vec(aPGint, myPChar));
1710 aN = aD1.Crossed(aD2);
1712 //Plane that must contain intersection curves
1713 gp_Pln anIntPln(myPChar, aN);
1715 IntAna_QuadQuadGeo INTER_QUAD_PLN(anIntPln,Con1,Tol,Tol);
1717 if(INTER_QUAD_PLN.IsDone()) {
1718 switch(INTER_QUAD_PLN.TypeInter()) {
1719 case IntAna_Ellipse: {
1720 typeres=IntAna_Ellipse;
1721 gp_Elips E=INTER_QUAD_PLN.Ellipse(1);
1723 dir1 = E.Position().Direction();
1724 dir2 = E.Position().XDirection();
1725 param1 = E.MajorRadius();
1726 param1bis = E.MinorRadius();
1730 case IntAna_Circle: {
1731 typeres=IntAna_Circle;
1732 gp_Circ C=INTER_QUAD_PLN.Circle(1);
1734 dir1 = C.Position().XDirection();
1735 dir2 = C.Position().YDirection();
1736 param1 = C.Radius();
1740 case IntAna_Parabola: {
1741 typeres=IntAna_Parabola;
1742 gp_Parab Prb=INTER_QUAD_PLN.Parabola(1);
1743 pt1 = Prb.Location();
1744 dir1 = Prb.Position().Direction();
1745 dir2 = Prb.Position().XDirection();
1746 param1 = Prb.Focal();
1750 case IntAna_Hyperbola: {
1751 typeres=IntAna_Hyperbola;
1752 gp_Hypr H=INTER_QUAD_PLN.Hyperbola(1);
1753 pt1 = pt2 = H.Location();
1754 dir1 = H.Position().Direction();
1755 dir2 = H.Position().XDirection();
1756 param1 = param2 = H.MajorRadius();
1757 param1bis = param2bis = H.MinorRadius();
1762 typeres=IntAna_NoGeometricSolution;
1768 typeres=IntAna_NoGeometricSolution;
1771 //=======================================================================
1772 //function : IntAna_QuadQuadGeo
1773 //purpose : Sphere - Cone
1774 //=======================================================================
1775 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Sphere& Sph,
1777 const Standard_Real Tol)
1778 : done(Standard_False),
1780 typeres(IntAna_Empty),
1791 myCommonGen(Standard_False),
1795 Perform(Sph,Con,Tol);
1797 //=======================================================================
1798 //function : Perform
1800 //=======================================================================
1801 void IntAna_QuadQuadGeo::Perform(const gp_Sphere& Sph,
1803 const Standard_Real)
1809 AxeOperator A1A2(Con.Axis(),Sph.Position().Axis());
1810 gp_Pnt Pt=Sph.Location();
1812 if((A1A2.Intersect() && (Pt.Distance(A1A2.PtIntersect())==0.0))
1814 gp_Pnt ConApex= Con.Apex();
1815 Standard_Real dApexSphCenter=Pt.Distance(ConApex);
1817 if(dApexSphCenter>RealEpsilon()) {
1818 ConDir = gp_Dir(gp_Vec(ConApex,Pt));
1821 ConDir = Con.Position().Direction();
1824 Standard_Real Rad=Sph.Radius();
1825 Standard_Real tga=Tan(Con.SemiAngle());
1829 //-- x: Roots of (x**2 + y**2 = Rad**2)
1830 //-- tga = y / (x+dApexSphCenter)
1831 Standard_Real tgatga = tga * tga;
1832 math_DirectPolynomialRoots Eq( 1.0+tgatga
1833 ,2.0*tgatga*dApexSphCenter
1834 ,-Rad*Rad + dApexSphCenter*dApexSphCenter*tgatga);
1836 Standard_Integer nbsol=Eq.NbSolutions();
1838 typeres=IntAna_Empty;
1841 typeres=IntAna_Circle;
1843 Standard_Real x = Eq.Value(1);
1844 Standard_Real dApexSphCenterpx = dApexSphCenter+x;
1846 pt1.SetCoord( ConApex.X() + (dApexSphCenterpx) * ConDir.X()
1847 ,ConApex.Y() + (dApexSphCenterpx) * ConDir.Y()
1848 ,ConApex.Z() + (dApexSphCenterpx) * ConDir.Z());
1849 param1 = tga * dApexSphCenterpx;
1850 param1 = Abs(param1);
1852 if(param1<=myEPSILON_MINI_CIRCLE_RADIUS) {
1853 typeres=IntAna_PointAndCircle;
1858 Standard_Real x=Eq.Value(2);
1859 Standard_Real dApexSphCenterpx = dApexSphCenter+x;
1861 pt2.SetCoord( ConApex.X() + (dApexSphCenterpx) * ConDir.X()
1862 ,ConApex.Y() + (dApexSphCenterpx) * ConDir.Y()
1863 ,ConApex.Z() + (dApexSphCenterpx) * ConDir.Z());
1864 param2 = tga * dApexSphCenterpx;
1865 param2 = Abs(param2);
1867 if(param2<=myEPSILON_MINI_CIRCLE_RADIUS) {
1868 typeres=IntAna_PointAndCircle;
1875 done=Standard_False;
1879 typeres=IntAna_NoGeometricSolution;
1883 //=======================================================================
1884 //function : IntAna_QuadQuadGeo
1885 //purpose : Sphere - Sphere
1886 //=======================================================================
1887 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo( const gp_Sphere& Sph1
1888 ,const gp_Sphere& Sph2
1889 ,const Standard_Real Tol)
1890 : done(Standard_False),
1892 typeres(IntAna_Empty),
1903 myCommonGen(Standard_False),
1907 Perform(Sph1,Sph2,Tol);
1909 //=======================================================================
1910 //function : Perform
1912 //=======================================================================
1913 void IntAna_QuadQuadGeo::Perform(const gp_Sphere& Sph1,
1914 const gp_Sphere& Sph2,
1915 const Standard_Real Tol)
1918 gp_Pnt O1=Sph1.Location();
1919 gp_Pnt O2=Sph2.Location();
1920 Standard_Real dO1O2=O1.Distance(O2);
1921 Standard_Real R1=Sph1.Radius();
1922 Standard_Real R2=Sph2.Radius();
1923 Standard_Real Rmin,Rmax;
1924 typeres=IntAna_Empty;
1925 param2bis=0.0; //-- pour eviter param2bis not used ....
1927 if(R1>R2) { Rmin=R2; Rmax=R1; } else { Rmin=R1; Rmax=R2; }
1929 if(dO1O2<=Tol && (Abs(R1-R2) <= Tol)) {
1930 typeres = IntAna_Same;
1933 if(dO1O2<=Tol) { return; }
1934 gp_Dir Dir=gp_Dir(gp_Vec(O1,O2));
1935 Standard_Real t = Rmax - dO1O2 - Rmin;
1937 //----------------------------------------------------------------------
1938 //-- |----------------- R1 --------------------|
1939 //-- |----dO1O2-----|-----------R2----------|
1942 //-- |------ R1 ------|---------dO1O2----------|
1943 //-- |-------------------R2-----------------------|
1945 //----------------------------------------------------------------------
1946 if(t >= 0.0 && t <=Tol) {
1947 typeres = IntAna_Point;
1950 if(R1==Rmax) t2=(R1 + (R2 + dO1O2)) * 0.5;
1951 else t2=(-R1+(dO1O2-R2))*0.5;
1953 pt1.SetCoord( O1.X() + t2*Dir.X()
1954 ,O1.Y() + t2*Dir.Y()
1955 ,O1.Z() + t2*Dir.Z());
1958 //-----------------------------------------------------------------
1959 //-- |----------------- dO1O2 --------------------|
1960 //-- |----R1-----|-----------R2----------|-Tol-|
1962 //-- |----------------- Rmax --------------------|
1963 //-- |----Rmin----|-------dO1O2-------|-Tol-|
1965 //-----------------------------------------------------------------
1966 if((dO1O2 > (R1+R2+Tol)) || (Rmax > (dO1O2+Rmin+Tol))) {
1967 typeres=IntAna_Empty;
1970 //---------------------------------------------------------------
1973 //---------------------------------------------------------------
1974 Standard_Real Alpha=0.5*(R1*R1-R2*R2+dO1O2*dO1O2)/(dO1O2);
1975 Standard_Real Beta = R1*R1-Alpha*Alpha;
1976 Beta = (Beta>0.0)? Sqrt(Beta) : 0.0;
1978 if(Beta<= myEPSILON_MINI_CIRCLE_RADIUS) {
1979 typeres = IntAna_Point;
1980 Alpha = (R1 + (dO1O2 - R2)) * 0.5;
1983 typeres = IntAna_Circle;
1987 pt1.SetCoord( O1.X() + Alpha*Dir.X()
1988 ,O1.Y() + Alpha*Dir.Y()
1989 ,O1.Z() + Alpha*Dir.Z());
1997 //=======================================================================
1998 //function : IntAna_QuadQuadGeo
1999 //purpose : Plane - Torus
2000 //=======================================================================
2001 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Pln& Pln,
2002 const gp_Torus& Tor,
2003 const Standard_Real Tol)
2004 : done(Standard_False),
2006 typeres(IntAna_Empty),
2017 myCommonGen(Standard_False),
2021 Perform(Pln,Tor,Tol);
2023 //=======================================================================
2024 //function : Perform
2026 //=======================================================================
2027 void IntAna_QuadQuadGeo::Perform(const gp_Pln& Pln,
2028 const gp_Torus& Tor,
2029 const Standard_Real Tol)
2031 done = Standard_True;
2033 Standard_Real aRMin, aRMaj;
2035 aRMin = Tor.MinorRadius();
2036 aRMaj = Tor.MajorRadius();
2037 if (aRMin >= aRMaj) {
2038 typeres = IntAna_NoGeometricSolution;
2042 const gp_Ax1 aPlnAx = Pln.Axis();
2043 const gp_Ax1 aTorAx = Tor.Axis();
2045 Standard_Boolean bParallel, bNormal;
2047 bParallel = aTorAx.IsParallel(aPlnAx, myEPSILON_AXES_PARA);
2048 bNormal = !bParallel ? aTorAx.IsNormal(aPlnAx, myEPSILON_AXES_PARA) : Standard_False;
2049 if (!bNormal && !bParallel) {
2050 typeres = IntAna_NoGeometricSolution;
2054 Standard_Real aDist;
2056 gp_Pnt aTorLoc = aTorAx.Location();
2058 Standard_Real aDt, X, Y, Z, A, B, C, D;
2060 Pln.Coefficients(A,B,C,D);
2061 aTorLoc.Coord(X,Y,Z);
2062 aDist = A*X + B*Y + C*Z + D;
2064 if ((Abs(aDist) - aRMin) > Tol) {
2065 typeres=IntAna_Empty;
2069 typeres = IntAna_Circle;
2071 pt1.SetCoord(X - aDist*A, Y - aDist*B, Z - aDist*C);
2072 aDt = Sqrt(Abs(aRMin*aRMin - aDist*aDist));
2073 param1 = aRMaj + aDt;
2074 dir1 = aTorAx.Direction();
2076 if ((Abs(aDist) < aRMin) && (aDt > Tol)) {
2078 param2 = aRMaj - aDt;
2085 aDist = Pln.Distance(aTorLoc);
2086 if (aDist > myEPSILON_DISTANCE) {
2087 typeres = IntAna_NoGeometricSolution;
2091 typeres = IntAna_Circle;
2092 param2 = param1 = aRMin;
2093 dir2 = dir1 = aPlnAx.Direction();
2096 gp_Dir aDir = aTorAx.Direction()^dir1;
2097 pt1.SetXYZ(aTorLoc.XYZ() + aRMaj*aDir.XYZ());
2098 pt2.SetXYZ(aTorLoc.XYZ() - aRMaj*aDir.XYZ());
2102 //=======================================================================
2103 //function : IntAna_QuadQuadGeo
2104 //purpose : Cylinder - Torus
2105 //=======================================================================
2106 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cylinder& Cyl,
2107 const gp_Torus& Tor,
2108 const Standard_Real Tol)
2109 : done(Standard_False),
2111 typeres(IntAna_Empty),
2122 myCommonGen(Standard_False),
2126 Perform(Cyl,Tor,Tol);
2128 //=======================================================================
2129 //function : Perform
2131 //=======================================================================
2132 void IntAna_QuadQuadGeo::Perform(const gp_Cylinder& Cyl,
2133 const gp_Torus& Tor,
2134 const Standard_Real Tol)
2136 done = Standard_True;
2138 Standard_Real aRMin, aRMaj;
2140 aRMin = Tor.MinorRadius();
2141 aRMaj = Tor.MajorRadius();
2142 if (aRMin >= aRMaj) {
2143 typeres = IntAna_NoGeometricSolution;
2147 const gp_Ax1 aCylAx = Cyl.Axis();
2148 const gp_Ax1 aTorAx = Tor.Axis();
2150 const gp_Lin aLin(aTorAx);
2151 const gp_Pnt aLocCyl = Cyl.Location();
2153 if (!aTorAx.IsParallel(aCylAx, myEPSILON_AXES_PARA) ||
2154 (aLin.Distance(aLocCyl) > myEPSILON_DISTANCE)) {
2155 typeres = IntAna_NoGeometricSolution;
2159 Standard_Real aRCyl;
2161 aRCyl = Cyl.Radius();
2162 if (((aRCyl + Tol) < (aRMaj - aRMin)) || ((aRCyl - Tol) > (aRMaj + aRMin))) {
2163 typeres = IntAna_Empty;
2167 typeres = IntAna_Circle;
2169 Standard_Real aDist = Sqrt(Abs(aRMin*aRMin - (aRCyl-aRMaj)*(aRCyl-aRMaj)));
2170 gp_XYZ aTorLoc = aTorAx.Location().XYZ();
2172 dir1 = aTorAx.Direction();
2173 pt1.SetXYZ(aTorLoc + aDist*dir1.XYZ());
2176 if ((aDist > Tol) && (aRCyl > (aRMaj - aRMin)) &&
2177 (aRCyl < (aRMaj + aRMin))) {
2179 pt2.SetXYZ(aTorLoc - aDist*dir2.XYZ());
2185 //=======================================================================
2186 //function : IntAna_QuadQuadGeo
2187 //purpose : Cone - Torus
2188 //=======================================================================
2189 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cone& Con,
2190 const gp_Torus& Tor,
2191 const Standard_Real Tol)
2192 : done(Standard_False),
2194 typeres(IntAna_Empty),
2205 myCommonGen(Standard_False),
2209 Perform(Con,Tor,Tol);
2211 //=======================================================================
2212 //function : Perform
2214 //=======================================================================
2215 void IntAna_QuadQuadGeo::Perform(const gp_Cone& Con,
2216 const gp_Torus& Tor,
2217 const Standard_Real Tol)
2219 done = Standard_True;
2221 Standard_Real aRMin, aRMaj;
2223 aRMin = Tor.MinorRadius();
2224 aRMaj = Tor.MajorRadius();
2225 if (aRMin >= aRMaj) {
2226 typeres = IntAna_NoGeometricSolution;
2230 const gp_Ax1 aConAx = Con.Axis();
2231 const gp_Ax1 aTorAx = Tor.Axis();
2233 const gp_Lin aLin(aTorAx);
2234 const gp_Pnt aConApex = Con.Apex();
2236 if (!aTorAx.IsParallel(aConAx, myEPSILON_AXES_PARA) ||
2237 (aLin.Distance(aConApex) > myEPSILON_DISTANCE)) {
2238 typeres = IntAna_NoGeometricSolution;
2242 Standard_Real anAngle, aDist, aParam[4], aDt;
2244 gp_Pnt aTorLoc, aPCT, aPN, aPt[4];
2247 anAngle = Con.SemiAngle();
2248 aTorLoc = aTorAx.Location();
2250 aPN.SetXYZ(aTorLoc.XYZ() + aRMaj*Tor.YAxis().Direction().XYZ());
2251 gp_Dir aDN (gp_Vec(aTorLoc, aPN));
2252 gp_Ax1 anAxCLRot(aConApex, aDN);
2253 gp_Lin aConL = aLin.Rotated(anAxCLRot, anAngle);
2254 gp_Dir aDL = aConL.Position().Direction();
2255 gp_Dir aXDir = Tor.XAxis().Direction();
2257 typeres = IntAna_Empty;
2259 for (i = 0; i < 2; ++i) {
2263 aPCT.SetXYZ(aTorLoc.XYZ() + aRMaj*aXDir.XYZ());
2265 aDist = aConL.Distance(aPCT);
2266 if (aDist > aRMin+Tol) {
2270 typeres = IntAna_Circle;
2272 gp_XYZ aPh = aPCT.XYZ() - aDist*aConL.Normal(aPCT).Direction().XYZ();
2273 aDt = Sqrt(Abs(aRMin*aRMin - aDist*aDist));
2276 gp_XYZ aDVal = aDt*aDL.XYZ();
2277 aP.SetXYZ(aPh + aDVal);
2278 aParam[nbint] = aLin.Distance(aP);
2279 aPt[nbint].SetXYZ(aP.XYZ() - aParam[nbint]*aXDir.XYZ());
2280 aDir[nbint] = aTorAx.Direction();
2282 if ((aDist < aRMin) && (aDt > Tol)) {
2283 aP.SetXYZ(aPh - aDVal);
2284 aParam[nbint] = aLin.Distance(aP);
2285 aPt[nbint].SetXYZ(aP.XYZ() - aParam[nbint]*aXDir.XYZ());
2286 aDir[nbint] = aDir[nbint-1];
2291 for (i = 0; i < nbint; ++i) {
2323 //=======================================================================
2324 //function : IntAna_QuadQuadGeo
2325 //purpose : Sphere - Torus
2326 //=======================================================================
2327 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Sphere& Sph,
2328 const gp_Torus& Tor,
2329 const Standard_Real Tol)
2330 : done(Standard_False),
2332 typeres(IntAna_Empty),
2343 myCommonGen(Standard_False),
2347 Perform(Sph,Tor,Tol);
2349 //=======================================================================
2350 //function : Perform
2352 //=======================================================================
2353 void IntAna_QuadQuadGeo::Perform(const gp_Sphere& Sph,
2354 const gp_Torus& Tor,
2355 const Standard_Real Tol)
2357 done = Standard_True;
2359 Standard_Real aRMin, aRMaj;
2361 aRMin = Tor.MinorRadius();
2362 aRMaj = Tor.MajorRadius();
2363 if (aRMin >= aRMaj) {
2364 typeres = IntAna_NoGeometricSolution;
2368 const gp_Ax1 aTorAx = Tor.Axis();
2369 const gp_Lin aLin(aTorAx);
2370 const gp_Pnt aSphLoc = Sph.Location();
2372 if (aLin.Distance(aSphLoc) > myEPSILON_DISTANCE) {
2373 typeres = IntAna_NoGeometricSolution;
2377 Standard_Real aRSph, aDist;
2380 gp_Dir aXDir = Tor.XAxis().Direction();
2381 aTorLoc.SetXYZ(aTorAx.Location().XYZ() + aRMaj*aXDir.XYZ());
2382 aRSph = Sph.Radius();
2384 gp_Vec aVec12(aTorLoc, aSphLoc);
2385 aDist = aVec12.Magnitude();
2386 if (((aDist - Tol) > (aRMin + aRSph)) ||
2387 ((aDist + Tol) < Abs(aRMin - aRSph))) {
2388 typeres = IntAna_Empty;
2392 typeres = IntAna_Circle;
2394 Standard_Real anAlpha, aBeta;
2396 anAlpha = 0.5*(aRMin*aRMin - aRSph*aRSph + aDist*aDist ) / aDist;
2397 aBeta = Sqrt(Abs(aRMin*aRMin - anAlpha*anAlpha));
2399 gp_Dir aDir12(aVec12);
2400 gp_XYZ aPh = aTorLoc.XYZ() + anAlpha*aDir12.XYZ();
2401 gp_Dir aDC = Tor.YAxis().Direction()^aDir12;
2404 gp_XYZ aDVal = aBeta*aDC.XYZ();
2405 aP.SetXYZ(aPh + aDVal);
2406 param1 = aLin.Distance(aP);
2407 pt1.SetXYZ(aP.XYZ() - param1*aXDir.XYZ());
2408 dir1 = aTorAx.Direction();
2410 if ((aDist < (aRSph + aRMin)) && (aDist > Abs(aRSph - aRMin)) &&
2411 (aDVal.Modulus() > Tol)) {
2412 aP.SetXYZ(aPh - aDVal);
2413 param2 = aLin.Distance(aP);
2414 pt2.SetXYZ(aP.XYZ() - param2*aXDir.XYZ());
2420 //=======================================================================
2421 //function : IntAna_QuadQuadGeo
2422 //purpose : Torus - Torus
2423 //=======================================================================
2424 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Torus& Tor1,
2425 const gp_Torus& Tor2,
2426 const Standard_Real Tol)
2427 : done(Standard_False),
2429 typeres(IntAna_Empty),
2440 myCommonGen(Standard_False),
2444 Perform(Tor1,Tor2,Tol);
2446 //=======================================================================
2447 //function : Perform
2449 //=======================================================================
2450 void IntAna_QuadQuadGeo::Perform(const gp_Torus& Tor1,
2451 const gp_Torus& Tor2,
2452 const Standard_Real Tol)
2454 done = Standard_True;
2456 Standard_Real aRMin1, aRMin2, aRMaj1, aRMaj2;
2458 aRMin1 = Tor1.MinorRadius();
2459 aRMaj1 = Tor1.MajorRadius();
2460 aRMin2 = Tor2.MinorRadius();
2461 aRMaj2 = Tor2.MajorRadius();
2462 if (aRMin1 >= aRMaj1 || aRMin2 >= aRMaj2) {
2463 typeres = IntAna_NoGeometricSolution;
2467 const gp_Ax1 anAx1 = Tor1.Axis();
2468 const gp_Ax1 anAx2 = Tor2.Axis();
2471 if (!anAx1.IsParallel(anAx2, myEPSILON_AXES_PARA) ||
2472 (aL1.Distance(anAx2.Location()) > myEPSILON_DISTANCE)) {
2473 typeres = IntAna_NoGeometricSolution;
2477 gp_Pnt aLoc1, aLoc2;
2479 aLoc1 = anAx1.Location();
2480 aLoc2 = anAx2.Location();
2482 if (aLoc1.IsEqual(aLoc2, Tol) &&
2483 (Abs(aRMin1 - aRMin2) <= Tol) &&
2484 (Abs(aRMaj1 - aRMaj2) <= Tol)) {
2485 typeres = IntAna_Same;
2489 Standard_Real aDist;
2492 gp_Dir aXDir1 = Tor1.XAxis().Direction();
2493 aP1.SetXYZ(aLoc1.XYZ() + aRMaj1*aXDir1.XYZ());
2494 aP2.SetXYZ(aLoc2.XYZ() + aRMaj2*aXDir1.XYZ());
2496 gp_Vec aV12(aP1, aP2);
2497 aDist = aV12.Magnitude();
2498 if (((aDist - Tol) > (aRMin1 + aRMin2)) ||
2499 ((aDist + Tol) < Abs(aRMin1 - aRMin2))) {
2500 typeres = IntAna_Empty;
2504 typeres = IntAna_Circle;
2506 Standard_Real anAlpha, aBeta;
2508 anAlpha = 0.5*(aRMin1*aRMin1 - aRMin2*aRMin2 + aDist*aDist ) / aDist;
2509 aBeta = Sqrt(Abs(aRMin1*aRMin1 - anAlpha*anAlpha));
2511 gp_Dir aDir12(aV12);
2512 gp_XYZ aPh = aP1.XYZ() + anAlpha*aDir12.XYZ();
2513 gp_Dir aDC = Tor1.YAxis().Direction()^aDir12;
2516 gp_XYZ aDVal = aBeta*aDC.XYZ();
2517 aP.SetXYZ(aPh + aDVal);
2518 param1 = aL1.Distance(aP);
2519 pt1.SetXYZ(aP.XYZ() - param1*aXDir1.XYZ());
2520 dir1 = anAx1.Direction();
2522 if ((aDist < (aRMin1 + aRMin2)) && (aDist > Abs(aRMin1 - aRMin2)) &&
2523 aDVal.Modulus() > Tol) {
2524 aP.SetXYZ(aPh - aDVal);
2525 param2 = aL1.Distance(aP);
2526 pt2.SetXYZ(aP.XYZ() - param2*aXDir1.XYZ());
2532 //=======================================================================
2534 //purpose : Returns a Point
2535 //=======================================================================
2536 gp_Pnt IntAna_QuadQuadGeo::Point(const Standard_Integer n) const
2538 if(!done) { StdFail_NotDone::Raise(); }
2539 if(n>nbint || n<1) { Standard_DomainError::Raise(); }
2540 if(typeres==IntAna_PointAndCircle) {
2541 if(n!=1) { Standard_DomainError::Raise(); }
2542 if(param1==0.0) return(pt1);
2545 else if(typeres==IntAna_Point) {
2546 if(n==1) return(pt1);
2550 // WNT (what can you expect from MicroSoft ?)
2551 return gp_Pnt(0,0,0);
2553 //=======================================================================
2555 //purpose : Returns a Line
2556 //=======================================================================
2557 gp_Lin IntAna_QuadQuadGeo::Line(const Standard_Integer n) const
2559 if(!done) { StdFail_NotDone::Raise(); }
2560 if((n>nbint) || (n<1) || (typeres!=IntAna_Line)) {
2561 Standard_DomainError::Raise();
2563 if(n==1) { return(gp_Lin(pt1,dir1)); }
2564 else { return(gp_Lin(pt2,dir2)); }
2566 //=======================================================================
2568 //purpose : Returns a Circle
2569 //=======================================================================
2570 gp_Circ IntAna_QuadQuadGeo::Circle(const Standard_Integer n) const
2572 if(!done) { StdFail_NotDone::Raise(); }
2573 if(typeres==IntAna_PointAndCircle) {
2574 if(n!=1) { Standard_DomainError::Raise(); }
2575 if(param2==0.0) return(gp_Circ(DirToAx2(pt1,dir1),param1));
2576 return(gp_Circ(DirToAx2(pt2,dir2),param2));
2578 else if((n>nbint) || (n<1) || (typeres!=IntAna_Circle)) {
2579 Standard_DomainError::Raise();
2581 if (n==1) { return(gp_Circ(DirToAx2(pt1,dir1),param1));}
2582 else if (n==2) { return(gp_Circ(DirToAx2(pt2,dir2),param2));}
2583 else if (n==3) { return(gp_Circ(DirToAx2(pt3,dir3),param3));}
2584 else { return(gp_Circ(DirToAx2(pt4,dir4),param4));}
2587 //=======================================================================
2588 //function : Ellipse
2589 //purpose : Returns a Elips
2590 //=======================================================================
2591 gp_Elips IntAna_QuadQuadGeo::Ellipse(const Standard_Integer n) const
2593 if(!done) { StdFail_NotDone::Raise(); }
2594 if((n>nbint) || (n<1) || (typeres!=IntAna_Ellipse)) {
2595 Standard_DomainError::Raise();
2599 Standard_Real R1=param1, R2=param1bis, aTmp;
2601 aTmp=R1; R1=R2; R2=aTmp;
2603 gp_Ax2 anAx2(pt1, dir1 ,dir2);
2604 gp_Elips anElips (anAx2, R1, R2);
2608 Standard_Real R1=param2, R2=param2bis, aTmp;
2610 aTmp=R1; R1=R2; R2=aTmp;
2612 gp_Ax2 anAx2(pt2, dir2 ,dir1);
2613 gp_Elips anElips (anAx2, R1, R2);
2617 //=======================================================================
2618 //function : Parabola
2619 //purpose : Returns a Parabola
2620 //=======================================================================
2621 gp_Parab IntAna_QuadQuadGeo::Parabola(const Standard_Integer n) const
2624 StdFail_NotDone::Raise();
2626 if (typeres!=IntAna_Parabola) {
2627 Standard_DomainError::Raise();
2629 if((n>nbint) || (n!=1)) {
2630 Standard_OutOfRange::Raise();
2632 return(gp_Parab(gp_Ax2( pt1
2637 //=======================================================================
2638 //function : Hyperbola
2639 //purpose : Returns a Hyperbola
2640 //=======================================================================
2641 gp_Hypr IntAna_QuadQuadGeo::Hyperbola(const Standard_Integer n) const
2644 StdFail_NotDone::Raise();
2646 if((n>nbint) || (n<1) || (typeres!=IntAna_Hyperbola)) {
2647 Standard_DomainError::Raise();
2650 return(gp_Hypr(gp_Ax2( pt1
2653 ,param1,param1bis));
2656 return(gp_Hypr(gp_Ax2( pt2
2659 ,param2,param2bis));
2662 //=======================================================================
2663 //function : HasCommonGen
2665 //=======================================================================
2666 Standard_Boolean IntAna_QuadQuadGeo::HasCommonGen() const
2670 //=======================================================================
2673 //=======================================================================
2674 const gp_Pnt& IntAna_QuadQuadGeo::PChar() const
2678 //=======================================================================
2679 //function : RefineDir
2681 //=======================================================================
2682 void RefineDir(gp_Dir& aDir)
2684 Standard_Integer k, m, n;
2685 Standard_Real aC[3];
2687 aDir.Coord(aC[0], aC[1], aC[2]);
2691 for (k=0; k<3; ++k) {
2692 if (aC[k]==1. || aC[k]==-1.) {
2695 else if (aC[k]!=0.) {
2701 Standard_Real aEps, aR1, aR2, aNum;
2707 for (k=0; k<3; ++k) {
2709 aNum=(m)? aC[k] : -aC[k];
2710 if (aNum>aR1 && aNum<aR2) {
2723 aDir.SetCoord(aC[0], aC[1], aC[2]);