1 // Created on: 1992-08-06
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
21 //----------------------------------------------------------------------
22 //-- Purposse: Geometric Intersection between two Natural Quadric
23 //-- If the intersection is not a conic,
24 //-- analytical methods must be called.
25 //----------------------------------------------------------------------
27 #define No_Standard_RangeError
28 #define No_Standard_OutOfRange
31 #include <IntAna_QuadQuadGeo.ixx>
33 #include <IntAna_IntConicQuad.hxx>
34 #include <StdFail_NotDone.hxx>
35 #include <Standard_DomainError.hxx>
36 #include <Standard_OutOfRange.hxx>
37 #include <math_DirectPolynomialRoots.hxx>
47 #include <gp_Pnt2d.hxx>
48 #include <gp_Vec2d.hxx>
49 #include <gp_Dir2d.hxx>
53 gp_Ax2 DirToAx2(const gp_Pnt& P,const gp_Dir& D);
55 //=======================================================================
57 //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
58 //=======================================================================
61 AxeOperator(const gp_Ax1& A1,const gp_Ax1& A2);
63 void Distance(Standard_Real& dist,
64 Standard_Real& Param1,
65 Standard_Real& Param2);
67 gp_Pnt PtIntersect() {
70 Standard_Boolean Coplanar(void) {
73 Standard_Boolean Same(void) {
74 return theparallel && (thedistance<myEPSILON_DISTANCE);
76 Standard_Real Distance(void) {
79 Standard_Boolean Intersect(void) {
80 return (thecoplanar && (!theparallel));
82 Standard_Boolean Parallel(void) {
85 Standard_Boolean Normal(void) {
90 Standard_Real Det33(const Standard_Real a11,
91 const Standard_Real a12,
92 const Standard_Real a13,
93 const Standard_Real a21,
94 const Standard_Real a22,
95 const Standard_Real a23,
96 const Standard_Real a31,
97 const Standard_Real a32,
98 const Standard_Real a33) {
99 Standard_Real theReturn =
100 a11*(a22*a33-a32*a23) - a21*(a12*a33-a32*a13) + a31*(a12*a23-a22*a13) ;
108 Standard_Real thedistance;
109 Standard_Boolean theparallel;
110 Standard_Boolean thecoplanar;
111 Standard_Boolean thenormal;
113 Standard_Real myEPSILON_DISTANCE;
114 Standard_Real myEPSILON_AXES_PARA;
117 //=======================================================================
118 //function : AxeOperator::AxeOperator
120 //=======================================================================
121 AxeOperator::AxeOperator(const gp_Ax1& A1,const gp_Ax1& A2)
123 myEPSILON_DISTANCE=0.00000000000001;
124 myEPSILON_AXES_PARA=0.000000000001;
127 //---------------------------------------------------------------------
128 gp_Dir V1=Axe1.Direction();
129 gp_Dir V2=Axe2.Direction();
130 gp_Pnt P1=Axe1.Location();
131 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,Standard_Real& Param1,Standard_Real& Param2)
197 gp_Vec O1O2(Axe1.Location(),Axe2.Location()); //-----------------------------
198 gp_Dir U1 = Axe1.Direction(); //-- juste pour voir.
199 gp_Dir U2 = Axe2.Direction();
201 gp_Dir N = U1.Crossed(U2);
202 Standard_Real D = Det33(U1.X(),U2.X(),N.X(),
204 U1.Z(),U2.Z(),N.Z());
206 dist = Det33(U1.X(),U2.X(),O1O2.X(),
207 U1.Y(),U2.Y(),O1O2.Y(),
208 U1.Z(),U2.Z(),O1O2.Z()) / D;
209 Param1 = Det33(O1O2.X(),U2.X(),N.X(),
210 O1O2.Y(),U2.Y(),N.Y(),
211 O1O2.Z(),U2.Z(),N.Z()) / (-D);
212 //------------------------------------------------------------
213 //-- On resout P1 * Dir1 + P2 * Dir2 + d * N = O1O2
214 //-- soit : Segment perpendiculaire : O1+P1 D1
216 Param2 = Det33(U1.X(),O1O2.X(),N.X(),
217 U1.Y(),O1O2.Y(),N.Y(),
218 U1.Z(),O1O2.Z(),N.Z()) / (D);
221 //=======================================================================
222 //function : DirToAx2
223 //purpose : returns a gp_Ax2 where D is the main direction
224 //=======================================================================
225 gp_Ax2 DirToAx2(const gp_Pnt& P,const gp_Dir& D)
227 Standard_Real x=D.X(); Standard_Real ax=Abs(x);
228 Standard_Real y=D.Y(); Standard_Real ay=Abs(y);
229 Standard_Real z=D.Z(); Standard_Real az=Abs(z);
230 if( (ax==0.0) || ((ax<ay) && (ax<az)) ) {
231 return(gp_Ax2(P,D,gp_Dir(gp_Vec(0.0,-z,y))));
233 else if( (ay==0.0) || ((ay<ax) && (ay<az)) ) {
234 return(gp_Ax2(P,D,gp_Dir(gp_Vec(-z,0.0,x))));
237 return(gp_Ax2(P,D,gp_Dir(gp_Vec(-y,x,0.0))));
240 //=======================================================================
241 //function : IntAna_QuadQuadGeo
242 //purpose : Empty constructor
243 //=======================================================================
244 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(void)
245 : done(Standard_False),
247 typeres(IntAna_Empty),
254 myCommonGen(Standard_False),
259 //=======================================================================
260 //function : InitTolerances
262 //=======================================================================
263 void IntAna_QuadQuadGeo::InitTolerances()
265 myEPSILON_DISTANCE = 0.00000000000001;
266 myEPSILON_ANGLE_CONE = 0.000000000001;
267 myEPSILON_MINI_CIRCLE_RADIUS = 0.000000001;
268 myEPSILON_CYLINDER_DELTA_RADIUS = 0.0000000000001;
269 myEPSILON_CYLINDER_DELTA_DISTANCE= 0.0000001;
270 myEPSILON_AXES_PARA = 0.000000000001;
272 //=======================================================================
273 //function : IntAna_QuadQuadGeo
275 //=======================================================================
276 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Pln& P1,
278 const Standard_Real TolAng,
279 const Standard_Real Tol)
280 : done(Standard_False),
282 typeres(IntAna_Empty),
289 myCommonGen(Standard_False),
293 Perform(P1,P2,TolAng,Tol);
295 //=======================================================================
298 //=======================================================================
299 void IntAna_QuadQuadGeo::Perform (const gp_Pln& P1,
301 const Standard_Real TolAng,
302 const Standard_Real Tol)
308 Standard_Real A1 = 0., B1 = 0., C1 = 0., D1 = 0., A2 = 0., B2 = 0., C2 = 0., D2 = 0.;
309 P1.Coefficients(A1,B1,C1,D1);
310 P2.Coefficients(A2,B2,C2,D2);
312 gp_Vec vd(gp_Vec(A1,B1,C1).Crossed(gp_Vec(A2,B2,C2)));
313 Standard_Real dist1= A2*P1.Location().X() + B2*P1.Location().Y() + C2*P1.Location().Z() + D2;
314 Standard_Real dist2= A1*P2.Location().X() + B1*P2.Location().Y() + C1*P2.Location().Z() + D1;
316 if(vd.Magnitude() <=TolAng) {
317 // normalles are collinear - planes are same or parallel
318 typeres = (Abs(dist1) <= Tol && Abs(dist2) <= Tol) ? IntAna_Same : IntAna_Empty;
321 Standard_Real denom=A1*A2 + B1*B2 + C1*C2;
323 Standard_Real denom2 = denom*denom;
324 Standard_Real ddenom = 1. - denom2;
325 denom = ( Abs(ddenom) <= 1.e-9 ) ? 1.e-9 : ddenom;
327 Standard_Real par1 = dist1/denom;
328 Standard_Real par2 = -dist2/denom;
330 gp_Vec inter1(gp_Vec(A1,B1,C1).Crossed(vd));
331 gp_Vec inter2(gp_Vec(A2,B2,C2).Crossed(vd));
333 Standard_Real X1=P1.Location().X() + par1*inter1.X();
334 Standard_Real Y1=P1.Location().Y() + par1*inter1.Y();
335 Standard_Real Z1=P1.Location().Z() + par1*inter1.Z();
336 Standard_Real X2=P2.Location().X() + par2*inter2.X();
337 Standard_Real Y2=P2.Location().Y() + par2*inter2.Y();
338 Standard_Real Z2=P2.Location().Z() + par2*inter2.Z();
340 pt1=gp_Pnt((X1+X2)*0.5, (Y1+Y2)*0.5, (Z1+Z2)*0.5);
342 typeres = IntAna_Line;
348 //=======================================================================
349 //function : IntAna_QuadQuadGeo
350 //purpose : Pln Cylinder
351 //=======================================================================
352 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo( const gp_Pln& P
353 ,const gp_Cylinder& Cl
354 ,const Standard_Real Tolang
355 ,const Standard_Real Tol)
356 : done(Standard_False),
358 typeres(IntAna_Empty),
365 myCommonGen(Standard_False),
369 Perform(P,Cl,Tolang,Tol);
371 //=======================================================================
374 //=======================================================================
375 void IntAna_QuadQuadGeo::Perform( const gp_Pln& P
376 ,const gp_Cylinder& Cl
377 ,const Standard_Real Tolang
378 ,const Standard_Real Tol)
380 done = Standard_False;
381 Standard_Real dist,radius;
382 Standard_Real A,B,C,D;
384 Standard_Real sint,cost,h;
385 gp_XYZ axex,axey,omega;
389 radius = Cl.Radius();
391 gp_Lin axec(Cl.Axis());
392 gp_XYZ normp(P.Axis().Direction().XYZ());
394 P.Coefficients(A,B,C,D);
395 axec.Location().Coord(X,Y,Z);
396 dist = A*X + B*Y + C*Z + D; // la distance axe/plan est evaluee a l origine de l axe.
398 Standard_Real tolang = Tolang;
399 Standard_Boolean newparams = Standard_False;
401 gp_Vec ldv( axec.Direction() );
403 Standard_Real dA = Abs( ldv.Angle( npv ) );
406 Standard_Real dang = Abs( ldv.Angle( npv ) ) - M_PI/2.;
407 Standard_Real dangle = Abs( dang );
408 if( dangle > Tolang )
410 Standard_Real sinda = Abs( Sin( dangle ) );
411 Standard_Real dif = Abs( sinda - Tol );
415 newparams = Standard_True;
421 IntAna_IntConicQuad inter(axec,P,tolang);
423 if (inter.IsParallel()) {
424 // Le resultat de l intersection Plan-Cylindre est de type droite.
425 // il y a 1 ou 2 droites
427 typeres = IntAna_Line;
428 omega.SetCoord(X-dist*A,Y-dist*B,Z-dist*C);
430 if (Abs(Abs(dist)-radius) < Tol)
437 gp_XYZ omegaXYZ(X,Y,Z);
438 gp_XYZ omegaXYZtrnsl( omegaXYZ + 100.*axec.Direction().XYZ() );
439 Standard_Real Xt,Yt,Zt,distt;
440 omegaXYZtrnsl.Coord(Xt,Yt,Zt);
441 distt = A*Xt + B*Yt + C*Zt + D;
442 gp_XYZ omega1( omegaXYZtrnsl.X()-distt*A, omegaXYZtrnsl.Y()-distt*B, omegaXYZtrnsl.Z()-distt*C );
444 ppt1.SetXYZ( omega1 );
445 gp_Vec vv1(pt1,ppt1);
450 dir1 = axec.Direction();
452 else if (Abs(dist) < radius)
455 h = Sqrt(radius*radius - dist*dist);
456 axey = axec.Direction().XYZ().Crossed(normp); // axey est normalise
458 pt1.SetXYZ(omega - h*axey);
459 pt2.SetXYZ(omega + h*axey);
463 gp_XYZ omegaXYZ(X,Y,Z);
464 gp_XYZ omegaXYZtrnsl( omegaXYZ + 100.*axec.Direction().XYZ() );
465 Standard_Real Xt,Yt,Zt,distt,ht;
466 omegaXYZtrnsl.Coord(Xt,Yt,Zt);
467 distt = A*Xt + B*Yt + C*Zt + D;
468 // ht = Sqrt(radius*radius - distt*distt);
469 Standard_Real anSqrtArg = radius*radius - distt*distt;
470 ht = (anSqrtArg > 0.) ? Sqrt(anSqrtArg) : 0.;
472 gp_XYZ omega1( omegaXYZtrnsl.X()-distt*A, omegaXYZtrnsl.Y()-distt*B, omegaXYZtrnsl.Z()-distt*C );
474 ppt1.SetXYZ( omega1 - ht*axey);
475 ppt2.SetXYZ( omega1 + ht*axey);
476 gp_Vec vv1(pt1,ppt1);
477 gp_Vec vv2(pt2,ppt2);
485 dir1 = axec.Direction();
486 dir2 = axec.Direction();
491 // debug JAG : le nbint = 0 doit etre remplace par typeres = IntAna_Empty
492 // et ne pas etre seulement supprime...
495 typeres = IntAna_Empty;
498 else { // Il y a un point d intersection. C est le centre du cercle
499 // ou de l ellipse solution.
502 axey = normp.Crossed(axec.Direction().XYZ());
503 sint = axey.Modulus();
505 pt1 = inter.Point(1);
507 if (sint < Tol/radius) {
509 // on construit un cercle avec comme axes X et Y ceux du cylindre
510 typeres = IntAna_Circle;
512 dir1 = axec.Direction(); // axe Z
513 dir2 = Cl.Position().XDirection();
518 // on construit un ellipse
519 typeres = IntAna_Ellipse;
520 cost = Abs(axec.Direction().XYZ().Dot(normp));
521 axex = axey.Crossed(normp);
523 dir1.SetXYZ(normp); //Modif ds ce bloc
526 param1 = radius/cost;
530 if(typeres == IntAna_Ellipse) {
531 if( param1>100000.0*param1bis
532 || param1bis>100000.0*param1) {
533 done = Standard_False;
537 done = Standard_True;
539 //=======================================================================
540 //function : IntAna_QuadQuadGeo
542 //=======================================================================
543 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Pln& P,
545 const Standard_Real Tolang,
546 const Standard_Real Tol)
547 : done(Standard_False),
549 typeres(IntAna_Empty),
556 myCommonGen(Standard_False),
560 Perform(P,Co,Tolang,Tol);
562 //=======================================================================
565 //=======================================================================
566 void IntAna_QuadQuadGeo::Perform(const gp_Pln& P,
568 const Standard_Real Tolang,
569 const Standard_Real Tol)
572 done = Standard_False;
575 Standard_Real A,B,C,D;
577 Standard_Real dist,sint,cost,sina,cosa,angl,costa;
581 gp_Lin axec(Co.Axis());
582 P.Coefficients(A,B,C,D);
583 gp_Pnt apex(Co.Apex());
586 dist = A*X + B*Y + C*Z + D; // distance signee sommet du cone/ Plan
588 gp_XYZ normp = P.Axis().Direction().XYZ();
589 if(P.Direct()==Standard_False) { //-- lbr le 14 jan 97
593 axey = normp.Crossed(Co.Axis().Direction().XYZ());
594 axex = axey.Crossed(normp);
597 angl = Co.SemiAngle();
600 sina = Abs(Sin(angl));
603 // Angle entre la normale au plan et l axe du cone, ramene entre 0. et PI/2.
605 sint = axey.Modulus();
606 cost = Abs(Co.Axis().Direction().XYZ().Dot(normp));
608 // Le calcul de costa permet de determiner si le plan contient
609 // un generatrice du cone : on calcul Sin((PI/2. - t) - angl)
611 costa = cost*cosa - sint*sina; // sin((PI/2 -t)-angl)=cos(t+angl)
612 // avec t ramene entre 0 et pi/2.
614 if (Abs(dist) < Tol) {
615 // on considere que le plan contient le sommet du cone.
616 // les solutions possibles sont donc : 1 point, 1 droite, 2 droites
617 // selon l inclinaison du plan.
619 if (Abs(costa) < Tolang) { // plan parallele a la generatrice
620 typeres = IntAna_Line;
622 gp_XYZ ptonaxe(apex.XYZ() + 10.*(Co.Axis().Direction().XYZ()));
623 // point sur l axe du cone cote z positif
625 dist = A*ptonaxe.X() + B*ptonaxe.Y() + C*ptonaxe.Z() + D;
626 ptonaxe = ptonaxe - dist*normp;
628 dir1.SetXYZ(ptonaxe - pt1.XYZ());
630 else if (cost < sina) { // plan "interieur" au cone
631 typeres = IntAna_Line;
635 dh = Sqrt(sina*sina-cost*cost)/cosa;
636 dir1.SetXYZ(axex + dh*axey);
637 dir2.SetXYZ(axex - dh*axey);
639 else { // plan "exterieur" au cone
640 typeres = IntAna_Point;
646 // Solutions possibles : cercle, ellipse, parabole, hyperbole selon
647 // l inclinaison du plan.
648 Standard_Real deltacenter, distance;
651 // Le plan contient la direction de l axe du cone. La solution est
653 typeres = IntAna_Hyperbola;
655 pt1.SetXYZ(apex.XYZ()-dist*normp);
659 param1 = param2 = Abs(dist/Tan(angl));
660 param1bis = param2bis = Abs(dist);
664 IntAna_IntConicQuad inter(axec,P,Tolang); // on a necessairement 1 point.
666 gp_Pnt center(inter.Point(1));
668 // En fonction de la position de l intersection par rapport au sommet
669 // du cone, on change l axe x en -x et y en -y. Le parametre du sommet
670 // sur axec est negatif (voir definition du cone)
672 distance = apex.Distance(center);
674 if (inter.ParamOnConic(1) + Co.RefRadius()/Tan(angl) < 0.) {
679 if (Abs(costa) < Tolang) { // plan parallele a une generatrice
680 typeres = IntAna_Parabola;
682 deltacenter = distance/2./cosa;
684 pt1.SetXYZ(center.XYZ()-deltacenter*axex);
687 param1 = deltacenter*sina*sina;
689 else if (sint < Tolang) { // plan perpendiculaire a l axe
690 typeres = IntAna_Circle;
693 dir1 = Co.Position().Direction();
694 dir2 = Co.Position().XDirection();
695 param1 = apex.Distance(center)*Abs(Tan(angl));
697 else if (cost < sina ) {
698 typeres = IntAna_Hyperbola;
702 deltacenter = sint*sina*sina*distance/(sina*sina - cost*cost);
703 pt1.SetXYZ(center.XYZ() - deltacenter*axex);
707 param1 = param2 = cost*sina*cosa*distance /(sina*sina-cost*cost);
708 param1bis = param2bis = cost*sina*distance / Sqrt(sina*sina-cost*cost);
711 else { // on a alors cost > sina
712 typeres = IntAna_Ellipse;
714 Standard_Real radius = cost*sina*cosa*distance/(cost*cost-sina*sina);
715 deltacenter = sint*sina*sina*distance/(cost*cost-sina*sina);
717 pt1.SetXYZ(center.XYZ() + deltacenter*axex);
721 param1bis = cost*sina*distance/ Sqrt(cost*cost - sina*sina);
726 //-- On a du mal a gerer plus loin (Value ProjLib, Params ... )
727 //-- des hyperboles trop bizarres
728 //-- On retourne False -> Traitement par biparametree
729 static Standard_Real EllipseLimit = 1.0E+9; //OCC513(apo) 1000000
730 static Standard_Real HyperbolaLimit = 2.0E+6; //OCC537(apo) 50000
731 if(typeres==IntAna_Ellipse && nbint>=1) {
732 if(Abs(param1) > EllipseLimit || Abs(param1bis) > EllipseLimit) {
737 if(typeres==IntAna_Hyperbola && nbint>=2) {
738 if(Abs(param2) > HyperbolaLimit || Abs(param2bis) > HyperbolaLimit) {
739 done = Standard_False;
743 if(typeres==IntAna_Hyperbola && nbint>=1) {
744 if(Abs(param1) > HyperbolaLimit || Abs(param1bis) > HyperbolaLimit) {
750 done = Standard_True;
753 //=======================================================================
754 //function : IntAna_QuadQuadGeo
755 //purpose : Pln Sphere
756 //=======================================================================
757 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Pln& P,
759 : done(Standard_False),
761 typeres(IntAna_Empty),
768 myCommonGen(Standard_False),
774 //=======================================================================
777 //=======================================================================
778 void IntAna_QuadQuadGeo::Perform( const gp_Pln& P
782 done = Standard_False;
783 Standard_Real A,B,C,D,dist, radius;
787 // debug JAG : on met typeres = IntAna_Empty par defaut...
788 typeres = IntAna_Empty;
790 P.Coefficients(A,B,C,D);
791 S.Location().Coord(X,Y,Z);
794 dist = A * X + B * Y + C * Z + D;
796 if (Abs( Abs(dist) - radius) < Epsilon(radius)) {
797 // on a une seule solution : le point projection du centre de la sphere
800 typeres = IntAna_Point;
801 pt1.SetCoord(X - dist*A, Y - dist*B, Z - dist*C);
803 else if (Abs(dist) < radius) {
804 // on a un cercle solution
806 typeres = IntAna_Circle;
807 pt1.SetCoord(X - dist*A, Y - dist*B, Z - dist*C);
808 dir1 = P.Axis().Direction();
809 if(P.Direct()==Standard_False) dir1.Reverse();
810 dir2 = P.Position().XDirection();
811 param1 = Sqrt(radius*radius - dist*dist);
813 param2bis=0.0; //-- pour eviter param2bis not used ....
814 done = Standard_True;
817 //=======================================================================
818 //function : IntAna_QuadQuadGeo
819 //purpose : Cylinder - Cylinder
820 //=======================================================================
821 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cylinder& Cyl1,
822 const gp_Cylinder& Cyl2,
823 const Standard_Real Tol)
824 : done(Standard_False),
826 typeres(IntAna_Empty),
833 myCommonGen(Standard_False),
837 Perform(Cyl1,Cyl2,Tol);
839 //=======================================================================
842 //=======================================================================
843 void IntAna_QuadQuadGeo::Perform(const gp_Cylinder& Cyl1,
844 const gp_Cylinder& Cyl2,
845 const Standard_Real Tol)
848 //---------------------------- Parallel axes -------------------------
849 AxeOperator A1A2(Cyl1.Axis(),Cyl2.Axis());
850 Standard_Real R1=Cyl1.Radius();
851 Standard_Real R2=Cyl2.Radius();
852 Standard_Real RmR, RmR_Relative;
853 RmR=(R1>R2)? (R1-R2) : (R2-R1);
855 Standard_Real Rmax, Rmin;
856 Rmax=(R1>R2)? R1 : R2;
857 Rmin=(R1>R2)? R2 : R1;
858 RmR_Relative=RmR/Rmax;
861 Standard_Real DistA1A2=A1A2.Distance();
863 if(A1A2.Parallel()) {
869 typeres=IntAna_Empty;
872 else { //-- DistA1A2 > Tol
873 gp_Pnt P1=Cyl1.Location();
874 gp_Pnt P2t=Cyl2.Location();
876 //-- P2t is projected on the plane (P1,DirCylX,DirCylY)
877 gp_Dir DirCyl = Cyl1.Position().Direction();
878 Standard_Real ProjP2OnDirCyl1=gp_Vec(DirCyl).Dot(gp_Vec(P1,P2t));
880 P2.SetCoord( P2t.X() - ProjP2OnDirCyl1*DirCyl.X()
881 ,P2t.Y() - ProjP2OnDirCyl1*DirCyl.Y()
882 ,P2t.Z() - ProjP2OnDirCyl1*DirCyl.Z());
884 Standard_Real R1pR2=R1+R2;
885 if(DistA1A2>(R1pR2+Tol)) {
886 typeres=IntAna_Empty;
889 else if(DistA1A2>(R1pR2)) {
890 //-- 1 Tangent line -------------------------------------OK
895 Standard_Real R1_R1pR2=R1/R1pR2;
896 pt1.SetCoord( P1.X() + R1_R1pR2 * (P2.X()-P1.X())
897 ,P1.Y() + R1_R1pR2 * (P2.Y()-P1.Y())
898 ,P1.Z() + R1_R1pR2 * (P2.Z()-P1.Z()));
901 else if(DistA1A2>RmR) {
902 //-- 2 lines ---------------------------------------------OK
907 gp_Dir DirA1A2=gp_Dir(P1P2);
908 gp_Dir Ortho_dir1_P1P2 = dir1.Crossed(DirA1A2);
910 Standard_Real Alpha=0.5*(R1*R1-R2*R2+DistA1A2*DistA1A2)/(DistA1A2);
912 // Standard_Real Beta = Sqrt(R1*R1-Alpha*Alpha);
913 Standard_Real anSqrtArg = R1*R1-Alpha*Alpha;
914 Standard_Real Beta = (anSqrtArg > 0.) ? Sqrt(anSqrtArg) : 0.;
916 if((Beta+Beta)<Tol) {
918 pt1.SetCoord( P1.X() + Alpha*DirA1A2.X()
919 ,P1.Y() + Alpha*DirA1A2.Y()
920 ,P1.Z() + Alpha*DirA1A2.Z());
923 pt1.SetCoord( P1.X() + Alpha*DirA1A2.X() + Beta*Ortho_dir1_P1P2.X()
924 ,P1.Y() + Alpha*DirA1A2.Y() + Beta*Ortho_dir1_P1P2.Y()
925 ,P1.Z() + Alpha*DirA1A2.Z() + Beta*Ortho_dir1_P1P2.Z() );
927 pt2.SetCoord( P1.X() + Alpha*DirA1A2.X() - Beta*Ortho_dir1_P1P2.X()
928 ,P1.Y() + Alpha*DirA1A2.Y() - Beta*Ortho_dir1_P1P2.Y()
929 ,P1.Z() + Alpha*DirA1A2.Z() - Beta*Ortho_dir1_P1P2.Z());
932 else if(DistA1A2>(RmR-Tol)) {
933 //-- 1 Tangent ------------------------------------------OK
937 Standard_Real R1_RmR=R1/RmR;
939 if(R1 < R2) R1_RmR = -R1_RmR;
941 pt1.SetCoord( P1.X() + R1_RmR * (P2.X()-P1.X())
942 ,P1.Y() + R1_RmR * (P2.Y()-P1.Y())
943 ,P1.Z() + R1_RmR * (P2.Z()-P1.Z()));
947 typeres=IntAna_Empty;
951 else { //-- No Parallel Axis ---------------------------------OK
952 if((RmR_Relative<=myEPSILON_CYLINDER_DELTA_RADIUS)
953 && (DistA1A2 <= myEPSILON_CYLINDER_DELTA_DISTANCE)) {
954 //-- PI/2 between the two axis and Intersection
955 //-- and identical radius
956 typeres=IntAna_Ellipse;
958 gp_Dir DirCyl1=Cyl1.Position().Direction();
959 gp_Dir DirCyl2=Cyl2.Position().Direction();
960 pt1=pt2=A1A2.PtIntersect();
962 Standard_Real A=DirCyl1.Angle(DirCyl2);
964 B=Abs(Sin(0.5*(M_PI-A)));
967 if(A==0.0 || B==0.0) {
973 gp_Vec dircyl1(DirCyl1);gp_Vec dircyl2(DirCyl2);
974 dir1 = gp_Dir(dircyl1.Added(dircyl2));
975 dir2 = gp_Dir(dircyl1.Subtracted(dircyl2));
977 param2 = Cyl1.Radius() / A;
978 param1 = Cyl1.Radius() / B;
979 param2bis= param1bis = Cyl1.Radius();
980 if(param1 < param1bis) {
981 A=param1; param1=param1bis; param1bis=A;
983 if(param2 < param2bis) {
984 A=param2; param2=param2bis; param2bis=A;
988 if(Abs(DistA1A2-Cyl1.Radius()-Cyl2.Radius())<Tol) {
989 typeres = IntAna_Point;
990 Standard_Real d,p1,p2;
992 gp_Dir D1 = Cyl1.Axis().Direction();
993 gp_Dir D2 = Cyl2.Axis().Direction();
994 A1A2.Distance(d,p1,p2);
995 gp_Pnt P = Cyl1.Axis().Location();
996 gp_Pnt P1(P.X() - p1*D1.X(),
999 P = Cyl2.Axis().Location();
1000 gp_Pnt P2(P.X() - p2*D2.X(),
1006 pt1.SetCoord(P1.X() + p1*D1.X(),
1008 P1.Z() + p1*D1.Z());
1012 typeres=IntAna_NoGeometricSolution;
1017 //=======================================================================
1018 //function : IntAna_QuadQuadGeo
1019 //purpose : Cylinder - Cone
1020 //=======================================================================
1021 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cylinder& Cyl,
1023 const Standard_Real Tol)
1024 : done(Standard_False),
1026 typeres(IntAna_Empty),
1033 myCommonGen(Standard_False),
1037 Perform(Cyl,Con,Tol);
1039 //=======================================================================
1040 //function : Perform
1042 //=======================================================================
1043 void IntAna_QuadQuadGeo::Perform(const gp_Cylinder& Cyl,
1045 const Standard_Real )
1048 AxeOperator A1A2(Cyl.Axis(),Con.Axis());
1050 gp_Pnt Pt=Con.Apex();
1051 Standard_Real dist=Cyl.Radius()/(Tan(Con.SemiAngle()));
1052 gp_Dir dir=Cyl.Position().Direction();
1053 pt1.SetCoord( Pt.X() + dist*dir.X()
1054 ,Pt.Y() + dist*dir.Y()
1055 ,Pt.Z() + dist*dir.Z());
1056 pt2.SetCoord( Pt.X() - dist*dir.X()
1057 ,Pt.Y() - dist*dir.Y()
1058 ,Pt.Z() - dist*dir.Z());
1060 param1=param2=Cyl.Radius();
1062 typeres=IntAna_Circle;
1066 typeres=IntAna_NoGeometricSolution;
1069 //=======================================================================
1071 //purpose : Cylinder - Sphere
1072 //=======================================================================
1073 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cylinder& Cyl,
1074 const gp_Sphere& Sph,
1075 const Standard_Real Tol)
1076 : done(Standard_False),
1078 typeres(IntAna_Empty),
1085 myCommonGen(Standard_False),
1089 Perform(Cyl,Sph,Tol);
1091 //=======================================================================
1092 //function : Perform
1094 //=======================================================================
1095 void IntAna_QuadQuadGeo::Perform( const gp_Cylinder& Cyl
1096 ,const gp_Sphere& Sph
1097 ,const Standard_Real)
1100 gp_Pnt Pt=Sph.Location();
1101 AxeOperator A1A2(Cyl.Axis(),Sph.Position().Axis());
1102 if((A1A2.Intersect() && Pt.Distance(A1A2.PtIntersect())==0.0 )
1104 if(Sph.Radius() < Cyl.Radius()) {
1105 typeres = IntAna_Empty;
1108 Standard_Real dist=Sqrt( Sph.Radius() * Sph.Radius() - Cyl.Radius() * Cyl.Radius() );
1109 gp_Dir dir=Cyl.Position().Direction();
1111 typeres=IntAna_Circle;
1112 pt1.SetCoord( Pt.X() + dist*dir.X()
1113 ,Pt.Y() + dist*dir.Y()
1114 ,Pt.Z() + dist*dir.Z());
1116 param1 = Cyl.Radius();
1117 if(dist>RealEpsilon()) {
1118 pt2.SetCoord( Pt.X() - dist*dir.X()
1119 ,Pt.Y() - dist*dir.Y()
1120 ,Pt.Z() - dist*dir.Z());
1121 param2=Cyl.Radius();
1127 typeres=IntAna_NoGeometricSolution;
1131 //=======================================================================
1132 //function : IntAna_QuadQuadGeo
1133 //purpose : Cone - Cone
1134 //=======================================================================
1135 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cone& Con1,
1136 const gp_Cone& Con2,
1137 const Standard_Real Tol)
1138 : done(Standard_False),
1140 typeres(IntAna_Empty),
1147 myCommonGen(Standard_False),
1151 Perform(Con1,Con2,Tol);
1154 //=======================================================================
1155 //function : Perform
1157 //=======================================================================
1158 void IntAna_QuadQuadGeo::Perform(const gp_Cone& Con1,
1159 const gp_Cone& Con2,
1160 const Standard_Real Tol)
1164 Standard_Real tg1, tg2, aDA1A2, aTol2;
1165 gp_Pnt aPApex1, aPApex2;
1167 tg1=Tan(Con1.SemiAngle());
1168 tg2=Tan(Con2.SemiAngle());
1170 if((tg1 * tg2) < 0.) {
1175 aPApex1=Con1.Apex();
1176 aPApex2=Con2.Apex();
1177 aDA1A2=aPApex1.SquareDistance(aPApex2);
1179 AxeOperator A1A2(Con1.Axis(),Con2.Axis());
1185 gp_Pnt P=Con1.Apex();
1186 gp_Dir D=Con1.Position().Direction();
1187 Standard_Real d=gp_Vec(D).Dot(gp_Vec(P,Con2.Apex()));
1189 if(Abs(tg1-tg2)>myEPSILON_ANGLE_CONE) {
1190 x=(d*tg2)/(tg1+tg2);
1191 pt1.SetCoord( P.X() + x*D.X()
1196 x=(d*tg2)/(tg2-tg1);
1197 pt2.SetCoord( P.X() + x*D.X()
1203 typeres=IntAna_Circle;
1206 if (fabs(d)<1.e-10) {
1207 typeres=IntAna_Same;
1210 typeres=IntAna_Circle;
1213 pt1.SetCoord( P.X() + x*D.X()
1216 param1 = Abs(x * tg1);
1220 } //-- fin A1A2.Same
1222 else if((Abs(tg1-tg2)<myEPSILON_ANGLE_CONE) && (A1A2.Parallel())) {
1223 //-- voir AnVer12mai98
1224 Standard_Real DistA1A2=A1A2.Distance();
1225 gp_Dir DA1=Con1.Position().Direction();
1226 gp_Vec O1O2(Con1.Apex(),Con2.Apex());
1227 Standard_Real O1O2_DA1=gp_Vec(DA1).Dot(O1O2);
1229 gp_Vec O1_Proj_A2(O1O2.X()-O1O2_DA1*DA1.X(),
1230 O1O2.Y()-O1O2_DA1*DA1.Y(),
1231 O1O2.Z()-O1O2_DA1*DA1.Z());
1232 gp_Dir DB1=gp_Dir(O1_Proj_A2);
1234 Standard_Real yO1O2=O1O2.Dot(gp_Vec(DA1));
1235 Standard_Real ABSTG1 = Abs(tg1);
1236 Standard_Real X2 = (DistA1A2/ABSTG1 - yO1O2)*0.5;
1237 Standard_Real X1 = X2+yO1O2;
1239 gp_Pnt P1(Con1.Apex().X() + X1*( DA1.X() + ABSTG1*DB1.X()),
1240 Con1.Apex().Y() + X1*( DA1.Y() + ABSTG1*DB1.Y()),
1241 Con1.Apex().Z() + X1*( DA1.Z() + ABSTG1*DB1.Z()));
1243 gp_Pnt MO1O2(0.5*(Con1.Apex().X()+Con2.Apex().X()),
1244 0.5*(Con1.Apex().Y()+Con2.Apex().Y()),
1245 0.5*(Con1.Apex().Z()+Con2.Apex().Z()));
1246 gp_Vec P1MO1O2(P1,MO1O2);
1248 gp_Dir DA1_X_DB1=DA1.Crossed(DB1);
1249 gp_Dir OrthoPln = DA1_X_DB1.Crossed(gp_Dir(P1MO1O2));
1251 IntAna_QuadQuadGeo INTER_QUAD_PLN(gp_Pln(P1,OrthoPln),Con1,Tol,Tol);
1252 if(INTER_QUAD_PLN.IsDone()) {
1253 switch(INTER_QUAD_PLN.TypeInter()) {
1254 case IntAna_Ellipse: {
1255 typeres=IntAna_Ellipse;
1256 gp_Elips E=INTER_QUAD_PLN.Ellipse(1);
1258 dir1 = E.Position().Direction();
1259 dir2 = E.Position().XDirection();
1260 param1 = E.MajorRadius();
1261 param1bis = E.MinorRadius();
1265 case IntAna_Circle: {
1266 typeres=IntAna_Circle;
1267 gp_Circ C=INTER_QUAD_PLN.Circle(1);
1269 dir1 = C.Position().XDirection();
1270 dir2 = C.Position().YDirection();
1271 param1 = C.Radius();
1275 case IntAna_Hyperbola: {
1276 typeres=IntAna_Hyperbola;
1277 gp_Hypr H=INTER_QUAD_PLN.Hyperbola(1);
1278 pt1 = pt2 = H.Location();
1279 dir1 = H.Position().Direction();
1280 dir2 = H.Position().XDirection();
1281 param1 = param2 = H.MajorRadius();
1282 param1bis = param2bis = H.MinorRadius();
1287 typeres=IntAna_Line;
1288 gp_Lin H=INTER_QUAD_PLN.Line(1);
1289 pt1 = pt2 = H.Location();
1290 dir1 = dir2 = H.Position().Direction();
1291 param1 = param2 = 0.0;
1292 param1bis = param2bis = 0.0;
1297 typeres=IntAna_NoGeometricSolution;
1300 }// else if((Abs(tg1-tg2)<EPSILON_ANGLE_CONE) && (A1A2.Parallel()))
1302 else if (aDA1A2<aTol2) {
1304 // When apices are coinsided there can be 3 possible cases
1305 // 3.1 - empty solution (iRet=0)
1306 // 3.2 - one line when cone1 touches cone2 (iRet=1)
1307 // 3.3 - two lines when cone1 intersects cone2 (iRet=2)
1309 Standard_Integer iRet;
1310 Standard_Real aGamma, aBeta1, aBeta2;
1311 Standard_Real aD1, aR1, aTgBeta1, aTgBeta2, aHalfPI;
1312 Standard_Real aCosGamma, aSinGamma, aDx, aR2, aRD2, aD2;
1313 gp_Pnt2d aP0, aPA1, aP1, aPA2;
1317 // Preliminary analysis. Determination of iRet
1322 aPA1.SetCoord(aD1, 0.);
1323 aP0.SetCoord(0., 0.);
1327 aGamma=aAx1.Angle(aAx2);
1328 if (aGamma>aHalfPI){
1331 aCosGamma=Cos(aGamma);
1332 aSinGamma=Sin(aGamma);
1334 aBeta1=Con1.SemiAngle();
1335 aTgBeta1=Tan(aBeta1);
1336 aTgBeta1=Abs(aTgBeta1);
1338 aBeta2=Con2.SemiAngle();
1339 aTgBeta2=Tan(aBeta2);
1340 aTgBeta2=Abs(aTgBeta2);
1343 aP1.SetCoord(aD1, aR1);
1346 aVAx2.SetCoord(aCosGamma, aSinGamma);
1347 gp_Dir2d aDAx2(aVAx2);
1348 gp_Lin2d aLAx2(aP0, aDAx2);
1350 gp_Vec2d aV(aP0, aP1);
1352 aPA2=aP0.Translated(aDx*aDAx2);
1355 aDx=aPA2.Distance(aP0);
1359 aRD2=aPA2.Distance(aP1);
1361 if (aRD2>(aR2+Tol)) {
1363 typeres=IntAna_Empty; //nothing
1364 //modified by NIZNHY-PKV Fri Mar 23 08:12:23 2012f
1366 //modified by NIZNHY-PKV Fri Mar 23 08:12:29 2012t
1369 iRet=1; //touch case => 1 line
1370 if (aRD2<(aR2-Tol)) {
1371 iRet=2;//intersection => couple of lines
1374 // Finding the solution in 3D
1377 gp_Pnt aQApex1, aQA1, aQA2, aQX, aQX1, aQX2;
1378 gp_Dir aD3Ax1, aD3Ax2;
1380 IntAna_QuadQuadGeo aIntr;
1382 aQApex1=Con1.Apex();
1383 aD3Ax1=aAx1.Direction();
1384 aQA1.SetCoord(aQApex1.X()+aD1*aD3Ax1.X(),
1385 aQApex1.Y()+aD1*aD3Ax1.Y(),
1386 aQApex1.Z()+aD1*aD3Ax1.Z());
1388 aDx=aD3Ax1.Dot(aAx2.Direction());
1392 aD3Ax2=aAx2.Direction();
1394 aD2=aD1*sqrt((1.+aTgBeta1*aTgBeta1)/(1.+aTgBeta2*aTgBeta2));
1396 aQA2.SetCoord(aQApex1.X()+aD2*aD3Ax2.X(),
1397 aQApex1.Y()+aD2*aD3Ax2.Y(),
1398 aQApex1.Z()+aD2*aD3Ax2.Z());
1400 gp_Pln aPln1(aQA1, aD3Ax1);
1401 gp_Pln aPln2(aQA2, aD3Ax2);
1403 aIntr.Perform(aPln1, aPln2, Tol, Tol);
1404 if (!aIntr.IsDone()) {
1405 iRet=-1; // just in case. it must not be so
1406 typeres=IntAna_NoGeometricSolution;
1411 const gp_Dir& aDLin=aLin.Direction();
1412 gp_Vec aVLin(aDLin);
1413 gp_Pnt aOrig=aLin.Location();
1414 gp_Vec aVr(aQA1, aOrig);
1416 aQX=aOrig.Translated(aDx*aVLin);
1420 typeres=IntAna_Line;
1431 gp_Vec aVX(aQApex1, aQX);
1438 aDa=aQA1.Distance(aQX);
1439 aDx=sqrt(aR1*aR1-aDa*aDa);
1440 aQX1=aQX.Translated(aDx*aVLin);
1441 aQX2=aQX.Translated(-aDx*aVLin);
1445 gp_Vec aVX1(aQApex1, aQX1);
1447 gp_Vec aVX2(aQApex1, aQX2);
1450 } //else if (aDA1A2<aTol2) {
1451 //Case when cones have common generatrix
1452 else if(A1A2.Intersect()) {
1453 //Check if apex of one cone belongs another one
1454 Standard_Real u, v, tol2 = Tol*Tol;
1455 ElSLib::Parameters(Con2, aPApex1, u, v);
1456 gp_Pnt p = ElSLib::Value(u, v, Con2);
1457 if(aPApex1.SquareDistance(p) > tol2) {
1458 typeres=IntAna_NoGeometricSolution;
1462 ElSLib::Parameters(Con1, aPApex2, u, v);
1463 p = ElSLib::Value(u, v, Con1);
1464 if(aPApex2.SquareDistance(p) > tol2) {
1465 typeres=IntAna_NoGeometricSolution;
1469 //Cones have a common generatrix passing through apexes
1470 myCommonGen = Standard_True;
1472 //common generatrix of cones
1473 gp_Lin aGen(aPApex1, gp_Dir(gp_Vec(aPApex1, aPApex2)));
1475 //Intersection point of axes
1476 gp_Pnt aPAxeInt = A1A2.PtIntersect();
1478 //Characteristic point of intersection curve
1479 u = ElCLib::Parameter(aGen, aPAxeInt);
1480 myPChar = ElCLib::Value(u, aGen);
1483 //Other generatrixes of cones laying in maximal plane
1484 gp_Lin aGen1 = aGen.Rotated(Con1.Axis(), M_PI);
1485 gp_Lin aGen2 = aGen.Rotated(Con2.Axis(), M_PI);
1487 //Intersection point of generatrixes
1488 gp_Dir aN; //solution plane normal
1489 gp_Dir aD1 = aGen1.Direction();
1491 gp_Dir aD2(aD1.Crossed(aGen.Direction()));
1493 if(aD1.IsParallel(aGen2.Direction(), Precision::Angular())) {
1494 aN = aD1.Crossed(aD2);
1496 else if(aGen1.SquareDistance(aGen2) > tol2) {
1497 //Something wrong ???
1498 typeres=IntAna_NoGeometricSolution;
1502 gp_Dir D1 = aGen1.Position().Direction();
1503 gp_Dir D2 = aGen2.Position().Direction();
1504 gp_Pnt O1 = aGen1.Location();
1505 gp_Pnt O2 = aGen2.Location();
1506 Standard_Real D1DotD2 = D1.Dot(D2);
1507 Standard_Real aSin = 1.-D1DotD2*D1DotD2;
1508 gp_Vec O1O2 (O1,O2);
1509 Standard_Real U2 = (D1.XYZ()*(O1O2.Dot(D1))-(O1O2.XYZ())).Dot(D2.XYZ());
1511 gp_Pnt aPGint(ElCLib::Value(U2, aGen2));
1513 aD1 = gp_Dir(gp_Vec(aPGint, myPChar));
1514 aN = aD1.Crossed(aD2);
1516 //Plane that must contain intersection curves
1517 gp_Pln anIntPln(myPChar, aN);
1519 IntAna_QuadQuadGeo INTER_QUAD_PLN(anIntPln,Con1,Tol,Tol);
1521 if(INTER_QUAD_PLN.IsDone()) {
1522 switch(INTER_QUAD_PLN.TypeInter()) {
1523 case IntAna_Ellipse: {
1524 typeres=IntAna_Ellipse;
1525 gp_Elips E=INTER_QUAD_PLN.Ellipse(1);
1527 dir1 = E.Position().Direction();
1528 dir2 = E.Position().XDirection();
1529 param1 = E.MajorRadius();
1530 param1bis = E.MinorRadius();
1534 case IntAna_Circle: {
1535 typeres=IntAna_Circle;
1536 gp_Circ C=INTER_QUAD_PLN.Circle(1);
1538 dir1 = C.Position().XDirection();
1539 dir2 = C.Position().YDirection();
1540 param1 = C.Radius();
1544 case IntAna_Parabola: {
1545 typeres=IntAna_Parabola;
1546 gp_Parab Prb=INTER_QUAD_PLN.Parabola(1);
1547 pt1 = Prb.Location();
1548 dir1 = Prb.Position().Direction();
1549 dir2 = Prb.Position().XDirection();
1550 param1 = Prb.Focal();
1554 case IntAna_Hyperbola: {
1555 typeres=IntAna_Hyperbola;
1556 gp_Hypr H=INTER_QUAD_PLN.Hyperbola(1);
1557 pt1 = pt2 = H.Location();
1558 dir1 = H.Position().Direction();
1559 dir2 = H.Position().XDirection();
1560 param1 = param2 = H.MajorRadius();
1561 param1bis = param2bis = H.MinorRadius();
1566 typeres=IntAna_NoGeometricSolution;
1572 typeres=IntAna_NoGeometricSolution;
1575 //=======================================================================
1576 //function : IntAna_QuadQuadGeo
1577 //purpose : Sphere - Cone
1578 //=======================================================================
1579 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Sphere& Sph,
1581 const Standard_Real Tol)
1582 : done(Standard_False),
1584 typeres(IntAna_Empty),
1591 myCommonGen(Standard_False),
1595 Perform(Sph,Con,Tol);
1597 //=======================================================================
1598 //function : Perform
1600 //=======================================================================
1601 void IntAna_QuadQuadGeo::Perform(const gp_Sphere& Sph,
1603 const Standard_Real)
1606 AxeOperator A1A2(Con.Axis(),Sph.Position().Axis());
1607 gp_Pnt Pt=Sph.Location();
1608 if((A1A2.Intersect() && (Pt.Distance(A1A2.PtIntersect())==0.0))
1610 gp_Pnt ConApex= Con.Apex();
1611 Standard_Real dApexSphCenter=Pt.Distance(ConApex);
1613 if(dApexSphCenter>RealEpsilon()) {
1614 ConDir = gp_Dir(gp_Vec(ConApex,Pt));
1617 ConDir = Con.Position().Direction();
1620 Standard_Real Rad=Sph.Radius();
1621 Standard_Real tga=Tan(Con.SemiAngle());
1625 //-- x: Roots of (x**2 + y**2 = Rad**2)
1626 //-- tga = y / (x+dApexSphCenter)
1627 Standard_Real tgatga = tga * tga;
1628 math_DirectPolynomialRoots Eq( 1.0+tgatga
1629 ,2.0*tgatga*dApexSphCenter
1630 ,-Rad*Rad + dApexSphCenter*dApexSphCenter*tgatga);
1632 Standard_Integer nbsol=Eq.NbSolutions();
1634 typeres=IntAna_Empty;
1637 typeres=IntAna_Circle;
1639 Standard_Real x = Eq.Value(1);
1640 Standard_Real dApexSphCenterpx = dApexSphCenter+x;
1642 pt1.SetCoord( ConApex.X() + (dApexSphCenterpx) * ConDir.X()
1643 ,ConApex.Y() + (dApexSphCenterpx) * ConDir.Y()
1644 ,ConApex.Z() + (dApexSphCenterpx) * ConDir.Z());
1645 param1 = tga * dApexSphCenterpx;
1646 param1 = Abs(param1);
1648 if(param1<=myEPSILON_MINI_CIRCLE_RADIUS) {
1649 typeres=IntAna_PointAndCircle;
1654 Standard_Real x=Eq.Value(2);
1655 Standard_Real dApexSphCenterpx = dApexSphCenter+x;
1657 pt2.SetCoord( ConApex.X() + (dApexSphCenterpx) * ConDir.X()
1658 ,ConApex.Y() + (dApexSphCenterpx) * ConDir.Y()
1659 ,ConApex.Z() + (dApexSphCenterpx) * ConDir.Z());
1660 param2 = tga * dApexSphCenterpx;
1661 param2 = Abs(param2);
1663 if(param2<=myEPSILON_MINI_CIRCLE_RADIUS) {
1664 typeres=IntAna_PointAndCircle;
1671 done=Standard_False;
1675 typeres=IntAna_NoGeometricSolution;
1679 //=======================================================================
1680 //function : IntAna_QuadQuadGeo
1681 //purpose : Sphere - Sphere
1682 //=======================================================================
1683 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo( const gp_Sphere& Sph1
1684 ,const gp_Sphere& Sph2
1685 ,const Standard_Real Tol)
1686 : done(Standard_False),
1688 typeres(IntAna_Empty),
1695 myCommonGen(Standard_False),
1699 Perform(Sph1,Sph2,Tol);
1701 //=======================================================================
1702 //function : Perform
1704 //=======================================================================
1705 void IntAna_QuadQuadGeo::Perform(const gp_Sphere& Sph1,
1706 const gp_Sphere& Sph2,
1707 const Standard_Real Tol)
1710 gp_Pnt O1=Sph1.Location();
1711 gp_Pnt O2=Sph2.Location();
1712 Standard_Real dO1O2=O1.Distance(O2);
1713 Standard_Real R1=Sph1.Radius();
1714 Standard_Real R2=Sph2.Radius();
1715 Standard_Real Rmin,Rmax;
1716 typeres=IntAna_Empty;
1717 param2bis=0.0; //-- pour eviter param2bis not used ....
1719 if(R1>R2) { Rmin=R2; Rmax=R1; } else { Rmin=R1; Rmax=R2; }
1721 if(dO1O2<=Tol && (Abs(R1-R2) <= Tol)) {
1722 typeres = IntAna_Same;
1725 if(dO1O2<=Tol) { return; }
1726 gp_Dir Dir=gp_Dir(gp_Vec(O1,O2));
1727 Standard_Real t = Rmax - dO1O2 - Rmin;
1729 //----------------------------------------------------------------------
1730 //-- |----------------- R1 --------------------|
1731 //-- |----dO1O2-----|-----------R2----------|
1734 //-- |------ R1 ------|---------dO1O2----------|
1735 //-- |-------------------R2-----------------------|
1737 //----------------------------------------------------------------------
1738 if(t >= 0.0 && t <=Tol) {
1739 typeres = IntAna_Point;
1742 if(R1==Rmax) t2=(R1 + (R2 + dO1O2)) * 0.5;
1743 else t2=(-R1+(dO1O2-R2))*0.5;
1745 pt1.SetCoord( O1.X() + t2*Dir.X()
1746 ,O1.Y() + t2*Dir.Y()
1747 ,O1.Z() + t2*Dir.Z());
1750 //-----------------------------------------------------------------
1751 //-- |----------------- dO1O2 --------------------|
1752 //-- |----R1-----|-----------R2----------|-Tol-|
1754 //-- |----------------- Rmax --------------------|
1755 //-- |----Rmin----|-------dO1O2-------|-Tol-|
1757 //-----------------------------------------------------------------
1758 if((dO1O2 > (R1+R2+Tol)) || (Rmax > (dO1O2+Rmin+Tol))) {
1759 typeres=IntAna_Empty;
1762 //---------------------------------------------------------------
1765 //---------------------------------------------------------------
1766 Standard_Real Alpha=0.5*(R1*R1-R2*R2+dO1O2*dO1O2)/(dO1O2);
1767 Standard_Real Beta = R1*R1-Alpha*Alpha;
1768 Beta = (Beta>0.0)? Sqrt(Beta) : 0.0;
1770 if(Beta<= myEPSILON_MINI_CIRCLE_RADIUS) {
1771 typeres = IntAna_Point;
1772 Alpha = (R1 + (dO1O2 - R2)) * 0.5;
1775 typeres = IntAna_Circle;
1779 pt1.SetCoord( O1.X() + Alpha*Dir.X()
1780 ,O1.Y() + Alpha*Dir.Y()
1781 ,O1.Z() + Alpha*Dir.Z());
1788 //=======================================================================
1790 //purpose : Returns a Point
1791 //=======================================================================
1792 gp_Pnt IntAna_QuadQuadGeo::Point(const Standard_Integer n) const
1794 if(!done) { StdFail_NotDone::Raise(); }
1795 if(n>nbint || n<1) { Standard_DomainError::Raise(); }
1796 if(typeres==IntAna_PointAndCircle) {
1797 if(n!=1) { Standard_DomainError::Raise(); }
1798 if(param1==0.0) return(pt1);
1801 else if(typeres==IntAna_Point) {
1802 if(n==1) return(pt1);
1806 // WNT (what can you expect from MicroSoft ?)
1807 return gp_Pnt(0,0,0);
1809 //=======================================================================
1811 //purpose : Returns a Line
1812 //=======================================================================
1813 gp_Lin IntAna_QuadQuadGeo::Line(const Standard_Integer n) const
1815 if(!done) { StdFail_NotDone::Raise(); }
1816 if((n>nbint) || (n<1) || (typeres!=IntAna_Line)) {
1817 Standard_DomainError::Raise();
1819 if(n==1) { return(gp_Lin(pt1,dir1)); }
1820 else { return(gp_Lin(pt2,dir2)); }
1822 //=======================================================================
1824 //purpose : Returns a Circle
1825 //=======================================================================
1826 gp_Circ IntAna_QuadQuadGeo::Circle(const Standard_Integer n) const
1828 if(!done) { StdFail_NotDone::Raise(); }
1829 if(typeres==IntAna_PointAndCircle) {
1830 if(n!=1) { Standard_DomainError::Raise(); }
1831 if(param2==0.0) return(gp_Circ(DirToAx2(pt1,dir1),param1));
1832 return(gp_Circ(DirToAx2(pt2,dir2),param2));
1834 else if((n>nbint) || (n<1) || (typeres!=IntAna_Circle)) {
1835 Standard_DomainError::Raise();
1837 if(n==1) { return(gp_Circ(DirToAx2(pt1,dir1),param1)); }
1838 else { return(gp_Circ(DirToAx2(pt2,dir2),param2)); }
1841 //=======================================================================
1842 //function : Ellipse
1843 //purpose : Returns a Elips
1844 //=======================================================================
1845 gp_Elips IntAna_QuadQuadGeo::Ellipse(const Standard_Integer n) const
1847 if(!done) { StdFail_NotDone::Raise(); }
1848 if((n>nbint) || (n<1) || (typeres!=IntAna_Ellipse)) {
1849 Standard_DomainError::Raise();
1853 Standard_Real R1=param1, R2=param1bis, aTmp;
1855 aTmp=R1; R1=R2; R2=aTmp;
1857 gp_Ax2 anAx2(pt1, dir1 ,dir2);
1858 gp_Elips anElips (anAx2, R1, R2);
1862 Standard_Real R1=param2, R2=param2bis, aTmp;
1864 aTmp=R1; R1=R2; R2=aTmp;
1866 gp_Ax2 anAx2(pt2, dir2 ,dir1);
1867 gp_Elips anElips (anAx2, R1, R2);
1871 //=======================================================================
1872 //function : Parabola
1873 //purpose : Returns a Parabola
1874 //=======================================================================
1875 gp_Parab IntAna_QuadQuadGeo::Parabola(const Standard_Integer n) const
1878 StdFail_NotDone::Raise();
1880 if (typeres!=IntAna_Parabola) {
1881 Standard_DomainError::Raise();
1883 if((n>nbint) || (n!=1)) {
1884 Standard_OutOfRange::Raise();
1886 return(gp_Parab(gp_Ax2( pt1
1891 //=======================================================================
1892 //function : Hyperbola
1893 //purpose : Returns a Hyperbola
1894 //=======================================================================
1895 gp_Hypr IntAna_QuadQuadGeo::Hyperbola(const Standard_Integer n) const
1898 StdFail_NotDone::Raise();
1900 if((n>nbint) || (n<1) || (typeres!=IntAna_Hyperbola)) {
1901 Standard_DomainError::Raise();
1904 return(gp_Hypr(gp_Ax2( pt1
1907 ,param1,param1bis));
1910 return(gp_Hypr(gp_Ax2( pt2
1913 ,param2,param2bis));
1916 //=======================================================================
1917 //function : HasCommonGen
1919 //=======================================================================
1920 Standard_Boolean IntAna_QuadQuadGeo::HasCommonGen() const
1924 //=======================================================================
1927 //=======================================================================
1928 const gp_Pnt& IntAna_QuadQuadGeo::PChar() const