0031303: Different calculation of offset direction in Adaptor2d_OffsetCurve and Geom2...
[occt.git] / src / Geom2dGcc / Geom2dGcc_Circ2d2TanRadGeo.cxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 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
973c2be1 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.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
7fd59977 14
578ce4be 15
5201d3e6 16#include <Adaptor2d_OffsetCurve.hxx>
7fd59977 17#include <ElCLib.hxx>
42cf5bc1 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>
42cf5bc1 24#include <Geom2dGcc_QCurve.hxx>
25#include <Geom2dInt_GInter.hxx>
7fd59977 26#include <gp_Ax2d.hxx>
27#include <gp_Circ2d.hxx>
28#include <gp_Lin2d.hxx>
42cf5bc1 29#include <gp_Pnt2d.hxx>
30#include <IntRes2d_Domain.hxx>
31#include <IntRes2d_IntersectionPoint.hxx>
7fd59977 32#include <Standard_NegativeValue.hxx>
33#include <Standard_OutOfRange.hxx>
34#include <StdFail_NotDone.hxx>
35#include <TColStd_Array1OfReal.hxx>
578ce4be 36
1d19db8d 37static const Standard_Integer aNbSolMAX = 16;
38
7fd59977 39// circulaire tant a une courbe et une droite ,de rayon donne
40//==============================================================
41
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//========================================================================
52
578ce4be 53Geom2dGcc_Circ2d2TanRadGeo::
54Geom2dGcc_Circ2d2TanRadGeo (const GccEnt_QualifiedLin& Qualified1,
55 const Geom2dGcc_QCurve& Qualified2,
56 const Standard_Real Radius ,
57 const Standard_Real Tolerance ):
7fd59977 58
59//========================================================================
60// initialisation des champs. +
61//========================================================================
62
1d19db8d 63cirsol(1,aNbSolMAX) ,
64qualifier1(1,aNbSolMAX),
65qualifier2(1,aNbSolMAX),
66TheSame1(1,aNbSolMAX) ,
67TheSame2(1,aNbSolMAX) ,
68pnttg1sol(1,aNbSolMAX),
69pnttg2sol(1,aNbSolMAX),
70par1sol(1,aNbSolMAX) ,
71par2sol(1,aNbSolMAX) ,
72pararg1(1,aNbSolMAX) ,
73pararg2(1,aNbSolMAX)
7fd59977 74{
75
74f5f8df 76 //========================================================================
77 // Traitement. +
78 //========================================================================
79
80 Standard_Real Tol = Abs(Tolerance);
81 Standard_Real thefirst = -100000.;
82 Standard_Real thelast = 100000.;
83 Standard_Real firstparam;
84 Standard_Real lastparam;
85 gp_Dir2d dirx(1.,0.);
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;
91 NbrSol = 0;
92 if (!(Qualified1.IsEnclosed() ||
93 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
94 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
95 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
96
9775fa61 97 throw GccEnt_BadQualifier();
74f5f8df 98 return;
99 }
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);
578ce4be 107 Geom2dAdaptor_Curve Cu2= Qualified2.Qualified();
9775fa61 108 if (Radius < 0.0) { throw Standard_NegativeValue(); }
74f5f8df 109 else {
110 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
111 // =======================================================
112 nbrcote1 = 1;
113 nbrcote2 = 1;
114 cote1(1) = Radius;
115 cote2(1) = Radius;
116 }
117 else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
118 // ==========================================================
119 nbrcote1 = 1;
120 nbrcote2 = 1;
121 cote1(1) = Radius;
122 cote2(1) = -Radius;
123 }
124 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
125 // ===========================================================
126 nbrcote1 = 1;
127 nbrcote2 = 1;
128 cote1(1) = -Radius;
129 cote2(1) = Radius;
130 }
131 else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
132 // =========================================================
133 nbrcote1 = 1;
134 nbrcote2 = 1;
135 cote1(1) = -Radius;
136 cote2(1) = -Radius;
137 }
138 if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
139 // =========================================================
140 nbrcote1 = 1;
141 nbrcote2 = 2;
142 cote1(1) = Radius;
143 cote2(1) = Radius;
144 cote2(2) = -Radius;
145 }
146 if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
147 // =========================================================
148 nbrcote1 = 2;
149 nbrcote2 = 1;
150 cote1(1) = Radius;
151 cote1(2) = -Radius;
152 cote2(1) = Radius;
153 }
154 else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
155 // =============================================================
156 nbrcote1 = 1;
157 nbrcote2 = 2;
158 cote1(1) = -Radius;
159 cote2(1) = Radius;
160 cote2(2) = -Radius;
161 }
162 if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
163 // ========================================================
164 nbrcote1 = 2;
165 nbrcote2 = 1;
166 cote1(1) = Radius;
167 cote1(2) = -Radius;
168 cote2(1) = -Radius;
169 }
170 else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
171 // =================================================================
172 nbrcote1 = 2;
173 nbrcote2 = 2;
174 cote1(1) = Radius;
175 cote1(2) = -Radius;
176 cote2(1) = Radius;
177 cote2(2) = -Radius;
178 }
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.
183 IntRes2d_Domain D1;
4c26106f 184 for (Standard_Integer jcote2 = 1; jcote2 <= nbrcote2 && NbrSol < aNbSolMAX; jcote2++) {
578ce4be 185 Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
68ad329c 186 //Adaptor2d_OffsetCurve C2(HCu2,cote2(jcote2));
187 Adaptor2d_OffsetCurve C2(HCu2, -cote2(jcote2));
5201d3e6 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);
578ce4be 192 Geom2dInt_TheIntConicCurveOfGInter Intp(Line,D1,C2,D2,Tol,Tol);
74f5f8df 193 if (Intp.IsDone()) {
194 if (!Intp.IsEmpty()) {
4c26106f 195 for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
74f5f8df 196 NbrSol++;
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();
204 }
205 else if (dc1.Dot(normL1) > 0.0) {
206 qualifier1(NbrSol) = GccEnt_outside;
207 }
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);
578ce4be 214 pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
74f5f8df 215 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
216 pnttg1sol(NbrSol));
217 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
218 pnttg2sol(NbrSol));
219 }
220 }
221 WellDone = Standard_True;
222 }
223 }
224 }
225 }
226}
7fd59977 227
228// circulaire tant a une courbe et un cercle ,de rayon donne
229//=============================================================
230
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//========================================================================
241
578ce4be 242Geom2dGcc_Circ2d2TanRadGeo::
243Geom2dGcc_Circ2d2TanRadGeo (const GccEnt_QualifiedCirc& Qualified1,
244 const Geom2dGcc_QCurve& Qualified2,
245 const Standard_Real Radius ,
246 const Standard_Real Tolerance ):
7fd59977 247
248//========================================================================
249// initialisation des champs. +
250//========================================================================
251
1d19db8d 252cirsol(1,aNbSolMAX) ,
253qualifier1(1,aNbSolMAX),
254qualifier2(1,aNbSolMAX),
255TheSame1(1,aNbSolMAX) ,
256TheSame2(1,aNbSolMAX) ,
257pnttg1sol(1,aNbSolMAX),
258pnttg2sol(1,aNbSolMAX),
259par1sol(1,aNbSolMAX) ,
260par2sol(1,aNbSolMAX) ,
261pararg1(1,aNbSolMAX) ,
262pararg2(1,aNbSolMAX)
7fd59977 263{
264
74f5f8df 265 //========================================================================
266 // Traitement. +
267 //========================================================================
268
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;
280 NbrSol = 0;
281 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
282 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
283 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
284 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
9775fa61 285 throw GccEnt_BadQualifier();
74f5f8df 286 return;
287 }
288 gp_Circ2d C1 = Qualified1.Qualified();
289 gp_Pnt2d center1(C1.Location());
578ce4be 290 Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
9775fa61 291 if (Radius < 0.0) { throw Standard_NegativeValue(); }
74f5f8df 292 else {
293 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
294 // =======================================================
295 nbrcote1 = 1;
296 nbrcote2 = 1;
297 cote1(1) = Radius;
298 cote2(1) = Radius;
299 }
300 else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
301 // ==========================================================
302 nbrcote1 = 1;
303 nbrcote2 = 1;
304 cote1(1) = Radius;
305 cote2(1) = -Radius;
306 }
307 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
308 // ===========================================================
309 nbrcote1 = 1;
310 nbrcote2 = 1;
311 cote1(1) = -Radius;
312 cote2(1) = Radius;
313 }
314 else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
315 // =========================================================
316 nbrcote1 = 1;
317 nbrcote2 = 1;
318 cote1(1) = -Radius;
319 cote2(1) = -Radius;
320 }
321 if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
322 // =========================================================
323 nbrcote1 = 1;
324 nbrcote2 = 2;
325 cote1(1) = Radius;
326 cote2(1) = Radius;
327 cote2(2) = -Radius;
328 }
329 if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
330 // =========================================================
331 nbrcote1 = 2;
332 nbrcote2 = 1;
333 cote1(1) = Radius;
334 cote1(2) = -Radius;
335 cote2(1) = Radius;
336 }
337 else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
338 // =============================================================
339 nbrcote1 = 1;
340 nbrcote2 = 2;
341 cote1(1) = -Radius;
342 cote2(1) = Radius;
343 cote2(2) = -Radius;
344 }
345 if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
346 // ========================================================
347 nbrcote1 = 2;
348 nbrcote2 = 1;
349 cote1(1) = Radius;
350 cote1(2) = -Radius;
351 cote2(1) = -Radius;
352 }
353 else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
354 // =================================================================
355 nbrcote1 = 2;
356 nbrcote2 = 2;
357 cote1(1) = Radius;
358 cote1(2) = -Radius;
359 cote2(1) = Radius;
360 cote2(2) = -Radius;
361 }
362 Standard_Real R1 = C1.Radius();
578ce4be 363 Geom2dInt_TheIntConicCurveOfGInter Intp;
4c26106f 364 for (Standard_Integer jcote1 = 1; jcote1 <= nbrcote1 && NbrSol < aNbSolMAX; jcote1++) {
74f5f8df 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++) {
578ce4be 370 Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
68ad329c 371 //Adaptor2d_OffsetCurve C2(HCu2,cote2(jcote2));
372 Adaptor2d_OffsetCurve C2(HCu2, -cote2(jcote2));
5201d3e6 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);
74f5f8df 377 Intp.Perform(Circ,D1,C2,D2,Tol,Tol);
378 if (Intp.IsDone()) {
379 if (!Intp.IsEmpty()) {
4c26106f 380 for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
74f5f8df 381 NbrSol++;
382 gp_Pnt2d Center(Intp.Point(i).Value());
383 cirsol(NbrSol) = gp_Circ2d(gp_Ax2d(Center,dirx),Radius);
384 // =======================================================
0797d9d3 385#ifdef OCCT_DEBUG
74f5f8df 386 gp_Dir2d dir1(Center.XY()-center1.XY());
7fd59977 387#else
74f5f8df 388 Center.XY() ;
389 center1.XY() ;
7fd59977 390#endif
74f5f8df 391 Standard_Real distcc1 = Center.Distance(center1);
392 if (!Qualified1.IsUnqualified()) {
393 qualifier1(NbrSol) = Qualified1.Qualifier();
394 }
395 else if (Abs(distcc1+Radius-R1) < Tol) {
396 qualifier1(NbrSol) = GccEnt_enclosed;
397 }
398 else if (Abs(distcc1-R1-Radius) < Tol) {
399 qualifier1(NbrSol) = GccEnt_outside;
400 }
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);
578ce4be 408 pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
74f5f8df 409 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
410 pnttg1sol(NbrSol));
411 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
412 pnttg2sol(NbrSol));
413 }
414 }
415 WellDone = Standard_True;
416 }
417 }
418 }
419 }
420}
7fd59977 421
422// circulaire tant a une courbe et un point ,de rayon donne
423//============================================================
424
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//========================================================================
435
578ce4be 436Geom2dGcc_Circ2d2TanRadGeo::
437Geom2dGcc_Circ2d2TanRadGeo (const Geom2dGcc_QCurve& Qualified1,
438 const gp_Pnt2d& Point2 ,
439 const Standard_Real Radius ,
440 const Standard_Real Tolerance ):
7fd59977 441
442//========================================================================
443// initialisation des champs. +
444//========================================================================
445
1d19db8d 446cirsol(1,aNbSolMAX) ,
447qualifier1(1,aNbSolMAX),
448qualifier2(1,aNbSolMAX),
449TheSame1(1,aNbSolMAX) ,
450TheSame2(1,aNbSolMAX) ,
451pnttg1sol(1,aNbSolMAX),
452pnttg2sol(1,aNbSolMAX),
453par1sol(1,aNbSolMAX) ,
454par2sol(1,aNbSolMAX) ,
455pararg1(1,aNbSolMAX) ,
456pararg2(1,aNbSolMAX)
7fd59977 457{
458
74f5f8df 459 //========================================================================
460 // Traitement. +
461 //========================================================================
462
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;
472 NbrSol = 0;
473 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
474 Qualified1.IsOutside() || Qualified1.IsUnqualified())) {
9775fa61 475 throw GccEnt_BadQualifier();
74f5f8df 476 return;
477 }
578ce4be 478 Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
9775fa61 479 if (Radius < 0.0) { throw Standard_NegativeValue(); }
74f5f8df 480 else {
481 if (Qualified1.IsEnclosed()) {
482 // ===========================
483 nbrcote1 = 1;
484 cote1(1) = Radius;
485 }
486 else if(Qualified1.IsOutside()) {
487 // ===============================
488 nbrcote1 = 1;
489 cote1(1) = -Radius;
490 }
491 else if(Qualified1.IsUnqualified()) {
492 // ===================================
493 nbrcote1 = 2;
494 cote1(1) = Radius;
495 cote1(2) = -Radius;
496 }
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);
578ce4be 501 Geom2dInt_TheIntConicCurveOfGInter Intp;
4c26106f 502 for (Standard_Integer jcote1 = 1; jcote1 <= nbrcote1 && NbrSol < aNbSolMAX; jcote1++) {
578ce4be 503 Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1);
68ad329c 504 //Adaptor2d_OffsetCurve Cu2(HCu1,cote1(jcote1));
505 Adaptor2d_OffsetCurve Cu2(HCu1,-cote1(jcote1));
5201d3e6 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);
74f5f8df 510 Intp.Perform(Circ,D1,Cu2,D2,Tol,Tol);
511 if (Intp.IsDone()) {
512 if (!Intp.IsEmpty()) {
4c26106f 513 for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++) {
74f5f8df 514 NbrSol++;
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.;
578ce4be 524 pnttg1sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol));
74f5f8df 525 pnttg2sol(NbrSol) = Point2;
526 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
527 pnttg1sol(NbrSol));
528 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
529 pnttg2sol(NbrSol));
530 }
531 }
532 WellDone = Standard_True;
533 }
534 }
535 }
536}
537
1d19db8d 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//=======================================================================
5201d3e6 546static void PrecRoot(const Adaptor2d_OffsetCurve& theC1,
547 const Adaptor2d_OffsetCurve& theC2,
578ce4be 548 const Standard_Real theU0,
549 const Standard_Real theV0,
578ce4be 550 Standard_Real& theUfinal,
551 Standard_Real& theVfinal)
74f5f8df 552{
1d19db8d 553/*
554It is necessary for precision to solve the system
555
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
559 \end{matrix}\right.
560
561Precision of any 2*2-system (two equation and two variables)
562
563 \left\{\begin{matrix}
564 S_{1}(u,v)=0\\
565 S_{2}(u,v)=0
566 \end{matrix}\right.
567
568by Newton method can be made as follows:
569
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}}
582 \end{matrix}\right.
583
584where u_{0} and v_{0} are initial values or values computed on previous iteration.
585*/
74f5f8df 586
1d19db8d 587 theUfinal = theU0;
588 theVfinal = theV0;
74f5f8df 589
74f5f8df 590 const Standard_Integer aNbIterMax = 100;
591
1d19db8d 592 Standard_Real aU = theU0, aV = theV0;
593 gp_Pnt2d aPu, aPv;
594 gp_Vec2d aD1u, aD1v, aD2u, aD2v;
74f5f8df 595
1d19db8d 596 Standard_Integer aNbIter = 0;
74f5f8df 597
1d19db8d 598 Standard_Real aStepU = 0.0, aStepV = 0.0;
74f5f8df 599
1d19db8d 600 Standard_Real aSQDistPrev = RealFirst();
74f5f8df 601
5201d3e6 602 theC1.D2(aU, aPu, aD1u, aD2u);
603 theC2.D2(aV, aPv, aD1v, aD2v);
578ce4be 604
1d19db8d 605 const Standard_Real aCrProd = Abs(aD1u.Crossed(aD1v));
606 if(aCrProd*aCrProd > 1.0e-6*
607 aD1u.SquareMagnitude()*aD1v.SquareMagnitude())
608 {
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.
612 return;
613 }
74f5f8df 614
615 do
616 {
1d19db8d 617 aNbIter++;
74f5f8df 618
1d19db8d 619 gp_Vec2d aVuv(aPv, aPu);
74f5f8df 620
1d19db8d 621 Standard_Real aSQDist = aVuv.SquareMagnitude();
622 if(IsEqual(aSQDist, 0.0))
623 break;
74f5f8df 624
1d19db8d 625 if((aNbIter == 1) || (aSQDist < aSQDistPrev))
74f5f8df 626 {
627 aSQDistPrev = aSQDist;
74f5f8df 628 theUfinal = aU;
629 theVfinal = aV;
630 }
74f5f8df 631
74f5f8df 632
1d19db8d 633 Standard_Real aG1 = aD1u.Magnitude();
634 Standard_Real aG2 = aD1v.Magnitude();
74f5f8df 635
1d19db8d 636 if(IsEqual(aG1, 0.0) || IsEqual(aG2, 0.0))
637 {//Here we do not processing singular cases.
638 break;
639 }
74f5f8df 640
1d19db8d 641 Standard_Real aF1 = aVuv.Dot(aD1u);
642 Standard_Real aF2 = aVuv.Dot(aD1v);
74f5f8df 643
1d19db8d 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);
7fd59977 648
1d19db8d 649 Standard_Real aTheta = aD1u*aD1v;
74f5f8df 650
1d19db8d 651 Standard_Real aS1 = aF1/aG1;
652 Standard_Real aS2 = aF2/aG2;
74f5f8df 653
1d19db8d 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));
74f5f8df 658
1d19db8d 659 Standard_Real aDet = aDS1u*aDS2v-aDS1v*aDS2u;
74f5f8df 660
1d19db8d 661 if(IsEqual(aDet, 0.0))
662 {
663 if(!IsEqual(aStepV, 0.0) && !IsEqual(aDS1u, 0.0))
664 {
665 aV += aStepV;
666 aU = aU - (aDS1v*aStepV - aS1)/aDS1u;
667 }
668 else if(!IsEqual(aStepU, 0.0) && !IsEqual(aDS1v, 0.0))
669 {
670 aU += aStepU;
671 aV = aV - (aDS1u*aStepU - aS1)/aDS1v;
672 }
673 else
674 {
675 break;
676 }
677 }
74f5f8df 678 else
1d19db8d 679 {
680 aStepU = -(aS1*aDS2v-aS2*aDS1v)/aDet;
681 aStepV = -(aS2*aDS1u-aS1*aDS2u)/aDet;
682
683 if(Abs(aStepU) < Epsilon(Abs(aU)))
684 {
685 if(Abs(aStepV) < Epsilon(Abs(aV)))
686 {
687 break;
688 }
689 }
74f5f8df 690
1d19db8d 691 aU += aStepU;
692 aV += aStepV;
693 }
74f5f8df 694
5201d3e6 695 theC1.D2(aU, aPu, aD1u, aD2u);
696 theC2.D2(aV, aPv, aD1v, aD2v);
74f5f8df 697 }
1d19db8d 698 while(aNbIter <= aNbIterMax);
699}
74f5f8df 700
74f5f8df 701
7fd59977 702
703// circulaire tant a deux courbes ,de rayon donne
704//==================================================
705
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//========================================================================
578ce4be 716Geom2dGcc_Circ2d2TanRadGeo::
717Geom2dGcc_Circ2d2TanRadGeo (const Geom2dGcc_QCurve& Qualified1,
718 const Geom2dGcc_QCurve& Qualified2,
719 const Standard_Real Radius ,
720 const Standard_Real Tolerance ):
7fd59977 721
722//========================================================================
723// initialisation des champs. +
724//========================================================================
725
1d19db8d 726cirsol(1,aNbSolMAX) ,
727qualifier1(1,aNbSolMAX),
728qualifier2(1,aNbSolMAX),
729TheSame1(1,aNbSolMAX) ,
730TheSame2(1,aNbSolMAX) ,
731pnttg1sol(1,aNbSolMAX),
732pnttg2sol(1,aNbSolMAX),
733par1sol(1,aNbSolMAX) ,
734par2sol(1,aNbSolMAX) ,
735pararg1(1,aNbSolMAX) ,
736pararg2(1,aNbSolMAX)
7fd59977 737{
738
74f5f8df 739 //========================================================================
740 // Traitement. +
741 //========================================================================
742
743 Standard_Real Tol = Abs(Tolerance);
5201d3e6 744#ifdef OCCT_DEBUG
745 const Standard_Real thefirst = -100000.;
746 const Standard_Real thelast = 100000.;
747#endif
74f5f8df 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;
754 NbrSol = 0;
755 if (!(Qualified1.IsEnclosed() || Qualified1.IsEnclosing() ||
756 Qualified1.IsOutside() || Qualified1.IsUnqualified()) ||
757 !(Qualified2.IsEnclosed() || Qualified2.IsEnclosing() ||
758 Qualified2.IsOutside() || Qualified2.IsUnqualified())) {
9775fa61 759 throw GccEnt_BadQualifier();
74f5f8df 760 return;
761 }
578ce4be 762 Geom2dAdaptor_Curve Cu1 = Qualified1.Qualified();
763 Geom2dAdaptor_Curve Cu2 = Qualified2.Qualified();
9775fa61 764 if (Radius < 0.0) { throw Standard_NegativeValue(); }
74f5f8df 765 else {
766 if (Qualified1.IsEnclosed() && Qualified2.IsEnclosed()) {
767 // =======================================================
768 nbrcote1 = 1;
769 nbrcote2 = 1;
770 cote1(1) = Radius;
771 cote2(1) = Radius;
772 }
773 else if(Qualified1.IsEnclosed() && Qualified2.IsOutside()) {
774 // ==========================================================
775 nbrcote1 = 1;
776 nbrcote2 = 1;
777 cote1(1) = Radius;
778 cote2(1) = -Radius;
779 }
780 else if (Qualified1.IsOutside() && Qualified2.IsEnclosed()) {
781 // ===========================================================
782 nbrcote1 = 1;
783 nbrcote2 = 1;
784 cote1(1) = -Radius;
785 cote2(1) = Radius;
786 }
787 else if(Qualified1.IsOutside() && Qualified2.IsOutside()) {
788 // =========================================================
789 nbrcote1 = 1;
790 nbrcote2 = 1;
791 cote1(1) = -Radius;
792 cote2(1) = -Radius;
793 }
794 if(Qualified1.IsEnclosed() && Qualified2.IsUnqualified()) {
795 // =========================================================
796 nbrcote1 = 1;
797 nbrcote2 = 2;
798 cote1(1) = Radius;
799 cote2(1) = Radius;
800 cote2(2) = -Radius;
801 }
802 if(Qualified1.IsUnqualified() && Qualified2.IsEnclosed()) {
803 // =========================================================
804 nbrcote1 = 2;
805 nbrcote2 = 1;
806 cote1(1) = Radius;
807 cote1(2) = -Radius;
808 cote2(1) = Radius;
809 }
810 else if(Qualified1.IsOutside() && Qualified2.IsUnqualified()) {
811 // =============================================================
812 nbrcote1 = 1;
813 nbrcote2 = 2;
814 cote1(1) = -Radius;
815 cote2(1) = Radius;
816 cote2(2) = -Radius;
817 }
818 if(Qualified1.IsUnqualified() && Qualified2.IsOutside()) {
819 // ========================================================
820 nbrcote1 = 2;
821 nbrcote2 = 1;
822 cote1(1) = Radius;
823 cote1(2) = -Radius;
824 cote2(1) = -Radius;
825 }
826 else if(Qualified1.IsUnqualified() && Qualified2.IsUnqualified()) {
827 // =================================================================
828 nbrcote1 = 2;
829 nbrcote2 = 2;
830 cote1(1) = Radius;
831 cote1(2) = -Radius;
832 cote2(1) = Radius;
833 cote2(2) = -Radius;
834 }
578ce4be 835 Geom2dInt_GInter Intp;
74f5f8df 836 for (Standard_Integer jcote1 = 1 ; jcote1 <= nbrcote1 ; jcote1++) {
578ce4be 837 Handle(Geom2dAdaptor_HCurve) HCu1 = new Geom2dAdaptor_HCurve(Cu1);
68ad329c 838 //Adaptor2d_OffsetCurve C1(HCu1,cote1(jcote1));
839 Adaptor2d_OffsetCurve C1(HCu1, -cote1(jcote1));
0797d9d3 840#ifdef OCCT_DEBUG
5201d3e6 841 Standard_Real firstparam = Max(C1.FirstParameter(), thefirst);
842 Standard_Real lastparam = Min(C1.LastParameter(), thelast);
ec7ed71c 843 IntRes2d_Domain D2C1(C1.Value(firstparam),firstparam,Tol,
844 C1.Value(lastparam),lastparam,Tol);
7fd59977 845#endif
4c26106f 846 for (Standard_Integer jcote2 = 1; jcote2 <= nbrcote2 && NbrSol < aNbSolMAX; jcote2++) {
578ce4be 847 Handle(Geom2dAdaptor_HCurve) HCu2 = new Geom2dAdaptor_HCurve(Cu2);
68ad329c 848 //Adaptor2d_OffsetCurve C2(HCu2,cote2(jcote2));
849 Adaptor2d_OffsetCurve C2(HCu2, -cote2(jcote2));
0797d9d3 850#ifdef OCCT_DEBUG
5201d3e6 851 firstparam = Max(C2.FirstParameter(), thefirst);
852 lastparam = Min(C2.LastParameter(),thelast);
ec7ed71c 853 IntRes2d_Domain D2C2(C2.Value(firstparam),firstparam,Tol,
854 C2.Value(lastparam),lastparam,Tol);
7fd59977 855#endif
74f5f8df 856 Intp.Perform(C1,C2,Tol,Tol);
857 if (Intp.IsDone()) {
858 if (!Intp.IsEmpty()) {
1d19db8d 859 const Standard_Real aSQApproxTol = Precision::Approximation() *
860 Precision::Approximation();
4c26106f 861 for (Standard_Integer i = 1; i <= Intp.NbPoints() && NbrSol < aNbSolMAX; i++)
74f5f8df 862 {
863 Standard_Real aU0 = Intp.Point(i).ParamOnFirst();
864 Standard_Real aV0 = Intp.Point(i).ParamOnSecond();
865
866 Standard_Real aU1 = aU0-Precision::PApproximation();
867 Standard_Real aV1 = aV0-Precision::PApproximation();
868
869 Standard_Real aU2 = aU0+Precision::PApproximation();
870 Standard_Real aV2 = aV0+Precision::PApproximation();
871
5201d3e6 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);
74f5f8df 876
1d19db8d 877 Standard_Real aDist1112 = P11.SquareDistance(P12);
878 Standard_Real aDist1122 = P11.SquareDistance(P22);
74f5f8df 879
1d19db8d 880 Standard_Real aDist1221 = P12.SquareDistance(P21);
881 Standard_Real aDist2122 = P21.SquareDistance(P22);
74f5f8df 882
1d19db8d 883 if( (Min(aDist1112, aDist1122) <= aSQApproxTol) &&
884 (Min(aDist1221, aDist2122) <= aSQApproxTol))
74f5f8df 885 {
1d19db8d 886 PrecRoot(C1, C2, aU0, aV0, aU0, aV0);
74f5f8df 887 }
888
889 NbrSol++;
5201d3e6 890 gp_Pnt2d Center(C1.Value(aU0));
74f5f8df 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();
578ce4be 899 pnttg1sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu1,pararg1(NbrSol));
900 pnttg2sol(NbrSol) = Geom2dGcc_CurveTool::Value(Cu2,pararg2(NbrSol));
74f5f8df 901 par1sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
902 pnttg1sol(NbrSol));
903 par2sol(NbrSol)=ElCLib::Parameter(cirsol(NbrSol),
904 pnttg2sol(NbrSol));
905 }
906 }
907
908 WellDone = Standard_True;
909 }
910 }
911 }
912 }
913}
7fd59977 914
915//=========================================================================
916
578ce4be 917Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
74f5f8df 918IsDone () const { return WellDone; }
7fd59977 919
578ce4be 920Standard_Integer Geom2dGcc_Circ2d2TanRadGeo::
74f5f8df 921NbSolutions () const { return NbrSol; }
7fd59977 922
578ce4be 923gp_Circ2d Geom2dGcc_Circ2d2TanRadGeo::
74f5f8df 924ThisSolution (const Standard_Integer Index) const
7fd59977 925{
9775fa61 926 if (!WellDone) { throw StdFail_NotDone(); }
927 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
7fd59977 928 return cirsol(Index);
929}
930
578ce4be 931void Geom2dGcc_Circ2d2TanRadGeo::
74f5f8df 932WhichQualifier(const Standard_Integer Index ,
933 GccEnt_Position& Qualif1 ,
934 GccEnt_Position& Qualif2 ) const
7fd59977 935{
9775fa61 936 if (!WellDone) { throw StdFail_NotDone(); }
937 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
7fd59977 938 else {
939 Qualif1 = qualifier1(Index);
940 Qualif2 = qualifier2(Index);
941 }
942}
943
578ce4be 944void Geom2dGcc_Circ2d2TanRadGeo::
74f5f8df 945Tangency1 (const Standard_Integer Index,
946 Standard_Real& ParSol,
947 Standard_Real& ParArg,
948 gp_Pnt2d& PntSol) const{
9775fa61 949 if (!WellDone) { throw StdFail_NotDone(); }
950 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
74f5f8df 951 else {
952 if (TheSame1(Index) == 0) {
953 ParSol = par1sol(Index);
954 ParArg = pararg1(Index);
955 PntSol = gp_Pnt2d(pnttg1sol(Index));
956 }
9775fa61 957 else { throw StdFail_NotDone(); }
74f5f8df 958 }
959}
7fd59977 960
578ce4be 961void Geom2dGcc_Circ2d2TanRadGeo::
74f5f8df 962Tangency2 (const Standard_Integer Index,
963 Standard_Real& ParSol,
964 Standard_Real& ParArg,
965 gp_Pnt2d& PntSol) const{
9775fa61 966 if (!WellDone) { throw StdFail_NotDone(); }
967 else if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
74f5f8df 968 else {
969 if (TheSame2(Index) == 0) {
970 ParSol = par2sol(Index);
971 ParArg = pararg2(Index);
972 PntSol = gp_Pnt2d(pnttg2sol(Index));
973 }
9775fa61 974 else { throw StdFail_NotDone(); }
74f5f8df 975 }
976}
7fd59977 977
578ce4be 978Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
74f5f8df 979IsTheSame1 (const Standard_Integer Index) const
7fd59977 980{
9775fa61 981 if (!WellDone) { throw StdFail_NotDone(); }
982 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
7fd59977 983
984 if (TheSame1(Index) == 0) { return Standard_False; }
985 return Standard_True;
986}
987
578ce4be 988Standard_Boolean Geom2dGcc_Circ2d2TanRadGeo::
74f5f8df 989IsTheSame2 (const Standard_Integer Index) const
7fd59977 990{
9775fa61 991 if (!WellDone) { throw StdFail_NotDone(); }
992 if (Index <= 0 ||Index > NbrSol) { throw Standard_OutOfRange(); }
7fd59977 993
994 if (TheSame2(Index) == 0) { return Standard_False; }
995 return Standard_True;
996}
997