1 // Created on: 1992-05-06
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16 
17 // a modifier le cas de 2 points confondus ( Insert a la place d'append ? )
18 
19 #include <ElCLib.hxx>
20 #include <gp.hxx>
21 #include <gp_Circ2d.hxx>
22 #include <gp_Elips2d.hxx>
23 #include <gp_Hypr2d.hxx>
24 #include <gp_Lin2d.hxx>
25 #include <gp_Parab2d.hxx>
26 #include <gp_Pnt2d.hxx>
27 #include <gp_Vec2d.hxx>
28 #include <IntCurve_IConicTool.hxx>
29 #include <IntCurve_IntConicConic.hxx>
30 #include <IntCurve_IntConicConic_Tool.hxx>
31 #include <IntCurve_PConic.hxx>
32 #include <IntImpParGen.hxx>
33 #include <IntRes2d_Domain.hxx>
34 #include <IntRes2d_IntersectionPoint.hxx>
35 #include <IntRes2d_IntersectionSegment.hxx>
36 #include <IntRes2d_TypeTrans.hxx>
37 #include <Precision.hxx>
38 #include <Standard_ConstructionError.hxx>
39 #include <Extrema_ExtElC2d.hxx>
40 
41 Standard_Boolean Affichage=Standard_False;
42 Standard_Boolean AffichageGraph=Standard_True;
43 
44 //modified by NIZHNY-MKK  Tue Feb 15 10:53:34 2000.BEGIN
45 // #define TOLERANCE_ANGULAIRE 0.00000001
46 #define TOLERANCE_ANGULAIRE 1.e-15 //the reason is at least to make an accordance between transition and position computation.
47 //modified by NIZHNY-MKK  Tue Feb 15 10:53:45 2000.END
48 
49 const Standard_Real PIsur2 = 0.5*M_PI;
50 
51 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
52 IntRes2d_Position FindPositionLL(Standard_Real&,const IntRes2d_Domain&);
53 const IntRes2d_IntersectionPoint SegmentToPoint( const IntRes2d_IntersectionPoint& Pa
54 						,const IntRes2d_Transition& T1a
55 						,const IntRes2d_Transition& T2a
56 						,const IntRes2d_IntersectionPoint& Pb
57 						,const IntRes2d_Transition& T1b
58 						,const IntRes2d_Transition& T2b);
59 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ProjectOnC2AndIntersectWithC2Domain(const gp_Circ2d & Circle1,const gp_Circ2d & Circle2,PeriodicInterval & C1DomainAndRes,PeriodicInterval & DomainC2,PeriodicInterval * SolutionC1,PeriodicInterval * SolutionC2,Standard_Integer & NbSolTotal,const Standard_Boolean IdentCircles)60 void ProjectOnC2AndIntersectWithC2Domain(const gp_Circ2d& Circle1
61                                          ,const gp_Circ2d& Circle2
62 					 ,PeriodicInterval& C1DomainAndRes
63 					 ,PeriodicInterval& DomainC2
64 					 ,PeriodicInterval* SolutionC1
65 					 ,PeriodicInterval* SolutionC2
66 					 ,Standard_Integer &NbSolTotal
67 					 ,const Standard_Boolean IdentCircles)
68 {
69 
70   if(C1DomainAndRes.IsNull()) return;
71   //-------------------------------------------------------------------------
72   //--  On cherche l intervalle correspondant sur C2
73   //--  Puis on intersecte l intervalle avec le domaine de C2
74   //--  Enfin, on cherche l intervalle correspondant sur C1
75   //--
76   Standard_Real C2inf =
77     ElCLib::CircleParameter(Circle2.Axis()
78 			    ,ElCLib::CircleValue(C1DomainAndRes.Binf
79 						 ,Circle1.Axis(),Circle1.Radius()));
80   Standard_Real C2sup =
81     ElCLib::CircleParameter(Circle2.Axis()
82 			    ,ElCLib::CircleValue(C1DomainAndRes.Bsup
83 						 ,Circle1.Axis(),Circle1.Radius()));
84 
85   PeriodicInterval C2Inter(C2inf,C2sup);
86 
87   if(!IdentCircles) {
88     if(C2Inter.Length() > M_PI)
89       C2Inter.Complement();
90   }
91   else {
92     if(C2sup<=C2inf) C2sup+=PIpPI;
93     if(C2inf>=PIpPI) {
94       C2sup-=PIpPI;
95       C2inf-=PIpPI;
96     }
97     C2Inter.Binf=C2inf;
98     C2Inter.Bsup=C2sup; //--- Verifier la longueur de l'intervalle sur C2
99     C2Inter.Bsup=C2inf+C1DomainAndRes.Bsup-C1DomainAndRes.Binf;
100   }
101 
102   PeriodicInterval C2InterAndDomain[2];
103 
104   for(Standard_Integer i=0; i<2 ; i++) {
105     C2InterAndDomain[i]=(i==0)?  DomainC2.FirstIntersection(C2Inter)
106                                : DomainC2.SecondIntersection(C2Inter);
107 
108     if(!C2InterAndDomain[i].IsNull()) {
109 
110       Standard_Real C1inf =
111 	ElCLib::CircleParameter(Circle1.Axis()
112 				,ElCLib::CircleValue(C2InterAndDomain[i].Binf
113 					,Circle2.Axis(),Circle2.Radius()));
114       Standard_Real C1sup =
115 	ElCLib::CircleParameter(Circle1.Axis()
116 				,ElCLib::CircleValue(C2InterAndDomain[i].Bsup
117 					,Circle2.Axis(),Circle2.Radius()));
118 
119       SolutionC1[NbSolTotal]=PeriodicInterval(C1inf,C1sup);
120       if(!IdentCircles) {
121 	if(SolutionC1[NbSolTotal].Length() > M_PI)
122 	  SolutionC1[NbSolTotal].Complement();
123       }
124       else {
125 	if(SolutionC1[NbSolTotal].Bsup <= SolutionC1[NbSolTotal].Binf) {
126 	  SolutionC1[NbSolTotal].Bsup+=PIpPI;
127 	}
128 	if(SolutionC1[NbSolTotal].Binf>=PIpPI) {
129 	  SolutionC1[NbSolTotal].Binf-=PIpPI;
130 	  SolutionC1[NbSolTotal].Bsup-=PIpPI;
131 	}
132       }
133       SolutionC2[NbSolTotal]=C2InterAndDomain[i];
134       NbSolTotal++;
135     }
136   }
137 }
138 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
139 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CircleCircleGeometricIntersection(const gp_Circ2d & C1,const gp_Circ2d & C2,const Standard_Real Tol,const Standard_Real TolTang,PeriodicInterval & C1_Res1,PeriodicInterval & C1_Res2,Standard_Integer & nbsol)140 void CircleCircleGeometricIntersection(const gp_Circ2d& C1
141 				       ,const gp_Circ2d& C2
142 				       ,const Standard_Real Tol
143 				       ,const Standard_Real TolTang
144 				       ,PeriodicInterval& C1_Res1
145 				       ,PeriodicInterval& C1_Res2
146 				       ,Standard_Integer& nbsol) {
147 
148   Standard_Real C1_binf1,C1_binf2=0,C1_bsup1,C1_bsup2=0;
149   Standard_Real dO1O2=(C1.Location()).Distance(C2.Location());
150   Standard_Real R1=C1.Radius();
151   Standard_Real R2=C2.Radius();
152   Standard_Real AbsR1mR2=Abs(R1-R2);
153   //----------------------------------------------------------------
154   if(dO1O2 > (R1+R2+Tol)) {
155     if(dO1O2 > (R1+R2+TolTang)) {
156       nbsol=0;
157       return;
158     }
159     else {
160       C1_binf1 = 0.0;
161       C1_bsup1 = 0.0;
162       nbsol = 1;
163     }
164   }
165   //----------------------------------------------------------------
166   else if(dO1O2 <= Tol  &&  AbsR1mR2<=Tol)  {
167     nbsol=3;
168     return;
169   }
170   else {
171     //----------------------------------------------------------------
172     Standard_Real R1pR2=R1+R2;
173     Standard_Real R1pTol=R1+Tol;
174     Standard_Real R1mTol=R1-Tol;
175 //    Standard_Real R1R1=R1*R1;
176     Standard_Real R2R2=R2*R2;
177     Standard_Real R1pTolR1pTol=R1pTol*R1pTol;
178     Standard_Real R1mTolR1mTol=R1mTol*R1mTol;
179     Standard_Real dO1O2dO1O2=dO1O2*dO1O2;
180     Standard_Real dAlpha1;
181     //--------------------------------------------------------------- Cas
182     //-- C2 coupe le cercle C1+ (=C(x1,y1,R1+Tol))
183     //--            1 seul segment donne par Inter C2 C1+
184     //--
185     if(dO1O2 > R1pR2-Tol) {
186       Standard_Real dx=(R1pTolR1pTol+dO1O2dO1O2-R2R2)/(dO1O2+dO1O2);
187       Standard_Real dy=(R1pTolR1pTol-dx*dx);
188       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
189       dAlpha1=ATan2(dy,dx);
190 
191       C1_binf1=-dAlpha1;
192       C1_bsup1=dAlpha1;
193       nbsol=1;
194     }
195     //--------------------------------------------------------------------
196     //--           2 segments donnes par Inter C2 avec C1- C1 C1+
197     //-- Seul le signe de dx change si dO1O2 < Max(R1,R2)
198     //--
199     else if(dO1O2 > AbsR1mR2-Tol) {  // -- +
200       //------------------- Intersection C2 C1+ --------------------------
201       Standard_Real dx=(R1pTolR1pTol+dO1O2dO1O2-R2R2)/(dO1O2+dO1O2);
202       Standard_Real dy=(R1pTolR1pTol-dx*dx);
203       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
204 
205       dAlpha1=ATan2(dy,dx);
206       C1_binf1=-dAlpha1;  C1_bsup2=dAlpha1;  //--  |...?     ?...|   Sur C1
207 
208       //------------------ Intersection C2 C1- -------------------------
209       dx=(R1mTolR1mTol+dO1O2dO1O2-R2R2)/(dO1O2+dO1O2);
210       dy=(R1mTolR1mTol-dx*dx);
211       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
212       dAlpha1=ATan2(dy,dx);
213 
214       C1_binf2=dAlpha1;  C1_bsup1=-dAlpha1;  //--  |...x     x...|   Sur C1
215       nbsol=2;
216       //------------------------------
217       //-- Les 2 intervalles sont ils
218       //-- en fait un seul inter ?
219       //--
220       if(dy==0) {    //-- Les 2 bornes internes sont identiques
221 	C1_bsup1 = C1_bsup2;
222 	nbsol = 1;
223       }
224       else {
225 	if(C1_binf1>C1_bsup1) {
226 	  dAlpha1 = C1_binf1; C1_binf1 = C1_bsup1; C1_bsup1 = dAlpha1;
227 	}
228 	if(C1_binf2>C1_bsup2) {
229 	  dAlpha1 = C1_binf2; C1_binf2 = C1_bsup2; C1_bsup2 = dAlpha1;
230 	}
231 	if(   ((C1_binf1<=C1_bsup2) && (C1_binf1>=C1_binf2))
232 	   || ((C1_bsup1<=C1_bsup2) && (C1_bsup1>=C1_binf2))) {
233 	  if(C1_binf1 > C1_binf2) C1_binf1 = C1_binf2;
234 	  if(C1_binf1 > C1_bsup2) C1_binf1 = C1_bsup2;
235 	  if(C1_bsup1 < C1_binf2) C1_bsup1 = C1_binf2;
236 	  if(C1_bsup1 < C1_bsup2) C1_bsup1 = C1_bsup2;
237 	  nbsol=1;
238 	}
239       }
240     }
241     //--------------------------------------------------------------
242     else {
243       if((dO1O2 > AbsR1mR2-TolTang) && (AbsR1mR2-TolTang)>0.0) {
244 	C1_binf1=0.0;
245 	C1_bsup1=0.0;
246 	nbsol = 1;
247       }
248       else {
249 	nbsol=0; return ;
250       }
251     }
252   }
253 
254   //-- std::cout<<" C1_binf1:"<<C1_binf1;
255   //-- std::cout<<" C1_bsup1:"<<C1_bsup1;
256   //-- std::cout<<" C1_binf2:"<<C1_binf2;
257   //-- std::cout<<" C1_bsup2:"<<C1_bsup2<<std::endl;
258   //----------------------------------------------------------------
259   //-- Mise en forme des resultats :
260   //--    Les calculs ont ete fait dans le repere x1,y1, (O1,O2)
261   //--    On se ramene au repere propre a C1
262 
263   gp_Vec2d Axe1=C1.XAxis().Direction();
264   gp_Vec2d AxeO1O2=gp_Vec2d(C1.Location(),C2.Location());
265 
266   Standard_Real dAngle1;
267   if(AxeO1O2.Magnitude() <= gp::Resolution())
268     dAngle1=Axe1.Angle(C2.XAxis().Direction());
269   else
270     dAngle1=Axe1.Angle(AxeO1O2);
271 
272   if(C1.IsDirect() == Standard_False) {
273     dAngle1 = -dAngle1;
274   }
275 
276 
277   C1_binf1+=dAngle1;  C1_bsup1+=dAngle1;
278 
279   //-- par construction aucun des segments ne peut exceder PI
280   //-- (permet de ne pas gerer trop de cas differents)
281 
282   C1_Res1.SetValues(C1_binf1,C1_bsup1);
283   if(C1_Res1.Length() > M_PI) C1_Res1.Complement();
284 
285   if(nbsol==2) {
286     C1_binf2+=dAngle1;  C1_bsup2+=dAngle1;
287     C1_Res2.SetValues(C1_binf2,C1_bsup2);
288     if(C1_Res2.Length() > M_PI) C1_Res2.Complement();
289   }
290   else {
291     C1_Res2.SetNull();
292   }
293 }
294 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
295 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ProjectOnLAndIntersectWithLDomain(const gp_Circ2d & Circle,const gp_Lin2d & Line,PeriodicInterval & CDomainAndRes,Interval & LDomain,PeriodicInterval * CircleSolution,Interval * LineSolution,Standard_Integer & NbSolTotal,const IntRes2d_Domain & RefLineDomain,const IntRes2d_Domain &)296 void ProjectOnLAndIntersectWithLDomain(const gp_Circ2d& Circle
297 				       ,const gp_Lin2d& Line
298 				       ,PeriodicInterval& CDomainAndRes
299 				       ,Interval& LDomain
300 				       ,PeriodicInterval* CircleSolution
301 				       ,Interval* LineSolution
302 				       ,Standard_Integer &NbSolTotal
303 				       ,const IntRes2d_Domain& RefLineDomain
304 //				       ,const IntRes2d_Domain& )
305 				       ,const IntRes2d_Domain& )
306 {
307 
308 
309   if(CDomainAndRes.IsNull()) return;
310   //-------------------------------------------------------------------------
311   //--  On cherche l intervalle correspondant sur C2
312   //--  Puis on intersecte l intervalle avec le domaine de C2
313   //--  Enfin, on cherche l intervalle correspondant sur C1
314   //--
315 
316   Standard_Real Linf=ElCLib::Parameter(Line
317 			     ,ElCLib::CircleValue(CDomainAndRes.Binf
318 						 ,Circle.Axis()
319 						 ,Circle.Radius()));
320   Standard_Real Lsup=ElCLib::Parameter(Line
321 			     ,ElCLib::CircleValue(CDomainAndRes.Bsup
322 						 ,Circle.Axis()
323 						 ,Circle.Radius()));
324 
325   Interval LInter(Linf,Lsup);   //-- Necessairement Borne
326 
327   Interval LInterAndDomain=LDomain.IntersectionWithBounded(LInter);
328 
329   if(!LInterAndDomain.IsNull) {
330 
331     Standard_Real DomLinf = (RefLineDomain.HasFirstPoint())? RefLineDomain.FirstParameter() : -Precision::Infinite();
332     Standard_Real DomLsup = (RefLineDomain.HasLastPoint())? RefLineDomain.LastParameter() : Precision::Infinite();
333 
334     Linf = LInterAndDomain.Binf;
335     Lsup = LInterAndDomain.Bsup;
336 
337     if(Linf<DomLinf) {
338       Linf = DomLinf;
339     }
340     if(Lsup<DomLinf) {
341       Lsup = DomLinf;
342     }
343 
344     if(Linf>DomLsup) {
345       Linf = DomLsup;
346     }
347     if(Lsup>DomLsup) {
348       Lsup = DomLsup;
349     }
350 
351     LInterAndDomain.Binf = Linf;
352     LInterAndDomain.Bsup = Lsup;
353 
354 #if 0
355     Standard_Real Cinf =
356       ElCLib::CircleParameter(Circle.Axis()
357 			      ,ElCLib::LineValue(LInterAndDomain.Binf,
358 					Line.Position()));
359     Standard_Real Csup =
360       ElCLib::CircleParameter(Circle.Axis()
361 			      ,ElCLib::LineValue(LInterAndDomain.Bsup
362 					,Line.Position()));
363 
364     if(Cinf<CDomainAndRes.Binf) Cinf = CDomainAndRes.Binf;
365     if(Csup>CDomainAndRes.Bsup) Csup = CDomainAndRes.Bsup;
366 #else
367     Standard_Real Cinf=CDomainAndRes.Binf;
368     Standard_Real Csup=CDomainAndRes.Bsup;
369 #endif
370     if(Cinf>=Csup) { Cinf = CDomainAndRes.Binf; Csup = CDomainAndRes.Bsup; }
371     CircleSolution[NbSolTotal]=PeriodicInterval(Cinf,Csup);
372     if(CircleSolution[NbSolTotal].Length() > M_PI)
373       CircleSolution[NbSolTotal].Complement();
374 
375     LineSolution[NbSolTotal]=LInterAndDomain;
376     NbSolTotal++;
377   }
378 }
379 
380 //=======================================================================
381 //function : LineCircleGeometricIntersection
382 //purpose  :
383 //~~ On cherche des segments d intersection dans le `tuyau`
384 //~~   R+Tol   R-Tol  ( Tol est TolConf : Tolerance de confusion d arc)
385 //~~ On Cherche un point d intersection a une distance TolTang du cercle.
386 //=======================================================================
LineCircleGeometricIntersection(const gp_Lin2d & Line,const gp_Circ2d & Circle,const Standard_Real Tol,const Standard_Real TolTang,PeriodicInterval & CInt1,PeriodicInterval & CInt2,Standard_Integer & nbsol)387 void LineCircleGeometricIntersection(const gp_Lin2d& Line,
388 				     const gp_Circ2d& Circle,
389 				     const Standard_Real Tol,
390 				     const Standard_Real TolTang,
391 				     PeriodicInterval& CInt1,
392 				     PeriodicInterval& CInt2,
393 				     Standard_Integer& nbsol)
394 {
395 
396 
397   Standard_Real dO1O2=Line.Distance(Circle.Location());
398   Standard_Real R=Circle.Radius();
399   Standard_Real RmTol=R-Tol;
400   Standard_Real binf1,binf2=0,bsup1,bsup2=0;
401 
402   //----------------------------------------------------------------
403   if(dO1O2 > (R+Tol))  {  //-- pas d intersection avec le 'tuyau'
404     if(dO1O2 > (R+TolTang)) {
405       nbsol=0;
406       return;
407     }
408     else {
409       binf1=0.0;
410       bsup1=0.0;
411       nbsol=1;
412     }
413   }
414   else {
415     //----------------------------------------------------------------
416     Standard_Boolean b2Sol;
417     Standard_Real dAlpha1;
418     //---------------------------------------------------------------
419     //-- Line coupe le cercle Circle+ (=C(x1,y1,R1+Tol))
420     b2Sol=Standard_False;
421     if (R>dO1O2+TolTang) {
422       Standard_Real aX2, aTol2;
423       //
424       aTol2=Tol*Tol;
425       aX2=4.*(R*R-dO1O2*dO1O2);
426       if (aX2>aTol2) {
427 	b2Sol=!b2Sol;
428       }
429     }
430     if(dO1O2 > RmTol && !b2Sol) {
431     //if(dO1O2 > RmTol) {
432       Standard_Real dx=dO1O2;
433       Standard_Real dy=0.0;     //(RpTol*RpTol-dx*dx); //Patch !!!
434       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
435       dAlpha1=ATan2(dy,dx);
436 
437       binf1=-dAlpha1;
438       bsup1=dAlpha1;
439       nbsol=1;
440     }
441     //--------------------------------------------------------------------
442     //--           2 segments donnes par Inter Line avec Circle-  Circle+
443     //--
444     else {
445       //------------------- Intersection Line Circle+ --------------------------
446       Standard_Real dx=dO1O2;
447       Standard_Real dy=R*R-dx*dx;    //(RpTol*RpTol-dx*dx); //Patch !!!
448       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
449 
450       dAlpha1=ATan2(dy,dx);
451       binf1=-dAlpha1;  bsup2=dAlpha1;  //--  |...?     ?...|   Sur C1
452 
453       //------------------ Intersection Line Circle-  -------------------------
454       dy=R*R-dx*dx;                  //(RmTol*RmTol-dx*dx); //Patch !!!
455       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
456       dAlpha1=ATan2(dy,dx);
457 
458       binf2=dAlpha1;  bsup1=-dAlpha1;  //--  |...x     x...|   Sur C1
459 
460       if((dAlpha1*R)<(Max(Tol,TolTang))) {
461 	bsup1 = bsup2;
462 	nbsol = 1;
463       }
464       else {
465 	nbsol=2;
466       }
467     }
468   }
469   //--------------------------------------------------------------
470   //-- Mise en forme des resultats :
471   //--    Les calculs ont ete fait dans le repere x1,y1, (O1,O2)
472   //--    On se ramene au repere propre a C1
473 
474   Standard_Real dAngle1=(Circle.XAxis().Direction()).Angle(Line.Direction());
475 
476 #if 0
477   //---------------------------------------------
478   //-- Si le cercle est indirect alors l origine
479   //-- est vue en -dAngle1.
480   //--
481   if(Circle.IsDirect() == Standard_False) {
482     dAngle1 = -dAngle1;
483   }
484 #endif
485 
486 
487   Standard_Real a,b,c,d;
488   Line.Coefficients(a,b,c);
489 
490   d = a*Circle.Location().X() + b*Circle.Location().Y() + c;
491 
492   if(d>0.0)  dAngle1+= PIsur2;
493   else       dAngle1-= PIsur2;
494 
495 
496   if(dAngle1<0.0) dAngle1+=PIpPI;
497   else if(dAngle1>PIpPI) dAngle1-=PIpPI;
498 
499 
500   binf1+=dAngle1;  bsup1+=dAngle1;
501 
502   //-- par construction aucun des segments ne peut exceder PI
503   //-- (permet de ne pas gerer trop de cas differents)
504 
505   if(Circle.IsDirect() == Standard_False) {
506     Standard_Real t=binf1; binf1=bsup1; bsup1=t;
507     binf1 = -binf1;
508     bsup1 = -bsup1;
509   }
510 
511 
512   CInt1.SetValues(binf1,bsup1);
513   if(CInt1.Length() > M_PI) CInt1.Complement();
514 
515 
516   if(nbsol==2) {
517     binf2+=dAngle1;  bsup2+=dAngle1;
518 
519     if(Circle.IsDirect() == Standard_False) {
520       Standard_Real t=binf2; binf2=bsup2; bsup2=t;
521       binf2 = -binf2;
522       bsup2 = -bsup2;
523     }
524 
525     CInt2.SetValues(binf2,bsup2);
526     if(CInt2.Length() > M_PI) CInt2.Complement();
527   }
528 //  Modified by Sergey KHROMOV - Thu Oct 26 17:51:05 2000 Begin
529   else {
530     if (CInt1.Bsup > PIpPI && CInt1.Binf < PIpPI) {
531       nbsol = 2;
532       binf2 = CInt1.Binf;
533       bsup2 = PIpPI;
534       binf1 = 0.;
535       CInt1.SetValues(binf1,CInt1.Bsup - PIpPI);
536       if(CInt1.Length() > M_PI) CInt1.Complement();
537       CInt2.SetValues(binf2,bsup2);
538       if(CInt2.Length() > M_PI) CInt2.Complement();
539     }
540   }
541 //  Modified by Sergey KHROMOV - Thu Oct 26 17:51:13 2000 End
542 }
543 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
544 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DomainIntersection(const IntRes2d_Domain & Domain,const Standard_Real U1inf,const Standard_Real U1sup,Standard_Real & Res1inf,Standard_Real & Res1sup,IntRes2d_Position & PosInf,IntRes2d_Position & PosSup)545 void DomainIntersection(const IntRes2d_Domain& Domain
546 			,const Standard_Real U1inf
547 			,const Standard_Real U1sup
548 			,Standard_Real& Res1inf
549 			,Standard_Real& Res1sup
550 			,IntRes2d_Position& PosInf
551 			,IntRes2d_Position& PosSup) {
552 
553   if(Domain.HasFirstPoint()) {
554     if(U1sup < (Domain.FirstParameter()-Domain.FirstTolerance())) {
555       Res1inf=1; Res1sup=-1;
556       return;
557     }
558     if(U1inf>(Domain.FirstParameter()+Domain.FirstTolerance())) {
559       Res1inf=U1inf;
560       PosInf=IntRes2d_Middle;
561     }
562     else {
563       Res1inf=Domain.FirstParameter();
564       PosInf=IntRes2d_Head;
565     }
566   }
567   else {
568     Res1inf=U1inf;
569     PosInf=IntRes2d_Middle;
570   }
571 
572   if(Domain.HasLastPoint()) {
573     if(U1inf >(Domain.LastParameter()+Domain.LastTolerance())) {
574       Res1inf=1; Res1sup=-1;
575       return;
576     }
577     if(U1sup<(Domain.LastParameter()-Domain.LastTolerance())) {
578       Res1sup=U1sup;
579       PosSup=IntRes2d_Middle;
580     }
581     else {
582       Res1sup=Domain.LastParameter();
583       PosSup=IntRes2d_End;
584     }
585   }
586   else {
587     Res1sup=U1sup;
588     PosSup=IntRes2d_Middle;
589   }
590   //-- Si un des points est en bout ,
591   //-- on s assure que les parametres sont corrects
592   if(Res1inf>Res1sup) {
593     if(PosSup==IntRes2d_Middle) {
594       Res1sup=Res1inf;
595     }
596     else {
597       Res1inf=Res1sup;
598     }
599   }
600   //--- Traitement des cas ou une intersection vraie est dans la tolerance
601   //--  d un des bouts
602   /*if(PosInf==IntRes2d_Head) {
603     if(Res1sup <= (Res1inf+Domain.FirstTolerance())) {
604       Res1sup=Res1inf;
605       PosSup=IntRes2d_Head;
606     }
607   }
608   if(PosSup==IntRes2d_End) {
609     if(Res1inf >= (Res1sup-Domain.LastTolerance())) {
610       Res1inf=Res1sup;
611       PosInf=IntRes2d_End;
612     }
613   }*/
614 }
615 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
616 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LineLineGeometricIntersection(const gp_Lin2d & L1,const gp_Lin2d & L2,const Standard_Real Tol,Standard_Real & U1,Standard_Real & U2,Standard_Real & SinDemiAngle,Standard_Integer & nbsol)617 void LineLineGeometricIntersection(const gp_Lin2d& L1
618 				   ,const gp_Lin2d& L2
619 				   ,const Standard_Real Tol
620 				   ,Standard_Real& U1
621 				   ,Standard_Real& U2
622 				   ,Standard_Real& SinDemiAngle
623 				   ,Standard_Integer& nbsol) {
624 
625   Standard_Real U1x=L1.Direction().X();
626   Standard_Real U1y=L1.Direction().Y();
627   Standard_Real U2x=L2.Direction().X();
628   Standard_Real U2y=L2.Direction().Y();
629   Standard_Real Uo21x = L2.Location().X() - L1.Location().X();
630   Standard_Real Uo21y = L2.Location().Y() - L1.Location().Y();
631 
632   Standard_Real D=U1y*U2x-U1x*U2y;
633 
634 //modified by NIZHNY-MKK  Tue Feb 15 10:54:04 2000.BEGIN
635 //   if(Abs(D)<1e-15) { //-- Droites //
636   if(Abs(D) < TOLERANCE_ANGULAIRE) {
637 //modified by NIZHNY-MKK  Tue Feb 15 10:54:11 2000.END
638     D=U1y*Uo21x - U1x*Uo21y;
639     nbsol=(Abs(D)<=Tol)? 2 : 0;
640   }
641   else {
642     U1=(Uo21y * U2x - Uo21x * U2y)/D;
643     U2=(Uo21y * U1x - Uo21x * U1y)/D;
644 
645     //------------------- Calcul du Sin du demi angle  entre L1 et L2
646     //----
647     if(D<0.0) D=-D;
648     if(D>1.0) D=1.0;                      //-- Deja vu !
649     SinDemiAngle=Sin(0.5*ASin(D));
650     nbsol=1;
651   }
652 }
653 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
654 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
655 /*IntCurve_IntConicConic::IntCurve_IntConicConic(const gp_Lin2d& L1
656 					       ,const IntRes2d_Domain& D1
657 					       ,const gp_Lin2d& L2
658 					       ,const IntRes2d_Domain& D2
659 					       ,const Standard_Real TolConf
660 					       ,const Standard_Real Tol)  {
661   Perform(L1,D1,L2,D2,TolConf,Tol);
662 }
663 
664 
665 IntCurve_IntConicConic::IntCurve_IntConicConic(const gp_Lin2d& L1
666 					       ,const IntRes2d_Domain& D1
667 					       ,const gp_Circ2d& C2
668 					       ,const IntRes2d_Domain& D2
669 					       ,const Standard_Real TolConf
670 					       ,const Standard_Real Tol) {
671 
672   Perform(L1,D1,C2,D2,TolConf,Tol);
673 }
674 
675 
676 IntCurve_IntConicConic::IntCurve_IntConicConic(const gp_Circ2d& C1
677                                               ,const IntRes2d_Domain& D1
678                                               ,const gp_Circ2d& C2
679                                               ,const IntRes2d_Domain& D2
680 					      ,const Standard_Real TolConf
681                                               ,const Standard_Real Tol) {
682   SetReversedParameters(Standard_False);
683   Perform(C1,D1,C2,D2,TolConf,Tol);
684 }*/ //amv OCC12547
685 //----------------------------------------------------------------------
Perform(const gp_Circ2d & Circle1,const IntRes2d_Domain & DomainCirc1,const gp_Circ2d & _Circle2,const IntRes2d_Domain & _DomainCirc2,const Standard_Real TolConf,const Standard_Real Tol)686 void IntCurve_IntConicConic::Perform(const gp_Circ2d& Circle1
687 				,const IntRes2d_Domain& DomainCirc1
688 				,const gp_Circ2d& _Circle2
689 				,const IntRes2d_Domain& _DomainCirc2
690 				,const Standard_Real TolConf,const Standard_Real Tol) {
691 
692 
693 //-- TRES TRES MAL FAIT    A REPRENDRE UN JOUR ....   (lbr Octobre 98)
694   gp_Circ2d Circle2=_Circle2;
695   IntRes2d_Domain  DomainCirc2=_DomainCirc2;
696   Standard_Boolean IndirectCircles=Standard_False;
697   if(Circle1.IsDirect() != _Circle2.IsDirect())
698   {
699     IndirectCircles=Standard_True;
700     Circle2=_Circle2.Reversed();
701     DomainCirc2.SetValues(_DomainCirc2.LastPoint(),
702       PIpPI-_DomainCirc2.LastParameter(),
703       _DomainCirc2.LastTolerance(),
704       _DomainCirc2.FirstPoint(),
705       PIpPI-_DomainCirc2.FirstParameter(),
706       _DomainCirc2.FirstTolerance());
707     DomainCirc2.SetEquivalentParameters(0.0,PIpPI);
708   }
709 
710   this->ResetFields();
711   Standard_Integer nbsol=0;
712   PeriodicInterval C1_Int1,C1_Int2;
713 
714   //------- Intersection sans tenir compte du domaine  ----> nbsol=0,1,2,3
715   CircleCircleGeometricIntersection(Circle1,Circle2,TolConf,Tol,C1_Int1,C1_Int2,nbsol);
716   done=Standard_True;
717 
718   if(nbsol==0) { //-- Pas de solutions
719     return;
720   }
721 
722   PeriodicInterval C1Domain(DomainCirc1);
723   //-- On se ramene entre 0 et 2PI
724   Standard_Real deltat = C1Domain.Bsup-C1Domain.Binf;
725   if(deltat>=PIpPI)
726   {
727     // make deltat not including the upper limit
728     deltat=NextAfter(PIpPI, 0.);
729   }
730 
731   while(C1Domain.Binf >= PIpPI)
732     C1Domain.Binf-=PIpPI;
733   while(C1Domain.Binf <  0.0)
734     C1Domain.Binf+=PIpPI;
735 
736   C1Domain.Bsup=C1Domain.Binf+deltat;
737 
738   PeriodicInterval C2Domain(DomainCirc2);
739   deltat = C2Domain.Bsup-C2Domain.Binf;
740   if(deltat>=PIpPI)
741   {
742     deltat=NextAfter(PIpPI, 0.);
743   }
744 
745   while(C2Domain.Binf >= PIpPI)
746     C2Domain.Binf-=PIpPI;
747   while(C2Domain.Binf <  0.0)
748     C2Domain.Binf+=PIpPI;
749 
750   C2Domain.Bsup=C2Domain.Binf+deltat;
751 
752   Standard_Boolean IdentCircles=Standard_False;
753 
754   if(nbsol>2)
755   {
756     //-- Les 2 cercles sont confondus a Tol pres
757     C1_Int1.SetValues(0,PIpPI);
758     C1_Int2.SetNull();
759     //---------------------------------------------------------------
760     //-- Flag utilise pour specifier que les intervalles manipules
761     //--   peuvent etre de longueur superieure a pi.
762     //-- Pour des cercles non identiques, on a necessairement cette
763     //--   condition sur les resultats de l intersection geometrique
764     //--   ce qui permet de normaliser rapidement les intervalles.
765     //--   ex: -1 4 -> longueur > PI
766     //--        donc -1 4 devient  4 , 2*pi-1
767     //---------------------------------------------------------------
768     IdentCircles=Standard_True;
769   }
770 
771   Standard_Integer NbSolTotal=0;
772   PeriodicInterval SolutionC1[4];
773   PeriodicInterval SolutionC2[4];
774 
775   //----------------------------------------------------------------------
776   //----------- Traitement du premier intervalle Geometrique  C1_Int1 ----
777   //----------------------------------------------------------------------
778   //-- NbSolTotal est incremente a chaque Intervalle solution.
779   //-- On stocke les intervalles dans les tableaux : SolutionC1(C2)
780   //-- Dimensionnes a 4 elements.
781   //-- des Exemples faciles donnent 3 Intersections
782   //-- des Problemes numeriques peuvent en donner 4 ??????
783   //--
784   PeriodicInterval C1DomainAndRes=C1Domain.FirstIntersection(C1_Int1);
785 
786   ProjectOnC2AndIntersectWithC2Domain(Circle1,Circle2
787 				      ,C1DomainAndRes
788 				      ,C2Domain
789 				      ,SolutionC1,SolutionC2
790 				      ,NbSolTotal
791 				      ,IdentCircles);
792   //----------------------------------------------------------------------
793   //-- Seconde Intersection :  Par exemple :     2*PI-1  2*PI+1
794   //--                         Intersecte avec     0.5   2*PI-0.5
795   //--     Donne les intervalles : 0.5,1    et  2*PI-1,2*PI-0.5
796   //--
797   C1DomainAndRes=C1Domain.SecondIntersection(C1_Int1);
798 
799   ProjectOnC2AndIntersectWithC2Domain(Circle1,Circle2
800 				      ,C1DomainAndRes
801 				      ,C2Domain
802 				      ,SolutionC1,SolutionC2
803 				      ,NbSolTotal
804 				      ,IdentCircles);
805 
806   //----------------------------------------------------------------------
807   //----------- Traitement du second intervalle Geometrique   C1_Int2 ----
808   //----------------------------------------------------------------------
809   if(nbsol==2)
810   {
811     C1DomainAndRes=C1Domain.FirstIntersection(C1_Int2);
812 
813     ProjectOnC2AndIntersectWithC2Domain(Circle1,Circle2
814 					,C1DomainAndRes
815 					,C2Domain
816 					,SolutionC1,SolutionC2
817 					,NbSolTotal
818 					,IdentCircles);
819     //--------------------------------------------------------------------
820     C1DomainAndRes=C1Domain.SecondIntersection(C1_Int2);
821 
822     ProjectOnC2AndIntersectWithC2Domain(Circle1,Circle2
823 					,C1DomainAndRes
824 					,C2Domain
825 					,SolutionC1,SolutionC2
826 					,NbSolTotal
827 					,IdentCircles);
828   }
829   //----------------------------------------------------------------------
830   //-- Calcul de toutes les transitions et Positions.
831   //--
832   //----------------------------------------------------------------------
833   //-- On determine si des intervalles sont reduit a des points
834   //--      ( Rayon * Intervalle.Length()    <    Tol   )
835   //--
836   Standard_Real R1=Circle1.Radius();
837   Standard_Real R2=Circle2.Radius();
838   Standard_Real Tol2=Tol+Tol;     //---- Pour eviter de toujours retourner
839                                   //des segments
840   Standard_Integer i ;
841   if(Tol < (1e-10))
842     Tol2 = 1e-10;
843 
844   for( i=0; i<NbSolTotal ; i++)
845   {
846     if(((R1 * SolutionC1[i].Length()) <=Tol2) &&
847               ((R2 * SolutionC2[i].Length())<=Tol2))
848     {
849       Standard_Real t=(SolutionC1[i].Binf+SolutionC1[i].Bsup)*0.5;
850       SolutionC1[i].Binf=SolutionC1[i].Bsup=t;
851 
852       t=(SolutionC2[i].Binf+SolutionC2[i].Bsup)*0.5;
853       SolutionC2[i].Binf=SolutionC2[i].Bsup=t;
854     }
855   }
856 
857   //----------------------------------------------------------------------
858   //-- Traitement des intervalles (ou des points obtenus)
859   //--
860   gp_Ax22d Axis2C1=Circle1.Axis();
861   gp_Ax22d Axis2C2=Circle2.Axis();
862   gp_Pnt2d P1a,P1b,P2a,P2b;
863   gp_Vec2d Tan1,Tan2,Norm1,Norm2;
864   IntRes2d_Transition T1a,T1b,T2a,T2b;
865   IntRes2d_Position Pos1a,Pos1b,Pos2a,Pos2b;
866 
867   Standard_Boolean isOpposite =
868     ((Circle1.Location().SquareDistance(Circle2.Location())) > (R1*R1+R2*R2)) ?
869           Standard_True : Standard_False;
870 
871   //if(Circle1.IsDirect()) { std::cout<<" C1 Direct"<<std::endl; } else { std::cout<<" C1 INDirect"<<std::endl; }
872   //if(Circle2.IsDirect()) { std::cout<<" C2 Direct"<<std::endl; } else { std::cout<<" C2 INDirect"<<std::endl; }
873 
874   for(i=0; i<NbSolTotal; i++)
875   {
876     Standard_Real C2inf  = isOpposite ? SolutionC2[i].Bsup : SolutionC2[i].Binf;
877     Standard_Real C2sup  = isOpposite ? SolutionC2[i].Binf : SolutionC2[i].Bsup;
878     Standard_Real C1tinf = SolutionC1[i].Binf, C2tinf = C2inf;
879     Standard_Real C1inf=NormalizeOnCircleDomain(C1tinf,DomainCirc1);
880                   C2inf=NormalizeOnCircleDomain(C2tinf,DomainCirc2);
881 
882     Standard_Boolean isOutOfRange = Standard_False;
883     if(C1inf < DomainCirc1.FirstParameter())
884     {
885       if(C1tinf < DomainCirc1.FirstParameter())
886       {
887         C1inf = DomainCirc1.FirstParameter();
888         isOutOfRange = Standard_True;
889       }
890       else
891       {
892         C1inf = C1tinf;
893       }
894     }
895 
896     if(C1inf > DomainCirc1.LastParameter())
897     {
898       if(C1tinf > DomainCirc1.LastParameter())
899       {
900         C1inf = DomainCirc1.LastParameter();
901         isOutOfRange = Standard_True;
902       }
903       else
904       {
905         C1inf = C1tinf;
906       }
907     }
908 
909     if(C2inf < DomainCirc2.FirstParameter())
910     {
911       if(C2tinf < DomainCirc2.FirstParameter())
912       {
913         C2inf = DomainCirc2.FirstParameter();
914         isOutOfRange = Standard_True;
915       }
916       else
917       {
918         C2inf = C2tinf;
919       }
920     }
921 
922     if(C2inf > DomainCirc2.LastParameter())
923     {
924       if(C2tinf > DomainCirc2.LastParameter())
925       {
926         C2inf = DomainCirc2.LastParameter();
927         isOutOfRange = Standard_True;
928       }
929       else
930       {
931         C2inf = C2tinf;
932       }
933     }
934 
935     if(isOutOfRange)
936     {
937       gp_Pnt2d aP1, aP2;
938       gp_Vec2d aV11, aV12;
939       gp_Vec2d aV21, aV22;
940 
941       ElCLib::CircleD2(C1inf,Axis2C1,R1,aP1,aV11,aV12);
942       ElCLib::CircleD2(C2inf,Axis2C2,R2,aP2,aV21,aV22);
943 
944       if(aP1.SquareDistance(aP2) > Tol2*Tol2)
945       {//there are not any solutions in given parametric range.
946         continue;
947       }
948     }
949 
950     if(IndirectCircles)
951     {
952       ElCLib::CircleD2(C1inf,Axis2C1,R1,P1a,Tan1,Norm1);
953       ElCLib::CircleD2(C2inf,Axis2C2,R2,P2a,Tan2,Norm2);
954       Tan2.Reverse();
955 
956       IntImpParGen::DeterminePosition(Pos1a,DomainCirc1,P1a,C1inf);
957       IntImpParGen::DeterminePosition(Pos2a,_DomainCirc2,P2a,PIpPI-C2inf);
958       Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
959 
960 
961       IntRes2d_IntersectionPoint NewPoint1(P1a,C1inf,PIpPI-C2inf,T1a,T2a,Standard_False);
962 
963       if((SolutionC1[i].Length()>0.0 ) || (SolutionC2[i].Length() >0.0))
964       {
965         //-- On traite un intervalle non reduit a un point
966         Standard_Real C1sup=NormalizeOnCircleDomain(SolutionC1[i].Bsup,DomainCirc1);
967         if(C1sup<C1inf) C1sup+=PIpPI;
968         C2sup=NormalizeOnCircleDomain(C2sup,DomainCirc2);
969 
970         ElCLib::CircleD2(C1sup,Axis2C1,R1,P1b,Tan1,Norm1);
971         ElCLib::CircleD2(C2sup,Axis2C2,R2,P2b,Tan2,Norm2);
972         Tan2.Reverse();
973 
974         IntImpParGen::DeterminePosition(Pos1b,DomainCirc1,P1b,C1sup);
975         IntImpParGen::DeterminePosition(Pos2b,_DomainCirc2,P2b,PIpPI-C2sup);
976         Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);
977 
978         //--------------------------------------------------
979 
980         if (isOpposite)
981         {
982           if(nbsol!=3)
983           {
984             if(C2inf<C2sup)
985               C2inf+=PIpPI;
986           }
987         }
988         else
989         {
990           if(nbsol!=3)
991           {
992             if(C2sup<C2inf) C2sup+=PIpPI;
993           }
994         }
995 
996         IntRes2d_IntersectionPoint NewPoint2(P1b,C1sup,PIpPI-C2sup,T1b,T2b,Standard_False);
997         IntRes2d_IntersectionSegment NewSeg (NewPoint1,NewPoint2, !isOpposite, Standard_False);
998         Append(NewSeg);
999       }
1000       else
1001       {
1002         Append(NewPoint1);
1003       }
1004     }
1005     else
1006     {
1007       ElCLib::CircleD2(C1inf,Axis2C1,R1,P1a,Tan1,Norm1);
1008       ElCLib::CircleD2(C2inf,Axis2C2,R2,P2a,Tan2,Norm2);
1009 
1010       IntImpParGen::DeterminePosition(Pos1a,DomainCirc1,P1a,C1inf);
1011       IntImpParGen::DeterminePosition(Pos2a,DomainCirc2,P2a,C2inf);
1012       Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
1013 
1014 
1015       IntRes2d_IntersectionPoint NewPoint1(P1a,C1inf,C2inf,T1a,T2a,Standard_False);
1016 
1017       if((SolutionC1[i].Length()>0.0 ) || (SolutionC2[i].Length() >0.0))
1018       {
1019         //-- On traite un intervalle non reduit a un point
1020         Standard_Real C1sup=NormalizeOnCircleDomain(SolutionC1[i].Bsup,DomainCirc1);
1021         if(C1sup<C1inf) C1sup+=PIpPI;
1022         C2sup=NormalizeOnCircleDomain(C2sup,DomainCirc2);
1023 
1024         ElCLib::CircleD2(C1sup,Axis2C1,R1,P1b,Tan1,Norm1);
1025         ElCLib::CircleD2(C2sup,Axis2C2,R2,P2b,Tan2,Norm2);
1026 
1027         IntImpParGen::DeterminePosition(Pos1b,DomainCirc1,P1b,C1sup);
1028         IntImpParGen::DeterminePosition(Pos2b,DomainCirc2,P2b,C2sup);
1029         Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);
1030 
1031         //--------------------------------------------------
1032 
1033         if (isOpposite)
1034         {
1035             if(C2inf<C2sup)
1036               C2inf+=PIpPI;
1037         }
1038         else
1039         {
1040             if(C2sup<C2inf)
1041               C2sup+=PIpPI;
1042         }
1043 
1044         IntRes2d_IntersectionPoint NewPoint2(P1b,C1sup,C2sup,T1b,T2b,Standard_False);
1045         IntRes2d_IntersectionSegment NewSeg(NewPoint1,NewPoint2,isOpposite,Standard_False);
1046         Append(NewSeg);
1047       }
1048       else
1049       {
1050         Append(NewPoint1);
1051       }
1052     }
1053   }
1054 }
1055 //----------------------------------------------------------------------
FindPositionLL(Standard_Real & Param,const IntRes2d_Domain & Domain)1056 IntRes2d_Position FindPositionLL(Standard_Real &Param
1057 				 ,const IntRes2d_Domain& Domain)
1058 {
1059   Standard_Real aDPar = Precision::Infinite();
1060   IntRes2d_Position aPos = IntRes2d_Middle;
1061   Standard_Real aResPar = Param;
1062   if(Domain.HasFirstPoint()) {
1063     aDPar = Abs(Param-Domain.FirstParameter());
1064     if( aDPar <= Domain.FirstTolerance()) {
1065       aResPar=Domain.FirstParameter();
1066       aPos = IntRes2d_Head;
1067 
1068     }
1069   }
1070   if(Domain.HasLastPoint()) {
1071     Standard_Real aD2 = Abs(Param-Domain.LastParameter());
1072     if( aD2 <= Domain.LastTolerance() && (aPos == IntRes2d_Middle || aD2 < aDPar ))
1073     {
1074       aResPar=Domain.LastParameter();
1075       aPos = IntRes2d_End;
1076     }
1077   }
1078   Param = aResPar;
1079   return aPos;
1080 }
1081 //--------------------------------------------------------------------
1082 //gka 0022833
1083 // Method to compute of point of intersection for case
1084 //when specified domain less than specified tolerance for intersection
getDomainParametrs(const IntRes2d_Domain & theDomain,Standard_Real & theFirst,Standard_Real & theLast,Standard_Real & theTol1,Standard_Real & theTol2)1085 static inline void getDomainParametrs(const IntRes2d_Domain& theDomain,
1086                                       Standard_Real& theFirst,
1087                                       Standard_Real& theLast,
1088                                       Standard_Real& theTol1,
1089                                       Standard_Real& theTol2)
1090 {
1091   theFirst = (theDomain.HasFirstPoint() ? theDomain.FirstParameter() : -Precision::Infinite());
1092   theLast = (theDomain.HasLastPoint() ? theDomain.LastParameter() : Precision::Infinite());
1093   theTol1 = (theDomain.HasFirstPoint() ? theDomain.FirstTolerance() : 0.);
1094   theTol2 = (theDomain.HasLastPoint() ? theDomain.LastTolerance() : 0.);
1095 }
1096 
1097 
1098 //=======================================================================
1099 //function : computeIntPoint
1100 //purpose  :
1101 //=======================================================================
computeIntPoint(const IntRes2d_Domain & theCurDomain,const IntRes2d_Domain & theDomainOther,const gp_Lin2d & theCurLin,const gp_Lin2d & theOtherLin,Standard_Real theCosT1T2,Standard_Real theParCur,Standard_Real theParOther,Standard_Real & theResInf,Standard_Real & theResSup,Standard_Integer theNum,IntRes2d_TypeTrans theCurTrans,IntRes2d_IntersectionPoint & theNewPoint)1102 static Standard_Boolean computeIntPoint(const IntRes2d_Domain& theCurDomain,
1103 					const IntRes2d_Domain& theDomainOther,
1104 					const gp_Lin2d& theCurLin,
1105 					const gp_Lin2d& theOtherLin,
1106 					Standard_Real theCosT1T2,
1107 					Standard_Real theParCur, Standard_Real theParOther,
1108 					Standard_Real& theResInf, Standard_Real& theResSup,
1109 					Standard_Integer theNum,
1110 					IntRes2d_TypeTrans theCurTrans,
1111 					IntRes2d_IntersectionPoint& theNewPoint)
1112 {
1113   if(fabs(theResSup-theParCur) > fabs(theResInf-theParCur))
1114     theResSup = theResInf;
1115 
1116   Standard_Real aRes2 = theParOther + (theResSup - theParCur) * theCosT1T2;
1117 
1118   Standard_Real aFirst2, aLast2, aTol21, aTol22, aTol11, aTol12 ;
1119 
1120   getDomainParametrs(theDomainOther,aFirst2, aLast2, aTol21, aTol22);
1121 
1122   if( aRes2  < aFirst2 - aTol21 || aRes2  > aLast2 + aTol22 ) {
1123     return Standard_False;
1124   }
1125 
1126   //------ compute parameters of intersection point --
1127   IntRes2d_Transition aT1,aT2;
1128   IntRes2d_Position aPos1a = FindPositionLL(theResSup,theCurDomain);
1129   IntRes2d_Position aPos2a = FindPositionLL(aRes2,theDomainOther);
1130   IntRes2d_TypeTrans anOtherTrans = ( theCurTrans == IntRes2d_Out ?
1131       IntRes2d_In : ( theCurTrans == IntRes2d_In ? IntRes2d_Out : IntRes2d_Undecided ) );
1132 
1133   if( theCurTrans != IntRes2d_Undecided )
1134   {
1135     aT1.SetValue(Standard_False, aPos1a, theCurTrans);
1136     aT2.SetValue(Standard_False,  aPos2a, anOtherTrans);
1137   }
1138   else
1139   {
1140     Standard_Boolean anOpposite = theCosT1T2 < 0.;
1141     aT1.SetValue(Standard_False,aPos1a,IntRes2d_Unknown,anOpposite);
1142     aT2.SetValue(Standard_False,aPos2a,IntRes2d_Unknown,anOpposite);
1143   }
1144   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1145   //--------------------------------------------------
1146   //gka bug 0022833
1147   Standard_Real aResU1 = theParCur;
1148   Standard_Real aResU2 = theParOther;
1149 
1150   Standard_Real aFirst1, aLast1;
1151   getDomainParametrs(theCurDomain,aFirst1, aLast1, aTol11, aTol12);
1152 
1153   Standard_Boolean isInside1 = (theParCur >= aFirst1 && theParCur <= aLast1);
1154   Standard_Boolean isInside2 = (theParOther >= aFirst2 && theParOther <= aLast2);
1155 
1156   if(!isInside1 || !isInside2)
1157   {
1158     if(isInside1)
1159     {
1160       gp_Pnt2d Pt1=ElCLib::Value(aRes2,theOtherLin);
1161       aResU2 = aRes2;
1162       Standard_Real aPar1 = ElCLib::Parameter(theCurLin,Pt1);
1163       aResU1 =((aPar1 >= aFirst1 && aPar1<= aLast1) ?  aPar1 : theResSup);
1164 
1165     }
1166     else if(isInside2)
1167     {
1168       gp_Pnt2d aPt1=ElCLib::Value(theResSup,theCurLin);
1169       aResU1 = theResSup;
1170       Standard_Real aPar2 = ElCLib::Parameter(theOtherLin,aPt1);
1171       aResU2= ((aPar2 >= aFirst2 && aPar2<= aLast2) ? aPar2 : aRes2);
1172     }
1173     else
1174     {
1175       //PKVf
1176       // check that parameters are within range on both curves
1177       if ( theParCur < aFirst1-aTol11 || theParCur > aLast1+aTol12 ||
1178            theParOther < aFirst2-aTol21 || theParOther > aLast2+aTol22) {
1179         return Standard_False;
1180       }
1181       //PKVt
1182       aResU1 = theResSup;
1183       aResU2= aRes2;
1184     }
1185   }
1186   gp_Pnt2d aPres((ElCLib::Value(aResU1,theCurLin).XY() + ElCLib::Value(aResU2,theOtherLin).XY()) * 0.5 );
1187   if(theNum == 1 )
1188     theNewPoint.SetValues(aPres, aResU1, aResU2 ,aT1, aT2, Standard_False);
1189   else
1190     theNewPoint.SetValues(aPres, aResU2, aResU1 ,aT2, aT1, Standard_False);
1191   return Standard_True;
1192 }
1193 
1194 //=======================================================================
1195 //function : CheckLLCoincidence
1196 //purpose  : Returns true if input are trimmed curves and they coincide
1197 //           within tolerance
1198 //=======================================================================
CheckLLCoincidence(const gp_Lin2d & L1,const gp_Lin2d & L2,const IntRes2d_Domain & Domain1,const IntRes2d_Domain & Domain2,const Standard_Real theTol)1199 static Standard_Boolean CheckLLCoincidence(const gp_Lin2d& L1,
1200                                            const gp_Lin2d& L2,
1201                                            const IntRes2d_Domain& Domain1,
1202                                            const IntRes2d_Domain& Domain2,
1203                                            const Standard_Real theTol)
1204 {
1205   Standard_Boolean isFirst1 = (Domain1.HasFirstPoint() &&
1206     L2.Distance(Domain1.FirstPoint()) < theTol);
1207   Standard_Boolean isLast1 = (Domain1.HasLastPoint() &&
1208     L2.Distance(Domain1.LastPoint()) < theTol);
1209   if (isFirst1 && isLast1)
1210     return Standard_True;
1211   Standard_Boolean isFirst2 = (Domain2.HasFirstPoint() &&
1212     L1.Distance(Domain2.FirstPoint()) < theTol);
1213   Standard_Boolean isLast2 = (Domain2.HasLastPoint() &&
1214     L1.Distance(Domain2.LastPoint()) < theTol);
1215   return isFirst2 && isLast2;
1216 }
1217 
1218 //----------------------------------------------------------------------
Perform(const gp_Lin2d & L1,const IntRes2d_Domain & Domain1,const gp_Lin2d & L2,const IntRes2d_Domain & Domain2,const Standard_Real,const Standard_Real TolR)1219 void IntCurve_IntConicConic::Perform(const gp_Lin2d& L1
1220 				      ,const IntRes2d_Domain& Domain1
1221 				     ,const gp_Lin2d& L2
1222 				     ,const IntRes2d_Domain& Domain2
1223 				     ,const Standard_Real,const Standard_Real TolR) {
1224   this->ResetFields();
1225 
1226   //-- Coordonnees du point d intersection sur chacune des 2 droites
1227   Standard_Real U1,U2;
1228   //-- Nombre de points solution : 1 : Intersection
1229   //--                             0 : Non Confondues
1230   //--                             2 : Confondues a la tolerance pres
1231   Standard_Integer nbsol;
1232   IntRes2d_IntersectionPoint PtSeg1,PtSeg2;
1233   Standard_Real aHalfSinL1L2;
1234   Standard_Real Tol = TolR;
1235   if(Tol < Precision::PConfusion())
1236     Tol = Precision::PConfusion();
1237 
1238   LineLineGeometricIntersection(L1,L2,Tol,U1,U2,aHalfSinL1L2,nbsol);
1239 
1240   gp_Vec2d Tan1=L1.Direction();
1241   gp_Vec2d Tan2=L2.Direction();
1242 
1243   Standard_Real aCosT1T2 = Tan1.Dot(Tan2);
1244   Standard_Boolean isOpposite = (aCosT1T2 < 0.0) ? Standard_True : Standard_False;
1245 
1246   done=Standard_True;
1247 
1248   if(nbsol==1 && CheckLLCoincidence(L1, L2, Domain1, Domain2, Tol))
1249     nbsol = 2;
1250 
1251   if(nbsol==1) {
1252     //---------------------------------------------------
1253     //-- d: distance du point I a partir de laquelle  les
1254     //--  points de parametre U1+d et U2+-d sont ecartes
1255     //--  d une distance superieure a Tol.
1256     //---------------------------------------------------
1257     IntRes2d_Position Pos1a,Pos2a,Pos1b,Pos2b;
1258     Standard_Real d = 0.5 * Tol / aHalfSinL1L2;
1259     Standard_Real U1inf=U1-d;
1260     Standard_Real U1sup=U1+d;
1261     Standard_Real U1mU2=U1-U2;
1262     Standard_Real U1pU2=U1+U2;
1263     Standard_Real Res1inf,Res1sup;
1264     Standard_Real ProdVectTan;
1265 
1266 
1267     //---------------------------------------------------
1268     //-- On agrandit la zone U1inf U1sup pour tenir compte
1269     //-- des tolerances des points en bout
1270     //--
1271     if(Domain1.HasFirstPoint()) {
1272       if(L2.Distance(Domain1.FirstPoint()) < Domain1.FirstTolerance()) {
1273 	if(U1inf > Domain1.FirstParameter()) {
1274 	  U1inf = Domain1.FirstParameter();
1275 	}
1276 	if(U1sup < Domain1.FirstParameter()) {
1277 	  U1sup = Domain1.FirstParameter();
1278 	}
1279       }
1280     }
1281     if(Domain1.HasLastPoint()) {
1282       if(L2.Distance(Domain1.LastPoint()) < Domain1.LastTolerance()) {
1283 	if(U1inf > Domain1.LastParameter()) {
1284 	  U1inf = Domain1.LastParameter();
1285 	}
1286 	if(U1sup < Domain1.LastParameter()) {
1287 	  U1sup = Domain1.LastParameter();
1288 	}
1289       }
1290     }
1291     if(Domain2.HasFirstPoint()) {
1292       if(L1.Distance(Domain2.FirstPoint()) < Domain2.FirstTolerance()) {
1293 	Standard_Real p = ElCLib::Parameter(L1,Domain2.FirstPoint());
1294 	if(U1inf > p) {
1295 	  U1inf = p;
1296 	}
1297 	if(U1sup < p) {
1298 	  U1sup = p;
1299 	}
1300       }
1301     }
1302     if(Domain2.HasLastPoint()) {
1303       if(L1.Distance(Domain2.LastPoint()) < Domain2.LastTolerance()) {
1304 	Standard_Real p = ElCLib::Parameter(L1,Domain2.LastPoint());
1305 	if(U1inf > p) {
1306 	  U1inf = p;
1307 	}
1308 	if(U1sup < p) {
1309 	  U1sup = p;
1310 	}
1311       }
1312     }
1313     //-----------------------------------------------------------------
1314 
1315     DomainIntersection(Domain1,U1inf,U1sup,Res1inf,Res1sup,Pos1a,Pos1b);
1316 
1317     if((Res1sup-Res1inf)<0.0) {
1318       //-- Si l intersection est vide
1319       //--
1320     }
1321     else { //-- (Domain1  INTER   Zone Intersection)    non vide
1322 
1323       ProdVectTan=Tan1.Crossed(Tan2);
1324 
1325       //#####################################################################
1326       //##  Longueur Minimale d un segment    Sur Courbe 1
1327       //#####################################################################
1328 
1329       Standard_Real LongMiniSeg=Tol;
1330 
1331 
1332       if(((Res1sup-Res1inf)<=LongMiniSeg)
1333         || ((Pos1a==Pos1b)&&(Pos1a!=IntRes2d_Middle)))
1334       {
1335         //-------------------------------  Un seul Point -------------------
1336         //--- lorsque la longueur du segment est inferieure a ??
1337         //--- ou si deux points designent le meme bout
1338         //gka #0022833
1339         IntRes2d_TypeTrans aCurTrans = ( ProdVectTan >= TOLERANCE_ANGULAIRE ?
1340              IntRes2d_Out : ( ProdVectTan <= -TOLERANCE_ANGULAIRE ? IntRes2d_In : IntRes2d_Undecided ) );
1341 
1342         IntRes2d_IntersectionPoint NewPoint1;
1343         if( computeIntPoint(Domain1, Domain2, L1, L2, aCosT1T2, U1, U2, Res1inf, Res1sup, 1, aCurTrans, NewPoint1 ) )
1344           Append(NewPoint1);
1345 
1346         //------------------------------------------------------
1347 
1348 
1349       }  //---------------   Fin du cas  :   1 seul point --------------------
1350 
1351       else {
1352 	//-- Intersection AND Domain1  --------> Segment ---------------------
1353 	Standard_Real U2inf,U2sup;
1354 	Standard_Real Res2inf,Res2sup;
1355 
1356 	if (isOpposite) { U2inf = U1pU2 -Res1sup; U2sup= U1pU2-Res1inf; }
1357 	else            { U2inf = Res1inf-U1mU2;  U2sup= Res1sup-U1mU2; }
1358 
1359 	DomainIntersection(Domain2,U2inf,U2sup,Res2inf,Res2sup,Pos2a,Pos2b);
1360 
1361 	//####################################################################
1362 	//##  Test sur la longueur minimale d un segment sur Ligne2
1363 	//####################################################################
1364 	Standard_Real Res2sup_m_Res2inf = Res2sup-Res2inf;
1365 	if(Res2sup_m_Res2inf < 0.0) {
1366 	  //-- Pas de solutions On retourne Vide
1367 	}
1368 	else if((Res2sup_m_Res2inf > LongMiniSeg)
1369 		|| ((Pos2a==Pos2b)&&(Pos2a!=IntRes2d_Middle)))     {
1370 	  //----------- Calcul des attributs du segment --------------
1371 	  //-- Attention, les bornes Res1inf(sup) bougent donc il faut
1372 	  //--  eventuellement recalculer les attributs
1373 
1374 	  if(isOpposite) { Res1inf=U1pU2-Res2sup; Res1sup=U1pU2-Res2inf;
1375 			 Standard_Real Tampon=Res2inf; Res2inf=Res2sup; Res2sup=Tampon;
1376 			 IntRes2d_Position Pos=Pos2a; Pos2a=Pos2b; Pos2b=Pos;
1377 		       }
1378 	  else         { Res1inf=U1mU2+Res2inf; Res1sup=U1mU2+Res2sup; }
1379 
1380 	  Pos1a=FindPositionLL(Res1inf,Domain1);
1381 	  Pos1b=FindPositionLL(Res1sup,Domain1);
1382 
1383 	  IntRes2d_Transition T1a,T2a,T1b,T2b;
1384 
1385 	  if(ProdVectTan>=TOLERANCE_ANGULAIRE) {  // &&&&&&&&&&&&&&&
1386 	    T1a.SetValue(Standard_False,Pos1a,IntRes2d_Out);
1387 	    T2a.SetValue(Standard_False,Pos2a,IntRes2d_In);
1388 	  }
1389 	  else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1390 	    T1a.SetValue(Standard_False,Pos1a,IntRes2d_In);
1391 	    T2a.SetValue(Standard_False,Pos2a,IntRes2d_Out);
1392 	  }
1393 	  else {
1394 	    T1a.SetValue (Standard_False, Pos1a, IntRes2d_Unknown, isOpposite);
1395 	    T2a.SetValue (Standard_False, Pos2a, IntRes2d_Unknown, isOpposite);
1396 	  }
1397 
1398 
1399 	  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1400 	  //~~~~~~~  C O N V E N T I O N    -    S E G M E N T     ~~~~~~~
1401 	  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1402 	  //~~ On Renvoie un segment dans les cas suivants :            ~~
1403 	  //~~   (1) Extremite L1 L2   ------>    Extremite L1 L2       ~~
1404 	  //~~   (2) Extremite L1 L2   ------>    Intersection          ~~
1405 	  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1406 
1407 	  Standard_Boolean ResultIsAPoint=Standard_False;
1408 
1409 	  if(((Res1sup-Res1inf)<=LongMiniSeg)
1410 	     || (Abs(Res2sup-Res2inf)<=LongMiniSeg)) {
1411 	    //-- On force la creation d un point
1412 	    ResultIsAPoint=Standard_True;
1413 	  }
1414 	  else {
1415 	    //------------------------------------------------------------
1416 	    //-- On traite les cas ou l intersection est situee du
1417 	    //-- Mauvais cote du domaine
1418 	    //-- Attention : Res2inf <-> Pos2a        Res2sup <-> Pos2b
1419 	    //--  et         Res1inf <-> Pos1a        Res1sup <-> Pos1b
1420 	    //--             avec Res1inf <= Res1sup
1421 	    //------------------------------------------------------------
1422 	    //-- Le point sera : Res1inf,Res2inf,T1a(Pos1a),T2a(Pos2a)
1423 	    //------------------------------------------------------------
1424 
1425 	    if(Pos1a==IntRes2d_Head) {
1426 	      if(Pos1b!=IntRes2d_End && U1<Res1inf)    { ResultIsAPoint=Standard_True; U1=Res1inf; U2=Res2inf; }
1427 	    }
1428 	    if(Pos1b==IntRes2d_End)  {
1429 	      if(Pos1a!=IntRes2d_Head && U1>Res1sup)   { ResultIsAPoint=Standard_True; U1=Res1sup; U2=Res2sup; }
1430 	    }
1431 
1432             if(Pos2a==IntRes2d_Head) {
1433 	      if(Pos2b!=IntRes2d_End && U2<Res2inf)    { ResultIsAPoint=Standard_True; U2=Res2inf; U1=Res1inf; }
1434 	    }
1435 	    else {
1436 	      if(Pos2a==IntRes2d_End)  {
1437 		if(Pos2b!=IntRes2d_Head && U2>Res2inf) { ResultIsAPoint=Standard_True; U2=Res2inf; U1=Res1inf; }
1438 	      }
1439 	    }
1440 	    if(Pos2b==IntRes2d_Head) {
1441 	      if(Pos2a!=IntRes2d_End && U2<Res2sup)    { ResultIsAPoint=Standard_True; U2=Res2sup; U1=Res1sup; }
1442 	    }
1443 	    else {
1444 	      if(Pos2b==IntRes2d_End) {
1445 		if(Pos2a!=IntRes2d_Head && U2>Res2sup) { ResultIsAPoint=Standard_True; U2=Res2sup; U1=Res1sup; }
1446 	      }
1447 	    }
1448 	  }
1449 
1450 
1451 
1452 	  if((!ResultIsAPoint) && (Pos1a!=IntRes2d_Middle || Pos2a!=IntRes2d_Middle)) {
1453 	    if(ProdVectTan>=TOLERANCE_ANGULAIRE) { //&&&&&&&&&&&&&&
1454 	      T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1455 	      T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1456 	    }
1457 	    else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) { //&&&&&&&&&&&&&&
1458 	      T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1459 	      T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1460 	    }
1461 	    else {
1462 	      T1b.SetValue (Standard_False, Pos1b, IntRes2d_Unknown, isOpposite);
1463 	      T2b.SetValue (Standard_False, Pos2b, IntRes2d_Unknown, isOpposite);
1464 	    }
1465 	    gp_Pnt2d Ptdebut;
1466 	    if(Pos1a==IntRes2d_Middle) {
1467 	      Standard_Real t3;
1468 	      if (isOpposite) {
1469 		t3 = (Pos2a == IntRes2d_Head)? Res2sup : Res2inf;
1470 	      }
1471 	      else {
1472 		t3 = (Pos2a == IntRes2d_Head)? Res2inf : Res2sup;
1473 	      }
1474 	      Ptdebut=ElCLib::Value(t3,L2);
1475 	      Res1inf=ElCLib::Parameter(L1,Ptdebut);
1476 	    }
1477 	    else {
1478 	      Standard_Real t4 = (Pos1a == IntRes2d_Head)? Res1inf : Res1sup;
1479 	      Ptdebut=ElCLib::Value(t4,L1);
1480 	      Res2inf=ElCLib::Parameter(L2,Ptdebut);
1481 	    }
1482 	    PtSeg1.SetValues(Ptdebut,Res1inf,Res2inf,T1a,T2a,Standard_False);
1483 	    if(Pos1b!=IntRes2d_Middle || Pos2b!=IntRes2d_Middle) {
1484 	      //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1485 	      //~~ Ajustement des parametres et du point renvoye
1486 	      gp_Pnt2d Ptfin;
1487 	      if(Pos1b==IntRes2d_Middle) {
1488 		Ptfin=ElCLib::Value(Res2sup,L2);
1489 		Res1sup=ElCLib::Parameter(L1,Ptfin);
1490 	      }
1491 	      else {
1492 		Ptfin=ElCLib::Value(Res1sup,L1);
1493 		Res2sup=ElCLib::Parameter(L2,Ptfin);
1494 	      }
1495 	      PtSeg2.SetValues(Ptfin,Res1sup,Res2sup,T1b,T2b,Standard_False);
1496 	      IntRes2d_IntersectionSegment Segment (PtSeg1, PtSeg2, isOpposite, Standard_False);
1497 	      Append(Segment);
1498 	    }
1499 	    else { //-- Extremite(L1 ou L2)  ------>   Point Middle(L1 et L2)
1500 
1501 	      Pos1b=FindPositionLL(U1,Domain1);
1502 	      Pos2b=FindPositionLL(U2,Domain2);
1503 	      if(ProdVectTan>=TOLERANCE_ANGULAIRE) {
1504 		T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1505 		T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1506 	      }
1507 	      else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1508 		T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1509 		T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1510 	      }
1511 	      else {
1512 		T1b.SetValue (Standard_False, Pos1b, IntRes2d_Unknown, isOpposite);
1513 		T2b.SetValue (Standard_False, Pos2b, IntRes2d_Unknown, isOpposite);
1514 	      }
1515 
1516 	      PtSeg2.SetValues(ElCLib::Value(U2,L2),U1,U2,T1b,T2b,Standard_False);
1517 
1518 	      if((Abs(Res1inf-U1) >LongMiniSeg) && (Abs(Res2inf-U2) >LongMiniSeg)) {
1519 		IntRes2d_IntersectionSegment Segment (PtSeg1, PtSeg2, isOpposite, Standard_False);
1520 		Append(Segment);
1521 	      }
1522 	      else {
1523 		Append(SegmentToPoint(PtSeg1,T1a,T2a,PtSeg2,T1b,T2b));
1524 	      }
1525 	    }
1526 
1527 	  } //-- (Pos1a!=IntRes2d_Middle || Pos2a!=IntRes2d_Middle) --
1528 	  else {  //-- Pos1a == Pos2a == Middle
1529 	    if(Pos1b==IntRes2d_Middle) Pos1b=Pos1a;
1530 	    if(Pos2b==IntRes2d_Middle) Pos2b=Pos2a;
1531 	    if(ResultIsAPoint) {
1532 	      //-- Middle sur le segment A
1533 	      //--
1534 	      if(Pos1b!=IntRes2d_Middle || Pos2b!=IntRes2d_Middle) {
1535 		gp_Pnt2d Ptfin;
1536 		if(Pos1b==IntRes2d_Middle) {
1537 		  Standard_Real t2;
1538 		  if (isOpposite) {
1539 		    t2 = (Pos2b == IntRes2d_Head)? Res2sup : Res2inf;
1540 		  }
1541 		  else {
1542 		    t2 = (Pos2b == IntRes2d_Head)? Res2inf : Res2sup;
1543 		  }
1544 		  Ptfin=ElCLib::Value(t2,L2);
1545 		  Res1sup=ElCLib::Parameter(L1,Ptfin);
1546 //modified by NIZHNY-MKK  Tue Feb 15 10:54:51 2000.BEGIN
1547 		  Pos1b=FindPositionLL(Res1sup,Domain1);
1548 //modified by NIZHNY-MKK  Tue Feb 15 10:54:55 2000.END
1549 
1550 		}
1551 		else {
1552 		  Standard_Real t1 = (Pos1b == IntRes2d_Head)? Res1inf : Res1sup;
1553 		  Ptfin=ElCLib::Value(t1,L1);
1554 		  Res2sup=ElCLib::Parameter(L2,Ptfin);
1555 //modified by NIZHNY-MKK  Tue Feb 15 10:55:08 2000.BEGIN
1556 		  Pos2b=FindPositionLL(Res2sup,Domain2);
1557 //modified by NIZHNY-MKK  Tue Feb 15 10:55:11 2000.END
1558 		}
1559 		if(ProdVectTan>=TOLERANCE_ANGULAIRE) {
1560 		  T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1561 		  T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1562 		}
1563 		else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1564 		  T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1565 		  T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1566 		}
1567 		else {
1568 		  T1b.SetValue (Standard_False, Pos1b, IntRes2d_Unknown, isOpposite);
1569 		  T2b.SetValue (Standard_False, Pos2b, IntRes2d_Unknown, isOpposite);
1570 		}
1571 	        PtSeg2.SetValues(Ptfin,Res1sup,Res2sup,T1b,T2b,Standard_False);
1572 		Append(PtSeg2);
1573 	      }
1574 	      else {
1575 		Pos1b=FindPositionLL(U1,Domain1);
1576 		Pos2b=FindPositionLL(U2,Domain2);
1577 
1578 		if(ProdVectTan>=TOLERANCE_ANGULAIRE) {
1579 		  T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1580 		  T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1581 		}
1582 		else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1583 		  T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1584 		  T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1585 		}
1586 		else {
1587 		  T1b.SetValue (Standard_False, Pos1b, IntRes2d_Unknown, isOpposite);
1588 		  T2b.SetValue (Standard_False, Pos2b, IntRes2d_Unknown, isOpposite);
1589 		}
1590 		PtSeg1.SetValues(ElCLib::Value(U2,L2),U1,U2,T1b,T2b,Standard_False);
1591 		Append(PtSeg1);
1592 	      }
1593 	    }
1594 	    else {
1595 	      PtSeg1.SetValues(ElCLib::Value(U2,L2),U1,U2,T1a,T2a,Standard_False);
1596 
1597 	      if((Pos1b!=IntRes2d_Middle || Pos2b!=IntRes2d_Middle)) {
1598 		if(ProdVectTan>=TOLERANCE_ANGULAIRE) {
1599 		  T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1600 		  T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1601 		}
1602 		else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1603 		  T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1604 		  T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1605 		}
1606 		else {
1607 		  T1b.SetValue (Standard_False, Pos1b, IntRes2d_Unknown, isOpposite);
1608 		  T2b.SetValue (Standard_False, Pos2b, IntRes2d_Unknown, isOpposite);
1609 		}
1610 		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1611 		//~~ Ajustement des parametres et du point renvoye
1612 		gp_Pnt2d Ptfin;
1613 		if(Pos1b==IntRes2d_Middle) {
1614 		  Ptfin=ElCLib::Value(Res2sup,L2);
1615 		  Res1sup=ElCLib::Parameter(L1,Ptfin);
1616 		}
1617 		else {
1618 		  Ptfin=ElCLib::Value(Res1sup,L1);
1619 		  Res2sup=ElCLib::Parameter(L2,Ptfin);
1620 		}
1621 
1622 	        PtSeg2.SetValues(Ptfin,Res1sup,Res2sup,T1b,T2b,Standard_False);
1623 
1624 		if((Abs(U1-Res1sup)>LongMiniSeg)
1625 		   ||(Abs(U2-Res2sup)>LongMiniSeg)) {
1626 		  //-- Modif du 1er Octobre 92 (Pour Composites)
1627 
1628 		  IntRes2d_IntersectionSegment Segment (PtSeg1, PtSeg2, isOpposite, Standard_False);
1629 		  Append(Segment);
1630 		}
1631 		else {
1632 		  Append(SegmentToPoint(PtSeg1,T1a,T2a,PtSeg2,T1b,T2b));
1633 		}
1634 	      }
1635 	      else {
1636 		Append(PtSeg1);
1637 	      }
1638 	    }
1639 	  }
1640 	} //----- Fin Creation Segment ----(Res2sup-Res2inf>Tol)-------------
1641 	else {
1642 	  //------ (Intersection And Domain1)  AND  Domain2  --> Point ------
1643 	  //-- Attention Res1sup peut etre  different de  U2
1644 	  //--   Mais on a Res1sup-Res1inf < Tol
1645 
1646           //gka #0022833
1647     IntRes2d_TypeTrans aCurTrans = ( ProdVectTan >= TOLERANCE_ANGULAIRE ?
1648            IntRes2d_In : ( ProdVectTan <= -TOLERANCE_ANGULAIRE ? IntRes2d_Out : IntRes2d_Undecided ) );
1649 
1650           IntRes2d_IntersectionPoint NewPoint1;
1651     if( computeIntPoint(Domain2, Domain1, L2, L1, aCosT1T2, U2, U1, Res2inf, Res2sup, 2, aCurTrans, NewPoint1 ) )
1652             Append(NewPoint1);
1653 
1654 	}
1655       }
1656     }
1657 
1658 //#ifdef OCCT_DEBUG
1659 //  if (NbPoints() || NbSegments())
1660 //  {
1661 //    static int cnt = 0; cnt++;
1662 //
1663 //    printf("line l1_%03d %.15g %.15g %.15g %.15g\n", cnt, L1.Location().X(), L1.Location().Y(), L1.Direction().X(), L1.Direction().Y());
1664 //
1665 //    if (Domain1.HasFirstPoint() && Domain1.HasLastPoint())
1666 //      printf("trim l1_%03d l1_%03d %.15g %.15g\n", cnt, cnt, Domain1.FirstParameter(), Domain1.LastParameter());
1667 //
1668 //    printf("line l2_%03d %.15g %.15g %.15g %.15g\n", cnt, L2.Location().X(), L2.Location().Y(), L2.Direction().X(), L2.Direction().Y());
1669 //
1670 //    if (Domain2.HasFirstPoint() && Domain2.HasLastPoint())
1671 //      printf("trim l2_%03d l2_%03d %.15g %.15g\n", cnt, cnt, Domain2.FirstParameter(), Domain2.LastParameter());
1672 //
1673 //    for (int i=1; i <= NbPoints(); i++)
1674 //      printf("point p%d_%03d %.15g %.15g\n", i, cnt, Point(i).Value().X(), Point(i).Value().Y());
1675 //
1676 //    for (int i=1; i <= NbSegments(); i++)
1677 //      printf("point s1_%d_%03d %.15g %.15g; point s2_%d_%03d %.15g %.15g\n", i, cnt, Segment(i).FirstPoint().Value().X(), Segment(i).FirstPoint().Value().Y(), i, cnt, Segment(i).LastPoint().Value().X(), Segment(i).LastPoint().Value().Y());
1678 //  }
1679 //#endif
1680 
1681   }
1682   else {
1683     if(nbsol==2) {  //== Droites confondues a la tolerance pres
1684       //--On traite ici le cas de segments resultats non neccess. bornes
1685       //--
1686       //--On prend la droite D1 comme reference ( pour le sens positif )
1687       //--
1688       Standard_Integer ResHasFirstPoint=0;
1689       Standard_Integer ResHasLastPoint=0;
1690       Standard_Real ParamStart = 0.,ParamStart2,ParamEnd = 0.,ParamEnd2;
1691       Standard_Real Org2SurL1=ElCLib::Parameter(L1,L2.Location());
1692       //== 3 : L1 et L2 bornent
1693       //== 2 :       L2 borne
1694       //== 1 : L1 borne
1695       if(Domain1.HasFirstPoint()) ResHasFirstPoint=1;
1696       if(Domain1.HasLastPoint())   ResHasLastPoint=1;
1697       if (isOpposite) {
1698 	if(Domain2.HasLastPoint())     ResHasFirstPoint+=2;
1699 	if(Domain2.HasFirstPoint())   ResHasLastPoint+=2;
1700       }
1701       else {
1702 	if(Domain2.HasLastPoint())     ResHasLastPoint+=2;
1703 	if(Domain2.HasFirstPoint())   ResHasFirstPoint+=2;
1704       }
1705       if(ResHasFirstPoint==0 && ResHasLastPoint==0) {
1706 	//~~~~ Creation d un segment infini avec Opposite
1707 	Append (IntRes2d_IntersectionSegment (isOpposite));
1708       }
1709       else {  //-- On obtient au pire une demi-droite
1710 	switch(ResHasFirstPoint) {
1711 	case 1:
1712 	  ParamStart=Domain1.FirstParameter();
1713 	  ParamStart2 = isOpposite ? (Org2SurL1 - ParamStart) : (ParamStart - Org2SurL1);
1714 	  break;
1715 	case 2:
1716 	  if (isOpposite) {
1717 	    ParamStart2=Domain2.LastParameter();
1718 	    ParamStart=Org2SurL1 - ParamStart2;
1719 	  }
1720 	  else {
1721 	    ParamStart2=Domain2.FirstParameter();
1722 	    ParamStart=Org2SurL1 + ParamStart2;
1723 	  }
1724 	  break;
1725 	case 3:
1726 	  if (isOpposite) {
1727 	    ParamStart2=Domain2.LastParameter();
1728 	    ParamStart=Org2SurL1 - ParamStart2;
1729 	    if(ParamStart < Domain1.FirstParameter()) {
1730 	      ParamStart=Domain1.FirstParameter();
1731 	      ParamStart2=Org2SurL1 -  ParamStart;
1732 	    }
1733 	  }
1734 	  else {
1735 	    ParamStart2=Domain2.FirstParameter();
1736 	    ParamStart=Org2SurL1 + ParamStart2;
1737 	    if(ParamStart < Domain1.FirstParameter()) {
1738 	      ParamStart=Domain1.FirstParameter();
1739 	      ParamStart2=ParamStart - Org2SurL1;
1740 	    }
1741 	  }
1742 	  break;
1743 	default:  //~~~ Segment Infini a gauche
1744 	  break;
1745 	}
1746 
1747 	switch(ResHasLastPoint) {
1748 	case 1:
1749 	  ParamEnd=Domain1.LastParameter();
1750 	  ParamEnd2 = isOpposite ? (Org2SurL1 - ParamEnd) : (ParamEnd - Org2SurL1);
1751 	  break;
1752 	case 2:
1753 	  if (isOpposite) {
1754 	    ParamEnd2=Domain2.FirstParameter();
1755 	    ParamEnd=Org2SurL1 - ParamEnd2;
1756 	  }
1757 	  else {
1758 	    ParamEnd2=Domain2.LastParameter();
1759 	    ParamEnd=Org2SurL1 + ParamEnd2;
1760 	  }
1761 	  break;
1762 	case 3:
1763 	  if (isOpposite) {
1764 	    ParamEnd2=Domain2.FirstParameter();
1765 	    ParamEnd=Org2SurL1 - ParamEnd2;
1766 	    if(ParamEnd > Domain1.LastParameter()) {
1767 	      ParamEnd=Domain1.LastParameter();
1768 	      ParamEnd2=Org2SurL1 -  ParamEnd;
1769 	    }
1770 	  }
1771 	  else {
1772 	    ParamEnd2=Domain2.LastParameter();
1773 	    ParamEnd=Org2SurL1 + ParamEnd2;
1774 	    if(ParamEnd > Domain1.LastParameter()) {
1775 	      ParamEnd=Domain1.LastParameter();
1776 	      ParamEnd2=ParamEnd - Org2SurL1;
1777 	    }
1778 	  }
1779 	default:  //~~~ Segment Infini a droite
1780 	  break;
1781 	}
1782 
1783 	IntRes2d_Transition Tinf,Tsup;
1784 
1785 	if(ResHasFirstPoint) {
1786 	  if(ResHasLastPoint) {
1787 	    //~~~ Creation de la borne superieure
1788 	    //~~~ L1 :     |------------->       ou          |-------------->
1789 	    //~~~ L2 : <------------|            ou  <----|
1790 	    if(ParamEnd >= (ParamStart-Tol)) {
1791 	      //~~~ Creation d un segment
1792 	      IntRes2d_Position Pos1,Pos2;
1793 	      Pos1=FindPositionLL(ParamStart,Domain1);
1794 	      Pos2=FindPositionLL(ParamStart2,Domain2);
1795 	      Tinf.SetValue (Standard_True, Pos1, IntRes2d_Unknown, isOpposite);
1796 	      Tsup.SetValue (Standard_True, Pos2, IntRes2d_Unknown, isOpposite);
1797 	      IntRes2d_IntersectionPoint P1(ElCLib::Value(ParamStart,L1)
1798 					    ,ParamStart,ParamStart2
1799 					    ,Tinf,Tsup,Standard_False);
1800 	      if(ParamEnd > (ParamStart+Tol)) {
1801 		//~~~ Le segment est assez long
1802 		Pos1=FindPositionLL(ParamEnd,Domain1);
1803 		Pos2=FindPositionLL(ParamEnd2,Domain2);
1804 		Tinf.SetValue (Standard_True, Pos1, IntRes2d_Unknown, isOpposite);
1805 		Tsup.SetValue (Standard_True, Pos2, IntRes2d_Unknown, isOpposite);
1806 
1807 		IntRes2d_IntersectionPoint P2(ElCLib::Value(ParamEnd,L1)
1808 					      ,ParamEnd,ParamEnd2
1809 					      ,Tinf,Tsup,Standard_False);
1810 		IntRes2d_IntersectionSegment Seg (P1, P2, isOpposite, Standard_False);
1811 		Append(Seg);
1812 	      }
1813 	      else {   //~~~~ le segment est de longueur inferieure a Tol
1814 		Append(P1);
1815 	      }
1816 	    } //-- if( ParamEnd >= ...)
1817 	  }   //-- if(ResHasLastPoint)
1818 	  else {
1819 	    //~~~ Creation de la demi droite   |----------->
1820 	    IntRes2d_Position Pos1=FindPositionLL(ParamStart,Domain1);
1821 	    IntRes2d_Position Pos2=FindPositionLL(ParamStart2,Domain2);
1822 	    Tinf.SetValue (Standard_True, Pos1, IntRes2d_Unknown, isOpposite);
1823 	    Tsup.SetValue (Standard_True, Pos2, IntRes2d_Unknown, isOpposite);
1824 
1825 	    IntRes2d_IntersectionPoint P(ElCLib::Value(ParamStart,L1)
1826 					  ,ParamStart,ParamStart2
1827 					  ,Tinf,Tsup,Standard_False);
1828 	    IntRes2d_IntersectionSegment Seg (P, Standard_True, isOpposite, Standard_False);
1829 	    Append(Seg);
1830 	  }
1831 	}
1832 	else {
1833 	  IntRes2d_Position Pos1=FindPositionLL(ParamEnd,Domain1);
1834 	  IntRes2d_Position Pos2=FindPositionLL(ParamEnd2,Domain2);
1835 	  Tinf.SetValue (Standard_True, Pos1, IntRes2d_Unknown, isOpposite);
1836 	  Tsup.SetValue (Standard_True, Pos2, IntRes2d_Unknown, isOpposite);
1837 
1838 	  IntRes2d_IntersectionPoint P2(ElCLib::Value(ParamEnd,L1)
1839 					,ParamEnd,ParamEnd2
1840 					,Tinf,Tsup,Standard_False);
1841 	  IntRes2d_IntersectionSegment Seg (P2, Standard_False, isOpposite, Standard_False);
1842 	  Append(Seg);
1843 	  //~~~ Creation de la demi droite   <-----------|
1844 	}
1845       }
1846     }
1847   }
1848 }
1849 
1850 
1851 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1852 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Perform(const gp_Lin2d & Line,const IntRes2d_Domain & LIG_Domain,const gp_Circ2d & Circle,const IntRes2d_Domain & CIRC_Domain,const Standard_Real TolConf,const Standard_Real Tol)1853 void IntCurve_IntConicConic::Perform(const gp_Lin2d& Line
1854 				     ,const IntRes2d_Domain& LIG_Domain
1855 				     ,const gp_Circ2d& Circle
1856 				     ,const IntRes2d_Domain& CIRC_Domain
1857 				     ,const Standard_Real TolConf,const Standard_Real Tol) {
1858 
1859 //--  if(! CIRC_Domain.IsClosed()) {
1860 //--    throw Standard_ConstructionError("Domaine incorrect");
1861 //--  }
1862 
1863   Standard_Boolean TheReversedParameters=ReversedParameters();
1864   this->ResetFields();
1865   this->SetReversedParameters(TheReversedParameters);
1866 
1867   Standard_Integer nbsol=0;
1868   PeriodicInterval CInt1,CInt2;
1869 
1870   LineCircleGeometricIntersection(Line,Circle,TolConf,Tol
1871 				  ,CInt1,CInt2
1872 				  ,nbsol);
1873 
1874   done=Standard_True;
1875 
1876   if(nbsol==0) { //-- Pas de solutions
1877     return;
1878   }
1879 
1880 //  Modified by Sergey KHROMOV - Mon Dec 18 11:13:18 2000 Begin
1881   if (nbsol == 2 && CInt2.Bsup == CInt1.Binf + PIpPI) {
1882     Standard_Real FirstBound = CIRC_Domain.FirstParameter();
1883     Standard_Real LastBound = CIRC_Domain.LastParameter();
1884     Standard_Real FirstTol = CIRC_Domain.FirstTolerance();
1885     Standard_Real LastTol = CIRC_Domain.LastTolerance();
1886     if (CInt1.Binf == 0 && FirstBound - FirstTol > CInt1.Bsup) {
1887       nbsol = 1;
1888       CInt1.SetValues(CInt2.Binf, CInt2.Bsup);
1889     } else if (CInt2.Bsup == PIpPI && LastBound + LastTol < CInt2.Binf)
1890       nbsol = 1;
1891   }
1892 //  Modified by Sergey KHROMOV - Mon Dec 18 11:13:20 2000 End
1893 
1894   PeriodicInterval CDomain(CIRC_Domain);
1895   Standard_Real deltat = CDomain.Bsup-CDomain.Binf;
1896   while(CDomain.Binf >= PIpPI) CDomain.Binf-=PIpPI;
1897   while(CDomain.Binf <  0.0)   CDomain.Binf+=PIpPI;
1898   CDomain.Bsup=CDomain.Binf+deltat;
1899 
1900   //------------------------------------------------------------
1901   //-- Ajout : Jeudi 28 mars 96
1902   //-- On agrandit artificiellement les domaines
1903   Standard_Real BinfModif = CDomain.Binf;
1904   Standard_Real BsupModif = CDomain.Bsup;
1905   BinfModif-=CIRC_Domain.FirstTolerance() / Circle.Radius();
1906   BsupModif+=CIRC_Domain.LastTolerance() / Circle.Radius();
1907   deltat = BsupModif-BinfModif;
1908   if(deltat<=PIpPI) {
1909     CDomain.Binf = BinfModif;
1910     CDomain.Bsup = BsupModif;
1911   }
1912   else {
1913     Standard_Real t=PIpPI-deltat;
1914     t*=0.5;
1915     CDomain.Binf = BinfModif+t;
1916     CDomain.Bsup = BsupModif-t;
1917   }
1918   deltat = CDomain.Bsup-CDomain.Binf;
1919   while(CDomain.Binf >= PIpPI) CDomain.Binf-=PIpPI;
1920   while(CDomain.Binf <  0.0)   CDomain.Binf+=PIpPI;
1921   CDomain.Bsup=CDomain.Binf+deltat;
1922   //-- ------------------------------------------------------------
1923 
1924   Interval LDomain(LIG_Domain);
1925 
1926   Standard_Integer NbSolTotal=0;
1927 
1928   PeriodicInterval SolutionCircle[4];
1929   Interval SolutionLine[4];
1930 
1931   //----------------------------------------------------------------------
1932   //----------- Traitement du premier intervalle Geometrique  CInt1   ----
1933   //----------------------------------------------------------------------
1934   //-- NbSolTotal est incremente a chaque Intervalle solution.
1935   //-- On stocke les intervalles dans les tableaux : SolutionCircle[4]
1936   //--                                            et SolutionLine[4]
1937   //-- des Exemples faciles donnent 3 Intersections
1938   //-- des Problemes numeriques peuvent peut etre en donner 4 ??????
1939   //--
1940   PeriodicInterval CDomainAndRes=CDomain.FirstIntersection(CInt1);
1941 
1942   ProjectOnLAndIntersectWithLDomain(Circle,Line
1943 				    ,CDomainAndRes
1944 				    ,LDomain
1945 				    ,SolutionCircle
1946 				    ,SolutionLine
1947 				    ,NbSolTotal
1948 				    ,LIG_Domain
1949 				    ,CIRC_Domain);
1950 
1951   CDomainAndRes=CDomain.SecondIntersection(CInt1);
1952 
1953   ProjectOnLAndIntersectWithLDomain(Circle,Line
1954 				    ,CDomainAndRes
1955 				    ,LDomain
1956 				    ,SolutionCircle
1957 				    ,SolutionLine
1958 				    ,NbSolTotal
1959 				    ,LIG_Domain
1960 				    ,CIRC_Domain);
1961 
1962   //----------------------------------------------------------------------
1963   //----------- Traitement du second intervalle Geometrique   C1_Int2 ----
1964   //----------------------------------------------------------------------
1965   if(nbsol==2) {
1966     CDomainAndRes=CDomain.FirstIntersection(CInt2);
1967 
1968     ProjectOnLAndIntersectWithLDomain(Circle,Line
1969 				      ,CDomainAndRes
1970 				      ,LDomain
1971 				      ,SolutionCircle
1972 				      ,SolutionLine
1973 				      ,NbSolTotal
1974 				      ,LIG_Domain
1975 				      ,CIRC_Domain);
1976 
1977     //--------------------------------------------------------------------
1978     CDomainAndRes=CDomain.SecondIntersection(CInt2);
1979 
1980 
1981     ProjectOnLAndIntersectWithLDomain(Circle,Line
1982 				      ,CDomainAndRes
1983 				      ,LDomain
1984 				      ,SolutionCircle
1985 				      ,SolutionLine
1986 				      ,NbSolTotal
1987 				      ,LIG_Domain
1988 				      ,CIRC_Domain);
1989   }
1990 
1991 
1992 
1993 
1994 
1995 
1996 
1997 
1998 
1999   //----------------------------------------------------------------------
2000   //-- Calcul de toutes les transitions et Positions.
2001   //--
2002   //-- On determine si des intervalles sont reduit a des points
2003   //--      ( Rayon * Intervalle.Length()    <    TolConf   )   ### Modif 19 Nov Tol-->TolConf
2004   //--
2005   Standard_Real R=Circle.Radius();
2006   Standard_Integer i ;
2007   Standard_Real MaxTol = TolConf;
2008   if(MaxTol<Tol) MaxTol = Tol;
2009   if(MaxTol<1.0e-10) MaxTol = 1.0e-10;
2010 
2011   for( i=0; i<NbSolTotal ; i++) {
2012     if((R * SolutionCircle[i].Length())<MaxTol
2013        && (SolutionLine[i].Length())<MaxTol) {
2014 
2015       Standard_Real t=(SolutionCircle[i].Binf+SolutionCircle[i].Bsup)*0.5;
2016       SolutionCircle[i].Binf=SolutionCircle[i].Bsup=t;
2017 
2018       t=(SolutionLine[i].Binf+SolutionLine[i].Bsup)*0.5;
2019       SolutionLine[i].Binf=SolutionLine[i].Bsup=t;
2020     }
2021   }
2022 #if 0
2023   if(NbSolTotal == 2) {
2024     if(SolutionLine[0].Binf==SolutionLine[0].BSup) {
2025       if(SolutionLine[1].Binf==SolutionLine[1].BSup) {
2026 	if(Abs(SolutionLine[0].Binf-SolutionLine[1].Binf)<TolConf) {
2027 	  SolutionLine[0].Binf=0.5*(SolutionLine[0].BSup+SolutionLine[1].BSup);
2028 	  SolutionLine[0].BSup=SolutionLine[0].Binf;
2029 	  NbSolTotal = 1;
2030 	}
2031       }
2032     }
2033   }
2034 #endif
2035   //----------------------------------------------------------------------
2036   //-- Traitement des intervalles (ou des points obtenus)
2037   //--
2038   if(NbSolTotal) {
2039     gp_Ax22d CircleAxis=Circle.Axis();
2040     gp_Ax2d LineAxis=Line.Position();
2041     gp_Pnt2d P1a,P2a,P1b,P2b;
2042     gp_Vec2d Tan1,Tan2,Norm1;
2043     gp_Vec2d Norm2(0.0,0.0);
2044     IntRes2d_Transition T1a,T2a,T1b,T2b;
2045     IntRes2d_Position Pos1a,Pos1b,Pos2a,Pos2b;
2046 
2047     ElCLib::CircleD1(SolutionCircle[0].Binf,CircleAxis,R,P1a,Tan1);
2048     ElCLib::LineD1(SolutionLine[0].Binf,LineAxis,P2a,Tan2);
2049 
2050     Standard_Boolean isOpposite = (Tan1.Dot (Tan2) < 0.0);
2051 
2052 
2053     for(i=0; i<NbSolTotal; i++ ) {
2054 
2055 
2056       //-- 7 aout 97
2057       //-- On recentre Bin et Bsup de facon a avoir une portion commune avec CIRC_Domain
2058       Standard_Real p1=SolutionCircle[i].Binf;
2059       Standard_Real p2=SolutionCircle[i].Bsup;
2060       Standard_Real q1=CIRC_Domain.FirstParameter();
2061       Standard_Real q2=CIRC_Domain.LastParameter();
2062       //--          |------ CircDomain ------|   [-- Sol --]
2063       if(p1>q2) {
2064 	do {
2065 	  p1-=PIpPI;
2066 	  p2-=PIpPI;
2067 	}
2068 	while( (p1>q2) );
2069       }
2070       else if(p2<q1) {
2071 	do {
2072 	  p1+=PIpPI;
2073 	  p2+=PIpPI;
2074 	}
2075 	while( (p2<q1) );
2076       }
2077       if(p1<q1 && p2>q1) {
2078 	p1=q1;
2079       }
2080       if(p1<q2 && p2>q2) {
2081 	p2=q2;
2082       }
2083 
2084 #if 0
2085       if(SolutionCircle[i].Binf!=p1 || SolutionCircle[i].Bsup!=p2) {
2086 	printf("\n IntCurve_IntConicConic_1.cxx : (%g , %g) --> (%g , %g)\n",
2087 	       SolutionCircle[i].Binf,SolutionCircle[i].Bsup,p1,p2);
2088       }
2089 #endif
2090       SolutionCircle[i].Binf=p1;
2091       SolutionCircle[i].Bsup=p2;
2092 
2093 //-- Fin 7 aout 97
2094 
2095 
2096       Standard_Real Linf = isOpposite ? SolutionLine[i].Bsup : SolutionLine[i].Binf;
2097       Standard_Real Lsup = isOpposite ? SolutionLine[i].Binf : SolutionLine[i].Bsup;
2098 
2099       //---------------------------------------------------------------
2100       //-- Si les parametres sur le cercle sont en premier
2101       //-- On doit retourner ces parametres dans l ordre croissant
2102       //---------------------------------------------------------------
2103       if(Linf > Lsup) {
2104 	Standard_Real T=SolutionCircle[i].Binf;
2105 	SolutionCircle[i].Binf=SolutionCircle[i].Bsup;
2106 	SolutionCircle[i].Bsup=T;
2107 
2108 	T=Linf; Linf=Lsup; Lsup=T;
2109       }
2110 
2111 
2112       ElCLib::CircleD2(SolutionCircle[i].Binf,CircleAxis,R,P1a,Tan1,Norm1);
2113       ElCLib::LineD1(Linf,LineAxis,P2a,Tan2);
2114 
2115       IntImpParGen::DeterminePosition(Pos1a,CIRC_Domain,P1a,SolutionCircle[i].Binf);
2116       IntImpParGen::DeterminePosition(Pos2a,LIG_Domain,P2a,Linf);
2117       Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
2118       Standard_Real Cinf;
2119       if(Pos1a==IntRes2d_End) {
2120 	Cinf = CIRC_Domain.LastParameter();
2121 	P1a  = CIRC_Domain.LastPoint();
2122 	Linf = ElCLib::Parameter(Line,P1a);
2123 
2124 	ElCLib::CircleD2(Cinf,CircleAxis,R,P1a,Tan1,Norm1);
2125 	ElCLib::LineD1(Linf,LineAxis,P2a,Tan2);
2126 	IntImpParGen::DeterminePosition(Pos1a,CIRC_Domain,P1a,Cinf);
2127 	IntImpParGen::DeterminePosition(Pos2a,LIG_Domain,P2a,Linf);
2128 	Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
2129       }
2130       else if(Pos1a==IntRes2d_Head) {
2131 	Cinf = CIRC_Domain.FirstParameter();
2132 	P1a  = CIRC_Domain.FirstPoint();
2133 	Linf = ElCLib::Parameter(Line,P1a);
2134 
2135 	ElCLib::CircleD2(Cinf,CircleAxis,R,P1a,Tan1,Norm1);
2136 	ElCLib::LineD1(Linf,LineAxis,P2a,Tan2);
2137 	IntImpParGen::DeterminePosition(Pos1a,CIRC_Domain,P1a,Cinf);
2138 	IntImpParGen::DeterminePosition(Pos2a,LIG_Domain,P2a,Linf);
2139 	Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
2140       }
2141       else {
2142 	Cinf=NormalizeOnCircleDomain(SolutionCircle[i].Binf,CIRC_Domain);
2143       }
2144 
2145       IntRes2d_IntersectionPoint NewPoint1(P1a,Linf,Cinf,T2a,T1a,ReversedParameters());
2146 
2147       if((SolutionLine[i].Length()+SolutionCircle[i].Length()) >0.0) {
2148 
2149 	ElCLib::CircleD2(SolutionCircle[i].Bsup,CircleAxis,R,P1b,Tan1,Norm1);
2150         ElCLib::LineD1(Lsup,LineAxis,P2b,Tan2);
2151 
2152 	IntImpParGen::DeterminePosition(Pos1b,CIRC_Domain,P1b,SolutionCircle[i].Bsup);
2153 	IntImpParGen::DeterminePosition(Pos2b,LIG_Domain,P2b,Lsup);
2154 	Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);
2155 	Standard_Real Csup;
2156 	if(Pos1b==IntRes2d_End) {
2157 	  Csup = CIRC_Domain.LastParameter();
2158 	  P1b  = CIRC_Domain.LastPoint();
2159 	  Lsup = ElCLib::Parameter(Line,P1b);
2160 	  ElCLib::CircleD2(Csup,CircleAxis,R,P1b,Tan1,Norm1);
2161 	  ElCLib::LineD1(Lsup,LineAxis,P2b,Tan2);
2162 
2163 	  IntImpParGen::DeterminePosition(Pos1b,CIRC_Domain,P1b,Csup);
2164 	  IntImpParGen::DeterminePosition(Pos2b,LIG_Domain,P2b,Lsup);
2165 	  Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);
2166 	}
2167 	else if(Pos1b==IntRes2d_Head) {
2168 	  Csup = CIRC_Domain.FirstParameter();
2169 	  P1b  = CIRC_Domain.FirstPoint();
2170 	  Lsup = ElCLib::Parameter(Line,P1b);
2171 	  ElCLib::CircleD2(Csup,CircleAxis,R,P1b,Tan1,Norm1);
2172 	  ElCLib::LineD1(Lsup,LineAxis,P2b,Tan2);
2173 
2174 	  IntImpParGen::DeterminePosition(Pos1b,CIRC_Domain,P1b,Csup);
2175 	  IntImpParGen::DeterminePosition(Pos2b,LIG_Domain,P2b,Lsup);
2176 	  Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);
2177 	}
2178 	else {
2179 	  Csup=NormalizeOnCircleDomain(SolutionCircle[i].Bsup,CIRC_Domain);
2180 	}
2181 
2182 	IntRes2d_IntersectionPoint NewPoint2(P1b,Lsup,Csup,T2b,T1b,ReversedParameters());
2183 
2184 	if(((Abs(Csup-Cinf)*R >  MaxTol) && (Abs(Lsup-Linf) > MaxTol))
2185 	   || (T1a.TransitionType() != T2a.TransitionType())) {
2186 	  //-- Verifier egalement les transitions
2187 
2188 	  IntRes2d_IntersectionSegment NewSeg (NewPoint1, NewPoint2, isOpposite, ReversedParameters());
2189 	  Append(NewSeg);
2190 	}
2191 	else {
2192 	  if(Pos1a!=IntRes2d_Middle ||  Pos2a!=IntRes2d_Middle) {
2193 	    Insert(NewPoint1);
2194 	  }
2195 	  if(Pos1b!=IntRes2d_Middle ||  Pos2b!=IntRes2d_Middle) {
2196 	    Insert(NewPoint2);
2197 	  }
2198 
2199 	}
2200       }
2201       else {
2202         //--Standard_Real Cmid=NormalizeOnCircleDomain(0.5*(SolutionCircle[i].Bsup+SolutionCircle[i].Binf)
2203 	//--					   ,CIRC_Domain);
2204 	//--IntRes2d_IntersectionPoint NewPoint(P2a,0.5*(Linf+Lsup)
2205 	//--				    ,Cmid
2206 	//--				    ,T2a,T1a,ReversedParameters());
2207 	Insert(NewPoint1);
2208       }
2209     }
2210   }
2211 }
2212 
2213 
2214 
2215 
SegmentToPoint(const IntRes2d_IntersectionPoint & Pa,const IntRes2d_Transition & T1a,const IntRes2d_Transition & T2a,const IntRes2d_IntersectionPoint & Pb,const IntRes2d_Transition & T1b,const IntRes2d_Transition & T2b)2216 const IntRes2d_IntersectionPoint SegmentToPoint( const IntRes2d_IntersectionPoint& Pa
2217 						,const IntRes2d_Transition& T1a
2218 						,const IntRes2d_Transition& T2a
2219 						,const IntRes2d_IntersectionPoint& Pb
2220 						,const IntRes2d_Transition& T1b
2221 						,const IntRes2d_Transition& T2b) {
2222 
2223   if((T1b.PositionOnCurve() == IntRes2d_Middle)
2224      && (T2b.PositionOnCurve() == IntRes2d_Middle)) {
2225     return(Pa);
2226   }
2227   if((T1a.PositionOnCurve() == IntRes2d_Middle)
2228      && (T2a.PositionOnCurve() == IntRes2d_Middle)) {
2229     return(Pb);
2230   }
2231 
2232   IntRes2d_Transition t1 = T1a;
2233   IntRes2d_Transition t2 = T2a;
2234   Standard_Real u1 = Pa.ParamOnFirst();
2235   Standard_Real u2 = Pa.ParamOnSecond();
2236 
2237 
2238   if(t1.PositionOnCurve() == IntRes2d_Middle) {
2239     t1.SetPosition(T1b.PositionOnCurve());
2240     u1 = Pb.ParamOnFirst();
2241   }
2242   if(t2.PositionOnCurve() == IntRes2d_Middle) {
2243     t2.SetPosition(T2b.PositionOnCurve());
2244     u2 = Pb.ParamOnSecond();
2245   }
2246   return(IntRes2d_IntersectionPoint(Pa.Value(),u1,u2,t1,t2,Standard_False));
2247 }
2248 
2249 //=======================================================================
2250 //function : LineEllipseGeometricIntersection
2251 //purpose  :
2252 //=======================================================================
LineEllipseGeometricIntersection(const gp_Lin2d & Line,const gp_Elips2d & Ellipse,const Standard_Real,const Standard_Real TolTang,PeriodicInterval & EInt1,PeriodicInterval & EInt2,Standard_Integer & nbsol)2253 void LineEllipseGeometricIntersection(const gp_Lin2d& Line,
2254   const gp_Elips2d& Ellipse,
2255   const Standard_Real ,
2256   const Standard_Real TolTang,
2257   PeriodicInterval& EInt1,
2258   PeriodicInterval& EInt2,
2259   Standard_Integer& nbsol)
2260 {
2261 
2262   const gp_Ax22d& anElAxis = Ellipse.Axis();
2263   gp_Trsf2d aTr;
2264   aTr.SetTransformation(anElAxis.XAxis());
2265   gp_Elips2d aTEllipse = Ellipse.Transformed(aTr);
2266   gp_Lin2d aTLine = Line.Transformed(aTr);
2267   Standard_Real aDY = aTLine.Position().Direction().Y();
2268   Standard_Boolean IsVert = Abs(aDY) > 1. - 2. * Epsilon(1.);
2269   //
2270   Standard_Real a = aTEllipse.MajorRadius();
2271   Standard_Real b = aTEllipse.MinorRadius();
2272   Standard_Real a2 = a * a;
2273   Standard_Real b2 = b * b;
2274   //
2275   Standard_Real eps0 = 1.e-12;
2276   if (b / a < 1.e-5)
2277   {
2278     eps0 = 1.e-6;
2279   }
2280   //
2281   Standard_Real anA, aB, aC;
2282   aTLine.Coefficients(anA, aB, aC);
2283   if (IsVert)
2284   {
2285     aC += aB * aTLine.Position().Location().Y();
2286     aB = 0.;
2287   }
2288   //
2289   Standard_Real x1 = 0., y1 = 0., x2 = 0., y2 = 0.;
2290   if (Abs(aB) > eps0 )
2291   {
2292     Standard_Real m = -anA / aB;
2293     Standard_Real m2 = m * m;
2294     Standard_Real c = -aC / aB;
2295     Standard_Real c2 = c * c;
2296     Standard_Real D = a2 * m2 + b2 - c2;
2297     if (D < 0.)
2298     {
2299       Extrema_ExtElC2d anExt(aTLine, aTEllipse);
2300       Standard_Integer i, imin = 0;
2301       Standard_Real dmin = RealLast();
2302       for (i = 1; i <= anExt.NbExt(); ++i)
2303       {
2304         if (anExt.SquareDistance(i) < dmin)
2305         {
2306           dmin = anExt.SquareDistance(i);
2307           imin = i;
2308         }
2309       }
2310       if (imin > 0 && dmin <= TolTang * TolTang)
2311       {
2312         nbsol = 1;
2313         Extrema_POnCurv2d aP1, aP2;
2314         anExt.Points(imin, aP1, aP2);
2315         Standard_Real pe1 = aP2.Parameter();
2316         EInt1.SetValues(pe1, pe1);
2317       }
2318       else
2319       {
2320         nbsol = 0;
2321       }
2322       return;
2323     }
2324     D = Sqrt(D);
2325     Standard_Real n = a2 * m2 + b2;
2326     Standard_Real k = a * b * D / n;
2327     Standard_Real l = -a2 * m * c / n;
2328     x1 = l + k;
2329     y1 = m * x1 + c;
2330     x2 = l - k;
2331     y2 = m * x2 + c;
2332     nbsol = 2;
2333   }
2334   else
2335   {
2336     x1 = -aC / anA;
2337     if (Abs(x1) > a + TolTang)
2338     {
2339       nbsol = 0;
2340       return;
2341     }
2342     else if (Abs(x1) >= a - Epsilon(1. + a))
2343     {
2344       nbsol = 1;
2345       y1 = 0.;
2346     }
2347     else
2348     {
2349       y1 = b * Sqrt(1. - x1 * x1 / a2);
2350       x2 = x1;
2351       y2 = -y1;
2352       nbsol = 2;
2353     }
2354   }
2355 
2356   gp_Pnt2d aP1(x1, y1);
2357   gp_Pnt2d aP2(x2, y2);
2358   Standard_Real pe1 = 0., pe2 = 0.;
2359   pe1 = ElCLib::Parameter(aTEllipse, aP1);
2360   if (nbsol > 1)
2361   {
2362     pe2 = ElCLib::Parameter(aTEllipse, aP2);
2363     if (pe2 < pe1)
2364     {
2365       Standard_Real t = pe1;
2366       pe1 = pe2;
2367       pe2 = t;
2368     }
2369     EInt2.SetValues(pe2, pe2);
2370   }
2371   EInt1.SetValues(pe1, pe1);
2372 
2373 
2374 }
2375 //=======================================================================
2376 //function : ProjectOnLAndIntersectWithLDomain
2377 //purpose  :
2378 //=======================================================================
ProjectOnLAndIntersectWithLDomain(const gp_Elips2d & Ellipse,const gp_Lin2d & Line,PeriodicInterval & EDomainAndRes,Interval & LDomain,PeriodicInterval * EllipseSolution,Interval * LineSolution,Standard_Integer & NbSolTotal,const IntRes2d_Domain & RefLineDomain,const IntRes2d_Domain &)2379 void ProjectOnLAndIntersectWithLDomain(const gp_Elips2d& Ellipse
2380   , const gp_Lin2d& Line
2381   , PeriodicInterval& EDomainAndRes
2382   , Interval& LDomain
2383   , PeriodicInterval* EllipseSolution
2384   , Interval* LineSolution
2385   , Standard_Integer &NbSolTotal
2386   , const IntRes2d_Domain& RefLineDomain
2387   , const IntRes2d_Domain&)
2388 {
2389 
2390   if (EDomainAndRes.IsNull()) return;
2391   //-------------------------------------------------------------------------
2392   //--  On cherche l intervalle correspondant sur C2
2393   //--  Puis on intersecte l intervalle avec le domaine de C2
2394   //--  Enfin, on cherche l intervalle correspondant sur C1
2395   //--
2396 
2397   Standard_Real Linf = ElCLib::Parameter(Line
2398     , ElCLib::Value(EDomainAndRes.Binf, Ellipse));
2399   Standard_Real Lsup = ElCLib::Parameter(Line
2400     , ElCLib::Value(EDomainAndRes.Bsup, Ellipse));
2401 
2402   Interval LInter(Linf, Lsup);   //-- Necessairement Borne
2403 
2404   Interval LInterAndDomain = LDomain.IntersectionWithBounded(LInter);
2405 
2406   if (!LInterAndDomain.IsNull) {
2407 
2408     Standard_Real DomLinf = (RefLineDomain.HasFirstPoint()) ? RefLineDomain.FirstParameter() : -Precision::Infinite();
2409     Standard_Real DomLsup = (RefLineDomain.HasLastPoint()) ? RefLineDomain.LastParameter() : Precision::Infinite();
2410 
2411     Linf = LInterAndDomain.Binf;
2412     Lsup = LInterAndDomain.Bsup;
2413 
2414     if (Linf<DomLinf) {
2415       Linf = DomLinf;
2416     }
2417     if (Lsup<DomLinf) {
2418       Lsup = DomLinf;
2419     }
2420 
2421     if (Linf>DomLsup) {
2422       Linf = DomLsup;
2423     }
2424     if (Lsup>DomLsup) {
2425       Lsup = DomLsup;
2426     }
2427 
2428     LInterAndDomain.Binf = Linf;
2429     LInterAndDomain.Bsup = Lsup;
2430 
2431 
2432     Standard_Real Einf = EDomainAndRes.Binf;
2433     Standard_Real Esup = EDomainAndRes.Bsup;
2434 
2435     if (Einf >= Esup) { Einf = EDomainAndRes.Binf; Esup = EDomainAndRes.Bsup; }
2436     EllipseSolution[NbSolTotal] = PeriodicInterval(Einf, Esup);
2437     if (EllipseSolution[NbSolTotal].Length() > M_PI)
2438       EllipseSolution[NbSolTotal].Complement();
2439 
2440     LineSolution[NbSolTotal] = LInterAndDomain;
2441     NbSolTotal++;
2442   }
2443 }
2444 
2445 //=======================================================================
2446 //function : Perform
2447 //purpose  : Line - Ellipse
2448 //=======================================================================
Perform(const gp_Lin2d & L,const IntRes2d_Domain & DL,const gp_Elips2d & E,const IntRes2d_Domain & DE,const Standard_Real TolConf,const Standard_Real Tol)2449 void IntCurve_IntConicConic::Perform(const gp_Lin2d& L, const
2450   IntRes2d_Domain& DL, const gp_Elips2d& E,
2451   const IntRes2d_Domain& DE, const Standard_Real TolConf,
2452   const Standard_Real Tol)
2453 {
2454   Standard_Boolean TheReversedParameters = ReversedParameters();
2455   this->ResetFields();
2456   this->SetReversedParameters(TheReversedParameters);
2457 
2458   Standard_Integer nbsol = 0;
2459   PeriodicInterval EInt1, EInt2;
2460 
2461   LineEllipseGeometricIntersection(L, E, TolConf, Tol, EInt1, EInt2, nbsol);
2462   done = Standard_True;
2463   if (nbsol == 0)
2464   {
2465     return;
2466   }
2467   //
2468   if (nbsol == 2 && EInt2.Bsup == EInt1.Binf + PIpPI) {
2469     Standard_Real FirstBound = DE.FirstParameter();
2470     Standard_Real LastBound = DE.LastParameter();
2471     Standard_Real FirstTol = DE.FirstTolerance();
2472     Standard_Real LastTol = DE.LastTolerance();
2473     if (EInt1.Binf == 0 && FirstBound - FirstTol > EInt1.Bsup)
2474     {
2475       nbsol = 1;
2476       EInt1.SetValues(EInt2.Binf, EInt2.Bsup);
2477     }
2478     else if (EInt2.Bsup == PIpPI && LastBound + LastTol < EInt2.Binf)
2479     {
2480       nbsol = 1;
2481     }
2482   }
2483   //
2484   PeriodicInterval EDomain(DE);
2485   Standard_Real deltat = EDomain.Bsup - EDomain.Binf;
2486   while (EDomain.Binf >= PIpPI) EDomain.Binf -= PIpPI;
2487   while (EDomain.Binf <  0.0)   EDomain.Binf += PIpPI;
2488   EDomain.Bsup = EDomain.Binf + deltat;
2489   //
2490   Standard_Real BinfModif = EDomain.Binf;
2491   Standard_Real BsupModif = EDomain.Bsup;
2492   BinfModif -= DE.FirstTolerance() / E.MinorRadius();
2493   BsupModif += DE.LastTolerance() / E.MinorRadius();
2494   deltat = BsupModif - BinfModif;
2495   if (deltat <= PIpPI) {
2496     EDomain.Binf = BinfModif;
2497     EDomain.Bsup = BsupModif;
2498   }
2499   else {
2500     Standard_Real t = PIpPI - deltat;
2501     t *= 0.5;
2502     EDomain.Binf = BinfModif + t;
2503     EDomain.Bsup = BsupModif - t;
2504   }
2505   deltat = EDomain.Bsup - EDomain.Binf;
2506   while (EDomain.Binf >= PIpPI) EDomain.Binf -= PIpPI;
2507   while (EDomain.Binf <  0.0)   EDomain.Binf += PIpPI;
2508   EDomain.Bsup = EDomain.Binf + deltat;
2509   //
2510   Interval LDomain(DL);
2511 
2512   Standard_Integer NbSolTotal = 0;
2513 
2514   PeriodicInterval SolutionEllipse[4];
2515   Interval SolutionLine[4];
2516   //----------------------------------------------------------------------
2517   //----------- Treatment of first geometric interval EInt1           ----
2518   //----------------------------------------------------------------------
2519   PeriodicInterval EDomainAndRes = EDomain.FirstIntersection(EInt1);
2520 
2521   ProjectOnLAndIntersectWithLDomain(E, L, EDomainAndRes, LDomain, SolutionEllipse
2522     , SolutionLine, NbSolTotal, DL, DE);
2523 
2524   EDomainAndRes = EDomain.SecondIntersection(EInt1);
2525 
2526   ProjectOnLAndIntersectWithLDomain(E, L, EDomainAndRes, LDomain, SolutionEllipse
2527     , SolutionLine, NbSolTotal, DL, DE);
2528 
2529 
2530   //----------------------------------------------------------------------
2531   //----------- Treatment of second geometric interval EInt2          ----
2532   //----------------------------------------------------------------------
2533   if (nbsol == 2)
2534   {
2535     EDomainAndRes = EDomain.FirstIntersection(EInt2);
2536 
2537     ProjectOnLAndIntersectWithLDomain(E, L, EDomainAndRes, LDomain, SolutionEllipse
2538       , SolutionLine, NbSolTotal, DL, DE);
2539 
2540     EDomainAndRes = EDomain.SecondIntersection(EInt2);
2541 
2542     ProjectOnLAndIntersectWithLDomain(E, L, EDomainAndRes, LDomain, SolutionEllipse
2543       , SolutionLine, NbSolTotal, DL, DE);
2544   }
2545 
2546   //----------------------------------------------------------------------
2547   //-- Calculation of Transitions at Positions.
2548   //----------------------------------------------------------------------
2549   Standard_Real R = E.MinorRadius();
2550   Standard_Integer i;
2551   Standard_Real MaxTol = TolConf;
2552   if (MaxTol<Tol) MaxTol = Tol;
2553   if (MaxTol<1.0e-10) MaxTol = 1.0e-10;
2554 
2555   for (i = 0; i<NbSolTotal; i++) {
2556     if ((R * SolutionEllipse[i].Length())<MaxTol
2557       && (SolutionLine[i].Length())<MaxTol) {
2558 
2559       Standard_Real t = (SolutionEllipse[i].Binf + SolutionEllipse[i].Bsup)*0.5;
2560       SolutionEllipse[i].Binf = SolutionEllipse[i].Bsup = t;
2561 
2562       t = (SolutionLine[i].Binf + SolutionLine[i].Bsup)*0.5;
2563       SolutionLine[i].Binf = SolutionLine[i].Bsup = t;
2564     }
2565   }
2566   //
2567   if (NbSolTotal) {
2568     gp_Ax22d EllipseAxis = E.Axis();
2569     gp_Ax2d LineAxis = L.Position();
2570     gp_Pnt2d P1a, P2a, P1b, P2b;
2571     gp_Vec2d Tan1, Tan2, Norm1;
2572     gp_Vec2d Norm2(0.0, 0.0);
2573     IntRes2d_Transition T1a, T2a, T1b, T2b;
2574     IntRes2d_Position Pos1a, Pos1b, Pos2a, Pos2b;
2575 
2576     ElCLib::EllipseD1(SolutionEllipse[0].Binf, EllipseAxis, E.MajorRadius(), E.MinorRadius(), P1a, Tan1);
2577     ElCLib::LineD1(SolutionLine[0].Binf, LineAxis, P2a, Tan2);
2578 
2579     Standard_Boolean isOpposite = (Tan1.Dot(Tan2) < 0.0);
2580     for (i = 0; i<NbSolTotal; i++)
2581     {
2582       Standard_Real p1 = SolutionEllipse[i].Binf;
2583       Standard_Real p2 = SolutionEllipse[i].Bsup;
2584       Standard_Real q1 = DE.FirstParameter();
2585       Standard_Real q2 = DE.LastParameter();
2586 
2587       if (p1>q2) {
2588         do {
2589           p1 -= PIpPI;
2590           p2 -= PIpPI;
2591         } while ((p1>q2));
2592       }
2593       else if (p2<q1) {
2594         do {
2595           p1 += PIpPI;
2596           p2 += PIpPI;
2597         } while ((p2<q1));
2598       }
2599       if (p1<q1 && p2>q1) {
2600         p1 = q1;
2601       }
2602       if (p1<q2 && p2>q2) {
2603         p2 = q2;
2604       }
2605 
2606       SolutionEllipse[i].Binf = p1;
2607       SolutionEllipse[i].Bsup = p2;
2608 
2609       Standard_Real Linf = isOpposite ? SolutionLine[i].Bsup : SolutionLine[i].Binf;
2610       Standard_Real Lsup = isOpposite ? SolutionLine[i].Binf : SolutionLine[i].Bsup;
2611 
2612       if (Linf > Lsup) {
2613         Standard_Real T = SolutionEllipse[i].Binf;
2614         SolutionEllipse[i].Binf = SolutionEllipse[i].Bsup;
2615         SolutionEllipse[i].Bsup = T;
2616         T = Linf; Linf = Lsup; Lsup = T;
2617       }
2618 
2619 
2620       ElCLib::EllipseD2(SolutionEllipse[i].Binf, EllipseAxis, E.MajorRadius(),
2621                         E.MinorRadius(), P1a, Tan1, Norm1);
2622       ElCLib::LineD1(Linf, LineAxis, P2a, Tan2);
2623 
2624       IntImpParGen::DeterminePosition(Pos1a, DE, P1a, SolutionEllipse[i].Binf);
2625       IntImpParGen::DeterminePosition(Pos2a, DL, P2a, Linf);
2626       Determine_Transition_LC(Pos1a, Tan1, Norm1, T1a, Pos2a, Tan2, Norm2, T2a, Tol);
2627       Standard_Real Einf;
2628       if (Pos1a == IntRes2d_End) {
2629         Einf = DE.LastParameter();
2630         P1a = DE.LastPoint();
2631         Linf = ElCLib::Parameter(L, P1a);
2632 
2633         ElCLib::EllipseD2(Einf, EllipseAxis, E.MajorRadius(),
2634                           E.MinorRadius(), P1a, Tan1, Norm1);
2635         ElCLib::LineD1(Linf, LineAxis, P2a, Tan2);
2636         IntImpParGen::DeterminePosition(Pos1a, DE, P1a, Einf);
2637         IntImpParGen::DeterminePosition(Pos2a, DL, P2a, Linf);
2638         Determine_Transition_LC(Pos1a, Tan1, Norm1, T1a, Pos2a, Tan2, Norm2, T2a, Tol);
2639       }
2640       else if (Pos1a == IntRes2d_Head) {
2641         Einf = DE.FirstParameter();
2642         P1a = DE.FirstPoint();
2643         Linf = ElCLib::Parameter(L, P1a);
2644 
2645         ElCLib::EllipseD2(Einf, EllipseAxis, E.MajorRadius(),
2646                           E.MinorRadius(), P1a, Tan1, Norm1);
2647         ElCLib::LineD1(Linf, LineAxis, P2a, Tan2);
2648         IntImpParGen::DeterminePosition(Pos1a, DE, P1a, Einf);
2649         IntImpParGen::DeterminePosition(Pos2a, DL, P2a, Linf);
2650         Determine_Transition_LC(Pos1a, Tan1, Norm1, T1a, Pos2a, Tan2, Norm2, T2a, Tol);
2651       }
2652       else {
2653         Einf = NormalizeOnCircleDomain(SolutionEllipse[i].Binf, DE);
2654       }
2655 
2656       IntRes2d_IntersectionPoint NewPoint1(P1a, Linf, Einf, T2a, T1a, ReversedParameters());
2657 
2658       if ((SolutionLine[i].Length() + SolutionEllipse[i].Length()) >0.0) {
2659 
2660         ElCLib::EllipseD2(SolutionEllipse[i].Binf, EllipseAxis, E.MajorRadius(),
2661                           E.MinorRadius(), P1b, Tan1, Norm1);
2662         ElCLib::LineD1(Lsup, LineAxis, P2b, Tan2);
2663 
2664         IntImpParGen::DeterminePosition(Pos1b, DE, P1b, SolutionEllipse[i].Bsup);
2665         IntImpParGen::DeterminePosition(Pos2b, DL, P2b, Lsup);
2666         Determine_Transition_LC(Pos1b, Tan1, Norm1, T1b, Pos2b, Tan2, Norm2, T2b, Tol);
2667         Standard_Real Esup;
2668         if (Pos1b == IntRes2d_End) {
2669           Esup = DL.LastParameter();
2670           P1b = DE.LastPoint();
2671           Lsup = ElCLib::Parameter(L, P1b);
2672           ElCLib::EllipseD2(Esup, EllipseAxis, E.MajorRadius(),
2673                             E.MinorRadius(), P1b, Tan1, Norm1);
2674           ElCLib::LineD1(Lsup, LineAxis, P2b, Tan2);
2675 
2676           IntImpParGen::DeterminePosition(Pos1b, DE, P1b, Esup);
2677           IntImpParGen::DeterminePosition(Pos2b, DL, P2b, Lsup);
2678           Determine_Transition_LC(Pos1b, Tan1, Norm1, T1b, Pos2b, Tan2, Norm2, T2b, Tol);
2679         }
2680         else if (Pos1b == IntRes2d_Head) {
2681           Esup = DE.FirstParameter();
2682           P1b = DE.FirstPoint();
2683           Lsup = ElCLib::Parameter(L, P1b);
2684           ElCLib::EllipseD2(Esup, EllipseAxis, E.MajorRadius(),
2685                             E.MinorRadius(), P1b, Tan1, Norm1);
2686           ElCLib::LineD1(Lsup, LineAxis, P2b, Tan2);
2687 
2688           IntImpParGen::DeterminePosition(Pos1b, DE, P1b, Esup);
2689           IntImpParGen::DeterminePosition(Pos2b, DL, P2b, Lsup);
2690           Determine_Transition_LC(Pos1b, Tan1, Norm1, T1b, Pos2b, Tan2, Norm2, T2b, Tol);
2691         }
2692         else {
2693           Esup = NormalizeOnCircleDomain(SolutionEllipse[i].Bsup, DE);
2694         }
2695 
2696         IntRes2d_IntersectionPoint NewPoint2(P1b, Lsup, Esup, T2b, T1b, ReversedParameters());
2697 
2698         if (((Abs(Esup - Einf)*R >  MaxTol) && (Abs(Lsup - Linf) > MaxTol))
2699           || (T1a.TransitionType() != T2a.TransitionType())) {
2700           IntRes2d_IntersectionSegment NewSeg(NewPoint1, NewPoint2, isOpposite, ReversedParameters());
2701           Append(NewSeg);
2702         }
2703         else {
2704           if (Pos1a != IntRes2d_Middle || Pos2a != IntRes2d_Middle) {
2705             Insert(NewPoint1);
2706           }
2707           if (Pos1b != IntRes2d_Middle || Pos2b != IntRes2d_Middle) {
2708             Insert(NewPoint2);
2709           }
2710 
2711         }
2712       }
2713       else
2714       {
2715        Insert(NewPoint1);
2716       }
2717     }
2718   }
2719 }
2720 
2721