6f8beeac9e5ec0bebf895764a11fe26d33f40521
[occt.git] / src / IntCurve / IntCurve_IntConicConic_1.cxx
1 // Created on: 1992-05-06
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1992-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21 // a modifier le cas de 2 points confondus ( Insert a la place d'append ? ) 
22
23 #include <IntCurve_IntConicConic.jxx>
24
25 #include <IntCurve_IConicTool.hxx>
26 #include <IntCurve_PConic.hxx>
27 #include <IntRes2d_Domain.hxx>
28 #include <gp.hxx>
29 #include <IntCurve_IntConicConic_Tool.hxx>
30 #include <IntImpParGen.hxx>
31 #include <IntCurve_IntConicConic_1.hxx>
32 #include <ElCLib.hxx>
33 #include <Standard_ConstructionError.hxx>
34 #include <IntRes2d_IntersectionPoint.hxx>
35 #include <IntRes2d_IntersectionSegment.hxx>
36
37 #include <gp_Pnt2d.hxx>
38 #include <gp_Vec2d.hxx>
39 #include <Precision.hxx>
40 #include <IntRes2d_TypeTrans.hxx>
41
42 Standard_Boolean Affichage=Standard_False;
43 Standard_Boolean AffichageGraph=Standard_True;
44
45 //modified by NIZHNY-MKK  Tue Feb 15 10:53:34 2000.BEGIN
46 // #define TOLERANCE_ANGULAIRE 0.00000001
47 #define TOLERANCE_ANGULAIRE 1.e-15 //the reason is at least to make an accordance between transition and position computation.
48 //modified by NIZHNY-MKK  Tue Feb 15 10:53:45 2000.END
49
50 const Standard_Real PIsur2 = 0.5*M_PI;
51
52 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53 IntRes2d_Position FindPositionLL(Standard_Real&,const IntRes2d_Domain&);
54 const IntRes2d_IntersectionPoint SegmentToPoint( const IntRes2d_IntersectionPoint& Pa
55                                                 ,const IntRes2d_Transition& T1a
56                                                 ,const IntRes2d_Transition& T2a
57                                                 ,const IntRes2d_IntersectionPoint& Pb
58                                                 ,const IntRes2d_Transition& T1b
59                                                 ,const IntRes2d_Transition& T2b);  
60 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
61 void ProjectOnC2AndIntersectWithC2Domain(const gp_Circ2d& Circle1
62                                          ,const gp_Circ2d& Circle2
63                                          ,PeriodicInterval& C1DomainAndRes
64                                          ,PeriodicInterval& DomainC2
65                                          ,PeriodicInterval* SolutionC1
66                                          ,PeriodicInterval* SolutionC2
67                                          ,Standard_Integer &NbSolTotal
68                                          ,const Standard_Boolean IdentCircles)
69 {
70   
71   if(C1DomainAndRes.IsNull()) return;
72   //-------------------------------------------------------------------------
73   //--  On cherche l intervalle correspondant sur C2
74   //--  Puis on intersecte l intervalle avec le domaine de C2
75   //--  Enfin, on cherche l intervalle correspondant sur C1
76   //--
77   Standard_Real C2inf = 
78     ElCLib::CircleParameter(Circle2.Axis()
79                             ,ElCLib::CircleValue(C1DomainAndRes.Binf
80                                                  ,Circle1.Axis(),Circle1.Radius()));
81   Standard_Real C2sup = 
82     ElCLib::CircleParameter(Circle2.Axis()
83                             ,ElCLib::CircleValue(C1DomainAndRes.Bsup
84                                                  ,Circle1.Axis(),Circle1.Radius()));
85
86   PeriodicInterval C2Inter(C2inf,C2sup);
87
88   if(!IdentCircles) {
89     if(C2Inter.Length() > M_PI)
90       C2Inter.Complement();
91   }
92   else {
93     if(C2sup<=C2inf) C2sup+=PIpPI;
94     if(C2inf>=PIpPI) {
95       C2sup-=PIpPI;
96       C2inf-=PIpPI;
97     }
98     C2Inter.Binf=C2inf;
99     C2Inter.Bsup=C2sup; //--- Verifier la longueur de l'intervalle sur C2
100     C2Inter.Bsup=C2inf+C1DomainAndRes.Bsup-C1DomainAndRes.Binf;
101   }
102   
103   PeriodicInterval C2InterAndDomain[2];
104   
105   for(Standard_Integer i=0; i<2 ; i++) {
106     C2InterAndDomain[i]=(i==0)?  DomainC2.FirstIntersection(C2Inter)
107                                : DomainC2.SecondIntersection(C2Inter);
108   
109     if(!C2InterAndDomain[i].IsNull()) {
110
111       Standard_Real C1inf = 
112         ElCLib::CircleParameter(Circle1.Axis()
113                                 ,ElCLib::CircleValue(C2InterAndDomain[i].Binf
114                                         ,Circle2.Axis(),Circle2.Radius()));
115       Standard_Real C1sup = 
116         ElCLib::CircleParameter(Circle1.Axis()
117                                 ,ElCLib::CircleValue(C2InterAndDomain[i].Bsup
118                                         ,Circle2.Axis(),Circle2.Radius()));
119
120       SolutionC1[NbSolTotal]=PeriodicInterval(C1inf,C1sup);
121       if(!IdentCircles) {
122         if(SolutionC1[NbSolTotal].Length() > M_PI)
123           SolutionC1[NbSolTotal].Complement();
124       }
125       else {
126         if(SolutionC1[NbSolTotal].Bsup <= SolutionC1[NbSolTotal].Binf) {
127           SolutionC1[NbSolTotal].Bsup+=PIpPI;
128         }
129         if(SolutionC1[NbSolTotal].Binf>=PIpPI) {
130           SolutionC1[NbSolTotal].Binf-=PIpPI;
131           SolutionC1[NbSolTotal].Bsup-=PIpPI;     
132         }
133       }
134       SolutionC2[NbSolTotal]=C2InterAndDomain[i];
135       NbSolTotal++;
136     }
137   }
138 }
139 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
140 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
141 void CircleCircleGeometricIntersection(const gp_Circ2d& C1
142                                        ,const gp_Circ2d& C2
143                                        ,const Standard_Real Tol
144                                        ,const Standard_Real TolTang
145                                        ,PeriodicInterval& C1_Res1
146                                        ,PeriodicInterval& C1_Res2
147                                        ,Standard_Integer& nbsol) {
148   
149   Standard_Real C1_binf1,C1_binf2=0,C1_bsup1,C1_bsup2=0;
150   Standard_Real dO1O2=(C1.Location()).Distance(C2.Location());
151   Standard_Real R1=C1.Radius();
152   Standard_Real R2=C2.Radius();
153   Standard_Real AbsR1mR2=Abs(R1-R2);
154   //---------------------------------------------------------------- 
155   if(dO1O2 > (R1+R2+Tol)) {
156     if(dO1O2 > (R1+R2+TolTang)) { 
157       nbsol=0; 
158       return; 
159     }
160     else { 
161       C1_binf1 = 0.0;
162       C1_bsup1 = 0.0;
163       nbsol = 1;
164     }
165   }
166   //---------------------------------------------------------------- 
167   else if(dO1O2 <= Tol  &&  AbsR1mR2<=Tol)  { 
168     nbsol=3; 
169     return; 
170   }
171   else { 
172     //---------------------------------------------------------------- 
173     Standard_Real R1pR2=R1+R2;
174     Standard_Real R1pTol=R1+Tol;
175     Standard_Real R1mTol=R1-Tol;
176 //    Standard_Real R1R1=R1*R1;
177     Standard_Real R2R2=R2*R2;
178     Standard_Real R1pTolR1pTol=R1pTol*R1pTol;
179     Standard_Real R1mTolR1mTol=R1mTol*R1mTol;
180     Standard_Real dO1O2dO1O2=dO1O2*dO1O2;
181     Standard_Real dAlpha1;
182     //--------------------------------------------------------------- Cas 
183     //-- C2 coupe le cercle C1+ (=C(x1,y1,R1+Tol))
184     //--            1 seul segment donne par Inter C2 C1+
185     //--
186     if(dO1O2 > R1pR2-Tol) { 
187       Standard_Real dx=(R1pTolR1pTol+dO1O2dO1O2-R2R2)/(dO1O2+dO1O2);
188       Standard_Real dy=(R1pTolR1pTol-dx*dx);
189       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
190       dAlpha1=ATan2(dy,dx);
191       
192       C1_binf1=-dAlpha1;  
193       C1_bsup1=dAlpha1;
194       nbsol=1;
195     }
196     //--------------------------------------------------------------------
197     //--           2 segments donnes par Inter C2 avec C1- C1 C1+
198     //-- Seul le signe de dx change si dO1O2 < Max(R1,R2)
199     //-- 
200     else if(dO1O2 > AbsR1mR2-Tol) {  // -- + 
201       //------------------- Intersection C2 C1+ --------------------------
202       Standard_Real dx=(R1pTolR1pTol+dO1O2dO1O2-R2R2)/(dO1O2+dO1O2);
203       Standard_Real dy=(R1pTolR1pTol-dx*dx); 
204       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
205       
206       dAlpha1=ATan2(dy,dx);
207       C1_binf1=-dAlpha1;  C1_bsup2=dAlpha1;  //--  |...?     ?...|   Sur C1
208       
209       //------------------ Intersection C2 C1- -------------------------
210       dx=(R1mTolR1mTol+dO1O2dO1O2-R2R2)/(dO1O2+dO1O2);
211       dy=(R1mTolR1mTol-dx*dx);
212       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
213       dAlpha1=ATan2(dy,dx);
214       
215       C1_binf2=dAlpha1;  C1_bsup1=-dAlpha1;  //--  |...x     x...|   Sur C1
216       nbsol=2;    
217       //------------------------------
218       //-- Les 2 intervalles sont ils 
219       //-- en fait un seul inter ? 
220       //-- 
221       if(dy==0) {    //-- Les 2 bornes internes sont identiques 
222         C1_bsup1 = C1_bsup2; 
223         nbsol = 1;
224       }
225       else { 
226         if(C1_binf1>C1_bsup1) { 
227           dAlpha1 = C1_binf1; C1_binf1 = C1_bsup1; C1_bsup1 = dAlpha1; 
228         }
229         if(C1_binf2>C1_bsup2) { 
230           dAlpha1 = C1_binf2; C1_binf2 = C1_bsup2; C1_bsup2 = dAlpha1; 
231         }
232         if(   ((C1_binf1<=C1_bsup2) && (C1_binf1>=C1_binf2))
233            || ((C1_bsup1<=C1_bsup2) && (C1_bsup1>=C1_binf2))) { 
234           if(C1_binf1 > C1_binf2) C1_binf1 = C1_binf2;
235           if(C1_binf1 > C1_bsup2) C1_binf1 = C1_bsup2;
236           if(C1_bsup1 < C1_binf2) C1_bsup1 = C1_binf2;
237           if(C1_bsup1 < C1_bsup2) C1_bsup1 = C1_bsup2;
238           nbsol=1;
239         }
240       }
241     }
242     //--------------------------------------------------------------
243     //--    1 seul segment donne par Inter C2 avec C1- ou C1+
244     else if(dO1O2 > AbsR1mR2-Tol) {
245       
246       Standard_Real dx=(R1mTolR1mTol+dO1O2dO1O2-R2R2)/(dO1O2+dO1O2);
247       Standard_Real dy=(R1mTolR1mTol-dx*dx);
248       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
249       dAlpha1=ATan2(dy,dx);
250       
251       dx=(R1pTolR1pTol+dO1O2dO1O2-R2R2)/(dO1O2+dO1O2);
252       dy=(R1pTolR1pTol-dx*dx);
253       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
254       Standard_Real dAlpha2=ATan2(dy,dx);
255       
256       if(dAlpha2>dAlpha1) dAlpha1 = dAlpha2;
257       C1_binf1=-dAlpha1;  C1_bsup1=dAlpha1;
258       nbsol=1;
259     }
260     //--------------------------------------------------------------
261     else {
262       if((dO1O2 > AbsR1mR2-TolTang) && (AbsR1mR2-TolTang)>0.0) { 
263         C1_binf1=0.0;  
264         C1_bsup1=0.0;
265         nbsol = 1;
266       }
267       else { 
268         nbsol=0; return ;
269       }
270     }
271   }
272
273   //-- cout<<" C1_binf1:"<<C1_binf1;
274   //-- cout<<" C1_bsup1:"<<C1_bsup1;
275   //-- cout<<" C1_binf2:"<<C1_binf2;
276   //-- cout<<" C1_bsup2:"<<C1_bsup2<<endl;
277   //----------------------------------------------------------------
278   //-- Mise en forme des resultats : 
279   //--    Les calculs ont ete fait dans le repere x1,y1, (O1,O2)
280   //--    On se ramene au repere propre a C1
281
282   gp_Vec2d Axe1=C1.XAxis().Direction();
283   gp_Vec2d AxeO1O2=gp_Vec2d(C1.Location(),C2.Location());
284   
285   Standard_Real dAngle1;
286   if(AxeO1O2.Magnitude() <= gp::Resolution()) 
287     dAngle1=Axe1.Angle(C2.XAxis().Direction());
288   else
289     dAngle1=Axe1.Angle(AxeO1O2);
290
291   if(C1.IsDirect() == Standard_False) { 
292     dAngle1 = -dAngle1; 
293   }
294
295
296   C1_binf1+=dAngle1;  C1_bsup1+=dAngle1;
297   
298   //-- par construction aucun des segments ne peut exceder PI
299   //-- (permet de ne pas gerer trop de cas differents)
300
301   C1_Res1.SetValues(C1_binf1,C1_bsup1);
302   if(C1_Res1.Length() > M_PI) C1_Res1.Complement();
303
304   if(nbsol==2) {
305     C1_binf2+=dAngle1;  C1_bsup2+=dAngle1;
306     C1_Res2.SetValues(C1_binf2,C1_bsup2);
307     if(C1_Res2.Length() > M_PI) C1_Res2.Complement();
308   }
309   else {
310     C1_Res2.SetNull(); 
311   }
312 }
313 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
314 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
315 void ProjectOnLAndIntersectWithLDomain(const gp_Circ2d& Circle
316                                        ,const gp_Lin2d& Line
317                                        ,PeriodicInterval& CDomainAndRes
318                                        ,Interval& LDomain
319                                        ,PeriodicInterval* CircleSolution
320                                        ,Interval* LineSolution
321                                        ,Standard_Integer &NbSolTotal
322                                        ,const IntRes2d_Domain& RefLineDomain
323 //                                     ,const IntRes2d_Domain& )
324                                        ,const IntRes2d_Domain& )
325 {
326   
327   
328   if(CDomainAndRes.IsNull()) return;
329   //-------------------------------------------------------------------------
330   //--  On cherche l intervalle correspondant sur C2
331   //--  Puis on intersecte l intervalle avec le domaine de C2
332   //--  Enfin, on cherche l intervalle correspondant sur C1
333   //--
334
335   Standard_Real Linf=ElCLib::Parameter(Line
336                              ,ElCLib::CircleValue(CDomainAndRes.Binf
337                                                  ,Circle.Axis()
338                                                  ,Circle.Radius()));
339   Standard_Real Lsup=ElCLib::Parameter(Line
340                              ,ElCLib::CircleValue(CDomainAndRes.Bsup
341                                                  ,Circle.Axis()
342                                                  ,Circle.Radius()));
343
344   Interval LInter(Linf,Lsup);   //-- Necessairement Borne 
345   
346   Interval LInterAndDomain=LDomain.IntersectionWithBounded(LInter);
347
348   if(!LInterAndDomain.IsNull) {
349
350     Standard_Real DomLinf = (RefLineDomain.HasFirstPoint())? RefLineDomain.FirstParameter() : -Precision::Infinite();
351     Standard_Real DomLsup = (RefLineDomain.HasLastPoint())? RefLineDomain.LastParameter() : Precision::Infinite();
352     
353     Linf = LInterAndDomain.Binf;
354     Lsup = LInterAndDomain.Bsup;
355
356     if(Linf<DomLinf) {
357       Linf = DomLinf; 
358     }
359     if(Lsup<DomLinf) { 
360       Lsup = DomLinf; 
361     }
362     
363     if(Linf>DomLsup) {
364       Linf = DomLsup; 
365     }
366     if(Lsup>DomLsup) { 
367       Lsup = DomLsup; 
368     }
369   
370     LInterAndDomain.Binf = Linf;
371     LInterAndDomain.Bsup = Lsup;
372
373 #if 0     
374     Standard_Real Cinf = 
375       ElCLib::CircleParameter(Circle.Axis()                                            
376                               ,ElCLib::LineValue(LInterAndDomain.Binf,
377                                         Line.Position()));
378     Standard_Real Csup = 
379       ElCLib::CircleParameter(Circle.Axis()
380                               ,ElCLib::LineValue(LInterAndDomain.Bsup
381                                         ,Line.Position()));
382
383     if(Cinf<CDomainAndRes.Binf) Cinf = CDomainAndRes.Binf;
384     if(Csup>CDomainAndRes.Bsup) Csup = CDomainAndRes.Bsup;
385 #else
386     Standard_Real Cinf=CDomainAndRes.Binf;
387     Standard_Real Csup=CDomainAndRes.Bsup;
388 #endif
389     if(Cinf>=Csup) { Cinf = CDomainAndRes.Binf; Csup = CDomainAndRes.Bsup; } 
390     CircleSolution[NbSolTotal]=PeriodicInterval(Cinf,Csup);
391     if(CircleSolution[NbSolTotal].Length() > M_PI)
392       CircleSolution[NbSolTotal].Complement();
393     
394     LineSolution[NbSolTotal]=LInterAndDomain;
395     NbSolTotal++;
396   }
397 }
398
399 //=======================================================================
400 //function : LineCircleGeometricIntersection
401 //purpose  : 
402 //~~ On cherche des segments d intersection dans le `tuyau` 
403 //~~   R+Tol   R-Tol  ( Tol est TolConf : Tolerance de confusion d arc)
404 //~~ On Cherche un point d intersection a une distance TolTang du cercle.   
405 //=======================================================================
406 void LineCircleGeometricIntersection(const gp_Lin2d& Line,
407                                      const gp_Circ2d& Circle,
408                                      const Standard_Real Tol,
409                                      const Standard_Real TolTang,
410                                      PeriodicInterval& CInt1,
411                                      PeriodicInterval& CInt2,
412                                      Standard_Integer& nbsol) 
413 {
414   
415
416   Standard_Real dO1O2=Line.Distance(Circle.Location());
417   Standard_Real R=Circle.Radius();
418   Standard_Real RmTol=R-Tol;
419   Standard_Real binf1,binf2=0,bsup1,bsup2=0;
420     
421   //---------------------------------------------------------------- 
422   if(dO1O2 > (R+Tol))  {  //-- pas d intersection avec le 'tuyau'
423     if(dO1O2 > (R+TolTang)) {  
424       nbsol=0; 
425       return;
426     }
427     else { 
428       binf1=0.0;  
429       bsup1=0.0;
430       nbsol=1;
431     }
432   }
433   else { 
434     //---------------------------------------------------------------- 
435     Standard_Boolean b2Sol;
436     Standard_Real dAlpha1;
437     //---------------------------------------------------------------
438     //-- Line coupe le cercle Circle+ (=C(x1,y1,R1+Tol))
439     //modified by NIZNHY-PKV Thu May 12 12:25:17 2011f
440     b2Sol=Standard_False;
441     if (R>dO1O2+TolTang) {
442       Standard_Real aX2, aTol2;
443       //
444       aTol2=Tol*Tol;
445       aX2=4.*(R*R-dO1O2*dO1O2);
446       if (aX2>aTol2) {
447         b2Sol=!b2Sol;
448       }
449     }
450     if(dO1O2 > RmTol && !b2Sol) { 
451     //if(dO1O2 > RmTol) { 
452     //modified by NIZNHY-PKV Thu May 12 12:25:20 2011t
453       Standard_Real dx=dO1O2;
454       Standard_Real dy=0.0;     //(RpTol*RpTol-dx*dx); //Patch !!!
455       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
456       dAlpha1=ATan2(dy,dx);
457       
458       binf1=-dAlpha1;  
459       bsup1=dAlpha1;
460       nbsol=1;
461     }  
462     //--------------------------------------------------------------------
463     //--           2 segments donnes par Inter Line avec Circle-  Circle+
464     //-- 
465     else {
466       //------------------- Intersection Line Circle+ --------------------------
467       Standard_Real dx=dO1O2;
468       Standard_Real dy=R*R-dx*dx;    //(RpTol*RpTol-dx*dx); //Patch !!!
469       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
470       
471       dAlpha1=ATan2(dy,dx);
472       binf1=-dAlpha1;  bsup2=dAlpha1;  //--  |...?     ?...|   Sur C1
473       
474       //------------------ Intersection Line Circle-  -------------------------
475       dy=R*R-dx*dx;                  //(RmTol*RmTol-dx*dx); //Patch !!!
476       dy=(dy>=0.0)? Sqrt(dy) : 0.0;
477       dAlpha1=ATan2(dy,dx);
478       
479       binf2=dAlpha1;  bsup1=-dAlpha1;  //--  |...x     x...|   Sur C1
480
481       if((dAlpha1*R)<(Max(Tol,TolTang))) { 
482         bsup1 = bsup2; 
483         nbsol = 1;
484       }
485       else { 
486         nbsol=2;
487       }
488     }
489   }
490   //--------------------------------------------------------------
491   //-- Mise en forme des resultats : 
492   //--    Les calculs ont ete fait dans le repere x1,y1, (O1,O2)
493   //--    On se ramene au repere propre a C1
494   
495   Standard_Real dAngle1=(Circle.XAxis().Direction()).Angle(Line.Direction());
496   
497 #if 0 
498   //---------------------------------------------
499   //-- Si le cercle est indirect alors l origine
500   //-- est vue en -dAngle1. 
501   //--
502   if(Circle.IsDirect() == Standard_False) { 
503     dAngle1 = -dAngle1;
504   }
505 #endif  
506   
507   
508   Standard_Real a,b,c,d;
509   Line.Coefficients(a,b,c);
510   
511   d = a*Circle.Location().X() + b*Circle.Location().Y() + c;
512   
513   if(d>0.0)  dAngle1+= PIsur2;
514   else       dAngle1-= PIsur2;
515
516      
517   if(dAngle1<0.0) dAngle1+=PIpPI;
518   else if(dAngle1>PIpPI) dAngle1-=PIpPI;
519   
520   
521   binf1+=dAngle1;  bsup1+=dAngle1;
522   
523   //-- par construction aucun des segments ne peut exceder PI
524   //-- (permet de ne pas gerer trop de cas differents)
525   
526   if(Circle.IsDirect() == Standard_False) {
527     Standard_Real t=binf1; binf1=bsup1; bsup1=t;
528     binf1 = -binf1;
529     bsup1 = -bsup1;
530   }
531
532
533   CInt1.SetValues(binf1,bsup1);
534   if(CInt1.Length() > M_PI) CInt1.Complement();
535   
536
537   if(nbsol==2) {
538     binf2+=dAngle1;  bsup2+=dAngle1;
539
540     if(Circle.IsDirect() == Standard_False) {
541       Standard_Real t=binf2; binf2=bsup2; bsup2=t;
542       binf2 = -binf2;
543       bsup2 = -bsup2;
544     }
545
546     CInt2.SetValues(binf2,bsup2);
547     if(CInt2.Length() > M_PI) CInt2.Complement();
548   }
549 //  Modified by Sergey KHROMOV - Thu Oct 26 17:51:05 2000 Begin
550   else {
551     if (CInt1.Bsup > PIpPI && CInt1.Binf < PIpPI) {
552       nbsol = 2;
553       binf2 = CInt1.Binf;
554       bsup2 = PIpPI;
555       binf1 = 0.;
556       CInt1.SetValues(binf1,CInt1.Bsup - PIpPI);
557       if(CInt1.Length() > M_PI) CInt1.Complement();
558       CInt2.SetValues(binf2,bsup2);
559       if(CInt2.Length() > M_PI) CInt2.Complement();
560     }
561   }
562 //  Modified by Sergey KHROMOV - Thu Oct 26 17:51:13 2000 End
563 }
564 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
565 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
566 void DomainIntersection(const IntRes2d_Domain& Domain
567                         ,const Standard_Real U1inf
568                         ,const Standard_Real U1sup
569                         ,Standard_Real& Res1inf
570                         ,Standard_Real& Res1sup
571                         ,IntRes2d_Position& PosInf
572                         ,IntRes2d_Position& PosSup) {
573   
574   if(Domain.HasFirstPoint()) {
575     if(U1sup < (Domain.FirstParameter()-Domain.FirstTolerance())) {
576       Res1inf=1; Res1sup=-1; 
577       return;
578     }
579     if(U1inf>(Domain.FirstParameter()+Domain.FirstTolerance())) {
580       Res1inf=U1inf;
581       PosInf=IntRes2d_Middle;
582     }
583     else {
584       Res1inf=Domain.FirstParameter(); 
585       PosInf=IntRes2d_Head;
586     }
587   }
588   else {
589     Res1inf=U1inf; 
590     PosInf=IntRes2d_Middle;
591   }
592   
593   if(Domain.HasLastPoint()) {
594     if(U1inf >(Domain.LastParameter()+Domain.LastTolerance())) {
595       Res1inf=1; Res1sup=-1;
596       return;
597     }
598     if(U1sup<(Domain.LastParameter()-Domain.LastTolerance())) {
599       Res1sup=U1sup; 
600       PosSup=IntRes2d_Middle;
601     }
602     else {
603       Res1sup=Domain.LastParameter();
604       PosSup=IntRes2d_End;
605     }
606   }
607   else {
608     Res1sup=U1sup;
609     PosSup=IntRes2d_Middle;
610   }
611   //-- Si un des points est en bout ,
612   //-- on s assure que les parametres sont corrects
613   if(Res1inf>Res1sup) { 
614     if(PosSup==IntRes2d_Middle) {
615       Res1sup=Res1inf;
616     }
617     else {
618       Res1inf=Res1sup;
619     }
620   }
621   //--- Traitement des cas ou une intersection vraie est dans la tolerance
622   //--  d un des bouts
623   /*if(PosInf==IntRes2d_Head) {
624     if(Res1sup <= (Res1inf+Domain.FirstTolerance())) {
625       Res1sup=Res1inf;
626       PosSup=IntRes2d_Head;
627     }
628   }
629   if(PosSup==IntRes2d_End) {
630     if(Res1inf >= (Res1sup-Domain.LastTolerance())) {
631       Res1inf=Res1sup;
632       PosInf=IntRes2d_End;
633     }
634   }*/
635 }
636 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
637 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
638 void LineLineGeometricIntersection(const gp_Lin2d& L1
639                                    ,const gp_Lin2d& L2
640                                    ,const Standard_Real Tol
641                                    ,Standard_Real& U1
642                                    ,Standard_Real& U2
643                                    ,Standard_Real& SinDemiAngle
644                                    ,Standard_Integer& nbsol) {
645   
646   Standard_Real U1x=L1.Direction().X();
647   Standard_Real U1y=L1.Direction().Y();
648   Standard_Real U2x=L2.Direction().X();
649   Standard_Real U2y=L2.Direction().Y();
650   Standard_Real Uo21x = L2.Location().X() - L1.Location().X();
651   Standard_Real Uo21y = L2.Location().Y() - L1.Location().Y();
652   
653   Standard_Real D=U1y*U2x-U1x*U2y;
654
655 //modified by NIZHNY-MKK  Tue Feb 15 10:54:04 2000.BEGIN
656 //   if(Abs(D)<1e-15) { //-- Droites //
657   if(Abs(D) < TOLERANCE_ANGULAIRE) {
658 //modified by NIZHNY-MKK  Tue Feb 15 10:54:11 2000.END
659     D=U1y*Uo21x - U1x*Uo21y;
660     nbsol=(Abs(D)<=Tol)? 2 : 0;
661   }
662   else {
663     U1=(Uo21y * U2x - Uo21x * U2y)/D;
664     U2=(Uo21y * U1x - Uo21x * U1y)/D;
665     
666     //------------------- Calcul du Sin du demi angle  entre L1 et L2
667     //---- 
668     if(D<0.0) D=-D;
669     if(D>1.0) D=1.0;                      //-- Deja vu !
670     SinDemiAngle=Sin(0.5*ASin(D));
671     nbsol=1;
672   }
673 }
674 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
675 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
676 /*IntCurve_IntConicConic::IntCurve_IntConicConic(const gp_Lin2d& L1
677                                                ,const IntRes2d_Domain& D1
678                                                ,const gp_Lin2d& L2
679                                                ,const IntRes2d_Domain& D2
680                                                ,const Standard_Real TolConf
681                                                ,const Standard_Real Tol)  {
682   Perform(L1,D1,L2,D2,TolConf,Tol);
683 }
684
685
686 IntCurve_IntConicConic::IntCurve_IntConicConic(const gp_Lin2d& L1
687                                                ,const IntRes2d_Domain& D1
688                                                ,const gp_Circ2d& C2
689                                                ,const IntRes2d_Domain& D2
690                                                ,const Standard_Real TolConf
691                                                ,const Standard_Real Tol) {
692   
693   Perform(L1,D1,C2,D2,TolConf,Tol);
694 }
695
696
697 IntCurve_IntConicConic::IntCurve_IntConicConic(const gp_Circ2d& C1
698                                               ,const IntRes2d_Domain& D1
699                                               ,const gp_Circ2d& C2
700                                               ,const IntRes2d_Domain& D2
701                                               ,const Standard_Real TolConf
702                                               ,const Standard_Real Tol) {
703   SetReversedParameters(Standard_False);
704   Perform(C1,D1,C2,D2,TolConf,Tol);
705 }*/ //amv OCC12547
706 //----------------------------------------------------------------------
707 void IntCurve_IntConicConic::Perform(const gp_Circ2d& Circle1
708                                 ,const IntRes2d_Domain& DomainCirc1
709                                 ,const gp_Circ2d& _Circle2
710                                 ,const IntRes2d_Domain& _DomainCirc2
711                                 ,const Standard_Real TolConf,const Standard_Real Tol) {
712
713
714 //-- TRES TRES MAL FAIT    A REPRENDRE UN JOUR ....   (lbr Octobre 98) 
715   gp_Circ2d Circle2=_Circle2;
716   IntRes2d_Domain  DomainCirc2=_DomainCirc2;
717   Standard_Boolean IndirectCircles=Standard_False;
718   if(Circle1.IsDirect() != _Circle2.IsDirect()) { 
719     IndirectCircles=Standard_True;
720     Circle2=_Circle2.Reversed();
721     DomainCirc2.SetValues(_DomainCirc2.LastPoint(),
722                           PIpPI-_DomainCirc2.LastParameter(),
723                           _DomainCirc2.LastTolerance(),
724                           _DomainCirc2.FirstPoint(),
725                           PIpPI-_DomainCirc2.FirstParameter(),
726                           _DomainCirc2.FirstTolerance());
727     DomainCirc2.SetEquivalentParameters(0.0,PIpPI);
728   }
729   
730   this->ResetFields();
731   Standard_Integer nbsol=0;
732   PeriodicInterval C1_Int1,C1_Int2;
733
734   //------- Intersection sans tenir compte du domaine  ----> nbsol=0,1,2,3 
735   CircleCircleGeometricIntersection(Circle1,Circle2,TolConf,Tol,C1_Int1,C1_Int2,nbsol);
736   done=Standard_True;
737
738   if(nbsol==0) { //-- Pas de solutions 
739     return;
740   }
741
742   PeriodicInterval C1Domain(DomainCirc1); 
743   //-- On se ramene entre 0 et 2PI
744   Standard_Real deltat = C1Domain.Bsup-C1Domain.Binf;
745   if(deltat>=PIpPI) { deltat=PIpPI-1e-14; } 
746   
747   while(C1Domain.Binf >= PIpPI) C1Domain.Binf-=PIpPI;
748   while(C1Domain.Binf <  0.0)   C1Domain.Binf+=PIpPI;
749   C1Domain.Bsup=C1Domain.Binf+deltat;
750
751   PeriodicInterval C2Domain(DomainCirc2); 
752   deltat = C2Domain.Bsup-C2Domain.Binf;
753   if(deltat>=PIpPI) { deltat=PIpPI-1e-14; } 
754
755   while(C2Domain.Binf >= PIpPI) C2Domain.Binf-=PIpPI;
756   while(C2Domain.Binf <  0.0)   C2Domain.Binf+=PIpPI;
757   C2Domain.Bsup=C2Domain.Binf+deltat;
758
759   Standard_Boolean IdentCircles=Standard_False;
760
761   if(nbsol>2) {       
762     //-- Les 2 cercles sont confondus a Tol pres
763     C1_Int1.SetValues(0,PIpPI);
764     C1_Int2.SetNull(); 
765     //---------------------------------------------------------------
766     //-- Flag utilise pour specifier que les intervalles manipules
767     //--   peuvent etre de longueur superieure a pi. 
768     //-- Pour des cercles non identiques, on a necessairement cette
769     //--   condition sur les resultats de l intersection geometrique
770     //--   ce qui permet de normaliser rapidement les intervalles.
771     //--   ex: -1 4 -> longueur > PI  
772     //--        donc -1 4 devient  4 , 2*pi-1
773     //---------------------------------------------------------------
774     IdentCircles=Standard_True;
775   }
776
777   Standard_Integer NbSolTotal=0;
778   PeriodicInterval SolutionC1[4];
779   PeriodicInterval SolutionC2[4];
780   
781   //----------------------------------------------------------------------
782   //----------- Traitement du premier intervalle Geometrique  C1_Int1 ----
783   //----------------------------------------------------------------------
784   //-- NbSolTotal est incremente a chaque Intervalle solution.
785   //-- On stocke les intervalles dans les tableaux : SolutionC1(C2)
786   //-- Dimensionnes a 4 elements.
787   //-- des Exemples faciles donnent 3 Intersections
788   //-- des Problemes numeriques peuvent en donner 4 ??????
789   //--
790   PeriodicInterval C1DomainAndRes=C1Domain.FirstIntersection(C1_Int1);
791   
792   ProjectOnC2AndIntersectWithC2Domain(Circle1,Circle2
793                                       ,C1DomainAndRes
794                                       ,C2Domain
795                                       ,SolutionC1,SolutionC2
796                                       ,NbSolTotal
797                                       ,IdentCircles);
798   //----------------------------------------------------------------------
799   //-- Seconde Intersection :  Par exemple :     2*PI-1  2*PI+1
800   //--                         Intersecte avec     0.5   2*PI-0.5
801   //--     Donne les intervalles : 0.5,1    et  2*PI-1,2*PI-0.5
802   //--
803   C1DomainAndRes=C1Domain.SecondIntersection(C1_Int1);
804   
805   ProjectOnC2AndIntersectWithC2Domain(Circle1,Circle2
806                                       ,C1DomainAndRes
807                                       ,C2Domain
808                                       ,SolutionC1,SolutionC2
809                                       ,NbSolTotal
810                                       ,IdentCircles);
811
812   //----------------------------------------------------------------------
813   //----------- Traitement du second intervalle Geometrique   C1_Int2 ----
814   //----------------------------------------------------------------------
815   if(nbsol==2) {
816     C1DomainAndRes=C1Domain.FirstIntersection(C1_Int2);
817     
818     ProjectOnC2AndIntersectWithC2Domain(Circle1,Circle2
819                                         ,C1DomainAndRes
820                                         ,C2Domain
821                                         ,SolutionC1,SolutionC2
822                                         ,NbSolTotal
823                                         ,IdentCircles);
824     //--------------------------------------------------------------------
825     C1DomainAndRes=C1Domain.SecondIntersection(C1_Int2);
826     
827     ProjectOnC2AndIntersectWithC2Domain(Circle1,Circle2
828                                         ,C1DomainAndRes
829                                         ,C2Domain
830                                         ,SolutionC1,SolutionC2
831                                         ,NbSolTotal
832                                         ,IdentCircles);
833   }
834   //----------------------------------------------------------------------
835   //-- Calcul de toutes les transitions et Positions.
836   //--
837   //----------------------------------------------------------------------
838   //-- On determine si des intervalles sont reduit a des points 
839   //--      ( Rayon * Intervalle.Length()    <    Tol   )
840   //--
841   Standard_Real R1=Circle1.Radius();
842   Standard_Real R2=Circle2.Radius();
843   Standard_Real Tol2=Tol+Tol;     //---- Pour eviter de toujours retourner
844                                   //des segments
845   Standard_Integer i ;
846   if(Tol < (1e-10)) Tol2 = 1e-10; 
847   for( i=0; i<NbSolTotal ; i++) { 
848     if(((R1 * SolutionC1[i].Length()))<=Tol2 
849        && ((R2 * SolutionC2[i].Length()))<=Tol2) {
850       
851       Standard_Real t=(SolutionC1[i].Binf+SolutionC1[i].Bsup)*0.5;
852       SolutionC1[i].Binf=SolutionC1[i].Bsup=t;
853       
854       t=(SolutionC2[i].Binf+SolutionC2[i].Bsup)*0.5;
855       SolutionC2[i].Binf=SolutionC2[i].Bsup=t;
856     }
857   }
858
859   //----------------------------------------------------------------------
860   //-- Traitement des intervalles (ou des points obtenus)
861   //-- 
862   gp_Ax22d Axis2C1=Circle1.Axis();
863   gp_Ax22d Axis2C2=Circle2.Axis();
864   gp_Pnt2d P1a,P1b,P2a,P2b;
865   gp_Vec2d Tan1,Tan2,Norm1,Norm2;
866   IntRes2d_Transition T1a,T1b,T2a,T2b;
867   IntRes2d_Position Pos1a,Pos1b,Pos2a,Pos2b;
868
869   Standard_Boolean Opposite=((Circle1.Location().SquareDistance(Circle2.Location()))
870                    >(R1*R1+R2*R2))? Standard_True : Standard_False;
871
872   //if(Circle1.IsDirect()) { cout<<" C1 Direct"<<endl; } else { cout<<" C1 INDirect"<<endl; }
873   //if(Circle2.IsDirect()) { cout<<" C2 Direct"<<endl; } else { cout<<" C2 INDirect"<<endl; }
874
875   for(i=0; i<NbSolTotal; i++) {
876     Standard_Real C2inf=(Opposite)? SolutionC2[i].Bsup : SolutionC2[i].Binf;
877     Standard_Real C2sup=(Opposite)? SolutionC2[i].Binf : SolutionC2[i].Bsup;
878
879     Standard_Real C1inf=NormalizeOnCircleDomain(SolutionC1[i].Binf,DomainCirc1);
880     C2inf=NormalizeOnCircleDomain(C2inf,DomainCirc2);
881
882     if(IndirectCircles) { 
883       
884       ElCLib::CircleD2(C1inf,Axis2C1,R1,P1a,Tan1,Norm1); 
885       ElCLib::CircleD2(C2inf,Axis2C2,R2,P2a,Tan2,Norm2);
886       Tan2.Reverse();
887       
888       IntImpParGen::DeterminePosition(Pos1a,DomainCirc1,P1a,C1inf);
889       IntImpParGen::DeterminePosition(Pos2a,_DomainCirc2,P2a,PIpPI-C2inf);
890       Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
891       
892       
893       IntRes2d_IntersectionPoint NewPoint1(P1a,C1inf,PIpPI-C2inf,T1a,T2a,Standard_False);
894       
895       if((SolutionC1[i].Length()>0.0 ) || (SolutionC2[i].Length() >0.0)) {
896         //-- On traite un intervalle non reduit a un point
897         Standard_Real C1sup=NormalizeOnCircleDomain(SolutionC1[i].Bsup,DomainCirc1);
898         if(C1sup<C1inf) C1sup+=PIpPI;
899         C2sup=NormalizeOnCircleDomain(C2sup,DomainCirc2);
900         
901         ElCLib::CircleD2(C1sup,Axis2C1,R1,P1b,Tan1,Norm1); 
902         ElCLib::CircleD2(C2sup,Axis2C2,R2,P2b,Tan2,Norm2);
903         Tan2.Reverse();
904
905         IntImpParGen::DeterminePosition(Pos1b,DomainCirc1,P1b,C1sup);
906         IntImpParGen::DeterminePosition(Pos2b,_DomainCirc2,P2b,PIpPI-C2sup);
907         Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);
908         
909         //--------------------------------------------------
910         
911         if(Opposite) {
912           if(nbsol!=3) { 
913             if(C2inf<C2sup) C2inf+=PIpPI;
914           }
915         }
916         else {
917           if(nbsol!=3) { 
918             if(C2sup<C2inf) C2sup+=PIpPI;
919           }
920         }
921         
922         IntRes2d_IntersectionPoint NewPoint2(P1b,C1sup,PIpPI-C2sup,T1b,T2b,Standard_False);
923         IntRes2d_IntersectionSegment NewSeg(NewPoint1,NewPoint2,
924                                             (Opposite==Standard_True)? Standard_False : Standard_True,
925                                             Standard_False);
926         Append(NewSeg);
927         
928       }
929       else {
930         Append(NewPoint1);
931       }
932       
933     }
934     else { 
935       
936       ElCLib::CircleD2(C1inf,Axis2C1,R1,P1a,Tan1,Norm1); 
937       ElCLib::CircleD2(C2inf,Axis2C2,R2,P2a,Tan2,Norm2);
938       
939       IntImpParGen::DeterminePosition(Pos1a,DomainCirc1,P1a,C1inf);
940       IntImpParGen::DeterminePosition(Pos2a,DomainCirc2,P2a,C2inf);
941       Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
942       
943       
944       IntRes2d_IntersectionPoint NewPoint1(P1a,C1inf,C2inf,T1a,T2a,Standard_False);
945       
946       if((SolutionC1[i].Length()>0.0 ) || (SolutionC2[i].Length() >0.0)) {
947         //-- On traite un intervalle non reduit a un point
948         Standard_Real C1sup=NormalizeOnCircleDomain(SolutionC1[i].Bsup,DomainCirc1);
949         if(C1sup<C1inf) C1sup+=PIpPI;
950         C2sup=NormalizeOnCircleDomain(C2sup,DomainCirc2);
951         
952         ElCLib::CircleD2(C1sup,Axis2C1,R1,P1b,Tan1,Norm1); 
953         ElCLib::CircleD2(C2sup,Axis2C2,R2,P2b,Tan2,Norm2);
954         
955         IntImpParGen::DeterminePosition(Pos1b,DomainCirc1,P1b,C1sup);
956         IntImpParGen::DeterminePosition(Pos2b,DomainCirc2,P2b,C2sup);
957         Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);
958         
959         //--------------------------------------------------
960         
961         if(Opposite) {
962           if(nbsol!=3) { 
963             if(C2inf<C2sup) C2inf+=PIpPI;
964           }
965         }
966         else {
967           if(nbsol!=3) { 
968             if(C2sup<C2inf) C2sup+=PIpPI;
969           }
970         }
971         
972         IntRes2d_IntersectionPoint NewPoint2(P1b,C1sup,C2sup,T1b,T2b,Standard_False);
973         IntRes2d_IntersectionSegment NewSeg(NewPoint1,NewPoint2,Opposite,Standard_False);
974         Append(NewSeg);
975         
976       }
977       else {
978         Append(NewPoint1);
979       }
980     }
981   }
982 }
983 //----------------------------------------------------------------------
984 IntRes2d_Position FindPositionLL(Standard_Real &Param
985                                  ,const IntRes2d_Domain& Domain) 
986 {
987   Standard_Real aDPar = Precision::Infinite();
988   IntRes2d_Position aPos = IntRes2d_Middle; 
989   Standard_Real aResPar = Param;
990   if(Domain.HasFirstPoint()) {
991     aDPar = Abs(Param-Domain.FirstParameter());
992     if( aDPar <= Domain.FirstTolerance()) {
993       aResPar=Domain.FirstParameter();
994       aPos = IntRes2d_Head;
995      
996     }
997   }
998   if(Domain.HasLastPoint()) {
999     Standard_Real aD2 = Abs(Param-Domain.LastParameter());
1000     if( aD2 <= Domain.LastTolerance() && (aPos == IntRes2d_Middle || aD2 < aDPar )) 
1001     {
1002       aResPar=Domain.LastParameter();
1003       aPos = IntRes2d_End;
1004     }
1005   }
1006   Param = aResPar;
1007   return aPos;
1008 }
1009 //--------------------------------------------------------------------
1010 //gka 0022833
1011 // Method to compute of point of intersection for case
1012 //when specified domain less than specified tolerance for intersection
1013 static inline void getDomainParametrs(const IntRes2d_Domain& theDomain,
1014                                       Standard_Real& theFirst,
1015                                       Standard_Real& theLast,
1016                                       Standard_Real& theTol1,
1017                                       Standard_Real& theTol2)
1018 {
1019   theFirst = (theDomain.HasFirstPoint() ? theDomain.FirstParameter() : -Precision::Infinite());
1020   theLast = (theDomain.HasLastPoint() ? theDomain.LastParameter() : Precision::Infinite()); 
1021   theTol1 = (theDomain.HasFirstPoint() ? theDomain.FirstTolerance() : 0.);
1022   theTol2 = (theDomain.HasLastPoint() ? theDomain.LastTolerance() : 0.);
1023 }
1024
1025
1026 static Standard_Boolean computeIntPoint(const IntRes2d_Domain& theCurDomain,
1027                                                          const IntRes2d_Domain& theDomainOther,
1028                                                          const gp_Lin2d& theCurLin,
1029                                                          const gp_Lin2d& theOtherLin,   
1030                                                          Standard_Real theCosT1T2,
1031                                                          Standard_Real theParCur, Standard_Real theParOther,
1032                                                          Standard_Real& theResInf, Standard_Real& theResSup,
1033                                                          Standard_Integer theNum,
1034                                                          IntRes2d_TypeTrans theCurTrans,    
1035                                                          IntRes2d_IntersectionPoint& theNewPoint)
1036 {
1037   if(fabs(theResSup-theParCur) > fabs(theResInf-theParCur))
1038     theResSup = theResInf;
1039
1040   Standard_Real aRes2 = theParOther + (theResSup - theParCur) * theCosT1T2;
1041
1042   Standard_Real aFirst2, aLast2, aTol1, aTol2;
1043   getDomainParametrs(theDomainOther,aFirst2, aLast2, aTol1, aTol2);
1044   if( aRes2  < aFirst2 - aTol1 || aRes2  > aLast2 + aTol2 ) 
1045           return Standard_False;
1046         
1047   //------ compute parameters of intersection point --
1048   IntRes2d_Transition aT1,aT2;
1049   IntRes2d_Position aPos1a = FindPositionLL(theResSup,theCurDomain);
1050   IntRes2d_Position aPos2a = FindPositionLL(aRes2,theDomainOther);
1051   IntRes2d_TypeTrans anOtherTrans = ( theCurTrans == IntRes2d_Out ? 
1052       IntRes2d_In : ( theCurTrans == IntRes2d_In ? IntRes2d_Out : IntRes2d_Undecided ) );
1053
1054   if( theCurTrans != IntRes2d_Undecided )
1055   {
1056     aT1.SetValue(Standard_False, aPos1a, theCurTrans);
1057     aT2.SetValue(Standard_False,  aPos2a, anOtherTrans);
1058   }
1059   else  
1060   { 
1061     Standard_Boolean anOpposite = theCosT1T2 < 0.;
1062     aT1.SetValue(Standard_False,aPos1a,IntRes2d_Unknown,anOpposite);
1063     aT2.SetValue(Standard_False,aPos2a,IntRes2d_Unknown,anOpposite);
1064   }
1065   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1066   //--------------------------------------------------
1067   //gka bug 0022833 
1068   Standard_Real aResU1 = theParCur;
1069   Standard_Real aResU2 = theParOther;
1070
1071   Standard_Real aFirst1, aLast1;
1072   getDomainParametrs(theCurDomain,aFirst1, aLast1, aTol1, aTol2);
1073   
1074   Standard_Boolean isInside1 = (theParCur >= aFirst1 && theParCur <= aLast1);
1075   Standard_Boolean isInside2 = (theParOther >= aFirst2 && theParOther <= aLast2);
1076
1077   if(!isInside1 || !isInside2)
1078   {
1079     if(isInside1) 
1080     {
1081       gp_Pnt2d Pt1=ElCLib::Value(aRes2,theOtherLin);
1082       aResU2 = aRes2;
1083       Standard_Real aPar1 = ElCLib::Parameter(theCurLin,Pt1);
1084       aResU1 =((aPar1 >= aFirst1 && aPar1<= aLast1) ?  aPar1 : theResSup);
1085       
1086     }
1087     else if(isInside2)
1088     {
1089       gp_Pnt2d aPt1=ElCLib::Value(theResSup,theCurLin);
1090       aResU1 = theResSup;
1091       Standard_Real aPar2 = ElCLib::Parameter(theOtherLin,aPt1);
1092       aResU2= ((aPar2 >= aFirst2 && aPar2<= aLast2) ? aPar2 : aRes2);
1093     }
1094     else 
1095     {
1096       aResU1 = theResSup;
1097       aResU2= aRes2;
1098     }
1099   }
1100   gp_Pnt2d aPres((ElCLib::Value(aResU1,theCurLin).XY() + ElCLib::Value(aResU2,theOtherLin).XY()) * 0.5 );
1101   if(theNum == 1 )
1102     theNewPoint.SetValues(aPres, aResU1, aResU2 ,aT1, aT2, Standard_False);
1103   else
1104     theNewPoint.SetValues(aPres, aResU2, aResU1 ,aT2, aT1, Standard_False);
1105   return Standard_True;
1106 }
1107
1108 //----------------------------------------------------------------------
1109 void IntCurve_IntConicConic::Perform(const gp_Lin2d& L1
1110                                       ,const IntRes2d_Domain& Domain1
1111                                      ,const gp_Lin2d& L2
1112                                      ,const IntRes2d_Domain& Domain2
1113                                      ,const Standard_Real,const Standard_Real TolR) {  
1114   this->ResetFields();
1115
1116   //-- Coordonnees du point d intersection sur chacune des 2 droites
1117   Standard_Real U1,U2; 
1118   //-- Nombre de points solution : 1 : Intersection
1119   //--                             0 : Non Confondues
1120   //--                             2 : Confondues a la tolerance pres
1121   Standard_Integer nbsol;
1122   IntRes2d_IntersectionPoint PtSeg1,PtSeg2;
1123   Standard_Real SINL1L2;
1124   Standard_Real Tol = TolR;
1125   if(TolR< 1e-10) Tol = 1e-10;
1126   
1127
1128   LineLineGeometricIntersection(L1,L2,Tol,U1,U2,SINL1L2,nbsol);
1129
1130   gp_Vec2d Tan1=L1.Direction();
1131   gp_Vec2d Tan2=L2.Direction();
1132  
1133   Standard_Real aCosT1T2 = Tan1.Dot(Tan2);
1134   Standard_Boolean Opposite=(aCosT1T2 < 0.0)? Standard_True : Standard_False;
1135
1136   done=Standard_True;
1137
1138   if(nbsol==1) {
1139     //---------------------------------------------------
1140     //-- d: distance du point I a partir de laquelle  les 
1141     //--  points de parametre U1+d et U2+-d sont ecartes
1142     //--  d une distance superieure a Tol.
1143     //---------------------------------------------------
1144     IntRes2d_Position Pos1a,Pos2a,Pos1b,Pos2b;
1145     Standard_Real d=Tol/(SINL1L2);
1146     Standard_Real U1inf=U1-d;
1147     Standard_Real U1sup=U1+d;
1148     Standard_Real U1mU2=U1-U2;
1149     Standard_Real U1pU2=U1+U2;
1150     Standard_Real Res1inf,Res1sup;
1151     Standard_Real ProdVectTan;
1152     
1153
1154     //---------------------------------------------------
1155     //-- On agrandit la zone U1inf U1sup pour tenir compte 
1156     //-- des tolerances des points en bout
1157     //--
1158     if(Domain1.HasFirstPoint()) { 
1159       if(L2.Distance(Domain1.FirstPoint()) < Domain1.FirstTolerance()) { 
1160         if(U1inf > Domain1.FirstParameter()) { 
1161           U1inf = Domain1.FirstParameter();
1162         }
1163         if(U1sup < Domain1.FirstParameter()) { 
1164           U1sup = Domain1.FirstParameter();
1165         }
1166       }
1167     }
1168     if(Domain1.HasLastPoint()) { 
1169       if(L2.Distance(Domain1.LastPoint()) < Domain1.LastTolerance()) { 
1170         if(U1inf > Domain1.LastParameter()) { 
1171           U1inf = Domain1.LastParameter();
1172         }
1173         if(U1sup < Domain1.LastParameter()) { 
1174           U1sup = Domain1.LastParameter();
1175         }
1176       }
1177     }      
1178     if(Domain2.HasFirstPoint()) { 
1179       if(L1.Distance(Domain2.FirstPoint()) < Domain2.FirstTolerance()) { 
1180         Standard_Real p = ElCLib::Parameter(L1,Domain2.FirstPoint());
1181         if(U1inf > p) { 
1182           U1inf = p;
1183         }
1184         if(U1sup < p) { 
1185           U1sup = p;
1186         }
1187       }
1188     }
1189     if(Domain2.HasLastPoint()) { 
1190       if(L1.Distance(Domain2.LastPoint()) < Domain2.LastTolerance()) { 
1191         Standard_Real p = ElCLib::Parameter(L1,Domain2.LastPoint());
1192         if(U1inf > p) { 
1193           U1inf = p;
1194         }
1195         if(U1sup < p) { 
1196           U1sup = p;
1197         }
1198       }
1199     }
1200     //-----------------------------------------------------------------
1201
1202     DomainIntersection(Domain1,U1inf,U1sup,Res1inf,Res1sup,Pos1a,Pos1b);
1203     
1204     if((Res1sup-Res1inf)<0.0) {
1205       //-- Si l intersection est vide       
1206       //-- 
1207     }
1208     else { //-- (Domain1  INTER   Zone Intersection)    non vide
1209
1210       ProdVectTan=Tan1.Crossed(Tan2);
1211       
1212       //#####################################################################
1213       //##  Longueur Minimale d un segment    Sur Courbe 1 
1214       //##################################################################### 
1215
1216       Standard_Real LongMiniSeg=Tol;
1217
1218
1219       if(((Res1sup-Res1inf)<=LongMiniSeg)
1220         || ((Pos1a==Pos1b)&&(Pos1a!=IntRes2d_Middle)))     
1221       {
1222         //-------------------------------  Un seul Point -------------------
1223         //--- lorsque la longueur du segment est inferieure a ??
1224         //--- ou si deux points designent le meme bout
1225         //gka #0022833
1226         IntRes2d_TypeTrans aCurTrans = ( ProdVectTan >= TOLERANCE_ANGULAIRE ? 
1227              IntRes2d_Out : ( ProdVectTan <= -TOLERANCE_ANGULAIRE ? IntRes2d_In : IntRes2d_Undecided ) );
1228
1229         IntRes2d_IntersectionPoint NewPoint1;
1230         if( computeIntPoint(Domain1, Domain2, L1, L2, aCosT1T2, U1, U2, Res1inf, Res1sup, 1, aCurTrans, NewPoint1 ) )
1231           Append(NewPoint1);
1232
1233         //------------------------------------------------------
1234       
1235     
1236     }  //---------------   Fin du cas  :   1 seul point --------------------
1237       
1238       else {
1239         //-- Intersection AND Domain1  --------> Segment ---------------------
1240         Standard_Real U2inf,U2sup;
1241         Standard_Real Res2inf,Res2sup;
1242         
1243         if(Opposite) { U2inf = U1pU2 -Res1sup;  U2sup= U1pU2-Res1inf;  }
1244         else         { U2inf = Res1inf-U1mU2;   U2sup= Res1sup-U1mU2;  }
1245         
1246         DomainIntersection(Domain2,U2inf,U2sup,Res2inf,Res2sup,Pos2a,Pos2b);
1247
1248         //####################################################################
1249         //##  Test sur la longueur minimale d un segment sur Ligne2
1250         //####################################################################
1251         Standard_Real Res2sup_m_Res2inf = Res2sup-Res2inf;
1252         if(Res2sup_m_Res2inf < 0.0) {
1253           //-- Pas de solutions On retourne Vide
1254         }
1255         else if(((Res2sup-Res2inf) > LongMiniSeg)  
1256                 || ((Pos2a==Pos2b)&&(Pos2a!=IntRes2d_Middle)))     {
1257           //----------- Calcul des attributs du segment --------------
1258           //-- Attention, les bornes Res1inf(sup) bougent donc il faut
1259           //--  eventuellement recalculer les attributs
1260           
1261           if(Opposite) { Res1inf=U1pU2-Res2sup; Res1sup=U1pU2-Res2inf; 
1262                          Standard_Real Tampon=Res2inf; Res2inf=Res2sup; Res2sup=Tampon;
1263                          IntRes2d_Position Pos=Pos2a; Pos2a=Pos2b; Pos2b=Pos;
1264                        }
1265           else         { Res1inf=U1mU2+Res2inf; Res1sup=U1mU2+Res2sup; }
1266           
1267           Pos1a=FindPositionLL(Res1inf,Domain1);
1268           Pos1b=FindPositionLL(Res1sup,Domain1);          
1269           
1270           IntRes2d_Transition T1a,T2a,T1b,T2b;
1271           
1272           if(ProdVectTan>=TOLERANCE_ANGULAIRE) {  // &&&&&&&&&&&&&&&
1273             T1a.SetValue(Standard_False,Pos1a,IntRes2d_Out);      
1274             T2a.SetValue(Standard_False,Pos2a,IntRes2d_In);
1275           }
1276           else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1277             T1a.SetValue(Standard_False,Pos1a,IntRes2d_In);      
1278             T2a.SetValue(Standard_False,Pos2a,IntRes2d_Out);
1279           }
1280           else {
1281             T1a.SetValue(Standard_False,Pos1a,IntRes2d_Unknown,Opposite);
1282             T2a.SetValue(Standard_False,Pos2a,IntRes2d_Unknown,Opposite);
1283           }
1284           
1285
1286           //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1287           //~~~~~~~  C O N V E N T I O N    -    S E G M E N T     ~~~~~~~
1288           //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1289           //~~ On Renvoie un segment dans les cas suivants :            ~~
1290           //~~   (1) Extremite L1 L2   ------>    Extremite L1 L2       ~~
1291           //~~   (2) Extremite L1 L2   ------>    Intersection          ~~
1292           //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1293           
1294           Standard_Boolean ResultIsAPoint=Standard_False;
1295
1296           if(((Res1sup-Res1inf)<=LongMiniSeg) 
1297              || (Abs(Res2sup-Res2inf)<=LongMiniSeg)) {
1298             //-- On force la creation d un point
1299             ResultIsAPoint=Standard_True;
1300           }
1301           else {
1302             //------------------------------------------------------------
1303             //-- On traite les cas ou l intersection est situee du 
1304             //-- Mauvais cote du domaine 
1305             //-- Attention : Res2inf <-> Pos2a        Res2sup <-> Pos2b
1306             //--  et         Res1inf <-> Pos1a        Res1sup <-> Pos1b
1307             //--             avec Res1inf <= Res1sup
1308             //------------------------------------------------------------
1309             //-- Le point sera : Res1inf,Res2inf,T1a(Pos1a),T2a(Pos2a)
1310             //------------------------------------------------------------
1311
1312             if(Pos1a==IntRes2d_Head) { 
1313               if(Pos1b!=IntRes2d_End && U1<Res1inf)    { ResultIsAPoint=Standard_True; U1=Res1inf; U2=Res2inf; }
1314             }
1315             if(Pos1b==IntRes2d_End)  { 
1316               if(Pos1a!=IntRes2d_Head && U1>Res1sup)   { ResultIsAPoint=Standard_True; U1=Res1sup; U2=Res2sup; }
1317             }
1318         
1319             if(Pos2a==IntRes2d_Head) { 
1320               if(Pos2b!=IntRes2d_End && U2<Res2inf)    { ResultIsAPoint=Standard_True; U2=Res2inf; U1=Res1inf; }
1321             }
1322             else {
1323               if(Pos2a==IntRes2d_End)  { 
1324                 if(Pos2b!=IntRes2d_Head && U2>Res2inf) { ResultIsAPoint=Standard_True; U2=Res2inf; U1=Res1inf; }
1325               }
1326             }
1327             if(Pos2b==IntRes2d_Head) { 
1328               if(Pos2a!=IntRes2d_End && U2<Res2sup)    { ResultIsAPoint=Standard_True; U2=Res2sup; U1=Res1sup; }
1329             }
1330             else {
1331               if(Pos2b==IntRes2d_End) {
1332                 if(Pos2a!=IntRes2d_Head && U2>Res2sup) { ResultIsAPoint=Standard_True; U2=Res2sup; U1=Res1sup; }
1333               }
1334             }
1335           }
1336             
1337           
1338
1339           if((!ResultIsAPoint) && (Pos1a!=IntRes2d_Middle || Pos2a!=IntRes2d_Middle)) {
1340             IntRes2d_Transition T1b,T2b;
1341             if(ProdVectTan>=TOLERANCE_ANGULAIRE) { //&&&&&&&&&&&&&&
1342               T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1343               T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1344             }
1345             else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) { //&&&&&&&&&&&&&&
1346               T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1347               T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1348             }
1349             else {
1350               T1b.SetValue(Standard_False,Pos1b,IntRes2d_Unknown,Opposite);
1351               T2b.SetValue(Standard_False,Pos2b,IntRes2d_Unknown,Opposite);
1352             }
1353             gp_Pnt2d Ptdebut;
1354             if(Pos1a==IntRes2d_Middle) { 
1355               Standard_Real t3;
1356               if(Opposite) {
1357                 t3 = (Pos2a == IntRes2d_Head)? Res2sup : Res2inf;
1358               }
1359               else {
1360                 t3 = (Pos2a == IntRes2d_Head)? Res2inf : Res2sup;
1361               }
1362               Ptdebut=ElCLib::Value(t3,L2);
1363               Res1inf=ElCLib::Parameter(L1,Ptdebut);
1364             }
1365             else {
1366               Standard_Real t4 = (Pos1a == IntRes2d_Head)? Res1inf : Res1sup;
1367               Ptdebut=ElCLib::Value(t4,L1);
1368               Res2inf=ElCLib::Parameter(L2,Ptdebut);
1369             }
1370             PtSeg1.SetValues(Ptdebut,Res1inf,Res2inf,T1a,T2a,Standard_False);
1371             if(Pos1b!=IntRes2d_Middle || Pos2b!=IntRes2d_Middle) {
1372               //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1373               //~~ Ajustement des parametres et du point renvoye
1374               gp_Pnt2d Ptfin;
1375               if(Pos1b==IntRes2d_Middle) { 
1376                 Ptfin=ElCLib::Value(Res2sup,L2);
1377                 Res1sup=ElCLib::Parameter(L1,Ptfin);
1378               }
1379               else {
1380                 Ptfin=ElCLib::Value(Res1sup,L1);
1381                 Res2sup=ElCLib::Parameter(L2,Ptfin);
1382               }
1383               PtSeg2.SetValues(Ptfin,Res1sup,Res2sup,T1b,T2b,Standard_False);
1384               IntRes2d_IntersectionSegment Segment(PtSeg1,PtSeg2
1385                                                    ,Opposite,Standard_False);
1386               Append(Segment);  
1387             } 
1388             else { //-- Extremite(L1 ou L2)  ------>   Point Middle(L1 et L2)
1389
1390               Pos1b=FindPositionLL(U1,Domain1);
1391               Pos2b=FindPositionLL(U2,Domain2);         
1392               if(ProdVectTan>=TOLERANCE_ANGULAIRE) {
1393                 T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1394                 T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1395               }
1396               else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1397                 T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1398                 T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1399               }
1400               else {
1401                 T1b.SetValue(Standard_False,Pos1b,IntRes2d_Unknown,Opposite);
1402                 T2b.SetValue(Standard_False,Pos2b,IntRes2d_Unknown,Opposite);
1403               }
1404               
1405               PtSeg2.SetValues(ElCLib::Value(U2,L2),U1,U2,T1b,T2b,Standard_False);
1406
1407               if((Abs(Res1inf-U1) >LongMiniSeg) && (Abs(Res2inf-U2) >LongMiniSeg)) {
1408                 IntRes2d_IntersectionSegment Segment(PtSeg1,PtSeg2,Opposite,Standard_False);
1409                 Append(Segment);  
1410               }
1411               else {
1412                 Append(SegmentToPoint(PtSeg1,T1a,T2a,PtSeg2,T1b,T2b));
1413               }
1414             }
1415
1416           } //-- (Pos1a!=IntRes2d_Middle || Pos2a!=IntRes2d_Middle) --
1417           else {  //-- Pos1a == Pos2a == Middle
1418             if(Pos1b==IntRes2d_Middle) Pos1b=Pos1a;
1419             if(Pos2b==IntRes2d_Middle) Pos2b=Pos2a;
1420             if(ResultIsAPoint) {
1421               //-- Middle sur le segment A 
1422               //-- 
1423               if(Pos1b!=IntRes2d_Middle || Pos2b!=IntRes2d_Middle) {
1424                 gp_Pnt2d Ptfin;
1425                 if(Pos1b==IntRes2d_Middle) {
1426                   Standard_Real t2;
1427                   if(Opposite) { 
1428                     t2 = (Pos2b == IntRes2d_Head)? Res2sup : Res2inf;
1429                   }
1430                   else {
1431                     t2 = (Pos2b == IntRes2d_Head)? Res2inf : Res2sup;
1432                   }
1433                   Ptfin=ElCLib::Value(t2,L2);
1434                   Res1sup=ElCLib::Parameter(L1,Ptfin);
1435 //modified by NIZHNY-MKK  Tue Feb 15 10:54:51 2000.BEGIN
1436                   Pos1b=FindPositionLL(Res1sup,Domain1);
1437 //modified by NIZHNY-MKK  Tue Feb 15 10:54:55 2000.END
1438
1439                 }
1440                 else {
1441                   Standard_Real t1 = (Pos1b == IntRes2d_Head)? Res1inf : Res1sup;
1442                   Ptfin=ElCLib::Value(t1,L1);
1443                   Res2sup=ElCLib::Parameter(L2,Ptfin);
1444 //modified by NIZHNY-MKK  Tue Feb 15 10:55:08 2000.BEGIN
1445                   Pos2b=FindPositionLL(Res2sup,Domain2);
1446 //modified by NIZHNY-MKK  Tue Feb 15 10:55:11 2000.END
1447                 }
1448                 if(ProdVectTan>=TOLERANCE_ANGULAIRE) {
1449                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1450                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1451                 }
1452                 else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1453                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1454                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1455                 }
1456                 else {
1457                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_Unknown,Opposite);
1458                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_Unknown,Opposite);
1459                 }
1460                 PtSeg2.SetValues(Ptfin,Res1sup,Res2sup,T1b,T2b,Standard_False);
1461                 Append(PtSeg2);
1462               }
1463               else {
1464                 Pos1b=FindPositionLL(U1,Domain1);
1465                 Pos2b=FindPositionLL(U2,Domain2);               
1466                 
1467                 if(ProdVectTan>=TOLERANCE_ANGULAIRE) {
1468                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1469                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1470                 }
1471                 else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1472                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1473                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1474                 }
1475                 else {
1476                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_Unknown,Opposite);
1477                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_Unknown,Opposite);
1478                 }
1479                 PtSeg1.SetValues(ElCLib::Value(U2,L2),U1,U2,T1b,T2b,Standard_False);
1480                 Append(PtSeg1); 
1481               }
1482             }
1483             else {
1484               PtSeg1.SetValues(ElCLib::Value(U2,L2),U1,U2,T1a,T2a,Standard_False);
1485               
1486               if((Pos1b!=IntRes2d_Middle || Pos2b!=IntRes2d_Middle)) {
1487                 IntRes2d_Transition T1b,T2b;
1488                 if(ProdVectTan>=TOLERANCE_ANGULAIRE) {
1489                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1490                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1491                 }
1492                 else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1493                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1494                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1495                 }
1496                 else {
1497                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_Unknown,Opposite);
1498                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_Unknown,Opposite);
1499                 }
1500                 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1501                 //~~ Ajustement des parametres et du point renvoye
1502                 gp_Pnt2d Ptfin;             
1503                 if(Pos1b==IntRes2d_Middle) {
1504                   Ptfin=ElCLib::Value(Res2sup,L2);
1505                   Res1sup=ElCLib::Parameter(L1,Ptfin);
1506                 }
1507                 else {
1508                   Ptfin=ElCLib::Value(Res1sup,L1);
1509                   Res2sup=ElCLib::Parameter(L2,Ptfin);
1510                 }
1511
1512                 PtSeg2.SetValues(Ptfin,Res1sup,Res2sup,T1b,T2b,Standard_False);
1513                 
1514                 if((Abs(U1-Res1sup)>LongMiniSeg)
1515                    ||(Abs(U2-Res2sup)>LongMiniSeg)) { 
1516                   //-- Modif du 1er Octobre 92 (Pour Composites)
1517                   
1518                   IntRes2d_IntersectionSegment Segment(PtSeg1,PtSeg2
1519                                                        ,Opposite,Standard_False);
1520                   Append(Segment);  
1521                 }
1522                 else {
1523                   Append(SegmentToPoint(PtSeg1,T1a,T2a,PtSeg2,T1b,T2b));
1524                 }
1525               }
1526               else {
1527                 Append(PtSeg1); 
1528               }
1529             }
1530           }
1531         } //----- Fin Creation Segment ----(Res2sup-Res2inf>Tol)-------------
1532         else {
1533           //------ (Intersection And Domain1)  AND  Domain2  --> Point ------
1534           //-- Attention Res1sup peut etre  different de  U2
1535           //--   Mais on a Res1sup-Res1inf < Tol 
1536
1537     //gka #0022833
1538     IntRes2d_TypeTrans aCurTrans = ( ProdVectTan >= TOLERANCE_ANGULAIRE ? 
1539            IntRes2d_In : ( ProdVectTan <= -TOLERANCE_ANGULAIRE ? IntRes2d_Out : IntRes2d_Undecided ) );
1540
1541     IntRes2d_IntersectionPoint NewPoint1;
1542     if( computeIntPoint(Domain2, Domain1, L2, L1, aCosT1T2, U2, U1, Res2inf, Res2sup, 2, aCurTrans, NewPoint1 ) )
1543       Append(NewPoint1);
1544         
1545         }
1546       }
1547     }
1548   }
1549   else {
1550     if(nbsol==2) {  //== Droites confondues a la tolerance pres 
1551       //--On traite ici le cas de segments resultats non neccess. bornes
1552       //-- 
1553       //--On prend la droite D1 comme reference ( pour le sens positif )
1554       //--
1555       Standard_Integer ResHasFirstPoint=0;    
1556       Standard_Integer ResHasLastPoint=0;
1557       Standard_Real ParamStart,ParamStart2,ParamEnd,ParamEnd2;
1558       Standard_Real Org2SurL1=ElCLib::Parameter(L1,L2.Location());
1559       //== 3 : L1 et L2 bornent
1560       //== 2 :       L2 borne
1561       //== 1 : L1 borne
1562       if(Domain1.HasFirstPoint()) ResHasFirstPoint=1;
1563       if(Domain1.HasLastPoint())   ResHasLastPoint=1;
1564       if(Opposite) {
1565         if(Domain2.HasLastPoint())     ResHasFirstPoint+=2;
1566         if(Domain2.HasFirstPoint())   ResHasLastPoint+=2;
1567       }
1568       else {
1569         if(Domain2.HasLastPoint())     ResHasLastPoint+=2;
1570         if(Domain2.HasFirstPoint())   ResHasFirstPoint+=2;
1571       }
1572       if(ResHasFirstPoint==0 && ResHasLastPoint==0) {
1573         //~~~~ Creation d un segment infini avec Opposite
1574         Append(IntRes2d_IntersectionSegment(Opposite));
1575       }
1576       else {  //-- On obtient au pire une demi-droite
1577         switch(ResHasFirstPoint) {
1578         case 1: 
1579           ParamStart=Domain1.FirstParameter(); 
1580           ParamStart2=(Opposite)? (Org2SurL1-ParamStart) 
1581                                  :(ParamStart-Org2SurL1); 
1582           break;
1583         case 2:
1584           if(Opposite) {
1585             ParamStart2=Domain2.LastParameter();
1586             ParamStart=Org2SurL1 - ParamStart2; 
1587           }
1588           else {
1589             ParamStart2=Domain2.FirstParameter();
1590             ParamStart=Org2SurL1 + ParamStart2;
1591           }
1592           break;
1593         case 3:
1594           if(Opposite) {
1595             ParamStart2=Domain2.LastParameter();
1596             ParamStart=Org2SurL1 - ParamStart2; 
1597             if(ParamStart < Domain1.FirstParameter()) {
1598               ParamStart=Domain1.FirstParameter();
1599               ParamStart2=Org2SurL1 -  ParamStart;
1600             }
1601           }
1602           else {
1603             ParamStart2=Domain2.FirstParameter();
1604             ParamStart=Org2SurL1 + ParamStart2;
1605             if(ParamStart < Domain1.FirstParameter()) {
1606               ParamStart=Domain1.FirstParameter();
1607               ParamStart2=ParamStart - Org2SurL1;
1608             }
1609           }
1610           break;
1611         default:  //~~~ Segment Infini a gauche
1612           break;
1613         }
1614         
1615         switch(ResHasLastPoint) {
1616         case 1: 
1617           ParamEnd=Domain1.LastParameter(); 
1618           ParamEnd2=(Opposite)? (Org2SurL1-ParamEnd) 
1619                                  :(ParamEnd-Org2SurL1); 
1620           break;
1621         case 2:
1622           if(Opposite) {
1623             ParamEnd2=Domain2.FirstParameter();
1624             ParamEnd=Org2SurL1 - ParamEnd2; 
1625           }
1626           else {
1627             ParamEnd2=Domain2.LastParameter();
1628             ParamEnd=Org2SurL1 + ParamEnd2;
1629           }
1630           break;
1631         case 3:
1632           if(Opposite) {
1633             ParamEnd2=Domain2.FirstParameter();
1634             ParamEnd=Org2SurL1 - ParamEnd2; 
1635             if(ParamEnd > Domain1.LastParameter()) {
1636               ParamEnd=Domain1.LastParameter();
1637               ParamEnd2=Org2SurL1 -  ParamEnd;
1638             }
1639           }
1640           else {
1641             ParamEnd2=Domain2.LastParameter();
1642             ParamEnd=Org2SurL1 + ParamEnd2;
1643             if(ParamEnd > Domain1.LastParameter()) {
1644               ParamEnd=Domain1.LastParameter();
1645               ParamEnd2=ParamEnd - Org2SurL1;
1646             }
1647           }
1648         default:  //~~~ Segment Infini a droite
1649           break;
1650         }
1651         
1652         IntRes2d_Transition Tinf,Tsup;
1653
1654         if(ResHasFirstPoint) {
1655           if(ResHasLastPoint) {
1656             //~~~ Creation de la borne superieure
1657             //~~~ L1 :     |------------->       ou          |-------------->
1658             //~~~ L2 : <------------|            ou  <----|
1659             if(ParamEnd >= (ParamStart-Tol)) { 
1660               //~~~ Creation d un segment
1661               IntRes2d_Position Pos1,Pos2;
1662               Pos1=FindPositionLL(ParamStart,Domain1);
1663               Pos2=FindPositionLL(ParamStart2,Domain2);
1664               Tinf.SetValue(Standard_True,Pos1,IntRes2d_Unknown,Opposite);
1665               Tsup.SetValue(Standard_True,Pos2,IntRes2d_Unknown,Opposite);
1666               IntRes2d_IntersectionPoint P1(ElCLib::Value(ParamStart,L1)
1667                                             ,ParamStart,ParamStart2
1668                                             ,Tinf,Tsup,Standard_False);
1669               if(ParamEnd > (ParamStart+Tol)) {
1670                 //~~~ Le segment est assez long
1671                 Pos1=FindPositionLL(ParamEnd,Domain1);
1672                 Pos2=FindPositionLL(ParamEnd2,Domain2);
1673                 Tinf.SetValue(Standard_True,Pos1,IntRes2d_Unknown,Opposite);
1674                 Tsup.SetValue(Standard_True,Pos2,IntRes2d_Unknown,Opposite);
1675
1676                 IntRes2d_IntersectionPoint P2(ElCLib::Value(ParamEnd,L1)
1677                                               ,ParamEnd,ParamEnd2
1678                                               ,Tinf,Tsup,Standard_False);
1679                 IntRes2d_IntersectionSegment Seg(P1,P2,Opposite,Standard_False);
1680                 Append(Seg);
1681               }
1682               else {   //~~~~ le segment est de longueur inferieure a Tol
1683                 Append(P1);
1684               }
1685             } //-- if( ParamEnd >= ...)
1686           }   //-- if(ResHasLastPoint)
1687           else { 
1688             //~~~ Creation de la demi droite   |----------->
1689             IntRes2d_Position Pos1=FindPositionLL(ParamStart,Domain1);
1690             IntRes2d_Position Pos2=FindPositionLL(ParamStart2,Domain2);
1691             Tinf.SetValue(Standard_True,Pos1,IntRes2d_Unknown,Opposite);
1692             Tsup.SetValue(Standard_True,Pos2,IntRes2d_Unknown,Opposite);
1693
1694             IntRes2d_IntersectionPoint P(ElCLib::Value(ParamStart,L1)
1695                                           ,ParamStart,ParamStart2
1696                                           ,Tinf,Tsup,Standard_False);
1697             IntRes2d_IntersectionSegment Seg(P,Standard_True,Opposite,Standard_False);
1698             Append(Seg);
1699           }
1700         }
1701         else {
1702           IntRes2d_Position Pos1=FindPositionLL(ParamEnd,Domain1);
1703           IntRes2d_Position Pos2=FindPositionLL(ParamEnd2,Domain2);
1704           Tinf.SetValue(Standard_True,Pos1,IntRes2d_Unknown,Opposite);
1705           Tsup.SetValue(Standard_True,Pos2,IntRes2d_Unknown,Opposite);
1706
1707           IntRes2d_IntersectionPoint P2(ElCLib::Value(ParamEnd,L1)
1708                                         ,ParamEnd,ParamEnd2
1709                                         ,Tinf,Tsup,Standard_False);
1710           IntRes2d_IntersectionSegment Seg(P2,Standard_False,Opposite,Standard_False);
1711           Append(Seg);
1712           //~~~ Creation de la demi droite   <-----------|
1713         }
1714       }
1715     }
1716   }
1717 }
1718
1719
1720 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1721 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1722 void IntCurve_IntConicConic::Perform(const gp_Lin2d& Line
1723                                      ,const IntRes2d_Domain& LIG_Domain
1724                                      ,const gp_Circ2d& Circle
1725                                      ,const IntRes2d_Domain& CIRC_Domain
1726                                      ,const Standard_Real TolConf,const Standard_Real Tol) {
1727
1728 //--  if(! CIRC_Domain.IsClosed()) {
1729 //--    Standard_ConstructionError::Raise("Domaine incorrect");
1730 //--  }
1731
1732   Standard_Boolean TheReversedParameters=ReversedParameters();
1733   this->ResetFields();
1734   this->SetReversedParameters(TheReversedParameters);
1735
1736   Standard_Integer nbsol=0;
1737   PeriodicInterval CInt1,CInt2;  
1738   
1739   LineCircleGeometricIntersection(Line,Circle,TolConf,Tol
1740                                   ,CInt1,CInt2
1741                                   ,nbsol);
1742
1743   done=Standard_True;
1744
1745   if(nbsol==0) { //-- Pas de solutions 
1746     return;
1747   }
1748   
1749 //  Modified by Sergey KHROMOV - Mon Dec 18 11:13:18 2000 Begin
1750   if (nbsol == 2 && CInt2.Bsup == CInt1.Binf + PIpPI) {
1751     Standard_Real FirstBound = CIRC_Domain.FirstParameter();
1752     Standard_Real LastBound = CIRC_Domain.LastParameter();
1753     Standard_Real FirstTol = CIRC_Domain.FirstTolerance();
1754     Standard_Real LastTol = CIRC_Domain.LastTolerance();
1755     if (CInt1.Binf == 0 && FirstBound - FirstTol > CInt1.Bsup) {
1756       nbsol = 1;
1757       CInt1.SetValues(CInt2.Binf, CInt2.Bsup);
1758     } else if (CInt2.Bsup == PIpPI && LastBound + LastTol < CInt2.Binf)
1759       nbsol = 1;
1760   }
1761 //  Modified by Sergey KHROMOV - Mon Dec 18 11:13:20 2000 End
1762
1763   PeriodicInterval CDomain(CIRC_Domain);
1764   Standard_Real deltat = CDomain.Bsup-CDomain.Binf;
1765   while(CDomain.Binf >= PIpPI) CDomain.Binf-=PIpPI;
1766   while(CDomain.Binf <  0.0)   CDomain.Binf+=PIpPI;
1767   CDomain.Bsup=CDomain.Binf+deltat;
1768
1769   //------------------------------------------------------------
1770   //-- Ajout : Jeudi 28 mars 96 
1771   //-- On agrandit artificiellement les domaines
1772   Standard_Real BinfModif = CDomain.Binf;
1773   Standard_Real BsupModif = CDomain.Bsup;
1774   BinfModif-=CIRC_Domain.FirstTolerance() / Circle.Radius();
1775   BsupModif+=CIRC_Domain.LastTolerance() / Circle.Radius();
1776   deltat = BsupModif-BinfModif;
1777   if(deltat<=PIpPI) { 
1778     CDomain.Binf = BinfModif;
1779     CDomain.Bsup = BsupModif;
1780   }
1781   else { 
1782     Standard_Real t=PIpPI-deltat;
1783     t*=0.5;
1784     CDomain.Binf = BinfModif+t;
1785     CDomain.Bsup = BsupModif-t; 
1786   }
1787   deltat = CDomain.Bsup-CDomain.Binf;
1788   while(CDomain.Binf >= PIpPI) CDomain.Binf-=PIpPI;
1789   while(CDomain.Binf <  0.0)   CDomain.Binf+=PIpPI;
1790   CDomain.Bsup=CDomain.Binf+deltat;
1791   //-- ------------------------------------------------------------
1792
1793   Interval LDomain(LIG_Domain);
1794   
1795   Standard_Integer NbSolTotal=0;
1796   
1797   PeriodicInterval SolutionCircle[4];
1798   Interval SolutionLine[4];
1799   
1800   //----------------------------------------------------------------------
1801   //----------- Traitement du premier intervalle Geometrique  CInt1   ----
1802   //----------------------------------------------------------------------
1803   //-- NbSolTotal est incremente a chaque Intervalle solution.
1804   //-- On stocke les intervalles dans les tableaux : SolutionCircle[4] 
1805   //--                                            et SolutionLine[4]
1806   //-- des Exemples faciles donnent 3 Intersections
1807   //-- des Problemes numeriques peuvent peut etre en donner 4 ??????
1808   //--
1809   PeriodicInterval CDomainAndRes=CDomain.FirstIntersection(CInt1);
1810   
1811   ProjectOnLAndIntersectWithLDomain(Circle,Line
1812                                     ,CDomainAndRes
1813                                     ,LDomain
1814                                     ,SolutionCircle
1815                                     ,SolutionLine
1816                                     ,NbSolTotal
1817                                     ,LIG_Domain
1818                                     ,CIRC_Domain);
1819   
1820   CDomainAndRes=CDomain.SecondIntersection(CInt1);
1821   
1822   ProjectOnLAndIntersectWithLDomain(Circle,Line
1823                                     ,CDomainAndRes
1824                                     ,LDomain
1825                                     ,SolutionCircle
1826                                     ,SolutionLine
1827                                     ,NbSolTotal
1828                                     ,LIG_Domain
1829                                     ,CIRC_Domain);
1830   
1831   //----------------------------------------------------------------------
1832   //----------- Traitement du second intervalle Geometrique   C1_Int2 ----
1833   //----------------------------------------------------------------------
1834   if(nbsol==2) {
1835     CDomainAndRes=CDomain.FirstIntersection(CInt2);
1836     
1837     ProjectOnLAndIntersectWithLDomain(Circle,Line
1838                                       ,CDomainAndRes
1839                                       ,LDomain
1840                                       ,SolutionCircle
1841                                       ,SolutionLine
1842                                       ,NbSolTotal
1843                                       ,LIG_Domain
1844                                       ,CIRC_Domain);
1845     
1846     //--------------------------------------------------------------------
1847     CDomainAndRes=CDomain.SecondIntersection(CInt2);
1848     
1849     
1850     ProjectOnLAndIntersectWithLDomain(Circle,Line
1851                                       ,CDomainAndRes
1852                                       ,LDomain
1853                                       ,SolutionCircle
1854                                       ,SolutionLine
1855                                       ,NbSolTotal
1856                                       ,LIG_Domain
1857                                       ,CIRC_Domain);
1858   }
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868   //----------------------------------------------------------------------
1869   //-- Calcul de toutes les transitions et Positions.
1870   //--
1871   //-- On determine si des intervalles sont reduit a des points 
1872   //--      ( Rayon * Intervalle.Length()    <    TolConf   )   ### Modif 19 Nov Tol-->TolConf
1873   //--
1874   Standard_Real R=Circle.Radius();
1875   Standard_Integer i ;
1876   Standard_Real MaxTol = TolConf;
1877   if(MaxTol<Tol) MaxTol = Tol;
1878   if(MaxTol<1.0e-10) MaxTol = 1.0e-10; 
1879
1880   for( i=0; i<NbSolTotal ; i++) { 
1881     if((R * SolutionCircle[i].Length())<MaxTol 
1882        && (SolutionLine[i].Length())<MaxTol) {
1883       
1884       Standard_Real t=(SolutionCircle[i].Binf+SolutionCircle[i].Bsup)*0.5;
1885       SolutionCircle[i].Binf=SolutionCircle[i].Bsup=t;
1886       
1887       t=(SolutionLine[i].Binf+SolutionLine[i].Bsup)*0.5;
1888       SolutionLine[i].Binf=SolutionLine[i].Bsup=t;
1889     }
1890   }
1891 #if 0 
1892   if(NbSolTotal == 2) { 
1893     if(SolutionLine[0].Binf==SolutionLine[0].BSup) { 
1894       if(SolutionLine[1].Binf==SolutionLine[1].BSup) {
1895         if(Abs(SolutionLine[0].Binf-SolutionLine[1].Binf)<TolConf) { 
1896           SolutionLine[0].Binf=0.5*(SolutionLine[0].BSup+SolutionLine[1].BSup);
1897           SolutionLine[0].BSup=SolutionLine[0].Binf;
1898           NbSolTotal = 1;
1899         }
1900       }
1901     }
1902   }
1903 #endif
1904   //----------------------------------------------------------------------
1905   //-- Traitement des intervalles (ou des points obtenus)
1906   //-- 
1907   if(NbSolTotal) { 
1908     gp_Ax22d CircleAxis=Circle.Axis();
1909     gp_Ax2d LineAxis=Line.Position();
1910     gp_Pnt2d P1a,P2a,P1b,P2b;
1911     gp_Vec2d Tan1,Tan2,Norm1;
1912     gp_Vec2d Norm2(0.0,0.0);
1913     IntRes2d_Transition T1a,T2a,T1b,T2b;
1914     IntRes2d_Position Pos1a,Pos1b,Pos2a,Pos2b;
1915     
1916     ElCLib::CircleD1(SolutionCircle[0].Binf,CircleAxis,R,P1a,Tan1);
1917     ElCLib::LineD1(SolutionLine[0].Binf,LineAxis,P2a,Tan2);
1918     
1919     Standard_Boolean Opposite=((Tan1.Dot(Tan2))<0.0)? Standard_True : Standard_False;
1920     
1921     
1922     for(i=0; i<NbSolTotal; i++ ) {
1923
1924
1925       //-- 7 aout 97 
1926       //-- On recentre Bin et Bsup de facon a avoir une portion commune avec CIRC_Domain
1927       Standard_Real p1=SolutionCircle[i].Binf;
1928       Standard_Real p2=SolutionCircle[i].Bsup;
1929       Standard_Real q1=CIRC_Domain.FirstParameter();
1930       Standard_Real q2=CIRC_Domain.LastParameter();
1931       //--          |------ CircDomain ------|   [-- Sol --]
1932       if(p1>q2) {       
1933         do { 
1934           p1-=PIpPI; 
1935           p2-=PIpPI;
1936         }
1937         while( (p1>q2) );
1938       }
1939       else if(p2<q1) { 
1940         do { 
1941           p1+=PIpPI; 
1942           p2+=PIpPI;
1943         }
1944         while( (p2<q1) );       
1945       }
1946       if(p1<q1 && p2>q1) { 
1947         p1=q1;
1948       }
1949       if(p1<q2 && p2>q2) { 
1950         p2=q2;
1951       }
1952       
1953 #if 0
1954       if(SolutionCircle[i].Binf!=p1 || SolutionCircle[i].Bsup!=p2) { 
1955         printf("\n IntCurve_IntConicConic_1.cxx : (%g , %g) --> (%g , %g)\n",
1956                SolutionCircle[i].Binf,SolutionCircle[i].Bsup,p1,p2); 
1957       } 
1958 #endif
1959       SolutionCircle[i].Binf=p1;
1960       SolutionCircle[i].Bsup=p2;
1961       
1962 //-- Fin 7 aout 97
1963
1964       
1965       Standard_Real Linf=(Opposite)? SolutionLine[i].Bsup : SolutionLine[i].Binf;
1966       Standard_Real Lsup=(Opposite)? SolutionLine[i].Binf : SolutionLine[i].Bsup;
1967       
1968       //---------------------------------------------------------------
1969       //-- Si les parametres sur le cercle sont en premier 
1970       //-- On doit retourner ces parametres dans l ordre croissant
1971       //---------------------------------------------------------------
1972       if(Linf > Lsup) {
1973         Standard_Real T=SolutionCircle[i].Binf;
1974         SolutionCircle[i].Binf=SolutionCircle[i].Bsup;
1975         SolutionCircle[i].Bsup=T;
1976         
1977         T=Linf; Linf=Lsup; Lsup=T;
1978       }
1979       
1980       
1981       ElCLib::CircleD2(SolutionCircle[i].Binf,CircleAxis,R,P1a,Tan1,Norm1); 
1982       ElCLib::LineD1(Linf,LineAxis,P2a,Tan2);
1983       
1984       IntImpParGen::DeterminePosition(Pos1a,CIRC_Domain,P1a,SolutionCircle[i].Binf);
1985       IntImpParGen::DeterminePosition(Pos2a,LIG_Domain,P2a,Linf); 
1986       Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
1987       Standard_Real Cinf;
1988       if(Pos1a==IntRes2d_End) {
1989         Cinf = CIRC_Domain.LastParameter();
1990         P1a  = CIRC_Domain.LastPoint();
1991         Linf = ElCLib::Parameter(Line,P1a);
1992         
1993         ElCLib::CircleD2(Cinf,CircleAxis,R,P1a,Tan1,Norm1); 
1994         ElCLib::LineD1(Linf,LineAxis,P2a,Tan2); 
1995         IntImpParGen::DeterminePosition(Pos1a,CIRC_Domain,P1a,Cinf);
1996         IntImpParGen::DeterminePosition(Pos2a,LIG_Domain,P2a,Linf); 
1997         Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
1998       }
1999       else if(Pos1a==IntRes2d_Head) { 
2000         Cinf = CIRC_Domain.FirstParameter();
2001         P1a  = CIRC_Domain.FirstPoint();
2002         Linf = ElCLib::Parameter(Line,P1a);
2003         
2004         ElCLib::CircleD2(Cinf,CircleAxis,R,P1a,Tan1,Norm1); 
2005         ElCLib::LineD1(Linf,LineAxis,P2a,Tan2); 
2006         IntImpParGen::DeterminePosition(Pos1a,CIRC_Domain,P1a,Cinf);
2007         IntImpParGen::DeterminePosition(Pos2a,LIG_Domain,P2a,Linf); 
2008         Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
2009       }
2010       else { 
2011         Cinf=NormalizeOnCircleDomain(SolutionCircle[i].Binf,CIRC_Domain);
2012       }
2013
2014       IntRes2d_IntersectionPoint NewPoint1(P1a,Linf,Cinf,T2a,T1a,ReversedParameters());
2015       
2016       if((SolutionLine[i].Length()+SolutionCircle[i].Length()) >0.0) {
2017         
2018         ElCLib::CircleD2(SolutionCircle[i].Bsup,CircleAxis,R,P1b,Tan1,Norm1); 
2019         ElCLib::LineD1(Lsup,LineAxis,P2b,Tan2);
2020           
2021         IntImpParGen::DeterminePosition(Pos1b,CIRC_Domain,P1b,SolutionCircle[i].Bsup);
2022         IntImpParGen::DeterminePosition(Pos2b,LIG_Domain,P2b,Lsup);
2023         Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);
2024         Standard_Real Csup;
2025         if(Pos1b==IntRes2d_End) {
2026           Csup = CIRC_Domain.LastParameter();
2027           P1b  = CIRC_Domain.LastPoint();
2028           Lsup = ElCLib::Parameter(Line,P1b);
2029           ElCLib::CircleD2(Csup,CircleAxis,R,P1b,Tan1,Norm1); 
2030           ElCLib::LineD1(Lsup,LineAxis,P2b,Tan2);
2031           
2032           IntImpParGen::DeterminePosition(Pos1b,CIRC_Domain,P1b,Csup);
2033           IntImpParGen::DeterminePosition(Pos2b,LIG_Domain,P2b,Lsup);
2034           Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);      
2035         }
2036         else if(Pos1b==IntRes2d_Head) { 
2037           Csup = CIRC_Domain.FirstParameter();
2038           P1b  = CIRC_Domain.FirstPoint();
2039           Lsup = ElCLib::Parameter(Line,P1b);
2040           ElCLib::CircleD2(Csup,CircleAxis,R,P1b,Tan1,Norm1); 
2041           ElCLib::LineD1(Lsup,LineAxis,P2b,Tan2);
2042           
2043           IntImpParGen::DeterminePosition(Pos1b,CIRC_Domain,P1b,Csup);
2044           IntImpParGen::DeterminePosition(Pos2b,LIG_Domain,P2b,Lsup);
2045           Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);    
2046         }
2047         else { 
2048           Csup=NormalizeOnCircleDomain(SolutionCircle[i].Bsup,CIRC_Domain);
2049         }
2050
2051         IntRes2d_IntersectionPoint NewPoint2(P1b,Lsup,Csup,T2b,T1b,ReversedParameters());
2052         
2053         if(((Abs(Csup-Cinf)*R >  MaxTol) && (Abs(Lsup-Linf) > MaxTol))
2054            || (T1a.TransitionType() != T2a.TransitionType())) {  
2055           //-- Verifier egalement les transitions 
2056           
2057           IntRes2d_IntersectionSegment NewSeg(NewPoint1,NewPoint2
2058                                               ,Opposite,ReversedParameters());
2059           Append(NewSeg);
2060         }
2061         else { 
2062           if(Pos1a!=IntRes2d_Middle ||  Pos2a!=IntRes2d_Middle) { 
2063             Insert(NewPoint1);
2064           }
2065           if(Pos1b!=IntRes2d_Middle ||  Pos2b!=IntRes2d_Middle) { 
2066             Insert(NewPoint2);
2067           }
2068
2069         }
2070       }
2071       else {
2072         //--Standard_Real Cmid=NormalizeOnCircleDomain(0.5*(SolutionCircle[i].Bsup+SolutionCircle[i].Binf)
2073         //--                                       ,CIRC_Domain);        
2074         //--IntRes2d_IntersectionPoint NewPoint(P2a,0.5*(Linf+Lsup)
2075         //--                                ,Cmid
2076         //--                                ,T2a,T1a,ReversedParameters());
2077         Insert(NewPoint1);
2078       }
2079     }
2080   }
2081 }
2082
2083
2084
2085
2086 const IntRes2d_IntersectionPoint SegmentToPoint( const IntRes2d_IntersectionPoint& Pa
2087                                                 ,const IntRes2d_Transition& T1a
2088                                                 ,const IntRes2d_Transition& T2a
2089                                                 ,const IntRes2d_IntersectionPoint& Pb
2090                                                 ,const IntRes2d_Transition& T1b
2091                                                 ,const IntRes2d_Transition& T2b) {  
2092   
2093   if((T1b.PositionOnCurve() == IntRes2d_Middle) 
2094      && (T2b.PositionOnCurve() == IntRes2d_Middle)) { 
2095     return(Pa);
2096   }
2097   if((T1a.PositionOnCurve() == IntRes2d_Middle) 
2098      && (T2a.PositionOnCurve() == IntRes2d_Middle)) { 
2099     return(Pb);
2100   }
2101   
2102   IntRes2d_Transition t1 = T1a;
2103   IntRes2d_Transition t2 = T2a;
2104   Standard_Real u1 = Pa.ParamOnFirst();
2105   Standard_Real u2 = Pa.ParamOnSecond();
2106   
2107   
2108   if(t1.PositionOnCurve() == IntRes2d_Middle) { 
2109     t1.SetPosition(T1b.PositionOnCurve());
2110     u1 = Pb.ParamOnFirst();
2111   }
2112   if(t2.PositionOnCurve() == IntRes2d_Middle) {
2113     t2.SetPosition(T2b.PositionOnCurve());
2114     u2 = Pb.ParamOnSecond();
2115   } 
2116   return(IntRes2d_IntersectionPoint(Pa.Value(),u1,u2,t1,t2,Standard_False));
2117 }