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
30 #include <gp_Circ.hxx>
31 #include <gp_Cone.hxx>
32 #include <gp_Cylinder.hxx>
34 #include <gp_Dir2d.hxx>
35 #include <gp_Elips.hxx>
36 #include <gp_Hypr.hxx>
38 #include <gp_Parab.hxx>
41 #include <gp_Pnt2d.hxx>
42 #include <gp_Sphere.hxx>
43 #include <gp_Torus.hxx>
45 #include <gp_Vec2d.hxx>
47 #include <IntAna_IntConicQuad.hxx>
48 #include <IntAna_QuadQuadGeo.hxx>
49 #include <math_DirectPolynomialRoots.hxx>
50 #include <Standard_DomainError.hxx>
51 #include <Standard_OutOfRange.hxx>
52 #include <StdFail_NotDone.hxx>
53 #include <gce_MakePln.hxx>
54 #include <ProjLib.hxx>
55 #include <IntAna2d_AnaIntersection.hxx>
56 #include <IntAna2d_IntPoint.hxx>
59 #include <Geom2d_Line.hxx>
63 gp_Ax2 DirToAx2(const gp_Pnt& P,const gp_Dir& D);
65 void RefineDir(gp_Dir& aDir);
67 Standard_Real EstimDist(const gp_Cone& theCon1, const gp_Cone& theCon2);
69 //=======================================================================
71 //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
72 //=======================================================================
75 AxeOperator(const gp_Ax1& A1,const gp_Ax1& A2,
76 const Standard_Real theEpsDistance = 1.e-14,
77 const Standard_Real theEpsAxesPara = Precision::Angular());
79 void Distance(Standard_Real& dist,
80 Standard_Real& Param1,
81 Standard_Real& Param2);
83 gp_Pnt PtIntersect() {
86 Standard_Boolean Coplanar(void) {
89 Standard_Boolean Same(void) {
90 return theparallel && (thedistance<myEPSILON_DISTANCE);
92 Standard_Real Distance(void) {
95 Standard_Boolean Intersect(void) {
96 return (thecoplanar && (!theparallel));
98 Standard_Boolean Parallel(void) {
101 Standard_Boolean Normal(void) {
106 Standard_Real Det33(const Standard_Real a11,
107 const Standard_Real a12,
108 const Standard_Real a13,
109 const Standard_Real a21,
110 const Standard_Real a22,
111 const Standard_Real a23,
112 const Standard_Real a31,
113 const Standard_Real a32,
114 const Standard_Real a33) {
115 Standard_Real theReturn =
116 a11*(a22*a33-a32*a23) - a21*(a12*a33-a32*a13) + a31*(a12*a23-a22*a13) ;
124 Standard_Real thedistance;
125 Standard_Boolean theparallel;
126 Standard_Boolean thecoplanar;
127 Standard_Boolean thenormal;
129 Standard_Real myEPSILON_DISTANCE;
130 Standard_Real myEPSILON_AXES_PARA;
133 //=======================================================================
134 //function : AxeOperator::AxeOperator
136 //=======================================================================
137 AxeOperator::AxeOperator(const gp_Ax1& A1,const gp_Ax1& A2,
138 const Standard_Real theEpsDistance,
139 const Standard_Real theEpsAxesPara)
143 myEPSILON_DISTANCE (theEpsDistance),
144 myEPSILON_AXES_PARA (theEpsAxesPara)
146 //---------------------------------------------------------------------
147 gp_Dir V1=Axe1.Direction();
148 gp_Dir V2=Axe2.Direction();
149 gp_Pnt P1=Axe1.Location();
150 gp_Pnt P2=Axe2.Location();
154 thecoplanar= Standard_False;
155 thenormal = Standard_False;
157 //--- check if the two axis are parallel
158 theparallel=V1.IsParallel(V2, myEPSILON_AXES_PARA);
159 //--- Distance between the two axis
160 gp_XYZ perp(A1.Direction().XYZ().Crossed(A2.Direction().XYZ()));
163 thedistance = L1.Distance(A2.Location());
166 thedistance = Abs(gp_Vec(perp.Normalized()).Dot(gp_Vec(Axe1.Location(),
169 //--- check if Axis are Coplanar
171 if(thedistance<myEPSILON_DISTANCE) {
172 D33=Det33(V1.X(),V1.Y(),V1.Z()
173 ,V2.X(),V2.Y(),V2.Z()
174 ,P1.X()-P2.X(),P1.Y()-P2.Y(),P1.Z()-P2.Z());
175 if(Abs(D33)<=myEPSILON_DISTANCE) {
176 thecoplanar=Standard_True;
180 thenormal = Abs (V1.Dot(V2)) < myEPSILON_AXES_PARA;
182 //--- check if the two axis are concurrent
183 if (thecoplanar && !theparallel) {
184 Standard_Real smx=P2.X() - P1.X();
185 Standard_Real smy=P2.Y() - P1.Y();
186 Standard_Real smz=P2.Z() - P1.Z();
187 Standard_Real Det1,Det2,Det3,A;
188 Det1=V1.Y() * V2.X() - V1.X() * V2.Y();
189 Det2=V1.Z() * V2.Y() - V1.Y() * V2.Z();
190 Det3=V1.Z() * V2.X() - V1.X() * V2.Z();
192 if((Det1!=0.0) && ((Abs(Det1) >= Abs(Det2))&&(Abs(Det1) >= Abs(Det3)))) {
193 A=(smy * V2.X() - smx * V2.Y())/Det1;
196 && ((Abs(Det2) >= Abs(Det1))
197 &&(Abs(Det2) >= Abs(Det3)))) {
198 A=(smz * V2.Y() - smy * V2.Z())/Det2;
201 A=(smz * V2.X() - smx * V2.Z())/Det3;
203 ptintersect.SetCoord( P1.X() + A * V1.X()
205 ,P1.Z() + A * V1.Z());
208 ptintersect.SetCoord(0,0,0); //-- Pour eviter des FPE
211 //=======================================================================
212 //function : Distance
214 //=======================================================================
215 void AxeOperator::Distance(Standard_Real& dist,
216 Standard_Real& Param1,
217 Standard_Real& Param2)
219 gp_Vec O1O2(Axe1.Location(),Axe2.Location());
220 gp_Dir U1 = Axe1.Direction(); //-- juste pour voir.
221 gp_Dir U2 = Axe2.Direction();
223 gp_Dir N = U1.Crossed(U2);
224 Standard_Real D = Det33(U1.X(),U2.X(),N.X(),
226 U1.Z(),U2.Z(),N.Z());
228 dist = Det33(U1.X(),U2.X(),O1O2.X(),
229 U1.Y(),U2.Y(),O1O2.Y(),
230 U1.Z(),U2.Z(),O1O2.Z()) / D;
231 Param1 = Det33(O1O2.X(),U2.X(),N.X(),
232 O1O2.Y(),U2.Y(),N.Y(),
233 O1O2.Z(),U2.Z(),N.Z()) / (-D);
234 //------------------------------------------------------------
235 //-- On resout P1 * Dir1 + P2 * Dir2 + d * N = O1O2
236 //-- soit : Segment perpendiculaire : O1+P1 D1
238 Param2 = Det33(U1.X(),O1O2.X(),N.X(),
239 U1.Y(),O1O2.Y(),N.Y(),
240 U1.Z(),O1O2.Z(),N.Z()) / (D);
243 //=======================================================================
244 //function : DirToAx2
245 //purpose : returns a gp_Ax2 where D is the main direction
246 //=======================================================================
247 gp_Ax2 DirToAx2(const gp_Pnt& P,const gp_Dir& D)
249 Standard_Real x=D.X(); Standard_Real ax=Abs(x);
250 Standard_Real y=D.Y(); Standard_Real ay=Abs(y);
251 Standard_Real z=D.Z(); Standard_Real az=Abs(z);
252 if( (ax==0.0) || ((ax<ay) && (ax<az)) ) {
253 return(gp_Ax2(P,D,gp_Dir(gp_Vec(0.0,-z,y))));
255 else if( (ay==0.0) || ((ay<ax) && (ay<az)) ) {
256 return(gp_Ax2(P,D,gp_Dir(gp_Vec(-z,0.0,x))));
259 return(gp_Ax2(P,D,gp_Dir(gp_Vec(-y,x,0.0))));
263 //=======================================================================
264 //function : EstimDist
265 //purpose : returns a minimal distance from apex to any solution
266 //=======================================================================
267 Standard_Real EstimDist(const gp_Cone& theCon1, const gp_Cone& theCon2)
269 //It is supposed that axes of cones are coplanar and
270 //distance between them > Precision::Confusion()
271 gp_Pnt aPA1 = theCon1.Apex(), aPA2 = theCon2.Apex();
273 gp_Pnt aP3 = aPA1.Translated(theCon1.Position().Direction());
275 gce_MakePln aMkPln(aPA1, aPA2, aP3);
277 return Precision::Infinite();
279 const gp_Pln& aPln = aMkPln.Value();
281 gp_Lin anAx1(aPA1, theCon1.Position().Direction());
282 gp_Lin2d anAx12d = ProjLib::Project(aPln, anAx1);
284 Standard_Real anAng1 = theCon1.SemiAngle();
285 Lines1[0] = anAx12d.Rotated(anAx12d.Location(), anAng1);
286 Lines1[1] = anAx12d.Rotated(anAx12d.Location(), -anAng1);
288 gp_Lin anAx2(aPA2, theCon2.Position().Direction());
289 gp_Lin2d anAx22d = ProjLib::Project(aPln, anAx2);
291 Standard_Real anAng2 = theCon2.SemiAngle();
292 Lines2[0] = anAx22d.Rotated(anAx22d.Location(), anAng2);
293 Lines2[1] = anAx22d.Rotated(anAx22d.Location(), -anAng2);
296 Handle(Geom2d_Line) L10 = new Geom2d_Line(Lines1[0]);
297 Handle(Geom2d_Line) L11 = new Geom2d_Line(Lines1[1]);
298 Handle(Geom2d_Line) L20 = new Geom2d_Line(Lines2[0]);
299 Handle(Geom2d_Line) L21 = new Geom2d_Line(Lines2[1]);
302 Standard_Real aMinDist[2] = { Precision::Infinite(), Precision::Infinite() };
303 Standard_Integer i, j, k;
304 IntAna2d_AnaIntersection anInter;
305 for (i = 0; i < 2; ++i)
307 for (j = 0; j < 2; ++j)
309 anInter.Perform(Lines1[i], Lines2[j]);
310 if (anInter.IsDone())
312 Standard_Integer aNbPoints = anInter.NbPoints();
313 for (k = 1; k <= aNbPoints; ++k)
315 const IntAna2d_IntPoint& anIntP = anInter.Point(k);
316 Standard_Real aPar1 = Abs(anIntP.ParamOnFirst());
317 aMinDist[0] = Min(aPar1, aMinDist[0]);
318 Standard_Real aPar2 = Abs(anIntP.ParamOnSecond());
319 aMinDist[1] = Min(aPar2, aMinDist[1]);
325 Standard_Real aDist = Max(aMinDist[0], aMinDist[1]);
328 //=======================================================================
329 //function : IntAna_QuadQuadGeo
330 //purpose : Empty constructor
331 //=======================================================================
332 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(void)
333 : done(Standard_False),
335 typeres(IntAna_Empty),
346 myCommonGen(Standard_False),
351 //=======================================================================
352 //function : InitTolerances
354 //=======================================================================
355 void IntAna_QuadQuadGeo::InitTolerances()
357 myEPSILON_DISTANCE = 1.0e-14;
358 myEPSILON_ANGLE_CONE = Precision::Angular();
359 myEPSILON_MINI_CIRCLE_RADIUS = 0.01*Precision::Confusion();
360 myEPSILON_CYLINDER_DELTA_RADIUS = 1.0e-13;
361 myEPSILON_CYLINDER_DELTA_DISTANCE= Precision::Confusion();
362 myEPSILON_AXES_PARA = Precision::Angular();
364 //=======================================================================
365 //function : IntAna_QuadQuadGeo
367 //=======================================================================
368 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Pln& P1,
370 const Standard_Real TolAng,
371 const Standard_Real Tol)
372 : done(Standard_False),
374 typeres(IntAna_Empty),
385 myCommonGen(Standard_False),
389 Perform(P1,P2,TolAng,Tol);
391 //=======================================================================
394 //=======================================================================
395 void IntAna_QuadQuadGeo::Perform (const gp_Pln& P1,
397 const Standard_Real TolAng,
398 const Standard_Real Tol)
400 Standard_Real A1, B1, C1, D1, A2, B2, C2, D2, dist1, dist2, aMVD;
405 P1.Coefficients(A1,B1,C1,D1);
406 P2.Coefficients(A2,B2,C2,D2);
408 gp_Vec aVN1(A1,B1,C1);
409 gp_Vec aVN2(A2,B2,C2);
410 gp_Vec vd(aVN1.Crossed(aVN2));
412 const gp_Pnt& aLocP1=P1.Location();
413 const gp_Pnt& aLocP2=P2.Location();
415 dist1=A2*aLocP1.X() + B2*aLocP1.Y() + C2*aLocP1.Z() + D2;
416 dist2=A1*aLocP2.X() + B1*aLocP2.Y() + C1*aLocP2.Z() + D1;
420 // normalles are collinear - planes are same or parallel
421 typeres = (Abs(dist1) <= Tol && Abs(dist2) <= Tol) ? IntAna_Same
425 Standard_Real denom, denom2, ddenom, par1, par2;
426 Standard_Real X1, Y1, Z1, X2, Y2, Z2, aEps;
429 denom=A1*A2 + B1*B2 + C1*C2;
430 denom2 = denom*denom;
431 ddenom = 1. - denom2;
433 denom = ( Abs(ddenom) <= aEps ) ? aEps : ddenom;
438 gp_Vec inter1(aVN1.Crossed(vd));
439 gp_Vec inter2(aVN2.Crossed(vd));
441 X1=aLocP1.X() + par1*inter1.X();
442 Y1=aLocP1.Y() + par1*inter1.Y();
443 Z1=aLocP1.Z() + par1*inter1.Z();
444 X2=aLocP2.X() + par2*inter2.X();
445 Y2=aLocP2.Y() + par2*inter2.Y();
446 Z2=aLocP2.Z() + par2*inter2.Z();
448 pt1=gp_Pnt((X1+X2)*0.5, (Y1+Y2)*0.5, (Z1+Z2)*0.5);
450 typeres = IntAna_Line;
453 //-------------------------------------------------------
454 // When the value of the angle between the planes is small
455 // the origin of intersection line is computed with error
456 // [ ~0.0001 ] that can not br considered as small one
458 // for {A~=2.e-6, dist1=4.2e-5, dist2==1.e-4} =>
459 // {denom=3.4e-12, par1=12550297.6, par2=32605552.9, etc}
461 // the origin should be refined if it is possible
463 Standard_Real aTreshAng, aTreshDist;
465 aTreshAng=2.e-6; // 1.e-4 deg
468 if (aMVD < aTreshAng) {
469 Standard_Real aDist1, aDist2;
471 aDist1=A1*pt1.X() + B1*pt1.Y() + C1*pt1.Z() + D1;
472 aDist2=A2*pt1.X() + B2*pt1.Y() + C2*pt1.Z() + D2;
474 if (fabs(aDist1)>aTreshDist || fabs(aDist2)>aTreshDist) {
475 Standard_Boolean bIsDone, bIsParallel;
476 IntAna_IntConicQuad aICQ;
480 gp_Lin aL1(pt1, aDN1);
482 aICQ.Perform(aL1, P1, TolAng, Tol);
483 bIsDone=aICQ.IsDone();
488 const gp_Pnt& aPnt1=aICQ.Point(1);
489 //----------------------------------
491 gp_Dir aDL2(dir1.Crossed(aDN1));
492 gp_Lin aL2(aPnt1, aDL2);
494 aICQ.Perform(aL2, P2, TolAng, Tol);
495 bIsDone=aICQ.IsDone();
500 bIsParallel=aICQ.IsParallel();
505 const gp_Pnt& aPnt2=aICQ.Point(1);
513 //=======================================================================
514 //function : IntAna_QuadQuadGeo
515 //purpose : Pln Cylinder
516 //=======================================================================
517 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo( const gp_Pln& P
518 ,const gp_Cylinder& Cl
519 ,const Standard_Real Tolang
520 ,const Standard_Real Tol
521 ,const Standard_Real H)
522 : done(Standard_False),
524 typeres(IntAna_Empty),
535 myCommonGen(Standard_False),
539 Perform(P,Cl,Tolang,Tol,H);
541 //=======================================================================
544 //=======================================================================
545 void IntAna_QuadQuadGeo::Perform( const gp_Pln& P
546 ,const gp_Cylinder& Cl
547 ,const Standard_Real Tolang
548 ,const Standard_Real Tol
549 ,const Standard_Real H)
551 done = Standard_False;
552 Standard_Real dist,radius;
553 Standard_Real A,B,C,D;
555 Standard_Real sint,cost,h;
556 gp_XYZ axex,axey,omega;
560 radius = Cl.Radius();
562 gp_Lin axec(Cl.Axis());
563 gp_XYZ normp(P.Axis().Direction().XYZ());
565 P.Coefficients(A,B,C,D);
566 axec.Location().Coord(X,Y,Z);
567 // la distance axe/plan est evaluee a l origine de l axe.
568 dist = A*X + B*Y + C*Z + D;
570 Standard_Real tolang = Tolang;
571 Standard_Boolean newparams = Standard_False;
573 gp_Vec ldv( axec.Direction() );
575 Standard_Real dA = Abs( ldv.Angle( npv ) );
578 Standard_Real dang = Abs( ldv.Angle( npv ) ) - M_PI/2.;
579 Standard_Real dangle = Abs( dang );
580 if( dangle > Tolang )
582 Standard_Real sinda = Abs( Sin( dangle ) );
583 Standard_Real dif = Abs( sinda - Tol );
587 newparams = Standard_True;
593 IntAna_IntConicQuad inter(axec,P,tolang,Tol,H);
595 if (inter.IsParallel()) {
596 // Le resultat de l intersection Plan-Cylindre est de type droite.
597 // il y a 1 ou 2 droites
599 typeres = IntAna_Line;
600 omega.SetCoord(X-dist*A,Y-dist*B,Z-dist*C);
602 if (Abs(Abs(dist)-radius) < Tol)
609 gp_XYZ omegaXYZ(X,Y,Z);
610 gp_XYZ omegaXYZtrnsl( omegaXYZ + 100.*axec.Direction().XYZ() );
611 Standard_Real Xt,Yt,Zt,distt;
612 omegaXYZtrnsl.Coord(Xt,Yt,Zt);
613 distt = A*Xt + B*Yt + C*Zt + D;
614 gp_XYZ omega1(omegaXYZtrnsl.X()-distt*A,
615 omegaXYZtrnsl.Y()-distt*B,
616 omegaXYZtrnsl.Z()-distt*C );
618 ppt1.SetXYZ( omega1 );
619 gp_Vec vv1(pt1,ppt1);
624 dir1 = axec.Direction();
626 else if (Abs(dist) < radius)
629 h = Sqrt(radius*radius - dist*dist);
630 axey = axec.Direction().XYZ().Crossed(normp); // axey est normalise
632 pt1.SetXYZ(omega - h*axey);
633 pt2.SetXYZ(omega + h*axey);
637 gp_XYZ omegaXYZ(X,Y,Z);
638 gp_XYZ omegaXYZtrnsl( omegaXYZ + 100.*axec.Direction().XYZ() );
639 Standard_Real Xt,Yt,Zt,distt,ht;
640 omegaXYZtrnsl.Coord(Xt,Yt,Zt);
641 distt = A*Xt + B*Yt + C*Zt + D;
642 // ht = Sqrt(radius*radius - distt*distt);
643 Standard_Real anSqrtArg = radius*radius - distt*distt;
644 ht = (anSqrtArg > 0.) ? Sqrt(anSqrtArg) : 0.;
646 gp_XYZ omega1( omegaXYZtrnsl.X()-distt*A,
647 omegaXYZtrnsl.Y()-distt*B,
648 omegaXYZtrnsl.Z()-distt*C );
650 ppt1.SetXYZ( omega1 - ht*axey);
651 ppt2.SetXYZ( omega1 + ht*axey);
652 gp_Vec vv1(pt1,ppt1);
653 gp_Vec vv2(pt2,ppt2);
661 dir1 = axec.Direction();
662 dir2 = axec.Direction();
667 // debug JAG : le nbint = 0 doit etre remplace par typeres = IntAna_Empty
668 // et ne pas etre seulement supprime...
671 typeres = IntAna_Empty;
674 else { // Il y a un point d intersection. C est le centre du cercle
675 // ou de l ellipse solution.
678 axey = normp.Crossed(axec.Direction().XYZ());
679 sint = axey.Modulus();
681 pt1 = inter.Point(1);
683 if (sint < Tol/radius) {
685 // on construit un cercle avec comme axes X et Y ceux du cylindre
686 typeres = IntAna_Circle;
688 dir1 = axec.Direction(); // axe Z
689 dir2 = Cl.Position().XDirection();
694 // on construit un ellipse
695 typeres = IntAna_Ellipse;
696 cost = Abs(axec.Direction().XYZ().Dot(normp));
697 axex = axey.Crossed(normp);
699 dir1.SetXYZ(normp); //Modif ds ce bloc
702 param1 = radius/cost;
707 done = Standard_True;
709 //=======================================================================
710 //function : IntAna_QuadQuadGeo
712 //=======================================================================
713 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Pln& P,
715 const Standard_Real Tolang,
716 const Standard_Real Tol)
717 : done(Standard_False),
719 typeres(IntAna_Empty),
730 myCommonGen(Standard_False),
734 Perform(P,Co,Tolang,Tol);
736 //=======================================================================
739 //=======================================================================
740 void IntAna_QuadQuadGeo::Perform(const gp_Pln& P,
742 const Standard_Real Tolang,
743 const Standard_Real Tol)
746 done = Standard_False;
749 Standard_Real A,B,C,D;
751 Standard_Real dist,sint,cost,sina,cosa,angl,costa;
755 gp_Lin axec(Co.Axis());
756 P.Coefficients(A,B,C,D);
757 gp_Pnt apex(Co.Apex());
760 dist = A*X + B*Y + C*Z + D; // distance signee sommet du cone/ Plan
762 gp_XYZ normp = P.Axis().Direction().XYZ();
763 if(P.Direct()==Standard_False) { //-- lbr le 14 jan 97
767 axey = normp.Crossed(Co.Axis().Direction().XYZ());
768 axex = axey.Crossed(normp);
771 angl = Co.SemiAngle();
774 sina = Abs(Sin(angl));
777 // Angle entre la normale au plan et l axe du cone, ramene entre 0. et PI/2.
779 sint = axey.Modulus();
780 cost = Abs(Co.Axis().Direction().XYZ().Dot(normp));
782 // Le calcul de costa permet de determiner si le plan contient
783 // un generatrice du cone : on calcul Sin((PI/2. - t) - angl)
785 costa = cost*cosa - sint*sina; // sin((PI/2 -t)-angl)=cos(t+angl)
786 // avec t ramene entre 0 et pi/2.
788 if (Abs(dist) < Tol) {
789 // on considere que le plan contient le sommet du cone.
790 // les solutions possibles sont donc : 1 point, 1 droite, 2 droites
791 // selon l inclinaison du plan.
793 if (Abs(costa) < Tolang) { // plan parallele a la generatrice
794 typeres = IntAna_Line;
796 gp_XYZ ptonaxe(apex.XYZ() + 10.*(Co.Axis().Direction().XYZ()));
797 // point sur l axe du cone cote z positif
799 dist = A*ptonaxe.X() + B*ptonaxe.Y() + C*ptonaxe.Z() + D;
800 ptonaxe = ptonaxe - dist*normp;
802 dir1.SetXYZ(ptonaxe - pt1.XYZ());
804 else if (cost < sina) { // plan "interieur" au cone
805 typeres = IntAna_Line;
809 dh = Sqrt(sina*sina-cost*cost)/cosa;
810 dir1.SetXYZ(axex + dh*axey);
811 dir2.SetXYZ(axex - dh*axey);
813 else { // plan "exterieur" au cone
814 typeres = IntAna_Point;
820 // Solutions possibles : cercle, ellipse, parabole, hyperbole selon
821 // l inclinaison du plan.
822 Standard_Real deltacenter, distance;
825 // Le plan contient la direction de l axe du cone. La solution est
827 typeres = IntAna_Hyperbola;
829 pt1.SetXYZ(apex.XYZ()-dist*normp);
833 param1 = param2 = Abs(dist/Tan(angl));
834 param1bis = param2bis = Abs(dist);
838 IntAna_IntConicQuad inter(axec,P,Tolang); // on a necessairement 1 point.
840 gp_Pnt center(inter.Point(1));
842 // En fonction de la position de l intersection par rapport au sommet
843 // du cone, on change l axe x en -x et y en -y. Le parametre du sommet
844 // sur axec est negatif (voir definition du cone)
846 distance = apex.Distance(center);
848 if (inter.ParamOnConic(1) + Co.RefRadius()/Tan(angl) < 0.) {
853 if (Abs(costa) < Tolang) { // plan parallele a une generatrice
854 typeres = IntAna_Parabola;
856 deltacenter = distance/2./cosa;
858 pt1.SetXYZ(center.XYZ()-deltacenter*axex);
861 param1 = deltacenter*sina*sina;
863 else if (sint < Tolang) { // plan perpendiculaire a l axe
864 typeres = IntAna_Circle;
867 dir1 = Co.Position().Direction();
868 dir2 = Co.Position().XDirection();
869 param1 = apex.Distance(center)*Abs(Tan(angl));
871 else if (cost < sina ) {
872 typeres = IntAna_Hyperbola;
876 deltacenter = sint*sina*sina*distance/(sina*sina - cost*cost);
877 pt1.SetXYZ(center.XYZ() - deltacenter*axex);
881 param1 = param2 = cost*sina*cosa*distance /(sina*sina-cost*cost);
882 param1bis = param2bis = cost*sina*distance / Sqrt(sina*sina-cost*cost);
885 else { // on a alors cost > sina
886 typeres = IntAna_Ellipse;
888 Standard_Real radius = cost*sina*cosa*distance/(cost*cost-sina*sina);
889 deltacenter = sint*sina*sina*distance/(cost*cost-sina*sina);
891 pt1.SetXYZ(center.XYZ() + deltacenter*axex);
895 param1bis = cost*sina*distance/ Sqrt(cost*cost - sina*sina);
900 //-- On a du mal a gerer plus loin (Value ProjLib, Params ... )
901 //-- des hyperboles trop bizarres
902 //-- On retourne False -> Traitement par biparametree
903 static Standard_Real EllipseLimit = 1.0E+9; //OCC513(apo) 1000000
904 static Standard_Real HyperbolaLimit = 2.0E+6; //OCC537(apo) 50000
905 if(typeres==IntAna_Ellipse && nbint>=1) {
906 if(Abs(param1) > EllipseLimit || Abs(param1bis) > EllipseLimit) {
911 if(typeres==IntAna_Hyperbola && nbint>=2) {
912 if(Abs(param2) > HyperbolaLimit || Abs(param2bis) > HyperbolaLimit) {
913 done = Standard_False;
917 if(typeres==IntAna_Hyperbola && nbint>=1) {
918 if(Abs(param1) > HyperbolaLimit || Abs(param1bis) > HyperbolaLimit) {
924 done = Standard_True;
927 //=======================================================================
928 //function : IntAna_QuadQuadGeo
929 //purpose : Pln Sphere
930 //=======================================================================
931 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Pln& P,
933 : done(Standard_False),
935 typeres(IntAna_Empty),
946 myCommonGen(Standard_False),
952 //=======================================================================
955 //=======================================================================
956 void IntAna_QuadQuadGeo::Perform( const gp_Pln& P
960 done = Standard_False;
961 Standard_Real A,B,C,D,dist, radius;
965 // debug JAG : on met typeres = IntAna_Empty par defaut...
966 typeres = IntAna_Empty;
968 P.Coefficients(A,B,C,D);
969 S.Location().Coord(X,Y,Z);
972 dist = A * X + B * Y + C * Z + D;
974 if (Abs( Abs(dist) - radius) < Epsilon(radius)) {
975 // on a une seule solution : le point projection du centre de la sphere
978 typeres = IntAna_Point;
979 pt1.SetCoord(X - dist*A, Y - dist*B, Z - dist*C);
981 else if (Abs(dist) < radius) {
982 // on a un cercle solution
984 typeres = IntAna_Circle;
985 pt1.SetCoord(X - dist*A, Y - dist*B, Z - dist*C);
986 dir1 = P.Axis().Direction();
987 if(P.Direct()==Standard_False) dir1.Reverse();
988 dir2 = P.Position().XDirection();
989 param1 = Sqrt(radius*radius - dist*dist);
991 param2bis=0.0; //-- pour eviter param2bis not used ....
992 done = Standard_True;
995 //=======================================================================
996 //function : IntAna_QuadQuadGeo
997 //purpose : Cylinder - Cylinder
998 //=======================================================================
999 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cylinder& Cyl1,
1000 const gp_Cylinder& Cyl2,
1001 const Standard_Real Tol)
1002 : done(Standard_False),
1004 typeres(IntAna_Empty),
1015 myCommonGen(Standard_False),
1019 Perform(Cyl1,Cyl2,Tol);
1021 //=======================================================================
1022 //function : Perform
1024 //=======================================================================
1025 void IntAna_QuadQuadGeo::Perform(const gp_Cylinder& Cyl1,
1026 const gp_Cylinder& Cyl2,
1027 const Standard_Real Tol)
1030 //---------------------------- Parallel axes -------------------------
1031 AxeOperator A1A2(Cyl1.Axis(),Cyl2.Axis(),
1032 myEPSILON_CYLINDER_DELTA_DISTANCE, myEPSILON_AXES_PARA);
1033 Standard_Real R1=Cyl1.Radius();
1034 Standard_Real R2=Cyl2.Radius();
1035 Standard_Real RmR, RmR_Relative;
1036 RmR=(R1>R2)? (R1-R2) : (R2-R1);
1039 Rmax=(R1>R2)? R1 : R2;
1040 RmR_Relative=RmR/Rmax;
1043 Standard_Real DistA1A2=A1A2.Distance();
1051 typeres=IntAna_Same;
1055 typeres=IntAna_Empty;
1059 { //-- DistA1A2 > Tol
1060 gp_Pnt P1=Cyl1.Location();
1061 gp_Pnt P2t=Cyl2.Location();
1063 //-- P2t is projected on the plane (P1,DirCylX,DirCylY)
1064 gp_Dir DirCyl = Cyl1.Position().Direction();
1065 Standard_Real ProjP2OnDirCyl1=gp_Vec(DirCyl).Dot(gp_Vec(P1,P2t));
1067 //P2 is a projection the location of the 2nd cylinder on the base
1068 //of the 1st cylinder
1069 P2.SetCoord(P2t.X() - ProjP2OnDirCyl1*DirCyl.X(),
1070 P2t.Y() - ProjP2OnDirCyl1*DirCyl.Y(),
1071 P2t.Z() - ProjP2OnDirCyl1*DirCyl.Z());
1073 Standard_Real R1pR2=R1+R2;
1074 if(DistA1A2>(R1pR2+Tol))
1076 typeres=IntAna_Empty;
1079 else if((R1pR2 - DistA1A2) <= RealSmall())
1081 //-- 1 Tangent line -------------------------------------OK
1082 typeres=IntAna_Line;
1086 Standard_Real R1_R1pR2=R1/R1pR2;
1087 pt1.SetCoord( P1.X() + R1_R1pR2 * (P2.X()-P1.X()),
1088 P1.Y() + R1_R1pR2 * (P2.Y()-P1.Y()),
1089 P1.Z() + R1_R1pR2 * (P2.Z()-P1.Z()));
1091 else if(DistA1A2>RmR)
1093 //-- 2 lines ---------------------------------------------OK
1094 typeres=IntAna_Line;
1099 const Standard_Real aR1R1 = R1*R1;
1112 Two cylinders have axes collinear. Therefore, problem can be reformulated as
1113 to find intersection point of two circles (the bases of the cylinders) on
1114 the plane: 1st circle has center P1 and radius R1 (the radius of the
1115 1st cylinder) and 2nd circle has center P2 and radius R2 (the radius of the
1116 2nd cylinder). The plane is the base of the 1st cylinder. Points A and B
1117 are intersection point of these circles. Distance P1P2 is equal to DistA1A2.
1118 O1 is the intersection point of P1P2 and AB segments.
1120 At that, if distance AB < Tol we consider that the circles are tangent and
1121 has only one intersection point.
1123 AB = 2*R1*sin(angle AP1P2).
1125 AB^2 < Tol^2 => 4*R1*R1*sin(angle AP1P2)^2 < Tol*Tol.
1129 //Cosine and Square of Sine of the A-P1-P2 angle
1130 const Standard_Real aCos = 0.5*(aR1R1-R2*R2+DistA1A2*DistA1A2)/(R1*DistA1A2);
1131 const Standard_Real aSin2 = 1-aCos*aCos;
1133 const Standard_Boolean isTangent =((4.0*aR1R1*aSin2) < Tol*Tol);
1135 //Normalized vector P1P2
1136 const gp_Vec DirA1A2((P2.XYZ() - P1.XYZ())/DistA1A2);
1140 //Intercept the segment from P1 point along P1P2 direction
1141 //and having |P1O1| length
1143 pt1.SetXYZ(P1.XYZ() + DirA1A2.XYZ()*R1*aCos);
1147 //Sine of the A-P1-P2 angle (if aSin2 < 0 then isTangent == TRUE =>
1148 //go to another branch)
1149 const Standard_Real aSin = sqrt(aSin2);
1151 //1. Rotate P1P2 to the angle A-P1-P2 relative to P1
1152 //(clockwise and anticlockwise for getting
1153 //two intersection points).
1154 //2. Intercept the segment from P1 along direction,
1155 //determined in the preview paragraph and having R1 length
1156 const gp_Dir &aXDir = Cyl1.Position().XDirection(),
1157 &aYDir = Cyl1.Position().YDirection();
1158 const gp_Vec aR1Xdir = R1*aXDir.XYZ(),
1159 aR1Ydir = R1*aYDir.XYZ();
1161 //Source 2D-coordinates of the P1P2 vector normalized
1162 //in coordinate system, based on the X- and Y-directions
1163 //of the 1st cylinder in the plane of the 1st cylinder base
1164 //(P1 is the origin of the coordinate system).
1165 const Standard_Real aDx = DirA1A2.Dot(aXDir),
1166 aDy = DirA1A2.Dot(aYDir);
1168 //New coordinate (after rotation) of the P1P2 vector normalized.
1169 Standard_Real aNewDx = aDx*aCos - aDy*aSin,
1170 aNewDy = aDy*aCos + aDx*aSin;
1171 pt1.SetXYZ(P1.XYZ() + aNewDx*aR1Xdir.XYZ() + aNewDy*aR1Ydir.XYZ());
1173 aNewDx = aDx*aCos + aDy*aSin;
1174 aNewDy = aDy*aCos - aDx*aSin;
1175 pt2.SetXYZ(P1.XYZ() + aNewDx*aR1Xdir.XYZ() + aNewDy*aR1Ydir.XYZ());
1178 else if(DistA1A2>(RmR-Tol))
1180 //-- 1 Tangent ------------------------------------------OK
1181 typeres=IntAna_Line;
1184 Standard_Real R1_RmR=R1/RmR;
1189 pt1.SetCoord( P1.X() + R1_RmR * (P2.X()-P1.X()),
1190 P1.Y() + R1_RmR * (P2.Y()-P1.Y()),
1191 P1.Z() + R1_RmR * (P2.Z()-P1.Z()));
1195 typeres=IntAna_Empty;
1199 else { //-- No Parallel Axis ---------------------------------OK
1200 if((RmR_Relative<=myEPSILON_CYLINDER_DELTA_RADIUS)
1201 && A1A2.Intersect())
1203 //-- PI/2 between the two axis and Intersection
1204 //-- and identical radius
1205 typeres=IntAna_Ellipse;
1207 gp_Dir DirCyl1=Cyl1.Position().Direction();
1208 gp_Dir DirCyl2=Cyl2.Position().Direction();
1209 pt1=pt2=A1A2.PtIntersect();
1211 Standard_Real A=DirCyl1.Angle(DirCyl2);
1213 B=Abs(Sin(0.5*(M_PI-A)));
1216 if(A==0.0 || B==0.0)
1218 typeres=IntAna_Same;
1222 gp_Vec dircyl1(DirCyl1);gp_Vec dircyl2(DirCyl2);
1223 dir1 = gp_Dir(dircyl1.Added(dircyl2));
1224 dir2 = gp_Dir(dircyl1.Subtracted(dircyl2));
1226 param2 = Cyl1.Radius() / A;
1227 param1 = Cyl1.Radius() / B;
1228 param2bis= param1bis = Cyl1.Radius();
1229 if(param1 < param1bis)
1236 if(param2 < param2bis)
1245 if(Abs(DistA1A2-Cyl1.Radius()-Cyl2.Radius())<Tol)
1247 typeres = IntAna_Point;
1248 Standard_Real d,p1,p2;
1250 gp_Dir D1 = Cyl1.Axis().Direction();
1251 gp_Dir D2 = Cyl2.Axis().Direction();
1252 A1A2.Distance(d,p1,p2);
1253 gp_Pnt P = Cyl1.Axis().Location();
1254 gp_Pnt P1(P.X() - p1*D1.X(),
1258 P = Cyl2.Axis().Location();
1260 gp_Pnt P2(P.X() - p2*D2.X(),
1268 pt1.SetCoord(P1.X() + p1*D1.X(),
1270 P1.Z() + p1*D1.Z());
1275 typeres=IntAna_NoGeometricSolution;
1280 //=======================================================================
1281 //function : IntAna_QuadQuadGeo
1282 //purpose : Cylinder - Cone
1283 //=======================================================================
1284 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cylinder& Cyl,
1286 const Standard_Real Tol)
1287 : done(Standard_False),
1289 typeres(IntAna_Empty),
1300 myCommonGen(Standard_False),
1304 Perform(Cyl,Con,Tol);
1306 //=======================================================================
1307 //function : Perform
1309 //=======================================================================
1310 void IntAna_QuadQuadGeo::Perform(const gp_Cylinder& Cyl,
1312 const Standard_Real )
1315 AxeOperator A1A2(Cyl.Axis(),Con.Axis());
1317 gp_Pnt Pt=Con.Apex();
1318 Standard_Real dist=Cyl.Radius()/(Tan(Con.SemiAngle()));
1319 gp_Dir dir=Cyl.Position().Direction();
1320 pt1.SetCoord( Pt.X() + dist*dir.X()
1321 ,Pt.Y() + dist*dir.Y()
1322 ,Pt.Z() + dist*dir.Z());
1323 pt2.SetCoord( Pt.X() - dist*dir.X()
1324 ,Pt.Y() - dist*dir.Y()
1325 ,Pt.Z() - dist*dir.Z());
1327 param1=param2=Cyl.Radius();
1329 typeres=IntAna_Circle;
1333 typeres=IntAna_NoGeometricSolution;
1336 //=======================================================================
1338 //purpose : Cylinder - Sphere
1339 //=======================================================================
1340 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cylinder& Cyl,
1341 const gp_Sphere& Sph,
1342 const Standard_Real Tol)
1343 : done(Standard_False),
1345 typeres(IntAna_Empty),
1356 myCommonGen(Standard_False),
1360 Perform(Cyl,Sph,Tol);
1362 //=======================================================================
1363 //function : Perform
1365 //=======================================================================
1366 void IntAna_QuadQuadGeo::Perform( const gp_Cylinder& Cyl
1367 ,const gp_Sphere& Sph
1368 ,const Standard_Real)
1371 gp_Pnt Pt=Sph.Location();
1372 AxeOperator A1A2(Cyl.Axis(),Sph.Position().Axis());
1373 if((A1A2.Intersect() && Pt.Distance(A1A2.PtIntersect())==0.0 )
1375 if(Sph.Radius() < Cyl.Radius()) {
1376 typeres = IntAna_Empty;
1379 Standard_Real dist=Sqrt( Sph.Radius() * Sph.Radius() - Cyl.Radius() * Cyl.Radius() );
1380 gp_Dir dir=Cyl.Position().Direction();
1382 typeres=IntAna_Circle;
1383 pt1.SetCoord( Pt.X() + dist*dir.X()
1384 ,Pt.Y() + dist*dir.Y()
1385 ,Pt.Z() + dist*dir.Z());
1387 param1 = Cyl.Radius();
1388 if(dist>RealEpsilon()) {
1389 pt2.SetCoord( Pt.X() - dist*dir.X()
1390 ,Pt.Y() - dist*dir.Y()
1391 ,Pt.Z() - dist*dir.Z());
1392 param2=Cyl.Radius();
1398 typeres=IntAna_NoGeometricSolution;
1402 //=======================================================================
1403 //function : IntAna_QuadQuadGeo
1404 //purpose : Cone - Cone
1405 //=======================================================================
1406 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cone& Con1,
1407 const gp_Cone& Con2,
1408 const Standard_Real Tol)
1409 : done(Standard_False),
1411 typeres(IntAna_Empty),
1422 myCommonGen(Standard_False),
1426 Perform(Con1,Con2,Tol);
1429 //=======================================================================
1430 //function : Perform
1432 //=======================================================================
1433 void IntAna_QuadQuadGeo::Perform(const gp_Cone& Con1,
1434 const gp_Cone& Con2,
1435 const Standard_Real Tol)
1437 done = Standard_True;
1439 Standard_Real tg1, tg2, aDA1A2, aTol2;
1440 gp_Pnt aPApex1, aPApex2;
1442 Standard_Real TOL_APEX_CONF = 1.e-10;
1445 tg1 = Tan(Con1.SemiAngle());
1446 tg2 = Tan(Con2.SemiAngle());
1448 if ((tg1 * tg2) < 0.) {
1453 aPApex1 = Con1.Apex();
1454 aPApex2 = Con2.Apex();
1455 aDA1A2 = aPApex1.SquareDistance(aPApex2);
1457 AxeOperator A1A2(Con1.Axis(), Con2.Axis());
1459 Standard_Real aTolAng = myEPSILON_ANGLE_CONE;
1460 if ((Abs(tg1 - tg2) < Tol) && (A1A2.Parallel()))
1462 Standard_Real DistA1A2 = A1A2.Distance();
1463 if (DistA1A2 > 100. * Tol)
1465 Standard_Real aMinSolDist = EstimDist(Con1, Con2);
1466 if (aMinSolDist < Epsilon(1.))
1472 aTolAng = Max(myEPSILON_ANGLE_CONE, Tol / aMinSolDist);
1473 aTolAng = Min(aTolAng, Tol);
1482 gp_Pnt P=Con1.Apex();
1483 gp_Dir D=Con1.Position().Direction();
1484 Standard_Real d=gp_Vec(D).Dot(gp_Vec(P,Con2.Apex()));
1486 if(Abs(tg1-tg2)>myEPSILON_ANGLE_CONE) {
1487 if (fabs(d) < TOL_APEX_CONF) {
1488 typeres = IntAna_Point;
1493 x=(d*tg2)/(tg1+tg2);
1494 pt1.SetCoord( P.X() + x*D.X()
1499 x=(d*tg2)/(tg2-tg1);
1500 pt2.SetCoord( P.X() + x*D.X()
1506 typeres=IntAna_Circle;
1509 if (fabs(d) < TOL_APEX_CONF) {
1510 typeres=IntAna_Same;
1513 typeres=IntAna_Circle;
1516 pt1.SetCoord( P.X() + x*D.X()
1519 param1 = Abs(x * tg1);
1523 } //-- fin A1A2.Same
1525 else if((Abs(tg1-tg2) < aTolAng ) && (A1A2.Parallel())) {
1527 Standard_Real DistA1A2=A1A2.Distance();
1528 gp_Dir DA1=Con1.Position().Direction();
1529 gp_Vec O1O2(Con1.Apex(),Con2.Apex());
1530 gp_Dir O1O2n(O1O2); // normalization of the vector before projection
1531 Standard_Real O1O2_DA1=gp_Vec(DA1).Dot(gp_Vec(O1O2n));
1533 gp_Vec O1_Proj_A2(O1O2n.X()-O1O2_DA1*DA1.X(),
1534 O1O2n.Y()-O1O2_DA1*DA1.Y(),
1535 O1O2n.Z()-O1O2_DA1*DA1.Z());
1536 gp_Dir DB1=gp_Dir(O1_Proj_A2);
1538 Standard_Real yO1O2=O1O2.Dot(gp_Vec(DA1));
1539 Standard_Real ABSTG1 = Abs(tg1);
1540 Standard_Real X2 = (DistA1A2/ABSTG1 - yO1O2)*0.5;
1541 Standard_Real X1 = X2+yO1O2;
1543 gp_Pnt P1(Con1.Apex().X() + X1*( DA1.X() + ABSTG1*DB1.X()),
1544 Con1.Apex().Y() + X1*( DA1.Y() + ABSTG1*DB1.Y()),
1545 Con1.Apex().Z() + X1*( DA1.Z() + ABSTG1*DB1.Z()));
1547 gp_Pnt MO1O2(0.5*(Con1.Apex().X()+Con2.Apex().X()),
1548 0.5*(Con1.Apex().Y()+Con2.Apex().Y()),
1549 0.5*(Con1.Apex().Z()+Con2.Apex().Z()));
1550 gp_Vec P1MO1O2(P1,MO1O2);
1552 gp_Dir DA1_X_DB1=DA1.Crossed(DB1);
1553 gp_Dir OrthoPln = DA1_X_DB1.Crossed(gp_Dir(P1MO1O2));
1555 IntAna_QuadQuadGeo INTER_QUAD_PLN(gp_Pln(P1,OrthoPln),Con1,Tol,Tol);
1556 if(INTER_QUAD_PLN.IsDone()) {
1557 switch(INTER_QUAD_PLN.TypeInter()) {
1558 case IntAna_Ellipse: {
1559 typeres=IntAna_Ellipse;
1560 gp_Elips E=INTER_QUAD_PLN.Ellipse(1);
1562 dir1 = E.Position().Direction();
1563 dir2 = E.Position().XDirection();
1564 param1 = E.MajorRadius();
1565 param1bis = E.MinorRadius();
1569 case IntAna_Circle: {
1570 typeres=IntAna_Circle;
1571 gp_Circ C=INTER_QUAD_PLN.Circle(1);
1573 dir1 = C.Position().XDirection();
1574 dir2 = C.Position().YDirection();
1575 param1 = C.Radius();
1579 case IntAna_Hyperbola: {
1580 typeres=IntAna_Hyperbola;
1581 gp_Hypr H=INTER_QUAD_PLN.Hyperbola(1);
1582 pt1 = pt2 = H.Location();
1583 dir1 = H.Position().Direction();
1584 dir2 = H.Position().XDirection();
1585 param1 = param2 = H.MajorRadius();
1586 param1bis = param2bis = H.MinorRadius();
1591 typeres=IntAna_Line;
1592 gp_Lin H=INTER_QUAD_PLN.Line(1);
1593 pt1 = pt2 = H.Location();
1594 dir1 = dir2 = H.Position().Direction();
1595 param1 = param2 = 0.0;
1596 param1bis = param2bis = 0.0;
1601 typeres=IntAna_NoGeometricSolution;
1604 }// else if((Abs(tg1-tg2)<EPSILON_ANGLE_CONE) && (A1A2.Parallel()))
1606 else if (aDA1A2<aTol2) {
1608 // When apices are coincided there can be 3 possible cases
1609 // 3.1 - empty solution (iRet=0)
1610 // 3.2 - one line when cone1 touches cone2 (iRet=1)
1611 // 3.3 - two lines when cone1 intersects cone2 (iRet=2)
1613 Standard_Integer iRet;
1614 Standard_Real aGamma, aBeta1, aBeta2;
1615 Standard_Real aD1, aR1, aTgBeta1, aTgBeta2, aHalfPI;
1616 Standard_Real aCosGamma, aSinGamma, aDx, aR2, aRD2, aD2;
1617 gp_Pnt2d aP0, aPA1, aP1, aPA2;
1621 // Preliminary analysis. Determination of iRet
1626 aPA1.SetCoord(aD1, 0.);
1627 aP0.SetCoord(0., 0.);
1631 aGamma=aAx1.Angle(aAx2);
1632 if (aGamma>aHalfPI){
1635 aCosGamma=Cos(aGamma);
1636 aSinGamma=Sin(aGamma);
1638 aBeta1=Con1.SemiAngle();
1639 aTgBeta1=Tan(aBeta1);
1640 aTgBeta1=Abs(aTgBeta1);
1642 aBeta2=Con2.SemiAngle();
1643 aTgBeta2=Tan(aBeta2);
1644 aTgBeta2=Abs(aTgBeta2);
1647 aP1.SetCoord(aD1, aR1);
1650 aVAx2.SetCoord(aCosGamma, aSinGamma);
1651 gp_Dir2d aDAx2(aVAx2);
1652 gp_Lin2d aLAx2(aP0, aDAx2);
1654 gp_Vec2d aV(aP0, aP1);
1656 aPA2=aP0.Translated(aDx*aDAx2);
1659 aDx=aPA2.Distance(aP0);
1663 aRD2=aPA2.Distance(aP1);
1665 if (aRD2>(aR2+Tol)) {
1667 typeres=IntAna_Empty; //nothing
1671 iRet=1; //touch case => 1 line
1672 if (aRD2<(aR2-Tol)) {
1673 iRet=2;//intersection => couple of lines
1676 // Finding the solution in 3D
1679 gp_Pnt aQApex1, aQA1, aQA2, aQX, aQX1, aQX2;
1680 gp_Dir aD3Ax1, aD3Ax2;
1682 IntAna_QuadQuadGeo aIntr;
1684 aQApex1=Con1.Apex();
1685 aD3Ax1=aAx1.Direction();
1686 aQA1.SetCoord(aQApex1.X()+aD1*aD3Ax1.X(),
1687 aQApex1.Y()+aD1*aD3Ax1.Y(),
1688 aQApex1.Z()+aD1*aD3Ax1.Z());
1690 aDx=aD3Ax1.Dot(aAx2.Direction());
1694 aD3Ax2=aAx2.Direction();
1696 aD2=aD1*sqrt((1.+aTgBeta1*aTgBeta1)/(1.+aTgBeta2*aTgBeta2));
1698 aQA2.SetCoord(aQApex1.X()+aD2*aD3Ax2.X(),
1699 aQApex1.Y()+aD2*aD3Ax2.Y(),
1700 aQApex1.Z()+aD2*aD3Ax2.Z());
1702 gp_Pln aPln1(aQA1, aD3Ax1);
1703 gp_Pln aPln2(aQA2, aD3Ax2);
1705 aIntr.Perform(aPln1, aPln2, Tol, Tol);
1706 if (!aIntr.IsDone() || 0 == aIntr.NbSolutions()) {
1707 iRet=-1; // just in case. it must not be so
1708 typeres=IntAna_NoGeometricSolution;
1713 const gp_Dir& aDLin=aLin.Direction();
1714 gp_Vec aVLin(aDLin);
1715 gp_Pnt aOrig=aLin.Location();
1716 gp_Vec aVr(aQA1, aOrig);
1718 aQX=aOrig.Translated(aDx*aVLin);
1722 typeres=IntAna_Line;
1733 gp_Vec aVX(aQApex1, aQX);
1740 aDa=aQA1.Distance(aQX);
1741 aDx=sqrt(aR1*aR1-aDa*aDa);
1742 aQX1=aQX.Translated(aDx*aVLin);
1743 aQX2=aQX.Translated(-aDx*aVLin);
1747 gp_Vec aVX1(aQApex1, aQX1);
1749 gp_Vec aVX2(aQApex1, aQX2);
1752 } //else if (aDA1A2<aTol2) {
1753 //Case when cones have common generatrix
1754 else if(A1A2.Intersect()) {
1755 //Check if apex of one cone belongs another one
1756 Standard_Real u, v, tol2 = Tol*Tol;
1757 ElSLib::Parameters(Con2, aPApex1, u, v);
1758 gp_Pnt p = ElSLib::Value(u, v, Con2);
1759 if(aPApex1.SquareDistance(p) > tol2) {
1760 typeres=IntAna_NoGeometricSolution;
1764 ElSLib::Parameters(Con1, aPApex2, u, v);
1765 p = ElSLib::Value(u, v, Con1);
1766 if(aPApex2.SquareDistance(p) > tol2) {
1767 typeres=IntAna_NoGeometricSolution;
1771 //Cones have a common generatrix passing through apexes
1772 myCommonGen = Standard_True;
1774 //common generatrix of cones
1775 gp_Lin aGen(aPApex1, gp_Dir(gp_Vec(aPApex1, aPApex2)));
1777 //Intersection point of axes
1778 gp_Pnt aPAxeInt = A1A2.PtIntersect();
1780 //Characteristic point of intersection curve
1781 u = ElCLib::Parameter(aGen, aPAxeInt);
1782 myPChar = ElCLib::Value(u, aGen);
1785 //Other generatrixes of cones laying in maximal plane
1786 gp_Lin aGen1 = aGen.Rotated(Con1.Axis(), M_PI);
1787 gp_Lin aGen2 = aGen.Rotated(Con2.Axis(), M_PI);
1789 //Intersection point of generatrixes
1790 gp_Dir aN; //solution plane normal
1791 gp_Dir aD1 = aGen1.Direction();
1793 gp_Dir aD2(aD1.Crossed(aGen.Direction()));
1795 if(aD1.IsParallel(aGen2.Direction(), Precision::Angular())) {
1796 aN = aD1.Crossed(aD2);
1798 else if(aGen1.SquareDistance(aGen2) > tol2) {
1799 //Something wrong ???
1800 typeres=IntAna_NoGeometricSolution;
1804 gp_Dir D1 = aGen1.Position().Direction();
1805 gp_Dir D2 = aGen2.Position().Direction();
1806 gp_Pnt O1 = aGen1.Location();
1807 gp_Pnt O2 = aGen2.Location();
1808 Standard_Real D1DotD2 = D1.Dot(D2);
1809 Standard_Real aSin = 1.-D1DotD2*D1DotD2;
1810 gp_Vec O1O2 (O1,O2);
1811 Standard_Real U2 = (D1.XYZ()*(O1O2.Dot(D1))-(O1O2.XYZ())).Dot(D2.XYZ());
1813 gp_Pnt aPGint(ElCLib::Value(U2, aGen2));
1815 aD1 = gp_Dir(gp_Vec(aPGint, myPChar));
1816 aN = aD1.Crossed(aD2);
1818 //Plane that must contain intersection curves
1819 gp_Pln anIntPln(myPChar, aN);
1821 IntAna_QuadQuadGeo INTER_QUAD_PLN(anIntPln,Con1,Tol,Tol);
1823 if(INTER_QUAD_PLN.IsDone()) {
1824 switch(INTER_QUAD_PLN.TypeInter()) {
1825 case IntAna_Ellipse: {
1826 typeres=IntAna_Ellipse;
1827 gp_Elips E=INTER_QUAD_PLN.Ellipse(1);
1829 dir1 = E.Position().Direction();
1830 dir2 = E.Position().XDirection();
1831 param1 = E.MajorRadius();
1832 param1bis = E.MinorRadius();
1836 case IntAna_Circle: {
1837 typeres=IntAna_Circle;
1838 gp_Circ C=INTER_QUAD_PLN.Circle(1);
1840 dir1 = C.Position().XDirection();
1841 dir2 = C.Position().YDirection();
1842 param1 = C.Radius();
1846 case IntAna_Parabola: {
1847 typeres=IntAna_Parabola;
1848 gp_Parab Prb=INTER_QUAD_PLN.Parabola(1);
1849 pt1 = Prb.Location();
1850 dir1 = Prb.Position().Direction();
1851 dir2 = Prb.Position().XDirection();
1852 param1 = Prb.Focal();
1856 case IntAna_Hyperbola: {
1857 typeres=IntAna_Hyperbola;
1858 gp_Hypr H=INTER_QUAD_PLN.Hyperbola(1);
1859 pt1 = pt2 = H.Location();
1860 dir1 = H.Position().Direction();
1861 dir2 = H.Position().XDirection();
1862 param1 = param2 = H.MajorRadius();
1863 param1bis = param2bis = H.MinorRadius();
1868 typeres=IntAna_NoGeometricSolution;
1874 typeres=IntAna_NoGeometricSolution;
1877 //=======================================================================
1878 //function : IntAna_QuadQuadGeo
1879 //purpose : Sphere - Cone
1880 //=======================================================================
1881 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Sphere& Sph,
1883 const Standard_Real Tol)
1884 : done(Standard_False),
1886 typeres(IntAna_Empty),
1897 myCommonGen(Standard_False),
1901 Perform(Sph,Con,Tol);
1903 //=======================================================================
1904 //function : Perform
1906 //=======================================================================
1907 void IntAna_QuadQuadGeo::Perform(const gp_Sphere& Sph,
1909 const Standard_Real)
1915 AxeOperator A1A2(Con.Axis(),Sph.Position().Axis());
1916 gp_Pnt Pt=Sph.Location();
1918 if((A1A2.Intersect() && (Pt.Distance(A1A2.PtIntersect())==0.0))
1920 gp_Pnt ConApex= Con.Apex();
1921 Standard_Real dApexSphCenter=Pt.Distance(ConApex);
1923 if(dApexSphCenter>RealEpsilon()) {
1924 ConDir = gp_Dir(gp_Vec(ConApex,Pt));
1927 ConDir = Con.Position().Direction();
1930 Standard_Real Rad=Sph.Radius();
1931 Standard_Real tga=Tan(Con.SemiAngle());
1935 //-- x: Roots of (x**2 + y**2 = Rad**2)
1936 //-- tga = y / (x+dApexSphCenter)
1937 Standard_Real tgatga = tga * tga;
1938 math_DirectPolynomialRoots Eq( 1.0+tgatga
1939 ,2.0*tgatga*dApexSphCenter
1940 ,-Rad*Rad + dApexSphCenter*dApexSphCenter*tgatga);
1942 Standard_Integer nbsol=Eq.NbSolutions();
1944 typeres=IntAna_Empty;
1947 typeres=IntAna_Circle;
1949 Standard_Real x = Eq.Value(1);
1950 Standard_Real dApexSphCenterpx = dApexSphCenter+x;
1952 pt1.SetCoord( ConApex.X() + (dApexSphCenterpx) * ConDir.X()
1953 ,ConApex.Y() + (dApexSphCenterpx) * ConDir.Y()
1954 ,ConApex.Z() + (dApexSphCenterpx) * ConDir.Z());
1955 param1 = tga * dApexSphCenterpx;
1956 param1 = Abs(param1);
1958 if(param1<=myEPSILON_MINI_CIRCLE_RADIUS) {
1959 typeres=IntAna_PointAndCircle;
1964 Standard_Real x=Eq.Value(2);
1965 Standard_Real dApexSphCenterpx = dApexSphCenter+x;
1967 pt2.SetCoord( ConApex.X() + (dApexSphCenterpx) * ConDir.X()
1968 ,ConApex.Y() + (dApexSphCenterpx) * ConDir.Y()
1969 ,ConApex.Z() + (dApexSphCenterpx) * ConDir.Z());
1970 param2 = tga * dApexSphCenterpx;
1971 param2 = Abs(param2);
1973 if(param2<=myEPSILON_MINI_CIRCLE_RADIUS) {
1974 typeres=IntAna_PointAndCircle;
1981 done=Standard_False;
1985 typeres=IntAna_NoGeometricSolution;
1989 //=======================================================================
1990 //function : IntAna_QuadQuadGeo
1991 //purpose : Sphere - Sphere
1992 //=======================================================================
1993 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo( const gp_Sphere& Sph1
1994 ,const gp_Sphere& Sph2
1995 ,const Standard_Real Tol)
1996 : done(Standard_False),
1998 typeres(IntAna_Empty),
2009 myCommonGen(Standard_False),
2013 Perform(Sph1,Sph2,Tol);
2015 //=======================================================================
2016 //function : Perform
2018 //=======================================================================
2019 void IntAna_QuadQuadGeo::Perform(const gp_Sphere& Sph1,
2020 const gp_Sphere& Sph2,
2021 const Standard_Real Tol)
2024 gp_Pnt O1=Sph1.Location();
2025 gp_Pnt O2=Sph2.Location();
2026 Standard_Real dO1O2=O1.Distance(O2);
2027 Standard_Real R1=Sph1.Radius();
2028 Standard_Real R2=Sph2.Radius();
2029 Standard_Real Rmin,Rmax;
2030 typeres=IntAna_Empty;
2031 param2bis=0.0; //-- pour eviter param2bis not used ....
2033 if(R1>R2) { Rmin=R2; Rmax=R1; } else { Rmin=R1; Rmax=R2; }
2035 if(dO1O2<=Tol && (Abs(R1-R2) <= Tol)) {
2036 typeres = IntAna_Same;
2039 if(dO1O2<=Tol) { return; }
2040 gp_Dir Dir=gp_Dir(gp_Vec(O1,O2));
2041 Standard_Real t = Rmax - dO1O2 - Rmin;
2043 //----------------------------------------------------------------------
2044 //-- |----------------- R1 --------------------|
2045 //-- |----dO1O2-----|-----------R2----------|
2048 //-- |------ R1 ------|---------dO1O2----------|
2049 //-- |-------------------R2-----------------------|
2051 //----------------------------------------------------------------------
2052 if(t >= 0.0 && t <=Tol) {
2053 typeres = IntAna_Point;
2056 if(R1==Rmax) t2=(R1 + (R2 + dO1O2)) * 0.5;
2057 else t2=(-R1+(dO1O2-R2))*0.5;
2059 pt1.SetCoord( O1.X() + t2*Dir.X()
2060 ,O1.Y() + t2*Dir.Y()
2061 ,O1.Z() + t2*Dir.Z());
2064 //-----------------------------------------------------------------
2065 //-- |----------------- dO1O2 --------------------|
2066 //-- |----R1-----|-----------R2----------|-Tol-|
2068 //-- |----------------- Rmax --------------------|
2069 //-- |----Rmin----|-------dO1O2-------|-Tol-|
2071 //-----------------------------------------------------------------
2072 if((dO1O2 > (R1+R2+Tol)) || (Rmax > (dO1O2+Rmin+Tol))) {
2073 typeres=IntAna_Empty;
2076 //---------------------------------------------------------------
2079 //---------------------------------------------------------------
2080 Standard_Real Alpha=0.5*(R1*R1-R2*R2+dO1O2*dO1O2)/(dO1O2);
2081 Standard_Real Beta = R1*R1-Alpha*Alpha;
2082 Beta = (Beta>0.0)? Sqrt(Beta) : 0.0;
2084 if(Beta<= myEPSILON_MINI_CIRCLE_RADIUS) {
2085 typeres = IntAna_Point;
2086 Alpha = (R1 + (dO1O2 - R2)) * 0.5;
2089 typeres = IntAna_Circle;
2093 pt1.SetCoord( O1.X() + Alpha*Dir.X()
2094 ,O1.Y() + Alpha*Dir.Y()
2095 ,O1.Z() + Alpha*Dir.Z());
2103 //=======================================================================
2104 //function : IntAna_QuadQuadGeo
2105 //purpose : Plane - Torus
2106 //=======================================================================
2107 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Pln& Pln,
2108 const gp_Torus& Tor,
2109 const Standard_Real Tol)
2110 : done(Standard_False),
2112 typeres(IntAna_Empty),
2123 myCommonGen(Standard_False),
2127 Perform(Pln,Tor,Tol);
2129 //=======================================================================
2130 //function : Perform
2132 //=======================================================================
2133 void IntAna_QuadQuadGeo::Perform(const gp_Pln& Pln,
2134 const gp_Torus& Tor,
2135 const Standard_Real Tol)
2137 done = Standard_True;
2139 Standard_Real aRMin, aRMaj;
2141 aRMin = Tor.MinorRadius();
2142 aRMaj = Tor.MajorRadius();
2143 if (aRMin >= aRMaj) {
2144 typeres = IntAna_NoGeometricSolution;
2148 const gp_Ax1 aPlnAx = Pln.Axis();
2149 const gp_Ax1 aTorAx = Tor.Axis();
2151 Standard_Boolean bParallel, bNormal;
2153 bParallel = aTorAx.IsParallel(aPlnAx, myEPSILON_AXES_PARA);
2154 bNormal = !bParallel ? aTorAx.IsNormal(aPlnAx, myEPSILON_AXES_PARA) : Standard_False;
2155 if (!bNormal && !bParallel) {
2156 typeres = IntAna_NoGeometricSolution;
2160 Standard_Real aDist;
2162 gp_Pnt aTorLoc = aTorAx.Location();
2164 Standard_Real aDt, X, Y, Z, A, B, C, D, aDR, aTolNum;
2166 aTolNum=myEPSILON_CYLINDER_DELTA_RADIUS;
2168 Pln.Coefficients(A,B,C,D);
2169 aTorLoc.Coord(X,Y,Z);
2170 aDist = A*X + B*Y + C*Z + D;
2172 aDR=Abs(aDist) - aRMin;
2173 if (aDR > aTolNum) {
2174 typeres=IntAna_Empty;
2178 if (Abs(aDR) < aTolNum) {
2179 aDist = (aDist < 0) ? -aRMin : aRMin;
2182 typeres = IntAna_Circle;
2184 pt1.SetCoord(X - aDist*A, Y - aDist*B, Z - aDist*C);
2185 aDt = Sqrt(Abs(aRMin*aRMin - aDist*aDist));
2186 param1 = aRMaj + aDt;
2187 dir1 = aTorAx.Direction();
2189 if ((aDR < -aTolNum) && (aDt > Tol)) {
2191 param2 = aRMaj - aDt;
2198 aDist = Pln.Distance(aTorLoc);
2199 if (aDist > myEPSILON_DISTANCE) {
2200 typeres = IntAna_NoGeometricSolution;
2204 typeres = IntAna_Circle;
2205 param2 = param1 = aRMin;
2206 dir2 = dir1 = aPlnAx.Direction();
2209 gp_Dir aDir = aTorAx.Direction()^dir1;
2210 pt1.SetXYZ(aTorLoc.XYZ() + aRMaj*aDir.XYZ());
2211 pt2.SetXYZ(aTorLoc.XYZ() - aRMaj*aDir.XYZ());
2215 //=======================================================================
2216 //function : IntAna_QuadQuadGeo
2217 //purpose : Cylinder - Torus
2218 //=======================================================================
2219 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cylinder& Cyl,
2220 const gp_Torus& Tor,
2221 const Standard_Real Tol)
2222 : done(Standard_False),
2224 typeres(IntAna_Empty),
2235 myCommonGen(Standard_False),
2239 Perform(Cyl,Tor,Tol);
2241 //=======================================================================
2242 //function : Perform
2244 //=======================================================================
2245 void IntAna_QuadQuadGeo::Perform(const gp_Cylinder& Cyl,
2246 const gp_Torus& Tor,
2247 const Standard_Real Tol)
2249 done = Standard_True;
2251 Standard_Real aRMin, aRMaj;
2253 aRMin = Tor.MinorRadius();
2254 aRMaj = Tor.MajorRadius();
2255 if (aRMin >= aRMaj) {
2256 typeres = IntAna_NoGeometricSolution;
2260 const gp_Ax1 aCylAx = Cyl.Axis();
2261 const gp_Ax1 aTorAx = Tor.Axis();
2263 const gp_Lin aLin(aTorAx);
2264 const gp_Pnt aLocCyl = Cyl.Location();
2266 if (!aTorAx.IsParallel(aCylAx, myEPSILON_AXES_PARA) ||
2267 (aLin.Distance(aLocCyl) > myEPSILON_DISTANCE)) {
2268 typeres = IntAna_NoGeometricSolution;
2272 Standard_Real aRCyl;
2274 aRCyl = Cyl.Radius();
2275 if (((aRCyl + Tol) < (aRMaj - aRMin)) || ((aRCyl - Tol) > (aRMaj + aRMin))) {
2276 typeres = IntAna_Empty;
2280 typeres = IntAna_Circle;
2282 Standard_Real aDist = Sqrt(Abs(aRMin*aRMin - (aRCyl-aRMaj)*(aRCyl-aRMaj)));
2283 gp_XYZ aTorLoc = aTorAx.Location().XYZ();
2285 dir1 = aTorAx.Direction();
2286 pt1.SetXYZ(aTorLoc + aDist*dir1.XYZ());
2289 if ((aDist > Tol) && (aRCyl > (aRMaj - aRMin)) &&
2290 (aRCyl < (aRMaj + aRMin))) {
2292 pt2.SetXYZ(aTorLoc - aDist*dir2.XYZ());
2298 //=======================================================================
2299 //function : IntAna_QuadQuadGeo
2300 //purpose : Cone - Torus
2301 //=======================================================================
2302 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Cone& Con,
2303 const gp_Torus& Tor,
2304 const Standard_Real Tol)
2305 : done(Standard_False),
2307 typeres(IntAna_Empty),
2318 myCommonGen(Standard_False),
2322 Perform(Con,Tor,Tol);
2324 //=======================================================================
2325 //function : Perform
2327 //=======================================================================
2328 void IntAna_QuadQuadGeo::Perform(const gp_Cone& Con,
2329 const gp_Torus& Tor,
2330 const Standard_Real Tol)
2332 done = Standard_True;
2334 Standard_Real aRMin, aRMaj;
2336 aRMin = Tor.MinorRadius();
2337 aRMaj = Tor.MajorRadius();
2338 if (aRMin >= aRMaj) {
2339 typeres = IntAna_NoGeometricSolution;
2343 const gp_Ax1 aConAx = Con.Axis();
2344 const gp_Ax1 aTorAx = Tor.Axis();
2346 const gp_Lin aLin(aTorAx);
2347 const gp_Pnt aConApex = Con.Apex();
2349 if (!aTorAx.IsParallel(aConAx, myEPSILON_AXES_PARA) ||
2350 (aLin.Distance(aConApex) > myEPSILON_DISTANCE)) {
2351 typeres = IntAna_NoGeometricSolution;
2355 Standard_Real anAngle, aDist, aParam[4], aDt;
2357 gp_Pnt aTorLoc, aPCT, aPN, aPt[4];
2360 anAngle = Con.SemiAngle();
2361 aTorLoc = aTorAx.Location();
2363 aPN.SetXYZ(aTorLoc.XYZ() + aRMaj*Tor.YAxis().Direction().XYZ());
2364 gp_Dir aDN (gp_Vec(aTorLoc, aPN));
2365 gp_Ax1 anAxCLRot(aConApex, aDN);
2366 gp_Lin aConL = aLin.Rotated(anAxCLRot, anAngle);
2367 gp_Dir aDL = aConL.Position().Direction();
2368 gp_Dir aXDir = Tor.XAxis().Direction();
2370 typeres = IntAna_Empty;
2372 for (i = 0; i < 2; ++i) {
2376 aPCT.SetXYZ(aTorLoc.XYZ() + aRMaj*aXDir.XYZ());
2378 aDist = aConL.Distance(aPCT);
2379 if (aDist > aRMin+Tol) {
2383 typeres = IntAna_Circle;
2385 gp_XYZ aPh = aPCT.XYZ() - aDist*aConL.Normal(aPCT).Direction().XYZ();
2386 aDt = Sqrt(Abs(aRMin*aRMin - aDist*aDist));
2389 gp_XYZ aDVal = aDt*aDL.XYZ();
2390 aP.SetXYZ(aPh + aDVal);
2391 aParam[nbint] = aLin.Distance(aP);
2392 aPt[nbint].SetXYZ(aP.XYZ() - aParam[nbint]*aXDir.XYZ());
2393 aDir[nbint] = aTorAx.Direction();
2395 if ((aDist < aRMin) && (aDt > Tol)) {
2396 aP.SetXYZ(aPh - aDVal);
2397 aParam[nbint] = aLin.Distance(aP);
2398 aPt[nbint].SetXYZ(aP.XYZ() - aParam[nbint]*aXDir.XYZ());
2399 aDir[nbint] = aDir[nbint-1];
2404 for (i = 0; i < nbint; ++i) {
2436 //=======================================================================
2437 //function : IntAna_QuadQuadGeo
2438 //purpose : Sphere - Torus
2439 //=======================================================================
2440 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Sphere& Sph,
2441 const gp_Torus& Tor,
2442 const Standard_Real Tol)
2443 : done(Standard_False),
2445 typeres(IntAna_Empty),
2456 myCommonGen(Standard_False),
2460 Perform(Sph,Tor,Tol);
2462 //=======================================================================
2463 //function : Perform
2465 //=======================================================================
2466 void IntAna_QuadQuadGeo::Perform(const gp_Sphere& Sph,
2467 const gp_Torus& Tor,
2468 const Standard_Real Tol)
2470 done = Standard_True;
2472 Standard_Real aRMin, aRMaj;
2474 aRMin = Tor.MinorRadius();
2475 aRMaj = Tor.MajorRadius();
2476 if (aRMin >= aRMaj) {
2477 typeres = IntAna_NoGeometricSolution;
2481 const gp_Ax1 aTorAx = Tor.Axis();
2482 const gp_Lin aLin(aTorAx);
2483 const gp_Pnt aSphLoc = Sph.Location();
2485 if (aLin.Distance(aSphLoc) > myEPSILON_DISTANCE) {
2486 typeres = IntAna_NoGeometricSolution;
2490 Standard_Real aRSph, aDist;
2493 gp_Dir aXDir = Tor.XAxis().Direction();
2494 aTorLoc.SetXYZ(aTorAx.Location().XYZ() + aRMaj*aXDir.XYZ());
2495 aRSph = Sph.Radius();
2497 gp_Vec aVec12(aTorLoc, aSphLoc);
2498 aDist = aVec12.Magnitude();
2499 if (((aDist - Tol) > (aRMin + aRSph)) ||
2500 ((aDist + Tol) < Abs(aRMin - aRSph))) {
2501 typeres = IntAna_Empty;
2505 typeres = IntAna_Circle;
2507 Standard_Real anAlpha, aBeta;
2509 anAlpha = 0.5*(aRMin*aRMin - aRSph*aRSph + aDist*aDist ) / aDist;
2510 aBeta = Sqrt(Abs(aRMin*aRMin - anAlpha*anAlpha));
2512 gp_Dir aDir12(aVec12);
2513 gp_XYZ aPh = aTorLoc.XYZ() + anAlpha*aDir12.XYZ();
2514 gp_Dir aDC = Tor.YAxis().Direction()^aDir12;
2517 gp_XYZ aDVal = aBeta*aDC.XYZ();
2518 aP.SetXYZ(aPh + aDVal);
2519 param1 = aLin.Distance(aP);
2520 pt1.SetXYZ(aP.XYZ() - param1*aXDir.XYZ());
2521 dir1 = aTorAx.Direction();
2523 if ((aDist < (aRSph + aRMin)) && (aDist > Abs(aRSph - aRMin)) &&
2524 (aDVal.Modulus() > Tol)) {
2525 aP.SetXYZ(aPh - aDVal);
2526 param2 = aLin.Distance(aP);
2527 pt2.SetXYZ(aP.XYZ() - param2*aXDir.XYZ());
2533 //=======================================================================
2534 //function : IntAna_QuadQuadGeo
2535 //purpose : Torus - Torus
2536 //=======================================================================
2537 IntAna_QuadQuadGeo::IntAna_QuadQuadGeo(const gp_Torus& Tor1,
2538 const gp_Torus& Tor2,
2539 const Standard_Real Tol)
2540 : done(Standard_False),
2542 typeres(IntAna_Empty),
2553 myCommonGen(Standard_False),
2557 Perform(Tor1,Tor2,Tol);
2559 //=======================================================================
2560 //function : Perform
2562 //=======================================================================
2563 void IntAna_QuadQuadGeo::Perform(const gp_Torus& Tor1,
2564 const gp_Torus& Tor2,
2565 const Standard_Real Tol)
2567 done = Standard_True;
2569 Standard_Real aRMin1, aRMin2, aRMaj1, aRMaj2;
2571 aRMin1 = Tor1.MinorRadius();
2572 aRMaj1 = Tor1.MajorRadius();
2573 aRMin2 = Tor2.MinorRadius();
2574 aRMaj2 = Tor2.MajorRadius();
2576 const gp_Ax1& anAx1 = Tor1.Axis();
2577 const gp_Ax1& anAx2 = Tor2.Axis();
2579 const gp_Pnt& aLoc1 = anAx1.Location();
2580 const gp_Pnt& aLoc2 = anAx2.Location();
2583 if (!anAx1.IsParallel(anAx2, myEPSILON_AXES_PARA) ||
2584 (aL1.Distance(aLoc2) > myEPSILON_DISTANCE)) {
2585 typeres = IntAna_NoGeometricSolution;
2589 if (aLoc1.IsEqual(aLoc2, Tol) &&
2590 (Abs(aRMin1 - aRMin2) <= Tol) &&
2591 (Abs(aRMaj1 - aRMaj2) <= Tol)) {
2592 typeres = IntAna_Same;
2596 if (aRMin1 >= aRMaj1 || aRMin2 >= aRMaj2) {
2597 typeres = IntAna_NoGeometricSolution;
2601 Standard_Real aDist;
2604 gp_Dir aXDir1 = Tor1.XAxis().Direction();
2605 aP1.SetXYZ(aLoc1.XYZ() + aRMaj1*aXDir1.XYZ());
2606 aP2.SetXYZ(aLoc2.XYZ() + aRMaj2*aXDir1.XYZ());
2608 gp_Vec aV12(aP1, aP2);
2609 aDist = aV12.Magnitude();
2610 if (((aDist - Tol) > (aRMin1 + aRMin2)) ||
2611 ((aDist + Tol) < Abs(aRMin1 - aRMin2))) {
2612 typeres = IntAna_Empty;
2616 typeres = IntAna_Circle;
2618 Standard_Real anAlpha, aBeta;
2620 anAlpha = 0.5*(aRMin1*aRMin1 - aRMin2*aRMin2 + aDist*aDist ) / aDist;
2621 aBeta = Sqrt(Abs(aRMin1*aRMin1 - anAlpha*anAlpha));
2623 gp_Dir aDir12(aV12);
2624 gp_XYZ aPh = aP1.XYZ() + anAlpha*aDir12.XYZ();
2625 gp_Dir aDC = Tor1.YAxis().Direction()^aDir12;
2628 gp_XYZ aDVal = aBeta*aDC.XYZ();
2629 aP.SetXYZ(aPh + aDVal);
2630 param1 = aL1.Distance(aP);
2631 pt1.SetXYZ(aP.XYZ() - param1*aXDir1.XYZ());
2632 dir1 = anAx1.Direction();
2634 if ((aDist < (aRMin1 + aRMin2)) && (aDist > Abs(aRMin1 - aRMin2)) &&
2635 aDVal.Modulus() > Tol) {
2636 aP.SetXYZ(aPh - aDVal);
2637 param2 = aL1.Distance(aP);
2638 pt2.SetXYZ(aP.XYZ() - param2*aXDir1.XYZ());
2644 //=======================================================================
2646 //purpose : Returns a Point
2647 //=======================================================================
2648 gp_Pnt IntAna_QuadQuadGeo::Point(const Standard_Integer n) const
2650 if(!done) { throw StdFail_NotDone(); }
2651 if(n>nbint || n<1) { throw Standard_DomainError(); }
2652 if(typeres==IntAna_PointAndCircle) {
2653 if(n!=1) { throw Standard_DomainError(); }
2654 if(param1==0.0) return(pt1);
2657 else if(typeres==IntAna_Point) {
2658 if(n==1) return(pt1);
2662 // WNT (what can you expect from MicroSoft ?)
2663 return gp_Pnt(0,0,0);
2665 //=======================================================================
2667 //purpose : Returns a Line
2668 //=======================================================================
2669 gp_Lin IntAna_QuadQuadGeo::Line(const Standard_Integer n) const
2671 if(!done) { throw StdFail_NotDone(); }
2672 if((n>nbint) || (n<1) || (typeres!=IntAna_Line)) {
2673 throw Standard_DomainError();
2675 if(n==1) { return(gp_Lin(pt1,dir1)); }
2676 else { return(gp_Lin(pt2,dir2)); }
2678 //=======================================================================
2680 //purpose : Returns a Circle
2681 //=======================================================================
2682 gp_Circ IntAna_QuadQuadGeo::Circle(const Standard_Integer n) const
2684 if(!done) { throw StdFail_NotDone(); }
2685 if(typeres==IntAna_PointAndCircle) {
2686 if(n!=1) { throw Standard_DomainError(); }
2687 if(param2==0.0) return(gp_Circ(DirToAx2(pt1,dir1),param1));
2688 return(gp_Circ(DirToAx2(pt2,dir2),param2));
2690 else if((n>nbint) || (n<1) || (typeres!=IntAna_Circle)) {
2691 throw Standard_DomainError();
2693 if (n==1) { return(gp_Circ(DirToAx2(pt1,dir1),param1));}
2694 else if (n==2) { return(gp_Circ(DirToAx2(pt2,dir2),param2));}
2695 else if (n==3) { return(gp_Circ(DirToAx2(pt3,dir3),param3));}
2696 else { return(gp_Circ(DirToAx2(pt4,dir4),param4));}
2699 //=======================================================================
2700 //function : Ellipse
2701 //purpose : Returns a Elips
2702 //=======================================================================
2703 gp_Elips IntAna_QuadQuadGeo::Ellipse(const Standard_Integer n) const
2705 if(!done) { throw StdFail_NotDone(); }
2706 if((n>nbint) || (n<1) || (typeres!=IntAna_Ellipse)) {
2707 throw Standard_DomainError();
2711 Standard_Real R1=param1, R2=param1bis, aTmp;
2713 aTmp=R1; R1=R2; R2=aTmp;
2715 gp_Ax2 anAx2(pt1, dir1 ,dir2);
2716 gp_Elips anElips (anAx2, R1, R2);
2720 Standard_Real R1=param2, R2=param2bis, aTmp;
2722 aTmp=R1; R1=R2; R2=aTmp;
2724 gp_Ax2 anAx2(pt2, dir2 ,dir1);
2725 gp_Elips anElips (anAx2, R1, R2);
2729 //=======================================================================
2730 //function : Parabola
2731 //purpose : Returns a Parabola
2732 //=======================================================================
2733 gp_Parab IntAna_QuadQuadGeo::Parabola(const Standard_Integer n) const
2736 throw StdFail_NotDone();
2738 if (typeres!=IntAna_Parabola) {
2739 throw Standard_DomainError();
2741 if((n>nbint) || (n!=1)) {
2742 throw Standard_OutOfRange();
2744 return(gp_Parab(gp_Ax2( pt1
2749 //=======================================================================
2750 //function : Hyperbola
2751 //purpose : Returns a Hyperbola
2752 //=======================================================================
2753 gp_Hypr IntAna_QuadQuadGeo::Hyperbola(const Standard_Integer n) const
2756 throw StdFail_NotDone();
2758 if((n>nbint) || (n<1) || (typeres!=IntAna_Hyperbola)) {
2759 throw Standard_DomainError();
2762 return(gp_Hypr(gp_Ax2( pt1
2765 ,param1,param1bis));
2768 return(gp_Hypr(gp_Ax2( pt2
2771 ,param2,param2bis));
2774 //=======================================================================
2775 //function : HasCommonGen
2777 //=======================================================================
2778 Standard_Boolean IntAna_QuadQuadGeo::HasCommonGen() const
2782 //=======================================================================
2785 //=======================================================================
2786 const gp_Pnt& IntAna_QuadQuadGeo::PChar() const
2790 //=======================================================================
2791 //function : RefineDir
2793 //=======================================================================
2794 void RefineDir(gp_Dir& aDir)
2796 Standard_Integer k, m, n;
2797 Standard_Real aC[3];
2799 aDir.Coord(aC[0], aC[1], aC[2]);
2803 for (k=0; k<3; ++k) {
2804 if (aC[k]==1. || aC[k]==-1.) {
2807 else if (aC[k]!=0.) {
2813 Standard_Real aEps, aR1, aR2, aNum;
2819 for (k=0; k<3; ++k) {
2821 aNum=(m)? aC[k] : -aC[k];
2822 if (aNum>aR1 && aNum<aR2) {
2835 aDir.SetCoord(aC[0], aC[1], aC[2]);