1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <Geom2dGcc_Circ2d2TanRadGeo.ixx>
18 #include <gp_Ax2d.hxx>
19 #include <gp_Circ2d.hxx>
20 #include <gp_Lin2d.hxx>
21 #include <Standard_NegativeValue.hxx>
22 #include <Standard_OutOfRange.hxx>
23 #include <StdFail_NotDone.hxx>
24 #include <TColStd_Array1OfReal.hxx>
25 #include <GccEnt_BadQualifier.hxx>
26 #include <IntRes2d_Domain.hxx>
27 #include <IntRes2d_IntersectionPoint.hxx>
29 #include <Geom2dGcc_CurveTool.hxx>
30 #include <Adaptor3d_OffsetCurve.hxx>
31 #include <Geom2dAdaptor_HCurve.hxx>
32 #include <Geom2dGcc_CurveToolGeo.hxx>
33 #include <Geom2dInt_GInter.hxx>
35 static const Standard_Integer aNbSolMAX = 16;
37 // circulaire tant a une courbe et une droite ,de rayon donne
38 //==============================================================
40 //========================================================================
41 // On initialise WellDone a false. +
42 // On recupere la courbe Cu2 et la droite L1. +
43 // On sort en erreur dans les cas ou la construction est impossible. +
44 // On fait la parallele a Cu2 dans le bon sens. +
45 // On fait la parallele a L1 dans le bon sens. +
46 // On intersecte les paralleles ==> point de centre de la solution. +
47 // On cree la solution qu on ajoute aux solutions deja trouvees. +
48 // On remplit les champs. +
49 //========================================================================
51 Geom2dGcc_Circ2d2TanRadGeo::
52 Geom2dGcc_Circ2d2TanRadGeo (const GccEnt_QualifiedLin& Qualified1,
53 const Geom2dGcc_QCurve& Qualified2,
54 const Standard_Real Radius ,
55 const Standard_Real Tolerance ):
57 //========================================================================
58 // initialisation des champs. +
59 //========================================================================
62 qualifier1(1,aNbSolMAX),
63 qualifier2(1,aNbSolMAX),
64 TheSame1(1,aNbSolMAX) ,
65 TheSame2(1,aNbSolMAX) ,
66 pnttg1sol(1,aNbSolMAX),
67 pnttg2sol(1,aNbSolMAX),
68 par1sol(1,aNbSolMAX) ,
69 par2sol(1,aNbSolMAX) ,
70 pararg1(1,aNbSolMAX) ,
74 //========================================================================
76 //========================================================================
78 Standard_Real Tol = Abs(Tolerance);
79 Standard_Real thefirst = -100000.;
80 Standard_Real thelast = 100000.;
81 Standard_Real firstparam;
82 Standard_Real lastparam;
84 TColStd_Array1OfReal cote1(1,2);
85 TColStd_Array1OfReal cote2(1,2);
86 Standard_Integer nbrcote1=0;
87 Standard_Integer nbrcote2=0;
88 WellDone = Standard_False;
90 if (!(Qualified1.IsEnclosed() ||
91 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
92 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
93 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
95 GccEnt_BadQualifier::Raise();
98 gp_Lin2d L1 = Qualified1.Qualified();
99 Standard_Real x1dir = (L1.Direction()).X();
100 Standard_Real y1dir = (L1.Direction()).Y();
101 Standard_Real lxloc = (L1.Location()).X();
102 Standard_Real lyloc = (L1.Location()).Y();
103 gp_Pnt2d origin1(lxloc,lyloc);
104 gp_Dir2d normL1(-y1dir,x1dir);
105 Geom2dAdaptor_Curve Cu2= Qualified2.Qualified();
106 if (Radius < 0.0) { Standard_NegativeValue::Raise(); }
108 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
109 // =======================================================
115 else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
116 // ==========================================================
122 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
123 // ===========================================================
129 else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
130 // =========================================================
136 if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
137 // =========================================================
144 if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
145 // =========================================================
152 else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
153 // =============================================================
160 if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
161 // ========================================================
168 else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
169 // =================================================================
177 gp_Dir2d Dir(-y1dir,x1dir);
178 for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
179 gp_Pnt2d Point(L1.Location().XY()+cote1(jcote1)*Dir.XY());
180 gp_Lin2d Line(Point,L1.Direction()); // ligne avec deport.
182 for (Standard_Integer jcote2 = 1 ; jcote2 <= nbrcote2 ; jcote2++) {
183 Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
184 Adaptor3d_OffsetCurve C2(HCu2,cote2(jcote2));
185 firstparam = Max(Geom2dGcc_CurveToolGeo::FirstParameter(C2),thefirst);
186 lastparam = Min(Geom2dGcc_CurveToolGeo::LastParameter(C2),thelast);
187 IntRes2d_Domain D2(Geom2dGcc_CurveToolGeo::Value(C2,firstparam),firstparam,Tol,
188 Geom2dGcc_CurveToolGeo::Value(C2,lastparam),lastparam,Tol);
189 Geom2dInt_TheIntConicCurveOfGInter Intp(Line,D1,C2,D2,Tol,Tol);
191 if (!Intp.IsEmpty()) {
192 for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
194 gp_Pnt2d Center(Intp.Point(i).Value());
195 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
196 // =======================================================
197 gp_Dir2d dc1(origin1.XY()-Center.XY());
198 qualifier2(NbrSol) = Qualified2.Qualifier();
199 if (!Qualified1.IsUnqualified()) {
200 qualifier1(NbrSol) = Qualified1.Qualifier();
202 else if (dc1.Dot(normL1) > 0.0) {
203 qualifier1(NbrSol) = GccEnt_outside;
205 else { qualifier1(NbrSol) = GccEnt_enclosed; }
206 TheSame1(NbrSol) = 0;
207 TheSame2(NbrSol) = 0;
208 pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
209 pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
210 pnttg1sol(NbrSol) = ElCLib::Value(pararg1(NbrSol),L1);
211 pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
212 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
214 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
218 WellDone = Standard_True;
225 // circulaire tant a une courbe et un cercle ,de rayon donne
226 //=============================================================
228 //========================================================================
229 // On initialise WellDone a false. +
230 // On recupere la courbe Cu2 et le cercle C1. +
231 // On sort en erreur dans les cas ou la construction est impossible. +
232 // On fait la parallele a Cu2 dans le bon sens. +
233 // On fait la parallele a C1 dans le bon sens. +
234 // On intersecte les paralleles ==> point de centre de la solution. +
235 // On cree la solution qu on ajoute aux solutions deja trouvees. +
236 // On remplit les champs. +
237 //========================================================================
239 Geom2dGcc_Circ2d2TanRadGeo::
240 Geom2dGcc_Circ2d2TanRadGeo (const GccEnt_QualifiedCirc& Qualified1,
241 const Geom2dGcc_QCurve& Qualified2,
242 const Standard_Real Radius ,
243 const Standard_Real Tolerance ):
245 //========================================================================
246 // initialisation des champs. +
247 //========================================================================
249 cirsol(1,aNbSolMAX) ,
250 qualifier1(1,aNbSolMAX),
251 qualifier2(1,aNbSolMAX),
252 TheSame1(1,aNbSolMAX) ,
253 TheSame2(1,aNbSolMAX) ,
254 pnttg1sol(1,aNbSolMAX),
255 pnttg2sol(1,aNbSolMAX),
256 par1sol(1,aNbSolMAX) ,
257 par2sol(1,aNbSolMAX) ,
258 pararg1(1,aNbSolMAX) ,
262 //========================================================================
264 //========================================================================
266 Standard_Real Tol = Abs(Tolerance);
267 Standard_Real thefirst = -100000.;
268 Standard_Real thelast = 100000.;
269 Standard_Real firstparam;
270 Standard_Real lastparam;
271 gp_Dir2d dirx(1.,0.);
272 TColStd_Array1OfReal cote1(1,2);
273 TColStd_Array1OfReal cote2(1,2);
274 Standard_Integer nbrcote1=0;
275 Standard_Integer nbrcote2=0;
276 WellDone = Standard_False;
278 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
279 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
280 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
281 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
282 GccEnt_BadQualifier::Raise();
285 gp_Circ2d C1 = Qualified1.Qualified();
286 gp_Pnt2d center1(C1.Location());
287 Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
288 if (Radius < 0.0) { Standard_NegativeValue::Raise(); }
290 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
291 // =======================================================
297 else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
298 // ==========================================================
304 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
305 // ===========================================================
311 else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
312 // =========================================================
318 if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
319 // =========================================================
326 if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
327 // =========================================================
334 else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
335 // =============================================================
342 if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
343 // ========================================================
350 else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
351 // =================================================================
359 Standard_Real R1 = C1.Radius();
360 Geom2dInt_TheIntConicCurveOfGInter Intp;
361 for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
362 gp_Circ2d Circ(C1.XAxis(),R1+cote1(jcote1));
363 IntRes2d_Domain D1(ElCLib::Value(0.,Circ), 0.,Tol,
364 ElCLib::Value(2.*M_PI,Circ),2.*M_PI,Tol);
365 D1.SetEquivalentParameters(0.,2.*M_PI);
366 for (Standard_Integer jcote2 = 1 ; jcote2 <= nbrcote2 ; jcote2++) {
367 Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
368 Adaptor3d_OffsetCurve C2(HCu2,cote2(jcote2));
369 firstparam = Max(Geom2dGcc_CurveToolGeo::FirstParameter(C2),thefirst);
370 lastparam = Min(Geom2dGcc_CurveToolGeo::LastParameter(C2),thelast);
371 IntRes2d_Domain D2(Geom2dGcc_CurveToolGeo::Value(C2,firstparam),firstparam,Tol,
372 Geom2dGcc_CurveToolGeo::Value(C2,lastparam),lastparam,Tol);
373 Intp.Perform(Circ,D1,C2,D2,Tol,Tol);
375 if (!Intp.IsEmpty()) {
376 for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
378 gp_Pnt2d Center(Intp.Point(i).Value());
379 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
380 // =======================================================
382 gp_Dir2d dir1(Center.XY()-center1.XY());
387 Standard_Real distcc1 = Center.Distance(center1);
388 if (!Qualified1.IsUnqualified()) {
389 qualifier1(NbrSol) = Qualified1.Qualifier();
391 else if (Abs(distcc1+Radius-R1) < Tol) {
392 qualifier1(NbrSol) = GccEnt_enclosed;
394 else if (Abs(distcc1-R1-Radius) < Tol) {
395 qualifier1(NbrSol) = GccEnt_outside;
397 else { qualifier1(NbrSol) = GccEnt_enclosing; }
398 qualifier2(NbrSol) = Qualified2.Qualifier();
399 TheSame1(NbrSol) = 0;
400 TheSame2(NbrSol) = 0;
401 pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
402 pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
403 pnttg1sol(NbrSol) = ElCLib::Value(pararg1(NbrSol),C1);
404 pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
405 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
407 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
411 WellDone = Standard_True;
418 // circulaire tant a une courbe et un point ,de rayon donne
419 //============================================================
421 //========================================================================
422 // On initialise WellDone a false. +
423 // On recupere la courbe Cu1 et le point P2. +
424 // On sort en erreur dans les cas ou la construction est impossible. +
425 // On fait la parallele a Cu1 dans le bon sens. +
426 // On fait la parallele a P2 dans le bon sens. +
427 // On intersecte les paralleles ==> point de centre de la solution. +
428 // On cree la solution qu on ajoute aux solutions deja trouvees. +
429 // On remplit les champs. +
430 //========================================================================
432 Geom2dGcc_Circ2d2TanRadGeo::
433 Geom2dGcc_Circ2d2TanRadGeo (const Geom2dGcc_QCurve& Qualified1,
434 const gp_Pnt2d& Point2 ,
435 const Standard_Real Radius ,
436 const Standard_Real Tolerance ):
438 //========================================================================
439 // initialisation des champs. +
440 //========================================================================
442 cirsol(1,aNbSolMAX) ,
443 qualifier1(1,aNbSolMAX),
444 qualifier2(1,aNbSolMAX),
445 TheSame1(1,aNbSolMAX) ,
446 TheSame2(1,aNbSolMAX) ,
447 pnttg1sol(1,aNbSolMAX),
448 pnttg2sol(1,aNbSolMAX),
449 par1sol(1,aNbSolMAX) ,
450 par2sol(1,aNbSolMAX) ,
451 pararg1(1,aNbSolMAX) ,
455 //========================================================================
457 //========================================================================
459 Standard_Real Tol = Abs(Tolerance);
460 Standard_Real thefirst = -100000.;
461 Standard_Real thelast = 100000.;
462 Standard_Real firstparam;
463 Standard_Real lastparam;
464 gp_Dir2d dirx(1.,0.);
465 TColStd_Array1OfReal cote1(1,2);
466 Standard_Integer nbrcote1=0;
467 WellDone = Standard_False;
469 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
470 Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
471 GccEnt_BadQualifier::Raise();
474 Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
475 if (Radius < 0.0) { Standard_NegativeValue::Raise(); }
477 if (Qualified1.IsEnclosed()) {
478 // ===========================
482 else if(Qualified1.IsOutside()) {
483 // ===============================
487 else if(Qualified1.IsUnqualified()) {
488 // ===================================
493 gp_Circ2d Circ(gp_Ax2d(Point2,gp_Dir2d(1.,0.)),Radius);
494 IntRes2d_Domain D1(ElCLib::Value(0.,Circ), 0.,Tol,
495 ElCLib::Value(M_PI+M_PI,Circ),M_PI+M_PI,Tol);
496 D1.SetEquivalentParameters(0.,M_PI+M_PI);
497 Geom2dInt_TheIntConicCurveOfGInter Intp;
498 for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
499 Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1);
500 Adaptor3d_OffsetCurve Cu2(HCu1,cote1(jcote1));
501 firstparam = Max(Geom2dGcc_CurveToolGeo::FirstParameter(Cu2),thefirst);
502 lastparam = Min(Geom2dGcc_CurveToolGeo::LastParameter(Cu2),thelast);
503 IntRes2d_Domain D2(Geom2dGcc_CurveToolGeo::Value(Cu2,firstparam),firstparam,Tol,
504 Geom2dGcc_CurveToolGeo::Value(Cu2,lastparam),lastparam,Tol);
505 Intp.Perform(Circ,D1,Cu2,D2,Tol,Tol);
507 if (!Intp.IsEmpty()) {
508 for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++) {
510 gp_Pnt2d Center(Intp.Point(i).Value());
511 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
512 // =======================================================
513 qualifier1(NbrSol) = Qualified1.Qualifier();
514 qualifier2(NbrSol) = GccEnt_noqualifier;
515 TheSame1(NbrSol) = 0;
516 TheSame2(NbrSol) = 0;
517 pararg1(NbrSol) = Intp.Point(i).ParamOnSecond();
518 pararg2(NbrSol) = 0.;
519 pnttg1sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol));
520 pnttg2sol(NbrSol) = Point2;
521 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
523 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
527 WellDone = Standard_True;
533 //=======================================================================
534 //function : PrecRoot
535 //purpose : In case, when curves has tangent zones, intersection point
536 // found may be precised. This function uses precision algorithm
537 // of Extrema Curve-Curve method (dot product between every
538 // tangent vector and vector between points in two curves must
539 // be equal to zero).
540 //=======================================================================
541 static void PrecRoot(const Adaptor3d_OffsetCurve& theC1,
542 const Adaptor3d_OffsetCurve& theC2,
543 const Standard_Real theU0,
544 const Standard_Real theV0,
545 Standard_Real& theUfinal,
546 Standard_Real& theVfinal)
549 It is necessary for precision to solve the system
551 \left\{\begin{matrix}
552 (x_{1}(u)-x_{2}(v))*{x_{1}(u)}'+(y_{1}(u)-y_{2}(v))*{y_{1}(u)}'=0\\
553 (x_{1}(u)-x_{2}(v))*{x_{2}(v)}'+(y_{1}(u)-y_{2}(v))*{y_{2}(v)}'=0
556 Precision of any 2*2-system (two equation and two variables)
558 \left\{\begin{matrix}
563 by Newton method can be made as follows:
565 u=u_{0}-\left (\frac{\frac{\partial S_{2}}{\partial v}*S_{1}-
566 \frac{\partial S_{1}}{\partial v}*S_{2}}
567 {\frac{\partial S_{1}}{\partial u}*
568 \frac{\partial S_{2}}{\partial v}-
569 \frac{\partial S_{1}}{\partial v}*
570 \frac{\partial S_{2}}{\partial u}} \right )_{u_{0},v_{0}}\\
571 v=v_{0}-\left (\frac{\frac{\partial S_{1}}{\partial u}*S_{2}-
572 \frac{\partial S_{2}}{\partial u}*S_{1}}
573 {\frac{\partial S_{1}}{\partial u}*
574 \frac{\partial S_{2}}{\partial v}-
575 \frac{\partial S_{1}}{\partial v}*
576 \frac{\partial S_{2}}{\partial u}} \right )_{u_{0},v_{0}}
579 where u_{0} and v_{0} are initial values or values computed on previous iteration.
585 const Standard_Integer aNbIterMax = 100;
587 Standard_Real aU = theU0, aV = theV0;
589 gp_Vec2d aD1u, aD1v, aD2u, aD2v;
591 Standard_Integer aNbIter = 0;
593 Standard_Real aStepU = 0.0, aStepV = 0.0;
595 Standard_Real aSQDistPrev = RealFirst();
597 Geom2dGcc_CurveToolGeo::D2(theC1, aU, aPu, aD1u, aD2u);
598 Geom2dGcc_CurveToolGeo::D2(theC2, aV, aPv, aD1v, aD2v);
600 const Standard_Real aCrProd = Abs(aD1u.Crossed(aD1v));
601 if(aCrProd*aCrProd > 1.0e-6*
602 aD1u.SquareMagnitude()*aD1v.SquareMagnitude())
604 //Curves are not tangent. Therefore, we consider that
605 //2D-intersection algorithm have found good point which
606 //did not need in more precision.
614 gp_Vec2d aVuv(aPv, aPu);
616 Standard_Real aSQDist = aVuv.SquareMagnitude();
617 if(IsEqual(aSQDist, 0.0))
620 if((aNbIter == 1) || (aSQDist < aSQDistPrev))
622 aSQDistPrev = aSQDist;
628 Standard_Real aG1 = aD1u.Magnitude();
629 Standard_Real aG2 = aD1v.Magnitude();
631 if(IsEqual(aG1, 0.0) || IsEqual(aG2, 0.0))
632 {//Here we do not processing singular cases.
636 Standard_Real aF1 = aVuv.Dot(aD1u);
637 Standard_Real aF2 = aVuv.Dot(aD1v);
639 Standard_Real aFIu = aVuv.Dot(aD2u);
640 Standard_Real aFIv = aVuv.Dot(aD2v);
641 Standard_Real aPSIu = aD1u.Dot(aD2u);
642 Standard_Real aPSIv = aD1v.Dot(aD2v);
644 Standard_Real aTheta = aD1u*aD1v;
646 Standard_Real aS1 = aF1/aG1;
647 Standard_Real aS2 = aF2/aG2;
649 Standard_Real aDS1u = (aG1*aG1+aFIu)/aG1 - (aS1*aPSIu/(aG1*aG1));
650 Standard_Real aDS1v = -aTheta/aG1;
651 Standard_Real aDS2u = aTheta/aG2;
652 Standard_Real aDS2v = (aFIv-aG2*aG2)/aG2 - (aS2*aPSIv/(aG2*aG2));
654 Standard_Real aDet = aDS1u*aDS2v-aDS1v*aDS2u;
656 if(IsEqual(aDet, 0.0))
658 if(!IsEqual(aStepV, 0.0) && !IsEqual(aDS1u, 0.0))
661 aU = aU - (aDS1v*aStepV - aS1)/aDS1u;
663 else if(!IsEqual(aStepU, 0.0) && !IsEqual(aDS1v, 0.0))
666 aV = aV - (aDS1u*aStepU - aS1)/aDS1v;
675 aStepU = -(aS1*aDS2v-aS2*aDS1v)/aDet;
676 aStepV = -(aS2*aDS1u-aS1*aDS2u)/aDet;
678 if(Abs(aStepU) < Epsilon(Abs(aU)))
680 if(Abs(aStepV) < Epsilon(Abs(aV)))
690 Geom2dGcc_CurveToolGeo::D2(theC1, aU, aPu, aD1u, aD2u);
691 Geom2dGcc_CurveToolGeo::D2(theC2, aV, aPv, aD1v, aD2v);
693 while(aNbIter <= aNbIterMax);
698 // circulaire tant a deux courbes ,de rayon donne
699 //==================================================
701 //========================================================================
702 // On initialise WellDone a false. +
703 // On recupere les courbes Cu1 et Cu2. +
704 // On sort en erreur dans les cas ou la construction est impossible. +
705 // On fait la parallele a Cu1 dans le bon sens. +
706 // On fait la parallele a Cu2 dans le bon sens. +
707 // On intersecte les paralleles ==> point de centre de la solution. +
708 // On cree la solution qu on ajoute aux solutions deja trouvees. +
709 // On remplit les champs. +
710 //========================================================================
711 Geom2dGcc_Circ2d2TanRadGeo::
712 Geom2dGcc_Circ2d2TanRadGeo (const Geom2dGcc_QCurve& Qualified1,
713 const Geom2dGcc_QCurve& Qualified2,
714 const Standard_Real Radius ,
715 const Standard_Real Tolerance ):
717 //========================================================================
718 // initialisation des champs. +
719 //========================================================================
721 cirsol(1,aNbSolMAX) ,
722 qualifier1(1,aNbSolMAX),
723 qualifier2(1,aNbSolMAX),
724 TheSame1(1,aNbSolMAX) ,
725 TheSame2(1,aNbSolMAX) ,
726 pnttg1sol(1,aNbSolMAX),
727 pnttg2sol(1,aNbSolMAX),
728 par1sol(1,aNbSolMAX) ,
729 par2sol(1,aNbSolMAX) ,
730 pararg1(1,aNbSolMAX) ,
734 //========================================================================
736 //========================================================================
738 Standard_Real Tol = Abs(Tolerance);
739 Standard_Real thefirst = -100000.;
740 Standard_Real thelast = 100000.;
741 Standard_Real firstparam;
742 Standard_Real lastparam;
743 gp_Dir2d dirx(1.,0.);
744 TColStd_Array1OfReal cote1(1,2);
745 TColStd_Array1OfReal cote2(1,2);
746 Standard_Integer nbrcote1=0;
747 Standard_Integer nbrcote2=0;
748 WellDone = Standard_False;
750 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
751 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
752 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
753 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
754 GccEnt_BadQualifier::Raise();
757 Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
758 Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
759 if (Radius < 0.0) { Standard_NegativeValue::Raise(); }
761 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
762 // =======================================================
768 else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
769 // ==========================================================
775 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
776 // ===========================================================
782 else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
783 // =========================================================
789 if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
790 // =========================================================
797 if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
798 // =========================================================
805 else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
806 // =============================================================
813 if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
814 // ========================================================
821 else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
822 // =================================================================
830 Geom2dInt_GInter Intp;
831 for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
832 Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1);
833 Adaptor3d_OffsetCurve C1(HCu1,cote1(jcote1));
834 firstparam = Max(Geom2dGcc_CurveToolGeo::FirstParameter(C1),thefirst);
835 lastparam = Min(Geom2dGcc_CurveToolGeo::LastParameter(C1),thelast);
837 IntRes2d_Domain D2(Geom2dGcc_CurveToolGeo::Value(C1,firstparam),firstparam,Tol,
838 Geom2dGcc_CurveToolGeo::Value(C1,lastparam),lastparam,Tol);
840 Geom2dGcc_CurveToolGeo::Value(C1,firstparam);
841 Geom2dGcc_CurveToolGeo::Value(C1,lastparam);
843 for (Standard_Integer jcote2 = 1 ; jcote2 <= nbrcote2 ; jcote2++) {
844 Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
845 Adaptor3d_OffsetCurve C2(HCu2,cote2(jcote2));
846 firstparam = Max(Geom2dGcc_CurveToolGeo::FirstParameter(C2),thefirst);
847 lastparam = Min(Geom2dGcc_CurveToolGeo::LastParameter(C2),thelast);
849 IntRes2d_Domain D2(Geom2dGcc_CurveToolGeo::Value(C2,firstparam),firstparam,Tol,
850 Geom2dGcc_CurveToolGeo::Value(C2,lastparam),lastparam,Tol);
852 Geom2dGcc_CurveToolGeo::Value(C2,firstparam);
853 Geom2dGcc_CurveToolGeo::Value(C2,lastparam);
855 Intp.Perform(C1,C2,Tol,Tol);
857 if (!Intp.IsEmpty()) {
858 const Standard_Real aSQApproxTol = Precision::Approximation() *
859 Precision::Approximation();
860 for (Standard_Integer i = 1 ; i <= Intp.NbPoints() ; i++)
862 Standard_Real aU0 = Intp.Point(i).ParamOnFirst();
863 Standard_Real aV0 = Intp.Point(i).ParamOnSecond();
865 Standard_Real aU1 = aU0-Precision::PApproximation();
866 Standard_Real aV1 = aV0-Precision::PApproximation();
868 Standard_Real aU2 = aU0+Precision::PApproximation();
869 Standard_Real aV2 = aV0+Precision::PApproximation();
871 gp_Pnt2d P11 = Geom2dGcc_CurveToolGeo::Value(C1,aU1);
872 gp_Pnt2d P12 = Geom2dGcc_CurveToolGeo::Value(C2,aV1);
873 gp_Pnt2d P21 = Geom2dGcc_CurveToolGeo::Value(C1,aU2);
874 gp_Pnt2d P22 = Geom2dGcc_CurveToolGeo::Value(C2,aV2);
876 Standard_Real aDist1112 = P11.SquareDistance(P12);
877 Standard_Real aDist1122 = P11.SquareDistance(P22);
879 Standard_Real aDist1221 = P12.SquareDistance(P21);
880 Standard_Real aDist2122 = P21.SquareDistance(P22);
882 if( (Min(aDist1112, aDist1122) <= aSQApproxTol) &&
883 (Min(aDist1221, aDist2122) <= aSQApproxTol))
885 PrecRoot(C1, C2, aU0, aV0, aU0, aV0);
889 gp_Pnt2d Center(Geom2dGcc_CurveToolGeo::Value(C1, aU0));
890 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
891 // =======================================================
892 qualifier1(NbrSol) = Qualified1.Qualifier();
893 qualifier1(NbrSol) = Qualified1.Qualifier();
894 TheSame1(NbrSol) = 0;
895 TheSame2(NbrSol) = 0;
896 pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
897 pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
898 pnttg1sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol));
899 pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
900 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
902 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
907 WellDone = Standard_True;
914 //=========================================================================
916 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
917 IsDone () const { return WellDone; }
919 Standard_Integer Geom2dGcc_Circ2d2TanRadGeo::
920 NbSolutions () const { return NbrSol; }
922 gp_Circ2d Geom2dGcc_Circ2d2TanRadGeo::
923 ThisSolution (const Standard_Integer Index) const
925 if (!WellDone) { StdFail_NotDone::Raise(); }
926 if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
927 return cirsol(Index);
930 void Geom2dGcc_Circ2d2TanRadGeo::
931 WhichQualifier(const Standard_Integer Index ,
932 GccEnt_Position& Qualif1 ,
933 GccEnt_Position& Qualif2 ) const
935 if (!WellDone) { StdFail_NotDone::Raise(); }
936 else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
938 Qualif1 = qualifier1(Index);
939 Qualif2 = qualifier2(Index);
943 void Geom2dGcc_Circ2d2TanRadGeo::
944 Tangency1 (const Standard_Integer Index,
945 Standard_Real& ParSol,
946 Standard_Real& ParArg,
947 gp_Pnt2d& PntSol) const{
948 if (!WellDone) { StdFail_NotDone::Raise(); }
949 else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
951 if (TheSame1(Index) == 0) {
952 ParSol = par1sol(Index);
953 ParArg = pararg1(Index);
954 PntSol = gp_Pnt2d(pnttg1sol(Index));
956 else { StdFail_NotDone::Raise(); }
960 void Geom2dGcc_Circ2d2TanRadGeo::
961 Tangency2 (const Standard_Integer Index,
962 Standard_Real& ParSol,
963 Standard_Real& ParArg,
964 gp_Pnt2d& PntSol) const{
965 if (!WellDone) { StdFail_NotDone::Raise(); }
966 else if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
968 if (TheSame2(Index) == 0) {
969 ParSol = par2sol(Index);
970 ParArg = pararg2(Index);
971 PntSol = gp_Pnt2d(pnttg2sol(Index));
973 else { StdFail_NotDone::Raise(); }
977 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
978 IsTheSame1 (const Standard_Integer Index) const
980 if (!WellDone) { StdFail_NotDone::Raise(); }
981 if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
983 if (TheSame1(Index) == 0) { return Standard_False; }
984 return Standard_True;
987 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
988 IsTheSame2 (const Standard_Integer Index) const
990 if (!WellDone) { StdFail_NotDone::Raise(); }
991 if (Index <= 0 ||Index > NbrSol) { Standard_OutOfRange::Raise(); }
993 if (TheSame2(Index) == 0) { return Standard_False; }
994 return Standard_True;