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.
16 #include <Adaptor2d_OffsetCurve.hxx>
18 #include <GccEnt_BadQualifier.hxx>
19 #include <GccEnt_QualifiedCirc.hxx>
20 #include <GccEnt_QualifiedLin.hxx>
21 #include <Geom2dGcc_Circ2d2TanRadGeo.hxx>
22 #include <Geom2dGcc_CurveTool.hxx>
23 #include <Geom2dGcc_QCurve.hxx>
24 #include <Geom2dInt_GInter.hxx>
25 #include <gp_Ax2d.hxx>
26 #include <gp_Circ2d.hxx>
27 #include <gp_Lin2d.hxx>
28 #include <gp_Pnt2d.hxx>
29 #include <IntRes2d_Domain.hxx>
30 #include <IntRes2d_IntersectionPoint.hxx>
31 #include <Standard_NegativeValue.hxx>
32 #include <Standard_OutOfRange.hxx>
33 #include <StdFail_NotDone.hxx>
34 #include <TColStd_Array1OfReal.hxx>
36 static const Standard_Integer aNbSolMAX = 16;
38 // circulaire tant a une courbe et une droite ,de rayon donne
39 //==============================================================
41 //========================================================================
42 // On initialise WellDone a false. +
43 // On recupere la courbe Cu2 et la droite L1. +
44 // On sort en erreur dans les cas ou la construction est impossible. +
45 // On fait la parallele a Cu2 dans le bon sens. +
46 // On fait la parallele a L1 dans le bon sens. +
47 // On intersecte les paralleles ==> point de centre de la solution. +
48 // On cree la solution qu on ajoute aux solutions deja trouvees. +
49 // On remplit les champs. +
50 //========================================================================
52 Geom2dGcc_Circ2d2TanRadGeo::
53 Geom2dGcc_Circ2d2TanRadGeo (const GccEnt_QualifiedLin& Qualified1,
54 const Geom2dGcc_QCurve& Qualified2,
55 const Standard_Real Radius ,
56 const Standard_Real Tolerance ):
58 //========================================================================
59 // initialisation des champs. +
60 //========================================================================
63 qualifier1(1,aNbSolMAX),
64 qualifier2(1,aNbSolMAX),
65 TheSame1(1,aNbSolMAX) ,
66 TheSame2(1,aNbSolMAX) ,
67 pnttg1sol(1,aNbSolMAX),
68 pnttg2sol(1,aNbSolMAX),
69 par1sol(1,aNbSolMAX) ,
70 par2sol(1,aNbSolMAX) ,
71 pararg1(1,aNbSolMAX) ,
75 //========================================================================
77 //========================================================================
79 Standard_Real Tol = Abs(Tolerance);
80 Standard_Real thefirst = -100000.;
81 Standard_Real thelast = 100000.;
82 Standard_Real firstparam;
83 Standard_Real lastparam;
85 TColStd_Array1OfReal cote1(1,2);
86 TColStd_Array1OfReal cote2(1,2);
87 Standard_Integer nbrcote1=0;
88 Standard_Integer nbrcote2=0;
89 WellDone = Standard_False;
91 if (!(Qualified1.IsEnclosed() ||
92 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
93 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
94 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
96 throw GccEnt_BadQualifier();
99 gp_Lin2d L1 = Qualified1.Qualified();
100 Standard_Real x1dir = (L1.Direction()).X();
101 Standard_Real y1dir = (L1.Direction()).Y();
102 Standard_Real lxloc = (L1.Location()).X();
103 Standard_Real lyloc = (L1.Location()).Y();
104 gp_Pnt2d origin1(lxloc,lyloc);
105 gp_Dir2d normL1(-y1dir,x1dir);
106 Geom2dAdaptor_Curve Cu2= Qualified2.Qualified();
107 if (Radius < 0.0) { throw Standard_NegativeValue(); }
109 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
110 // =======================================================
116 else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
117 // ==========================================================
123 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
124 // ===========================================================
130 else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
131 // =========================================================
137 if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
138 // =========================================================
145 if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
146 // =========================================================
153 else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
154 // =============================================================
161 if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
162 // ========================================================
169 else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
170 // =================================================================
178 gp_Dir2d Dir(-y1dir,x1dir);
179 for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
180 gp_Pnt2d Point(L1.Location().XY()+cote1(jcote1)*Dir.XY());
181 gp_Lin2d Line(Point,L1.Direction()); // ligne avec deport.
183 for (Standard_Integer jcote2 = 1; jcote2 <= nbrcote2 && NbrSol < aNbSolMAX; jcote2++) {
184 Handle(Geom2dAdaptor_Curve) HCu2 = new Geom2dAdaptor_Curve(Cu2);
185 //Adaptor2d_OffsetCurve C2(HCu2,cote2(jcote2));
186 Adaptor2d_OffsetCurve C2(HCu2, -cote2(jcote2));
187 firstparam = Max(C2.FirstParameter(),thefirst);
188 lastparam = Min(C2.LastParameter(),thelast);
189 IntRes2d_Domain D2(C2.Value(firstparam), firstparam, Tol,
190 C2.Value(lastparam), lastparam, Tol);
191 Geom2dInt_TheIntConicCurveOfGInter Intp(Line,D1,C2,D2,Tol,Tol);
193 if (!Intp.IsEmpty()) {
194 for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
196 gp_Pnt2d Center(Intp.Point(i).Value());
197 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
198 // =======================================================
199 gp_Dir2d dc1(origin1.XY()-Center.XY());
200 qualifier2(NbrSol) = Qualified2.Qualifier();
201 if (!Qualified1.IsUnqualified()) {
202 qualifier1(NbrSol) = Qualified1.Qualifier();
204 else if (dc1.Dot(normL1) > 0.0) {
205 qualifier1(NbrSol) = GccEnt_outside;
207 else { qualifier1(NbrSol) = GccEnt_enclosed; }
208 TheSame1(NbrSol) = 0;
209 TheSame2(NbrSol) = 0;
210 pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
211 pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
212 pnttg1sol(NbrSol) = ElCLib::Value(pararg1(NbrSol),L1);
213 pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
214 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
216 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
220 WellDone = Standard_True;
227 // circulaire tant a une courbe et un cercle ,de rayon donne
228 //=============================================================
230 //========================================================================
231 // On initialise WellDone a false. +
232 // On recupere la courbe Cu2 et le cercle C1. +
233 // On sort en erreur dans les cas ou la construction est impossible. +
234 // On fait la parallele a Cu2 dans le bon sens. +
235 // On fait la parallele a C1 dans le bon sens. +
236 // On intersecte les paralleles ==> point de centre de la solution. +
237 // On cree la solution qu on ajoute aux solutions deja trouvees. +
238 // On remplit les champs. +
239 //========================================================================
241 Geom2dGcc_Circ2d2TanRadGeo::
242 Geom2dGcc_Circ2d2TanRadGeo (const GccEnt_QualifiedCirc& Qualified1,
243 const Geom2dGcc_QCurve& Qualified2,
244 const Standard_Real Radius ,
245 const Standard_Real Tolerance ):
247 //========================================================================
248 // initialisation des champs. +
249 //========================================================================
251 cirsol(1,aNbSolMAX) ,
252 qualifier1(1,aNbSolMAX),
253 qualifier2(1,aNbSolMAX),
254 TheSame1(1,aNbSolMAX) ,
255 TheSame2(1,aNbSolMAX) ,
256 pnttg1sol(1,aNbSolMAX),
257 pnttg2sol(1,aNbSolMAX),
258 par1sol(1,aNbSolMAX) ,
259 par2sol(1,aNbSolMAX) ,
260 pararg1(1,aNbSolMAX) ,
264 //========================================================================
266 //========================================================================
268 Standard_Real Tol = Abs(Tolerance);
269 Standard_Real thefirst = -100000.;
270 Standard_Real thelast = 100000.;
271 Standard_Real firstparam;
272 Standard_Real lastparam;
273 gp_Dir2d dirx(1.,0.);
274 TColStd_Array1OfReal cote1(1,2);
275 TColStd_Array1OfReal cote2(1,2);
276 Standard_Integer nbrcote1=0;
277 Standard_Integer nbrcote2=0;
278 WellDone = Standard_False;
280 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
281 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
282 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
283 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
284 throw GccEnt_BadQualifier();
287 gp_Circ2d C1 = Qualified1.Qualified();
288 gp_Pnt2d center1(C1.Location());
289 Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
290 if (Radius < 0.0) { throw Standard_NegativeValue(); }
292 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
293 // =======================================================
299 else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
300 // ==========================================================
306 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
307 // ===========================================================
313 else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
314 // =========================================================
320 if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
321 // =========================================================
328 if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
329 // =========================================================
336 else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
337 // =============================================================
344 if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
345 // ========================================================
352 else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
353 // =================================================================
361 Standard_Real R1 = C1.Radius();
362 Geom2dInt_TheIntConicCurveOfGInter Intp;
363 for (Standard_Integer jcote1 = 1; jcote1 <= nbrcote1 && NbrSol < aNbSolMAX; jcote1++) {
364 gp_Circ2d Circ(C1.XAxis(),R1+cote1(jcote1));
365 IntRes2d_Domain D1(ElCLib::Value(0.,Circ), 0.,Tol,
366 ElCLib::Value(2.*M_PI,Circ),2.*M_PI,Tol);
367 D1.SetEquivalentParameters(0.,2.*M_PI);
368 for (Standard_Integer jcote2 = 1 ; jcote2 <= nbrcote2 ; jcote2++) {
369 Handle(Geom2dAdaptor_Curve) HCu2 = new Geom2dAdaptor_Curve(Cu2);
370 //Adaptor2d_OffsetCurve C2(HCu2,cote2(jcote2));
371 Adaptor2d_OffsetCurve C2(HCu2, -cote2(jcote2));
372 firstparam = Max(C2.FirstParameter(),thefirst);
373 lastparam = Min(C2.LastParameter(),thelast);
374 IntRes2d_Domain D2(C2.Value(firstparam), firstparam, Tol,
375 C2.Value(lastparam), lastparam, Tol);
376 Intp.Perform(Circ,D1,C2,D2,Tol,Tol);
378 if (!Intp.IsEmpty()) {
379 for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
381 gp_Pnt2d Center(Intp.Point(i).Value());
382 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
383 // =======================================================
385 gp_Dir2d dir1(Center.XY()-center1.XY());
390 Standard_Real distcc1 = Center.Distance(center1);
391 if (!Qualified1.IsUnqualified()) {
392 qualifier1(NbrSol) = Qualified1.Qualifier();
394 else if (Abs(distcc1+Radius-R1) < Tol) {
395 qualifier1(NbrSol) = GccEnt_enclosed;
397 else if (Abs(distcc1-R1-Radius) < Tol) {
398 qualifier1(NbrSol) = GccEnt_outside;
400 else { qualifier1(NbrSol) = GccEnt_enclosing; }
401 qualifier2(NbrSol) = Qualified2.Qualifier();
402 TheSame1(NbrSol) = 0;
403 TheSame2(NbrSol) = 0;
404 pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
405 pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
406 pnttg1sol(NbrSol) = ElCLib::Value(pararg1(NbrSol),C1);
407 pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
408 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
410 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
414 WellDone = Standard_True;
421 // circulaire tant a une courbe et un point ,de rayon donne
422 //============================================================
424 //========================================================================
425 // On initialise WellDone a false. +
426 // On recupere la courbe Cu1 et le point P2. +
427 // On sort en erreur dans les cas ou la construction est impossible. +
428 // On fait la parallele a Cu1 dans le bon sens. +
429 // On fait la parallele a P2 dans le bon sens. +
430 // On intersecte les paralleles ==> point de centre de la solution. +
431 // On cree la solution qu on ajoute aux solutions deja trouvees. +
432 // On remplit les champs. +
433 //========================================================================
435 Geom2dGcc_Circ2d2TanRadGeo::
436 Geom2dGcc_Circ2d2TanRadGeo (const Geom2dGcc_QCurve& Qualified1,
437 const gp_Pnt2d& Point2 ,
438 const Standard_Real Radius ,
439 const Standard_Real Tolerance ):
441 //========================================================================
442 // initialisation des champs. +
443 //========================================================================
445 cirsol(1,aNbSolMAX) ,
446 qualifier1(1,aNbSolMAX),
447 qualifier2(1,aNbSolMAX),
448 TheSame1(1,aNbSolMAX) ,
449 TheSame2(1,aNbSolMAX) ,
450 pnttg1sol(1,aNbSolMAX),
451 pnttg2sol(1,aNbSolMAX),
452 par1sol(1,aNbSolMAX) ,
453 par2sol(1,aNbSolMAX) ,
454 pararg1(1,aNbSolMAX) ,
458 //========================================================================
460 //========================================================================
462 Standard_Real Tol = Abs(Tolerance);
463 Standard_Real thefirst = -100000.;
464 Standard_Real thelast = 100000.;
465 Standard_Real firstparam;
466 Standard_Real lastparam;
467 gp_Dir2d dirx(1.,0.);
468 TColStd_Array1OfReal cote1(1,2);
469 Standard_Integer nbrcote1=0;
470 WellDone = Standard_False;
472 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
473 Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
474 throw GccEnt_BadQualifier();
477 Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
478 if (Radius < 0.0) { throw Standard_NegativeValue(); }
480 if (Qualified1.IsEnclosed()) {
481 // ===========================
485 else if(Qualified1.IsOutside()) {
486 // ===============================
490 else if(Qualified1.IsUnqualified()) {
491 // ===================================
496 gp_Circ2d Circ(gp_Ax2d(Point2,gp_Dir2d(1.,0.)),Radius);
497 IntRes2d_Domain D1(ElCLib::Value(0.,Circ), 0.,Tol,
498 ElCLib::Value(M_PI+M_PI,Circ),M_PI+M_PI,Tol);
499 D1.SetEquivalentParameters(0.,M_PI+M_PI);
500 Geom2dInt_TheIntConicCurveOfGInter Intp;
501 for (Standard_Integer jcote1 = 1; jcote1 <= nbrcote1 && NbrSol < aNbSolMAX; jcote1++) {
502 Handle(Geom2dAdaptor_Curve) HCu1 = new Geom2dAdaptor_Curve(Cu1);
503 //Adaptor2d_OffsetCurve Cu2(HCu1,cote1(jcote1));
504 Adaptor2d_OffsetCurve Cu2(HCu1,-cote1(jcote1));
505 firstparam = Max(Cu2.FirstParameter(),thefirst);
506 lastparam = Min(Cu2.LastParameter(),thelast);
507 IntRes2d_Domain D2(Cu2.Value(firstparam), firstparam, Tol,
508 Cu2.Value(lastparam), lastparam, Tol);
509 Intp.Perform(Circ,D1,Cu2,D2,Tol,Tol);
511 if (!Intp.IsEmpty()) {
512 for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
514 gp_Pnt2d Center(Intp.Point(i).Value());
515 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
516 // =======================================================
517 qualifier1(NbrSol) = Qualified1.Qualifier();
518 qualifier2(NbrSol) = GccEnt_noqualifier;
519 TheSame1(NbrSol) = 0;
520 TheSame2(NbrSol) = 0;
521 pararg1(NbrSol) = Intp.Point(i).ParamOnSecond();
522 pararg2(NbrSol) = 0.;
523 pnttg1sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol));
524 pnttg2sol(NbrSol) = Point2;
525 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
527 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
531 WellDone = Standard_True;
537 //=======================================================================
538 //function : PrecRoot
539 //purpose : In case, when curves has tangent zones, intersection point
540 // found may be precised. This function uses precision algorithm
541 // of Extrema Curve-Curve method (dot product between every
542 // tangent vector and vector between points in two curves must
543 // be equal to zero).
544 //=======================================================================
545 static void PrecRoot(const Adaptor2d_OffsetCurve& theC1,
546 const Adaptor2d_OffsetCurve& theC2,
547 const Standard_Real theU0,
548 const Standard_Real theV0,
549 Standard_Real& theUfinal,
550 Standard_Real& theVfinal)
553 It is necessary for precision to solve the system
555 \left\{\begin{matrix}
556 (x_{1}(u)-x_{2}(v))*{x_{1}(u)}'+(y_{1}(u)-y_{2}(v))*{y_{1}(u)}'=0\\
557 (x_{1}(u)-x_{2}(v))*{x_{2}(v)}'+(y_{1}(u)-y_{2}(v))*{y_{2}(v)}'=0
560 Precision of any 2*2-system (two equation and two variables)
562 \left\{\begin{matrix}
567 by Newton method can be made as follows:
569 u=u_{0}-\left (\frac{\frac{\partial S_{2}}{\partial v}*S_{1}-
570 \frac{\partial S_{1}}{\partial v}*S_{2}}
571 {\frac{\partial S_{1}}{\partial u}*
572 \frac{\partial S_{2}}{\partial v}-
573 \frac{\partial S_{1}}{\partial v}*
574 \frac{\partial S_{2}}{\partial u}} \right )_{u_{0},v_{0}}\\
575 v=v_{0}-\left (\frac{\frac{\partial S_{1}}{\partial u}*S_{2}-
576 \frac{\partial S_{2}}{\partial u}*S_{1}}
577 {\frac{\partial S_{1}}{\partial u}*
578 \frac{\partial S_{2}}{\partial v}-
579 \frac{\partial S_{1}}{\partial v}*
580 \frac{\partial S_{2}}{\partial u}} \right )_{u_{0},v_{0}}
583 where u_{0} and v_{0} are initial values or values computed on previous iteration.
589 const Standard_Integer aNbIterMax = 100;
591 Standard_Real aU = theU0, aV = theV0;
593 gp_Vec2d aD1u, aD1v, aD2u, aD2v;
595 Standard_Integer aNbIter = 0;
597 Standard_Real aStepU = 0.0, aStepV = 0.0;
599 Standard_Real aSQDistPrev = RealFirst();
601 theC1.D2(aU, aPu, aD1u, aD2u);
602 theC2.D2(aV, aPv, aD1v, aD2v);
604 const Standard_Real aCrProd = Abs(aD1u.Crossed(aD1v));
605 if(aCrProd*aCrProd > 1.0e-6*
606 aD1u.SquareMagnitude()*aD1v.SquareMagnitude())
608 //Curves are not tangent. Therefore, we consider that
609 //2D-intersection algorithm have found good point which
610 //did not need in more precision.
618 gp_Vec2d aVuv(aPv, aPu);
620 Standard_Real aSQDist = aVuv.SquareMagnitude();
621 if(IsEqual(aSQDist, 0.0))
624 if((aNbIter == 1) || (aSQDist < aSQDistPrev))
626 aSQDistPrev = aSQDist;
632 Standard_Real aG1 = aD1u.Magnitude();
633 Standard_Real aG2 = aD1v.Magnitude();
635 if(IsEqual(aG1, 0.0) || IsEqual(aG2, 0.0))
636 {//Here we do not processing singular cases.
640 Standard_Real aF1 = aVuv.Dot(aD1u);
641 Standard_Real aF2 = aVuv.Dot(aD1v);
643 Standard_Real aFIu = aVuv.Dot(aD2u);
644 Standard_Real aFIv = aVuv.Dot(aD2v);
645 Standard_Real aPSIu = aD1u.Dot(aD2u);
646 Standard_Real aPSIv = aD1v.Dot(aD2v);
648 Standard_Real aTheta = aD1u*aD1v;
650 Standard_Real aS1 = aF1/aG1;
651 Standard_Real aS2 = aF2/aG2;
653 Standard_Real aDS1u = (aG1*aG1+aFIu)/aG1 - (aS1*aPSIu/(aG1*aG1));
654 Standard_Real aDS1v = -aTheta/aG1;
655 Standard_Real aDS2u = aTheta/aG2;
656 Standard_Real aDS2v = (aFIv-aG2*aG2)/aG2 - (aS2*aPSIv/(aG2*aG2));
658 Standard_Real aDet = aDS1u*aDS2v-aDS1v*aDS2u;
660 if(IsEqual(aDet, 0.0))
662 if(!IsEqual(aStepV, 0.0) && !IsEqual(aDS1u, 0.0))
665 aU = aU - (aDS1v*aStepV - aS1)/aDS1u;
667 else if(!IsEqual(aStepU, 0.0) && !IsEqual(aDS1v, 0.0))
670 aV = aV - (aDS1u*aStepU - aS1)/aDS1v;
679 aStepU = -(aS1*aDS2v-aS2*aDS1v)/aDet;
680 aStepV = -(aS2*aDS1u-aS1*aDS2u)/aDet;
682 if(Abs(aStepU) < Epsilon(Abs(aU)))
684 if(Abs(aStepV) < Epsilon(Abs(aV)))
694 theC1.D2(aU, aPu, aD1u, aD2u);
695 theC2.D2(aV, aPv, aD1v, aD2v);
697 while(aNbIter <= aNbIterMax);
702 // circulaire tant a deux courbes ,de rayon donne
703 //==================================================
705 //========================================================================
706 // On initialise WellDone a false. +
707 // On recupere les courbes Cu1 et Cu2. +
708 // On sort en erreur dans les cas ou la construction est impossible. +
709 // On fait la parallele a Cu1 dans le bon sens. +
710 // On fait la parallele a Cu2 dans le bon sens. +
711 // On intersecte les paralleles ==> point de centre de la solution. +
712 // On cree la solution qu on ajoute aux solutions deja trouvees. +
713 // On remplit les champs. +
714 //========================================================================
715 Geom2dGcc_Circ2d2TanRadGeo::
716 Geom2dGcc_Circ2d2TanRadGeo (const Geom2dGcc_QCurve& Qualified1,
717 const Geom2dGcc_QCurve& Qualified2,
718 const Standard_Real Radius ,
719 const Standard_Real Tolerance ):
721 //========================================================================
722 // initialisation des champs. +
723 //========================================================================
725 cirsol(1,aNbSolMAX) ,
726 qualifier1(1,aNbSolMAX),
727 qualifier2(1,aNbSolMAX),
728 TheSame1(1,aNbSolMAX) ,
729 TheSame2(1,aNbSolMAX) ,
730 pnttg1sol(1,aNbSolMAX),
731 pnttg2sol(1,aNbSolMAX),
732 par1sol(1,aNbSolMAX) ,
733 par2sol(1,aNbSolMAX) ,
734 pararg1(1,aNbSolMAX) ,
738 //========================================================================
740 //========================================================================
742 Standard_Real Tol = Abs(Tolerance);
744 const Standard_Real thefirst = -100000.;
745 const Standard_Real thelast = 100000.;
747 gp_Dir2d dirx(1.,0.);
748 TColStd_Array1OfReal cote1(1,2);
749 TColStd_Array1OfReal cote2(1,2);
750 Standard_Integer nbrcote1=0;
751 Standard_Integer nbrcote2=0;
752 WellDone = Standard_False;
754 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
755 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
756 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
757 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
758 throw GccEnt_BadQualifier();
761 Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
762 Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
763 if (Radius < 0.0) { throw Standard_NegativeValue(); }
765 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
766 // =======================================================
772 else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
773 // ==========================================================
779 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
780 // ===========================================================
786 else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
787 // =========================================================
793 if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
794 // =========================================================
801 if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
802 // =========================================================
809 else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
810 // =============================================================
817 if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
818 // ========================================================
825 else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
826 // =================================================================
834 Geom2dInt_GInter Intp;
835 for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
836 Handle(Geom2dAdaptor_Curve) HCu1 = new Geom2dAdaptor_Curve(Cu1);
837 //Adaptor2d_OffsetCurve C1(HCu1,cote1(jcote1));
838 Adaptor2d_OffsetCurve C1(HCu1, -cote1(jcote1));
840 Standard_Real firstparam = Max(C1.FirstParameter(), thefirst);
841 Standard_Real lastparam = Min(C1.LastParameter(), thelast);
842 IntRes2d_Domain D2C1(C1.Value(firstparam),firstparam,Tol,
843 C1.Value(lastparam),lastparam,Tol);
845 for (Standard_Integer jcote2 = 1; jcote2 <= nbrcote2 && NbrSol < aNbSolMAX; jcote2++) {
846 Handle(Geom2dAdaptor_Curve) HCu2 = new Geom2dAdaptor_Curve(Cu2);
847 //Adaptor2d_OffsetCurve C2(HCu2,cote2(jcote2));
848 Adaptor2d_OffsetCurve C2(HCu2, -cote2(jcote2));
850 firstparam = Max(C2.FirstParameter(), thefirst);
851 lastparam = Min(C2.LastParameter(),thelast);
852 IntRes2d_Domain D2C2(C2.Value(firstparam),firstparam,Tol,
853 C2.Value(lastparam),lastparam,Tol);
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() && NbrSol < aNbSolMAX; 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 = C1.Value(aU1);
872 gp_Pnt2d P12 = C2.Value(aV1);
873 gp_Pnt2d P21 = C1.Value(aU2);
874 gp_Pnt2d P22 = C2.Value(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(C1.Value(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) { throw StdFail_NotDone(); }
926 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
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) { throw StdFail_NotDone(); }
936 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
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) { throw StdFail_NotDone(); }
949 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
951 if (TheSame1(Index) == 0) {
952 ParSol = par1sol(Index);
953 ParArg = pararg1(Index);
954 PntSol = gp_Pnt2d(pnttg1sol(Index));
956 else { throw StdFail_NotDone(); }
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) { throw StdFail_NotDone(); }
966 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
968 if (TheSame2(Index) == 0) {
969 ParSol = par2sol(Index);
970 ParArg = pararg2(Index);
971 PntSol = gp_Pnt2d(pnttg2sol(Index));
973 else { throw StdFail_NotDone(); }
977 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
978 IsTheSame1 (const Standard_Integer Index) const
980 if (!WellDone) { throw StdFail_NotDone(); }
981 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
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) { throw StdFail_NotDone(); }
991 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
993 if (TheSame2(Index) == 0) { return Standard_False; }
994 return Standard_True;