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 <Geom2dAdaptor_HCurve.hxx>
22 #include <Geom2dGcc_Circ2d2TanRadGeo.hxx>
23 #include <Geom2dGcc_CurveTool.hxx>
24 #include <Geom2dGcc_QCurve.hxx>
25 #include <Geom2dInt_GInter.hxx>
26 #include <gp_Ax2d.hxx>
27 #include <gp_Circ2d.hxx>
28 #include <gp_Lin2d.hxx>
29 #include <gp_Pnt2d.hxx>
30 #include <IntRes2d_Domain.hxx>
31 #include <IntRes2d_IntersectionPoint.hxx>
32 #include <Standard_NegativeValue.hxx>
33 #include <Standard_OutOfRange.hxx>
34 #include <StdFail_NotDone.hxx>
35 #include <TColStd_Array1OfReal.hxx>
37 static const Standard_Integer aNbSolMAX = 16;
39 // circulaire tant a une courbe et une droite ,de rayon donne
40 //==============================================================
42 //========================================================================
43 // On initialise WellDone a false. +
44 // On recupere la courbe Cu2 et la droite L1. +
45 // On sort en erreur dans les cas ou la construction est impossible. +
46 // On fait la parallele a Cu2 dans le bon sens. +
47 // On fait la parallele a L1 dans le bon sens. +
48 // On intersecte les paralleles ==> point de centre de la solution. +
49 // On cree la solution qu on ajoute aux solutions deja trouvees. +
50 // On remplit les champs. +
51 //========================================================================
53 Geom2dGcc_Circ2d2TanRadGeo::
54 Geom2dGcc_Circ2d2TanRadGeo (const GccEnt_QualifiedLin& Qualified1,
55 const Geom2dGcc_QCurve& Qualified2,
56 const Standard_Real Radius ,
57 const Standard_Real Tolerance ):
59 //========================================================================
60 // initialisation des champs. +
61 //========================================================================
64 qualifier1(1,aNbSolMAX),
65 qualifier2(1,aNbSolMAX),
66 TheSame1(1,aNbSolMAX) ,
67 TheSame2(1,aNbSolMAX) ,
68 pnttg1sol(1,aNbSolMAX),
69 pnttg2sol(1,aNbSolMAX),
70 par1sol(1,aNbSolMAX) ,
71 par2sol(1,aNbSolMAX) ,
72 pararg1(1,aNbSolMAX) ,
76 //========================================================================
78 //========================================================================
80 Standard_Real Tol = Abs(Tolerance);
81 Standard_Real thefirst = -100000.;
82 Standard_Real thelast = 100000.;
83 Standard_Real firstparam;
84 Standard_Real lastparam;
86 TColStd_Array1OfReal cote1(1,2);
87 TColStd_Array1OfReal cote2(1,2);
88 Standard_Integer nbrcote1=0;
89 Standard_Integer nbrcote2=0;
90 WellDone = Standard_False;
92 if (!(Qualified1.IsEnclosed() ||
93 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
94 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
95 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
97 throw GccEnt_BadQualifier();
100 gp_Lin2d L1 = Qualified1.Qualified();
101 Standard_Real x1dir = (L1.Direction()).X();
102 Standard_Real y1dir = (L1.Direction()).Y();
103 Standard_Real lxloc = (L1.Location()).X();
104 Standard_Real lyloc = (L1.Location()).Y();
105 gp_Pnt2d origin1(lxloc,lyloc);
106 gp_Dir2d normL1(-y1dir,x1dir);
107 Geom2dAdaptor_Curve Cu2= Qualified2.Qualified();
108 if (Radius < 0.0) { throw Standard_NegativeValue(); }
110 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
111 // =======================================================
117 else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
118 // ==========================================================
124 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
125 // ===========================================================
131 else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
132 // =========================================================
138 if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
139 // =========================================================
146 if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
147 // =========================================================
154 else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
155 // =============================================================
162 if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
163 // ========================================================
170 else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
171 // =================================================================
179 gp_Dir2d Dir(-y1dir,x1dir);
180 for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
181 gp_Pnt2d Point(L1.Location().XY()+cote1(jcote1)*Dir.XY());
182 gp_Lin2d Line(Point,L1.Direction()); // ligne avec deport.
184 for (Standard_Integer jcote2 = 1; jcote2 <= nbrcote2 && NbrSol < aNbSolMAX; jcote2++) {
185 Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
186 //Adaptor2d_OffsetCurve C2(HCu2,cote2(jcote2));
187 Adaptor2d_OffsetCurve C2(HCu2, -cote2(jcote2));
188 firstparam = Max(C2.FirstParameter(),thefirst);
189 lastparam = Min(C2.LastParameter(),thelast);
190 IntRes2d_Domain D2(C2.Value(firstparam), firstparam, Tol,
191 C2.Value(lastparam), lastparam, Tol);
192 Geom2dInt_TheIntConicCurveOfGInter Intp(Line,D1,C2,D2,Tol,Tol);
194 if (!Intp.IsEmpty()) {
195 for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
197 gp_Pnt2d Center(Intp.Point(i).Value());
198 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
199 // =======================================================
200 gp_Dir2d dc1(origin1.XY()-Center.XY());
201 qualifier2(NbrSol) = Qualified2.Qualifier();
202 if (!Qualified1.IsUnqualified()) {
203 qualifier1(NbrSol) = Qualified1.Qualifier();
205 else if (dc1.Dot(normL1) > 0.0) {
206 qualifier1(NbrSol) = GccEnt_outside;
208 else { qualifier1(NbrSol) = GccEnt_enclosed; }
209 TheSame1(NbrSol) = 0;
210 TheSame2(NbrSol) = 0;
211 pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
212 pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
213 pnttg1sol(NbrSol) = ElCLib::Value(pararg1(NbrSol),L1);
214 pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
215 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
217 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
221 WellDone = Standard_True;
228 // circulaire tant a une courbe et un cercle ,de rayon donne
229 //=============================================================
231 //========================================================================
232 // On initialise WellDone a false. +
233 // On recupere la courbe Cu2 et le cercle C1. +
234 // On sort en erreur dans les cas ou la construction est impossible. +
235 // On fait la parallele a Cu2 dans le bon sens. +
236 // On fait la parallele a C1 dans le bon sens. +
237 // On intersecte les paralleles ==> point de centre de la solution. +
238 // On cree la solution qu on ajoute aux solutions deja trouvees. +
239 // On remplit les champs. +
240 //========================================================================
242 Geom2dGcc_Circ2d2TanRadGeo::
243 Geom2dGcc_Circ2d2TanRadGeo (const GccEnt_QualifiedCirc& Qualified1,
244 const Geom2dGcc_QCurve& Qualified2,
245 const Standard_Real Radius ,
246 const Standard_Real Tolerance ):
248 //========================================================================
249 // initialisation des champs. +
250 //========================================================================
252 cirsol(1,aNbSolMAX) ,
253 qualifier1(1,aNbSolMAX),
254 qualifier2(1,aNbSolMAX),
255 TheSame1(1,aNbSolMAX) ,
256 TheSame2(1,aNbSolMAX) ,
257 pnttg1sol(1,aNbSolMAX),
258 pnttg2sol(1,aNbSolMAX),
259 par1sol(1,aNbSolMAX) ,
260 par2sol(1,aNbSolMAX) ,
261 pararg1(1,aNbSolMAX) ,
265 //========================================================================
267 //========================================================================
269 Standard_Real Tol = Abs(Tolerance);
270 Standard_Real thefirst = -100000.;
271 Standard_Real thelast = 100000.;
272 Standard_Real firstparam;
273 Standard_Real lastparam;
274 gp_Dir2d dirx(1.,0.);
275 TColStd_Array1OfReal cote1(1,2);
276 TColStd_Array1OfReal cote2(1,2);
277 Standard_Integer nbrcote1=0;
278 Standard_Integer nbrcote2=0;
279 WellDone = Standard_False;
281 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
282 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
283 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
284 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
285 throw GccEnt_BadQualifier();
288 gp_Circ2d C1 = Qualified1.Qualified();
289 gp_Pnt2d center1(C1.Location());
290 Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
291 if (Radius < 0.0) { throw Standard_NegativeValue(); }
293 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
294 // =======================================================
300 else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
301 // ==========================================================
307 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
308 // ===========================================================
314 else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
315 // =========================================================
321 if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
322 // =========================================================
329 if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
330 // =========================================================
337 else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
338 // =============================================================
345 if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
346 // ========================================================
353 else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
354 // =================================================================
362 Standard_Real R1 = C1.Radius();
363 Geom2dInt_TheIntConicCurveOfGInter Intp;
364 for (Standard_Integer jcote1 = 1; jcote1 <= nbrcote1 && NbrSol < aNbSolMAX; jcote1++) {
365 gp_Circ2d Circ(C1.XAxis(),R1+cote1(jcote1));
366 IntRes2d_Domain D1(ElCLib::Value(0.,Circ), 0.,Tol,
367 ElCLib::Value(2.*M_PI,Circ),2.*M_PI,Tol);
368 D1.SetEquivalentParameters(0.,2.*M_PI);
369 for (Standard_Integer jcote2 = 1 ; jcote2 <= nbrcote2 ; jcote2++) {
370 Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
371 //Adaptor2d_OffsetCurve C2(HCu2,cote2(jcote2));
372 Adaptor2d_OffsetCurve C2(HCu2, -cote2(jcote2));
373 firstparam = Max(C2.FirstParameter(),thefirst);
374 lastparam = Min(C2.LastParameter(),thelast);
375 IntRes2d_Domain D2(C2.Value(firstparam), firstparam, Tol,
376 C2.Value(lastparam), lastparam, Tol);
377 Intp.Perform(Circ,D1,C2,D2,Tol,Tol);
379 if (!Intp.IsEmpty()) {
380 for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
382 gp_Pnt2d Center(Intp.Point(i).Value());
383 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
384 // =======================================================
386 gp_Dir2d dir1(Center.XY()-center1.XY());
391 Standard_Real distcc1 = Center.Distance(center1);
392 if (!Qualified1.IsUnqualified()) {
393 qualifier1(NbrSol) = Qualified1.Qualifier();
395 else if (Abs(distcc1+Radius-R1) < Tol) {
396 qualifier1(NbrSol) = GccEnt_enclosed;
398 else if (Abs(distcc1-R1-Radius) < Tol) {
399 qualifier1(NbrSol) = GccEnt_outside;
401 else { qualifier1(NbrSol) = GccEnt_enclosing; }
402 qualifier2(NbrSol) = Qualified2.Qualifier();
403 TheSame1(NbrSol) = 0;
404 TheSame2(NbrSol) = 0;
405 pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
406 pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
407 pnttg1sol(NbrSol) = ElCLib::Value(pararg1(NbrSol),C1);
408 pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
409 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
411 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
415 WellDone = Standard_True;
422 // circulaire tant a une courbe et un point ,de rayon donne
423 //============================================================
425 //========================================================================
426 // On initialise WellDone a false. +
427 // On recupere la courbe Cu1 et le point P2. +
428 // On sort en erreur dans les cas ou la construction est impossible. +
429 // On fait la parallele a Cu1 dans le bon sens. +
430 // On fait la parallele a P2 dans le bon sens. +
431 // On intersecte les paralleles ==> point de centre de la solution. +
432 // On cree la solution qu on ajoute aux solutions deja trouvees. +
433 // On remplit les champs. +
434 //========================================================================
436 Geom2dGcc_Circ2d2TanRadGeo::
437 Geom2dGcc_Circ2d2TanRadGeo (const Geom2dGcc_QCurve& Qualified1,
438 const gp_Pnt2d& Point2 ,
439 const Standard_Real Radius ,
440 const Standard_Real Tolerance ):
442 //========================================================================
443 // initialisation des champs. +
444 //========================================================================
446 cirsol(1,aNbSolMAX) ,
447 qualifier1(1,aNbSolMAX),
448 qualifier2(1,aNbSolMAX),
449 TheSame1(1,aNbSolMAX) ,
450 TheSame2(1,aNbSolMAX) ,
451 pnttg1sol(1,aNbSolMAX),
452 pnttg2sol(1,aNbSolMAX),
453 par1sol(1,aNbSolMAX) ,
454 par2sol(1,aNbSolMAX) ,
455 pararg1(1,aNbSolMAX) ,
459 //========================================================================
461 //========================================================================
463 Standard_Real Tol = Abs(Tolerance);
464 Standard_Real thefirst = -100000.;
465 Standard_Real thelast = 100000.;
466 Standard_Real firstparam;
467 Standard_Real lastparam;
468 gp_Dir2d dirx(1.,0.);
469 TColStd_Array1OfReal cote1(1,2);
470 Standard_Integer nbrcote1=0;
471 WellDone = Standard_False;
473 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
474 Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
475 throw GccEnt_BadQualifier();
478 Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
479 if (Radius < 0.0) { throw Standard_NegativeValue(); }
481 if (Qualified1.IsEnclosed()) {
482 // ===========================
486 else if(Qualified1.IsOutside()) {
487 // ===============================
491 else if(Qualified1.IsUnqualified()) {
492 // ===================================
497 gp_Circ2d Circ(gp_Ax2d(Point2,gp_Dir2d(1.,0.)),Radius);
498 IntRes2d_Domain D1(ElCLib::Value(0.,Circ), 0.,Tol,
499 ElCLib::Value(M_PI+M_PI,Circ),M_PI+M_PI,Tol);
500 D1.SetEquivalentParameters(0.,M_PI+M_PI);
501 Geom2dInt_TheIntConicCurveOfGInter Intp;
502 for (Standard_Integer jcote1 = 1; jcote1 <= nbrcote1 && NbrSol < aNbSolMAX; jcote1++) {
503 Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1);
504 //Adaptor2d_OffsetCurve Cu2(HCu1,cote1(jcote1));
505 Adaptor2d_OffsetCurve Cu2(HCu1,-cote1(jcote1));
506 firstparam = Max(Cu2.FirstParameter(),thefirst);
507 lastparam = Min(Cu2.LastParameter(),thelast);
508 IntRes2d_Domain D2(Cu2.Value(firstparam), firstparam, Tol,
509 Cu2.Value(lastparam), lastparam, Tol);
510 Intp.Perform(Circ,D1,Cu2,D2,Tol,Tol);
512 if (!Intp.IsEmpty()) {
513 for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
515 gp_Pnt2d Center(Intp.Point(i).Value());
516 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
517 // =======================================================
518 qualifier1(NbrSol) = Qualified1.Qualifier();
519 qualifier2(NbrSol) = GccEnt_noqualifier;
520 TheSame1(NbrSol) = 0;
521 TheSame2(NbrSol) = 0;
522 pararg1(NbrSol) = Intp.Point(i).ParamOnSecond();
523 pararg2(NbrSol) = 0.;
524 pnttg1sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol));
525 pnttg2sol(NbrSol) = Point2;
526 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
528 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
532 WellDone = Standard_True;
538 //=======================================================================
539 //function : PrecRoot
540 //purpose : In case, when curves has tangent zones, intersection point
541 // found may be precised. This function uses precision algorithm
542 // of Extrema Curve-Curve method (dot product between every
543 // tangent vector and vector between points in two curves must
544 // be equal to zero).
545 //=======================================================================
546 static void PrecRoot(const Adaptor2d_OffsetCurve& theC1,
547 const Adaptor2d_OffsetCurve& theC2,
548 const Standard_Real theU0,
549 const Standard_Real theV0,
550 Standard_Real& theUfinal,
551 Standard_Real& theVfinal)
554 It is necessary for precision to solve the system
556 \left\{\begin{matrix}
557 (x_{1}(u)-x_{2}(v))*{x_{1}(u)}'+(y_{1}(u)-y_{2}(v))*{y_{1}(u)}'=0\\
558 (x_{1}(u)-x_{2}(v))*{x_{2}(v)}'+(y_{1}(u)-y_{2}(v))*{y_{2}(v)}'=0
561 Precision of any 2*2-system (two equation and two variables)
563 \left\{\begin{matrix}
568 by Newton method can be made as follows:
570 u=u_{0}-\left (\frac{\frac{\partial S_{2}}{\partial v}*S_{1}-
571 \frac{\partial S_{1}}{\partial v}*S_{2}}
572 {\frac{\partial S_{1}}{\partial u}*
573 \frac{\partial S_{2}}{\partial v}-
574 \frac{\partial S_{1}}{\partial v}*
575 \frac{\partial S_{2}}{\partial u}} \right )_{u_{0},v_{0}}\\
576 v=v_{0}-\left (\frac{\frac{\partial S_{1}}{\partial u}*S_{2}-
577 \frac{\partial S_{2}}{\partial u}*S_{1}}
578 {\frac{\partial S_{1}}{\partial u}*
579 \frac{\partial S_{2}}{\partial v}-
580 \frac{\partial S_{1}}{\partial v}*
581 \frac{\partial S_{2}}{\partial u}} \right )_{u_{0},v_{0}}
584 where u_{0} and v_{0} are initial values or values computed on previous iteration.
590 const Standard_Integer aNbIterMax = 100;
592 Standard_Real aU = theU0, aV = theV0;
594 gp_Vec2d aD1u, aD1v, aD2u, aD2v;
596 Standard_Integer aNbIter = 0;
598 Standard_Real aStepU = 0.0, aStepV = 0.0;
600 Standard_Real aSQDistPrev = RealFirst();
602 theC1.D2(aU, aPu, aD1u, aD2u);
603 theC2.D2(aV, aPv, aD1v, aD2v);
605 const Standard_Real aCrProd = Abs(aD1u.Crossed(aD1v));
606 if(aCrProd*aCrProd > 1.0e-6*
607 aD1u.SquareMagnitude()*aD1v.SquareMagnitude())
609 //Curves are not tangent. Therefore, we consider that
610 //2D-intersection algorithm have found good point which
611 //did not need in more precision.
619 gp_Vec2d aVuv(aPv, aPu);
621 Standard_Real aSQDist = aVuv.SquareMagnitude();
622 if(IsEqual(aSQDist, 0.0))
625 if((aNbIter == 1) || (aSQDist < aSQDistPrev))
627 aSQDistPrev = aSQDist;
633 Standard_Real aG1 = aD1u.Magnitude();
634 Standard_Real aG2 = aD1v.Magnitude();
636 if(IsEqual(aG1, 0.0) || IsEqual(aG2, 0.0))
637 {//Here we do not processing singular cases.
641 Standard_Real aF1 = aVuv.Dot(aD1u);
642 Standard_Real aF2 = aVuv.Dot(aD1v);
644 Standard_Real aFIu = aVuv.Dot(aD2u);
645 Standard_Real aFIv = aVuv.Dot(aD2v);
646 Standard_Real aPSIu = aD1u.Dot(aD2u);
647 Standard_Real aPSIv = aD1v.Dot(aD2v);
649 Standard_Real aTheta = aD1u*aD1v;
651 Standard_Real aS1 = aF1/aG1;
652 Standard_Real aS2 = aF2/aG2;
654 Standard_Real aDS1u = (aG1*aG1+aFIu)/aG1 - (aS1*aPSIu/(aG1*aG1));
655 Standard_Real aDS1v = -aTheta/aG1;
656 Standard_Real aDS2u = aTheta/aG2;
657 Standard_Real aDS2v = (aFIv-aG2*aG2)/aG2 - (aS2*aPSIv/(aG2*aG2));
659 Standard_Real aDet = aDS1u*aDS2v-aDS1v*aDS2u;
661 if(IsEqual(aDet, 0.0))
663 if(!IsEqual(aStepV, 0.0) && !IsEqual(aDS1u, 0.0))
666 aU = aU - (aDS1v*aStepV - aS1)/aDS1u;
668 else if(!IsEqual(aStepU, 0.0) && !IsEqual(aDS1v, 0.0))
671 aV = aV - (aDS1u*aStepU - aS1)/aDS1v;
680 aStepU = -(aS1*aDS2v-aS2*aDS1v)/aDet;
681 aStepV = -(aS2*aDS1u-aS1*aDS2u)/aDet;
683 if(Abs(aStepU) < Epsilon(Abs(aU)))
685 if(Abs(aStepV) < Epsilon(Abs(aV)))
695 theC1.D2(aU, aPu, aD1u, aD2u);
696 theC2.D2(aV, aPv, aD1v, aD2v);
698 while(aNbIter <= aNbIterMax);
703 // circulaire tant a deux courbes ,de rayon donne
704 //==================================================
706 //========================================================================
707 // On initialise WellDone a false. +
708 // On recupere les courbes Cu1 et Cu2. +
709 // On sort en erreur dans les cas ou la construction est impossible. +
710 // On fait la parallele a Cu1 dans le bon sens. +
711 // On fait la parallele a Cu2 dans le bon sens. +
712 // On intersecte les paralleles ==> point de centre de la solution. +
713 // On cree la solution qu on ajoute aux solutions deja trouvees. +
714 // On remplit les champs. +
715 //========================================================================
716 Geom2dGcc_Circ2d2TanRadGeo::
717 Geom2dGcc_Circ2d2TanRadGeo (const Geom2dGcc_QCurve& Qualified1,
718 const Geom2dGcc_QCurve& Qualified2,
719 const Standard_Real Radius ,
720 const Standard_Real Tolerance ):
722 //========================================================================
723 // initialisation des champs. +
724 //========================================================================
726 cirsol(1,aNbSolMAX) ,
727 qualifier1(1,aNbSolMAX),
728 qualifier2(1,aNbSolMAX),
729 TheSame1(1,aNbSolMAX) ,
730 TheSame2(1,aNbSolMAX) ,
731 pnttg1sol(1,aNbSolMAX),
732 pnttg2sol(1,aNbSolMAX),
733 par1sol(1,aNbSolMAX) ,
734 par2sol(1,aNbSolMAX) ,
735 pararg1(1,aNbSolMAX) ,
739 //========================================================================
741 //========================================================================
743 Standard_Real Tol = Abs(Tolerance);
745 const Standard_Real thefirst = -100000.;
746 const Standard_Real thelast = 100000.;
748 gp_Dir2d dirx(1.,0.);
749 TColStd_Array1OfReal cote1(1,2);
750 TColStd_Array1OfReal cote2(1,2);
751 Standard_Integer nbrcote1=0;
752 Standard_Integer nbrcote2=0;
753 WellDone = Standard_False;
755 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
756 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
757 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
758 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
759 throw GccEnt_BadQualifier();
762 Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
763 Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
764 if (Radius < 0.0) { throw Standard_NegativeValue(); }
766 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
767 // =======================================================
773 else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
774 // ==========================================================
780 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
781 // ===========================================================
787 else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
788 // =========================================================
794 if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
795 // =========================================================
802 if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
803 // =========================================================
810 else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
811 // =============================================================
818 if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
819 // ========================================================
826 else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
827 // =================================================================
835 Geom2dInt_GInter Intp;
836 for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
837 Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1);
838 //Adaptor2d_OffsetCurve C1(HCu1,cote1(jcote1));
839 Adaptor2d_OffsetCurve C1(HCu1, -cote1(jcote1));
841 Standard_Real firstparam = Max(C1.FirstParameter(), thefirst);
842 Standard_Real lastparam = Min(C1.LastParameter(), thelast);
843 IntRes2d_Domain D2C1(C1.Value(firstparam),firstparam,Tol,
844 C1.Value(lastparam),lastparam,Tol);
846 for (Standard_Integer jcote2 = 1; jcote2 <= nbrcote2 && NbrSol < aNbSolMAX; jcote2++) {
847 Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
848 //Adaptor2d_OffsetCurve C2(HCu2,cote2(jcote2));
849 Adaptor2d_OffsetCurve C2(HCu2, -cote2(jcote2));
851 firstparam = Max(C2.FirstParameter(), thefirst);
852 lastparam = Min(C2.LastParameter(),thelast);
853 IntRes2d_Domain D2C2(C2.Value(firstparam),firstparam,Tol,
854 C2.Value(lastparam),lastparam,Tol);
856 Intp.Perform(C1,C2,Tol,Tol);
858 if (!Intp.IsEmpty()) {
859 const Standard_Real aSQApproxTol = Precision::Approximation() *
860 Precision::Approximation();
861 for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++)
863 Standard_Real aU0 = Intp.Point(i).ParamOnFirst();
864 Standard_Real aV0 = Intp.Point(i).ParamOnSecond();
866 Standard_Real aU1 = aU0-Precision::PApproximation();
867 Standard_Real aV1 = aV0-Precision::PApproximation();
869 Standard_Real aU2 = aU0+Precision::PApproximation();
870 Standard_Real aV2 = aV0+Precision::PApproximation();
872 gp_Pnt2d P11 = C1.Value(aU1);
873 gp_Pnt2d P12 = C2.Value(aV1);
874 gp_Pnt2d P21 = C1.Value(aU2);
875 gp_Pnt2d P22 = C2.Value(aV2);
877 Standard_Real aDist1112 = P11.SquareDistance(P12);
878 Standard_Real aDist1122 = P11.SquareDistance(P22);
880 Standard_Real aDist1221 = P12.SquareDistance(P21);
881 Standard_Real aDist2122 = P21.SquareDistance(P22);
883 if( (Min(aDist1112, aDist1122) <= aSQApproxTol) &&
884 (Min(aDist1221, aDist2122) <= aSQApproxTol))
886 PrecRoot(C1, C2, aU0, aV0, aU0, aV0);
890 gp_Pnt2d Center(C1.Value(aU0));
891 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
892 // =======================================================
893 qualifier1(NbrSol) = Qualified1.Qualifier();
894 qualifier1(NbrSol) = Qualified1.Qualifier();
895 TheSame1(NbrSol) = 0;
896 TheSame2(NbrSol) = 0;
897 pararg1(NbrSol) = Intp.Point(i).ParamOnFirst();
898 pararg2(NbrSol) = Intp.Point(i).ParamOnSecond();
899 pnttg1sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol));
900 pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
901 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
903 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
908 WellDone = Standard_True;
915 //=========================================================================
917 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
918 IsDone () const { return WellDone; }
920 Standard_Integer Geom2dGcc_Circ2d2TanRadGeo::
921 NbSolutions () const { return NbrSol; }
923 gp_Circ2d Geom2dGcc_Circ2d2TanRadGeo::
924 ThisSolution (const Standard_Integer Index) const
926 if (!WellDone) { throw StdFail_NotDone(); }
927 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
928 return cirsol(Index);
931 void Geom2dGcc_Circ2d2TanRadGeo::
932 WhichQualifier(const Standard_Integer Index ,
933 GccEnt_Position& Qualif1 ,
934 GccEnt_Position& Qualif2 ) const
936 if (!WellDone) { throw StdFail_NotDone(); }
937 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
939 Qualif1 = qualifier1(Index);
940 Qualif2 = qualifier2(Index);
944 void Geom2dGcc_Circ2d2TanRadGeo::
945 Tangency1 (const Standard_Integer Index,
946 Standard_Real& ParSol,
947 Standard_Real& ParArg,
948 gp_Pnt2d& PntSol) const{
949 if (!WellDone) { throw StdFail_NotDone(); }
950 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
952 if (TheSame1(Index) == 0) {
953 ParSol = par1sol(Index);
954 ParArg = pararg1(Index);
955 PntSol = gp_Pnt2d(pnttg1sol(Index));
957 else { throw StdFail_NotDone(); }
961 void Geom2dGcc_Circ2d2TanRadGeo::
962 Tangency2 (const Standard_Integer Index,
963 Standard_Real& ParSol,
964 Standard_Real& ParArg,
965 gp_Pnt2d& PntSol) const{
966 if (!WellDone) { throw StdFail_NotDone(); }
967 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
969 if (TheSame2(Index) == 0) {
970 ParSol = par2sol(Index);
971 ParArg = pararg2(Index);
972 PntSol = gp_Pnt2d(pnttg2sol(Index));
974 else { throw StdFail_NotDone(); }
978 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
979 IsTheSame1 (const Standard_Integer Index) const
981 if (!WellDone) { throw StdFail_NotDone(); }
982 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
984 if (TheSame1(Index) == 0) { return Standard_False; }
985 return Standard_True;
988 Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
989 IsTheSame2 (const Standard_Integer Index) const
991 if (!WellDone) { throw StdFail_NotDone(); }
992 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
994 if (TheSame2(Index) == 0) { return Standard_False; }
995 return Standard_True;