0026937: Eliminate NO_CXX_EXCEPTION macro support
[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-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_1.hxx>
31 #include <IntCurve_IntConicConic_Tool.hxx>
32 #include <IntCurve_PConic.hxx>
33 #include <IntImpParGen.hxx>
34 #include <IntRes2d_Domain.hxx>
35 #include <IntRes2d_IntersectionPoint.hxx>
36 #include <IntRes2d_IntersectionSegment.hxx>
37 #include <IntRes2d_TypeTrans.hxx>
38 #include <Precision.hxx>
39 #include <Standard_ConstructionError.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 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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   //-- cout<<" C1_binf1:"<<C1_binf1;
255   //-- cout<<" C1_bsup1:"<<C1_bsup1;
256   //-- cout<<" C1_binf2:"<<C1_binf2;
257   //-- cout<<" C1_bsup2:"<<C1_bsup2<<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 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 //=======================================================================
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 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 //----------------------------------------------------------------------
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 Opposite = 
868     ((Circle1.Location().SquareDistance(Circle2.Location())) > (R1*R1+R2*R2)) ? 
869           Standard_True : Standard_False;
870
871   //if(Circle1.IsDirect()) { cout<<" C1 Direct"<<endl; } else { cout<<" C1 INDirect"<<endl; }
872   //if(Circle2.IsDirect()) { cout<<" C2 Direct"<<endl; } else { cout<<" C2 INDirect"<<endl; }
873
874   for(i=0; i<NbSolTotal; i++)
875   {
876     Standard_Real C2inf=(Opposite)? SolutionC2[i].Bsup : SolutionC2[i].Binf;
877     Standard_Real C2sup=(Opposite)? 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(Opposite)
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,
998           (Opposite==Standard_True)? Standard_False : Standard_True,
999           Standard_False);
1000         Append(NewSeg);
1001       }
1002       else
1003       {
1004         Append(NewPoint1);
1005       }
1006     }
1007     else
1008     { 
1009       ElCLib::CircleD2(C1inf,Axis2C1,R1,P1a,Tan1,Norm1); 
1010       ElCLib::CircleD2(C2inf,Axis2C2,R2,P2a,Tan2,Norm2);
1011       
1012       IntImpParGen::DeterminePosition(Pos1a,DomainCirc1,P1a,C1inf);
1013       IntImpParGen::DeterminePosition(Pos2a,DomainCirc2,P2a,C2inf);
1014       Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
1015       
1016       
1017       IntRes2d_IntersectionPoint NewPoint1(P1a,C1inf,C2inf,T1a,T2a,Standard_False);
1018       
1019       if((SolutionC1[i].Length()>0.0 ) || (SolutionC2[i].Length() >0.0))
1020       {
1021         //-- On traite un intervalle non reduit a un point
1022         Standard_Real C1sup=NormalizeOnCircleDomain(SolutionC1[i].Bsup,DomainCirc1);
1023         if(C1sup<C1inf) C1sup+=PIpPI;
1024         C2sup=NormalizeOnCircleDomain(C2sup,DomainCirc2);
1025
1026         ElCLib::CircleD2(C1sup,Axis2C1,R1,P1b,Tan1,Norm1); 
1027         ElCLib::CircleD2(C2sup,Axis2C2,R2,P2b,Tan2,Norm2);
1028
1029         IntImpParGen::DeterminePosition(Pos1b,DomainCirc1,P1b,C1sup);
1030         IntImpParGen::DeterminePosition(Pos2b,DomainCirc2,P2b,C2sup);
1031         Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);
1032
1033         //--------------------------------------------------
1034
1035         if(Opposite)
1036         {
1037             if(C2inf<C2sup)
1038               C2inf+=PIpPI;
1039         }
1040         else
1041         {
1042             if(C2sup<C2inf)
1043               C2sup+=PIpPI;
1044         }
1045
1046         IntRes2d_IntersectionPoint NewPoint2(P1b,C1sup,C2sup,T1b,T2b,Standard_False);
1047         IntRes2d_IntersectionSegment NewSeg(NewPoint1,NewPoint2,Opposite,Standard_False);
1048         Append(NewSeg);
1049       }
1050       else
1051       {
1052         Append(NewPoint1);
1053       }
1054     }
1055   }
1056 }
1057 //----------------------------------------------------------------------
1058 IntRes2d_Position FindPositionLL(Standard_Real &Param
1059                                  ,const IntRes2d_Domain& Domain) 
1060 {
1061   Standard_Real aDPar = Precision::Infinite();
1062   IntRes2d_Position aPos = IntRes2d_Middle; 
1063   Standard_Real aResPar = Param;
1064   if(Domain.HasFirstPoint()) {
1065     aDPar = Abs(Param-Domain.FirstParameter());
1066     if( aDPar <= Domain.FirstTolerance()) {
1067       aResPar=Domain.FirstParameter();
1068       aPos = IntRes2d_Head;
1069      
1070     }
1071   }
1072   if(Domain.HasLastPoint()) {
1073     Standard_Real aD2 = Abs(Param-Domain.LastParameter());
1074     if( aD2 <= Domain.LastTolerance() && (aPos == IntRes2d_Middle || aD2 < aDPar )) 
1075     {
1076       aResPar=Domain.LastParameter();
1077       aPos = IntRes2d_End;
1078     }
1079   }
1080   Param = aResPar;
1081   return aPos;
1082 }
1083 //--------------------------------------------------------------------
1084 //gka 0022833
1085 // Method to compute of point of intersection for case
1086 //when specified domain less than specified tolerance for intersection
1087 static inline void getDomainParametrs(const IntRes2d_Domain& theDomain,
1088                                       Standard_Real& theFirst,
1089                                       Standard_Real& theLast,
1090                                       Standard_Real& theTol1,
1091                                       Standard_Real& theTol2)
1092 {
1093   theFirst = (theDomain.HasFirstPoint() ? theDomain.FirstParameter() : -Precision::Infinite());
1094   theLast = (theDomain.HasLastPoint() ? theDomain.LastParameter() : Precision::Infinite()); 
1095   theTol1 = (theDomain.HasFirstPoint() ? theDomain.FirstTolerance() : 0.);
1096   theTol2 = (theDomain.HasLastPoint() ? theDomain.LastTolerance() : 0.);
1097 }
1098
1099
1100 //=======================================================================
1101 //function : computeIntPoint
1102 //purpose  : 
1103 //=======================================================================
1104 static Standard_Boolean computeIntPoint(const IntRes2d_Domain& theCurDomain,
1105                                         const IntRes2d_Domain& theDomainOther,
1106                                         const gp_Lin2d& theCurLin,
1107                                         const gp_Lin2d& theOtherLin,   
1108                                         Standard_Real theCosT1T2,
1109                                         Standard_Real theParCur, Standard_Real theParOther,
1110                                         Standard_Real& theResInf, Standard_Real& theResSup,
1111                                         Standard_Integer theNum,
1112                                         IntRes2d_TypeTrans theCurTrans,    
1113                                         IntRes2d_IntersectionPoint& theNewPoint)
1114 {
1115   if(fabs(theResSup-theParCur) > fabs(theResInf-theParCur))
1116     theResSup = theResInf;
1117
1118   Standard_Real aRes2 = theParOther + (theResSup - theParCur) * theCosT1T2;
1119
1120   Standard_Real aFirst2, aLast2, aTol21, aTol22, aTol11, aTol12 ;
1121   
1122   getDomainParametrs(theDomainOther,aFirst2, aLast2, aTol21, aTol22);
1123   
1124   if( aRes2  < aFirst2 - aTol21 || aRes2  > aLast2 + aTol22 ) {
1125     return Standard_False;
1126   }
1127         
1128   //------ compute parameters of intersection point --
1129   IntRes2d_Transition aT1,aT2;
1130   IntRes2d_Position aPos1a = FindPositionLL(theResSup,theCurDomain);
1131   IntRes2d_Position aPos2a = FindPositionLL(aRes2,theDomainOther);
1132   IntRes2d_TypeTrans anOtherTrans = ( theCurTrans == IntRes2d_Out ? 
1133       IntRes2d_In : ( theCurTrans == IntRes2d_In ? IntRes2d_Out : IntRes2d_Undecided ) );
1134
1135   if( theCurTrans != IntRes2d_Undecided )
1136   {
1137     aT1.SetValue(Standard_False, aPos1a, theCurTrans);
1138     aT2.SetValue(Standard_False,  aPos2a, anOtherTrans);
1139   }
1140   else  
1141   { 
1142     Standard_Boolean anOpposite = theCosT1T2 < 0.;
1143     aT1.SetValue(Standard_False,aPos1a,IntRes2d_Unknown,anOpposite);
1144     aT2.SetValue(Standard_False,aPos2a,IntRes2d_Unknown,anOpposite);
1145   }
1146   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1147   //--------------------------------------------------
1148   //gka bug 0022833 
1149   Standard_Real aResU1 = theParCur;
1150   Standard_Real aResU2 = theParOther;
1151
1152   Standard_Real aFirst1, aLast1;
1153   getDomainParametrs(theCurDomain,aFirst1, aLast1, aTol11, aTol12);
1154   
1155   Standard_Boolean isInside1 = (theParCur >= aFirst1 && theParCur <= aLast1);
1156   Standard_Boolean isInside2 = (theParOther >= aFirst2 && theParOther <= aLast2);
1157
1158   if(!isInside1 || !isInside2)
1159   {
1160     if(isInside1) 
1161     {
1162       gp_Pnt2d Pt1=ElCLib::Value(aRes2,theOtherLin);
1163       aResU2 = aRes2;
1164       Standard_Real aPar1 = ElCLib::Parameter(theCurLin,Pt1);
1165       aResU1 =((aPar1 >= aFirst1 && aPar1<= aLast1) ?  aPar1 : theResSup);
1166       
1167     }
1168     else if(isInside2)
1169     {
1170       gp_Pnt2d aPt1=ElCLib::Value(theResSup,theCurLin);
1171       aResU1 = theResSup;
1172       Standard_Real aPar2 = ElCLib::Parameter(theOtherLin,aPt1);
1173       aResU2= ((aPar2 >= aFirst2 && aPar2<= aLast2) ? aPar2 : aRes2);
1174     }
1175     else 
1176     {
1177       //PKVf
1178       // check that parameters are within range on both curves
1179       if ( theParCur < aFirst1-aTol11 || theParCur > aLast1+aTol12 ||
1180            theParOther < aFirst2-aTol21 || theParOther > aLast2+aTol22) {
1181         return Standard_False;
1182       }
1183       //PKVt
1184       aResU1 = theResSup;
1185       aResU2= aRes2;
1186     }
1187   }
1188   gp_Pnt2d aPres((ElCLib::Value(aResU1,theCurLin).XY() + ElCLib::Value(aResU2,theOtherLin).XY()) * 0.5 );
1189   if(theNum == 1 )
1190     theNewPoint.SetValues(aPres, aResU1, aResU2 ,aT1, aT2, Standard_False);
1191   else
1192     theNewPoint.SetValues(aPres, aResU2, aResU1 ,aT2, aT1, Standard_False);
1193   return Standard_True;
1194 }
1195
1196 //=======================================================================
1197 //function : CheckLLCoincidence
1198 //purpose  : Returns true if input are trimmed curves and they coincide
1199 //           within tolerance
1200 //=======================================================================
1201 static Standard_Boolean CheckLLCoincidence(const gp_Lin2d& L1,
1202                                            const gp_Lin2d& L2,
1203                                            const IntRes2d_Domain& Domain1,
1204                                            const IntRes2d_Domain& Domain2,
1205                                            const Standard_Real theTol)
1206 {
1207   Standard_Boolean isFirst1 = (Domain1.HasFirstPoint() &&
1208     L2.Distance(Domain1.FirstPoint()) < theTol);
1209   Standard_Boolean isLast1 = (Domain1.HasLastPoint() &&
1210     L2.Distance(Domain1.LastPoint()) < theTol);
1211   if (isFirst1 && isLast1)
1212     return Standard_True;
1213   Standard_Boolean isFirst2 = (Domain2.HasFirstPoint() &&
1214     L1.Distance(Domain2.FirstPoint()) < theTol);
1215   Standard_Boolean isLast2 = (Domain2.HasLastPoint() &&
1216     L1.Distance(Domain2.LastPoint()) < theTol);
1217   return isFirst2 && isLast2;
1218 }
1219
1220 //----------------------------------------------------------------------
1221 void IntCurve_IntConicConic::Perform(const gp_Lin2d& L1
1222                                       ,const IntRes2d_Domain& Domain1
1223                                      ,const gp_Lin2d& L2
1224                                      ,const IntRes2d_Domain& Domain2
1225                                      ,const Standard_Real,const Standard_Real TolR) {  
1226   this->ResetFields();
1227
1228   //-- Coordonnees du point d intersection sur chacune des 2 droites
1229   Standard_Real U1,U2; 
1230   //-- Nombre de points solution : 1 : Intersection
1231   //--                             0 : Non Confondues
1232   //--                             2 : Confondues a la tolerance pres
1233   Standard_Integer nbsol;
1234   IntRes2d_IntersectionPoint PtSeg1,PtSeg2;
1235   Standard_Real aHalfSinL1L2;
1236   Standard_Real Tol = TolR;
1237   if(Tol < Precision::PConfusion())
1238     Tol = Precision::PConfusion();
1239
1240   LineLineGeometricIntersection(L1,L2,Tol,U1,U2,aHalfSinL1L2,nbsol);
1241
1242   gp_Vec2d Tan1=L1.Direction();
1243   gp_Vec2d Tan2=L2.Direction();
1244  
1245   Standard_Real aCosT1T2 = Tan1.Dot(Tan2);
1246   Standard_Boolean Opposite=(aCosT1T2 < 0.0)? Standard_True : Standard_False;
1247
1248   done=Standard_True;
1249
1250   if(nbsol==1 && CheckLLCoincidence(L1, L2, Domain1, Domain2, Tol))
1251     nbsol = 2;
1252
1253   if(nbsol==1) {
1254     //---------------------------------------------------
1255     //-- d: distance du point I a partir de laquelle  les 
1256     //--  points de parametre U1+d et U2+-d sont ecartes
1257     //--  d une distance superieure a Tol.
1258     //---------------------------------------------------
1259     IntRes2d_Position Pos1a,Pos2a,Pos1b,Pos2b;
1260     Standard_Real d = 0.5 * Tol / aHalfSinL1L2;
1261     Standard_Real U1inf=U1-d;
1262     Standard_Real U1sup=U1+d;
1263     Standard_Real U1mU2=U1-U2;
1264     Standard_Real U1pU2=U1+U2;
1265     Standard_Real Res1inf,Res1sup;
1266     Standard_Real ProdVectTan;
1267     
1268
1269     //---------------------------------------------------
1270     //-- On agrandit la zone U1inf U1sup pour tenir compte 
1271     //-- des tolerances des points en bout
1272     //--
1273     if(Domain1.HasFirstPoint()) { 
1274       if(L2.Distance(Domain1.FirstPoint()) < Domain1.FirstTolerance()) { 
1275         if(U1inf > Domain1.FirstParameter()) { 
1276           U1inf = Domain1.FirstParameter();
1277         }
1278         if(U1sup < Domain1.FirstParameter()) { 
1279           U1sup = Domain1.FirstParameter();
1280         }
1281       }
1282     }
1283     if(Domain1.HasLastPoint()) { 
1284       if(L2.Distance(Domain1.LastPoint()) < Domain1.LastTolerance()) { 
1285         if(U1inf > Domain1.LastParameter()) { 
1286           U1inf = Domain1.LastParameter();
1287         }
1288         if(U1sup < Domain1.LastParameter()) { 
1289           U1sup = Domain1.LastParameter();
1290         }
1291       }
1292     }      
1293     if(Domain2.HasFirstPoint()) { 
1294       if(L1.Distance(Domain2.FirstPoint()) < Domain2.FirstTolerance()) { 
1295         Standard_Real p = ElCLib::Parameter(L1,Domain2.FirstPoint());
1296         if(U1inf > p) { 
1297           U1inf = p;
1298         }
1299         if(U1sup < p) { 
1300           U1sup = p;
1301         }
1302       }
1303     }
1304     if(Domain2.HasLastPoint()) { 
1305       if(L1.Distance(Domain2.LastPoint()) < Domain2.LastTolerance()) { 
1306         Standard_Real p = ElCLib::Parameter(L1,Domain2.LastPoint());
1307         if(U1inf > p) { 
1308           U1inf = p;
1309         }
1310         if(U1sup < p) { 
1311           U1sup = p;
1312         }
1313       }
1314     }
1315     //-----------------------------------------------------------------
1316
1317     DomainIntersection(Domain1,U1inf,U1sup,Res1inf,Res1sup,Pos1a,Pos1b);
1318     
1319     if((Res1sup-Res1inf)<0.0) {
1320       //-- Si l intersection est vide       
1321       //-- 
1322     }
1323     else { //-- (Domain1  INTER   Zone Intersection)    non vide
1324
1325       ProdVectTan=Tan1.Crossed(Tan2);
1326       
1327       //#####################################################################
1328       //##  Longueur Minimale d un segment    Sur Courbe 1 
1329       //##################################################################### 
1330
1331       Standard_Real LongMiniSeg=Tol;
1332
1333
1334       if(((Res1sup-Res1inf)<=LongMiniSeg)
1335         || ((Pos1a==Pos1b)&&(Pos1a!=IntRes2d_Middle)))     
1336       {
1337         //-------------------------------  Un seul Point -------------------
1338         //--- lorsque la longueur du segment est inferieure a ??
1339         //--- ou si deux points designent le meme bout
1340         //gka #0022833
1341         IntRes2d_TypeTrans aCurTrans = ( ProdVectTan >= TOLERANCE_ANGULAIRE ? 
1342              IntRes2d_Out : ( ProdVectTan <= -TOLERANCE_ANGULAIRE ? IntRes2d_In : IntRes2d_Undecided ) );
1343
1344         IntRes2d_IntersectionPoint NewPoint1;
1345         if( computeIntPoint(Domain1, Domain2, L1, L2, aCosT1T2, U1, U2, Res1inf, Res1sup, 1, aCurTrans, NewPoint1 ) )
1346           Append(NewPoint1);
1347
1348         //------------------------------------------------------
1349       
1350     
1351       }  //---------------   Fin du cas  :   1 seul point --------------------
1352       
1353       else {
1354         //-- Intersection AND Domain1  --------> Segment ---------------------
1355         Standard_Real U2inf,U2sup;
1356         Standard_Real Res2inf,Res2sup;
1357         
1358         if(Opposite) { U2inf = U1pU2 -Res1sup;  U2sup= U1pU2-Res1inf;  }
1359         else         { U2inf = Res1inf-U1mU2;   U2sup= Res1sup-U1mU2;  }
1360         
1361         DomainIntersection(Domain2,U2inf,U2sup,Res2inf,Res2sup,Pos2a,Pos2b);
1362
1363         //####################################################################
1364         //##  Test sur la longueur minimale d un segment sur Ligne2
1365         //####################################################################
1366         Standard_Real Res2sup_m_Res2inf = Res2sup-Res2inf;
1367         if(Res2sup_m_Res2inf < 0.0) {
1368           //-- Pas de solutions On retourne Vide
1369         }
1370         else if((Res2sup_m_Res2inf > LongMiniSeg)  
1371                 || ((Pos2a==Pos2b)&&(Pos2a!=IntRes2d_Middle)))     {
1372           //----------- Calcul des attributs du segment --------------
1373           //-- Attention, les bornes Res1inf(sup) bougent donc il faut
1374           //--  eventuellement recalculer les attributs
1375           
1376           if(Opposite) { Res1inf=U1pU2-Res2sup; Res1sup=U1pU2-Res2inf; 
1377                          Standard_Real Tampon=Res2inf; Res2inf=Res2sup; Res2sup=Tampon;
1378                          IntRes2d_Position Pos=Pos2a; Pos2a=Pos2b; Pos2b=Pos;
1379                        }
1380           else         { Res1inf=U1mU2+Res2inf; Res1sup=U1mU2+Res2sup; }
1381           
1382           Pos1a=FindPositionLL(Res1inf,Domain1);
1383           Pos1b=FindPositionLL(Res1sup,Domain1);          
1384           
1385           IntRes2d_Transition T1a,T2a,T1b,T2b;
1386           
1387           if(ProdVectTan>=TOLERANCE_ANGULAIRE) {  // &&&&&&&&&&&&&&&
1388             T1a.SetValue(Standard_False,Pos1a,IntRes2d_Out);      
1389             T2a.SetValue(Standard_False,Pos2a,IntRes2d_In);
1390           }
1391           else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1392             T1a.SetValue(Standard_False,Pos1a,IntRes2d_In);      
1393             T2a.SetValue(Standard_False,Pos2a,IntRes2d_Out);
1394           }
1395           else {
1396             T1a.SetValue(Standard_False,Pos1a,IntRes2d_Unknown,Opposite);
1397             T2a.SetValue(Standard_False,Pos2a,IntRes2d_Unknown,Opposite);
1398           }
1399           
1400
1401           //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1402           //~~~~~~~  C O N V E N T I O N    -    S E G M E N T     ~~~~~~~
1403           //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1404           //~~ On Renvoie un segment dans les cas suivants :            ~~
1405           //~~   (1) Extremite L1 L2   ------>    Extremite L1 L2       ~~
1406           //~~   (2) Extremite L1 L2   ------>    Intersection          ~~
1407           //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1408           
1409           Standard_Boolean ResultIsAPoint=Standard_False;
1410
1411           if(((Res1sup-Res1inf)<=LongMiniSeg) 
1412              || (Abs(Res2sup-Res2inf)<=LongMiniSeg)) {
1413             //-- On force la creation d un point
1414             ResultIsAPoint=Standard_True;
1415           }
1416           else {
1417             //------------------------------------------------------------
1418             //-- On traite les cas ou l intersection est situee du 
1419             //-- Mauvais cote du domaine 
1420             //-- Attention : Res2inf <-> Pos2a        Res2sup <-> Pos2b
1421             //--  et         Res1inf <-> Pos1a        Res1sup <-> Pos1b
1422             //--             avec Res1inf <= Res1sup
1423             //------------------------------------------------------------
1424             //-- Le point sera : Res1inf,Res2inf,T1a(Pos1a),T2a(Pos2a)
1425             //------------------------------------------------------------
1426
1427             if(Pos1a==IntRes2d_Head) { 
1428               if(Pos1b!=IntRes2d_End && U1<Res1inf)    { ResultIsAPoint=Standard_True; U1=Res1inf; U2=Res2inf; }
1429             }
1430             if(Pos1b==IntRes2d_End)  { 
1431               if(Pos1a!=IntRes2d_Head && U1>Res1sup)   { ResultIsAPoint=Standard_True; U1=Res1sup; U2=Res2sup; }
1432             }
1433         
1434             if(Pos2a==IntRes2d_Head) { 
1435               if(Pos2b!=IntRes2d_End && U2<Res2inf)    { ResultIsAPoint=Standard_True; U2=Res2inf; U1=Res1inf; }
1436             }
1437             else {
1438               if(Pos2a==IntRes2d_End)  { 
1439                 if(Pos2b!=IntRes2d_Head && U2>Res2inf) { ResultIsAPoint=Standard_True; U2=Res2inf; U1=Res1inf; }
1440               }
1441             }
1442             if(Pos2b==IntRes2d_Head) { 
1443               if(Pos2a!=IntRes2d_End && U2<Res2sup)    { ResultIsAPoint=Standard_True; U2=Res2sup; U1=Res1sup; }
1444             }
1445             else {
1446               if(Pos2b==IntRes2d_End) {
1447                 if(Pos2a!=IntRes2d_Head && U2>Res2sup) { ResultIsAPoint=Standard_True; U2=Res2sup; U1=Res1sup; }
1448               }
1449             }
1450           }
1451             
1452           
1453
1454           if((!ResultIsAPoint) && (Pos1a!=IntRes2d_Middle || Pos2a!=IntRes2d_Middle)) {
1455             if(ProdVectTan>=TOLERANCE_ANGULAIRE) { //&&&&&&&&&&&&&&
1456               T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1457               T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1458             }
1459             else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) { //&&&&&&&&&&&&&&
1460               T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1461               T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1462             }
1463             else {
1464               T1b.SetValue(Standard_False,Pos1b,IntRes2d_Unknown,Opposite);
1465               T2b.SetValue(Standard_False,Pos2b,IntRes2d_Unknown,Opposite);
1466             }
1467             gp_Pnt2d Ptdebut;
1468             if(Pos1a==IntRes2d_Middle) { 
1469               Standard_Real t3;
1470               if(Opposite) {
1471                 t3 = (Pos2a == IntRes2d_Head)? Res2sup : Res2inf;
1472               }
1473               else {
1474                 t3 = (Pos2a == IntRes2d_Head)? Res2inf : Res2sup;
1475               }
1476               Ptdebut=ElCLib::Value(t3,L2);
1477               Res1inf=ElCLib::Parameter(L1,Ptdebut);
1478             }
1479             else {
1480               Standard_Real t4 = (Pos1a == IntRes2d_Head)? Res1inf : Res1sup;
1481               Ptdebut=ElCLib::Value(t4,L1);
1482               Res2inf=ElCLib::Parameter(L2,Ptdebut);
1483             }
1484             PtSeg1.SetValues(Ptdebut,Res1inf,Res2inf,T1a,T2a,Standard_False);
1485             if(Pos1b!=IntRes2d_Middle || Pos2b!=IntRes2d_Middle) {
1486               //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1487               //~~ Ajustement des parametres et du point renvoye
1488               gp_Pnt2d Ptfin;
1489               if(Pos1b==IntRes2d_Middle) { 
1490                 Ptfin=ElCLib::Value(Res2sup,L2);
1491                 Res1sup=ElCLib::Parameter(L1,Ptfin);
1492               }
1493               else {
1494                 Ptfin=ElCLib::Value(Res1sup,L1);
1495                 Res2sup=ElCLib::Parameter(L2,Ptfin);
1496               }
1497               PtSeg2.SetValues(Ptfin,Res1sup,Res2sup,T1b,T2b,Standard_False);
1498               IntRes2d_IntersectionSegment Segment(PtSeg1,PtSeg2
1499                                                    ,Opposite,Standard_False);
1500               Append(Segment);  
1501             } 
1502             else { //-- Extremite(L1 ou L2)  ------>   Point Middle(L1 et L2)
1503
1504               Pos1b=FindPositionLL(U1,Domain1);
1505               Pos2b=FindPositionLL(U2,Domain2);         
1506               if(ProdVectTan>=TOLERANCE_ANGULAIRE) {
1507                 T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1508                 T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1509               }
1510               else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1511                 T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1512                 T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1513               }
1514               else {
1515                 T1b.SetValue(Standard_False,Pos1b,IntRes2d_Unknown,Opposite);
1516                 T2b.SetValue(Standard_False,Pos2b,IntRes2d_Unknown,Opposite);
1517               }
1518               
1519               PtSeg2.SetValues(ElCLib::Value(U2,L2),U1,U2,T1b,T2b,Standard_False);
1520
1521               if((Abs(Res1inf-U1) >LongMiniSeg) && (Abs(Res2inf-U2) >LongMiniSeg)) {
1522                 IntRes2d_IntersectionSegment Segment(PtSeg1,PtSeg2,Opposite,Standard_False);
1523                 Append(Segment);  
1524               }
1525               else {
1526                 Append(SegmentToPoint(PtSeg1,T1a,T2a,PtSeg2,T1b,T2b));
1527               }
1528             }
1529
1530           } //-- (Pos1a!=IntRes2d_Middle || Pos2a!=IntRes2d_Middle) --
1531           else {  //-- Pos1a == Pos2a == Middle
1532             if(Pos1b==IntRes2d_Middle) Pos1b=Pos1a;
1533             if(Pos2b==IntRes2d_Middle) Pos2b=Pos2a;
1534             if(ResultIsAPoint) {
1535               //-- Middle sur le segment A 
1536               //-- 
1537               if(Pos1b!=IntRes2d_Middle || Pos2b!=IntRes2d_Middle) {
1538                 gp_Pnt2d Ptfin;
1539                 if(Pos1b==IntRes2d_Middle) {
1540                   Standard_Real t2;
1541                   if(Opposite) { 
1542                     t2 = (Pos2b == IntRes2d_Head)? Res2sup : Res2inf;
1543                   }
1544                   else {
1545                     t2 = (Pos2b == IntRes2d_Head)? Res2inf : Res2sup;
1546                   }
1547                   Ptfin=ElCLib::Value(t2,L2);
1548                   Res1sup=ElCLib::Parameter(L1,Ptfin);
1549 //modified by NIZHNY-MKK  Tue Feb 15 10:54:51 2000.BEGIN
1550                   Pos1b=FindPositionLL(Res1sup,Domain1);
1551 //modified by NIZHNY-MKK  Tue Feb 15 10:54:55 2000.END
1552
1553                 }
1554                 else {
1555                   Standard_Real t1 = (Pos1b == IntRes2d_Head)? Res1inf : Res1sup;
1556                   Ptfin=ElCLib::Value(t1,L1);
1557                   Res2sup=ElCLib::Parameter(L2,Ptfin);
1558 //modified by NIZHNY-MKK  Tue Feb 15 10:55:08 2000.BEGIN
1559                   Pos2b=FindPositionLL(Res2sup,Domain2);
1560 //modified by NIZHNY-MKK  Tue Feb 15 10:55:11 2000.END
1561                 }
1562                 if(ProdVectTan>=TOLERANCE_ANGULAIRE) {
1563                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1564                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1565                 }
1566                 else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1567                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1568                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1569                 }
1570                 else {
1571                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_Unknown,Opposite);
1572                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_Unknown,Opposite);
1573                 }
1574                 PtSeg2.SetValues(Ptfin,Res1sup,Res2sup,T1b,T2b,Standard_False);
1575                 Append(PtSeg2);
1576               }
1577               else {
1578                 Pos1b=FindPositionLL(U1,Domain1);
1579                 Pos2b=FindPositionLL(U2,Domain2);               
1580                 
1581                 if(ProdVectTan>=TOLERANCE_ANGULAIRE) {
1582                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1583                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1584                 }
1585                 else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1586                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1587                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1588                 }
1589                 else {
1590                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_Unknown,Opposite);
1591                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_Unknown,Opposite);
1592                 }
1593                 PtSeg1.SetValues(ElCLib::Value(U2,L2),U1,U2,T1b,T2b,Standard_False);
1594                 Append(PtSeg1); 
1595               }
1596             }
1597             else {
1598               PtSeg1.SetValues(ElCLib::Value(U2,L2),U1,U2,T1a,T2a,Standard_False);
1599               
1600               if((Pos1b!=IntRes2d_Middle || Pos2b!=IntRes2d_Middle)) {
1601                 if(ProdVectTan>=TOLERANCE_ANGULAIRE) {
1602                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_Out);
1603                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_In);
1604                 }
1605                 else if(ProdVectTan<=-TOLERANCE_ANGULAIRE) {
1606                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_In);
1607                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_Out);
1608                 }
1609                 else {
1610                   T1b.SetValue(Standard_False,Pos1b,IntRes2d_Unknown,Opposite);
1611                   T2b.SetValue(Standard_False,Pos2b,IntRes2d_Unknown,Opposite);
1612                 }
1613                 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1614                 //~~ Ajustement des parametres et du point renvoye
1615                 gp_Pnt2d Ptfin;             
1616                 if(Pos1b==IntRes2d_Middle) {
1617                   Ptfin=ElCLib::Value(Res2sup,L2);
1618                   Res1sup=ElCLib::Parameter(L1,Ptfin);
1619                 }
1620                 else {
1621                   Ptfin=ElCLib::Value(Res1sup,L1);
1622                   Res2sup=ElCLib::Parameter(L2,Ptfin);
1623                 }
1624
1625                 PtSeg2.SetValues(Ptfin,Res1sup,Res2sup,T1b,T2b,Standard_False);
1626                 
1627                 if((Abs(U1-Res1sup)>LongMiniSeg)
1628                    ||(Abs(U2-Res2sup)>LongMiniSeg)) { 
1629                   //-- Modif du 1er Octobre 92 (Pour Composites)
1630                   
1631                   IntRes2d_IntersectionSegment Segment(PtSeg1,PtSeg2
1632                                                        ,Opposite,Standard_False);
1633                   Append(Segment);  
1634                 }
1635                 else {
1636                   Append(SegmentToPoint(PtSeg1,T1a,T2a,PtSeg2,T1b,T2b));
1637                 }
1638               }
1639               else {
1640                 Append(PtSeg1); 
1641               }
1642             }
1643           }
1644         } //----- Fin Creation Segment ----(Res2sup-Res2inf>Tol)-------------
1645         else {
1646           //------ (Intersection And Domain1)  AND  Domain2  --> Point ------
1647           //-- Attention Res1sup peut etre  different de  U2
1648           //--   Mais on a Res1sup-Res1inf < Tol 
1649
1650           //gka #0022833
1651     IntRes2d_TypeTrans aCurTrans = ( ProdVectTan >= TOLERANCE_ANGULAIRE ? 
1652            IntRes2d_In : ( ProdVectTan <= -TOLERANCE_ANGULAIRE ? IntRes2d_Out : IntRes2d_Undecided ) );
1653
1654           IntRes2d_IntersectionPoint NewPoint1;
1655     if( computeIntPoint(Domain2, Domain1, L2, L1, aCosT1T2, U2, U1, Res2inf, Res2sup, 2, aCurTrans, NewPoint1 ) )
1656             Append(NewPoint1);
1657         
1658         }
1659       }
1660     }
1661
1662 //#ifdef OCCT_DEBUG
1663 //  if (NbPoints() || NbSegments())
1664 //  {
1665 //    static int cnt = 0; cnt++;
1666 //
1667 //    printf("line l1_%03d %.15g %.15g %.15g %.15g\n", cnt, L1.Location().X(), L1.Location().Y(), L1.Direction().X(), L1.Direction().Y());
1668 //
1669 //    if (Domain1.HasFirstPoint() && Domain1.HasLastPoint())
1670 //      printf("trim l1_%03d l1_%03d %.15g %.15g\n", cnt, cnt, Domain1.FirstParameter(), Domain1.LastParameter());
1671 //
1672 //    printf("line l2_%03d %.15g %.15g %.15g %.15g\n", cnt, L2.Location().X(), L2.Location().Y(), L2.Direction().X(), L2.Direction().Y());
1673 //
1674 //    if (Domain2.HasFirstPoint() && Domain2.HasLastPoint())
1675 //      printf("trim l2_%03d l2_%03d %.15g %.15g\n", cnt, cnt, Domain2.FirstParameter(), Domain2.LastParameter());
1676 //
1677 //    for (int i=1; i <= NbPoints(); i++)
1678 //      printf("point p%d_%03d %.15g %.15g\n", i, cnt, Point(i).Value().X(), Point(i).Value().Y());
1679 //
1680 //    for (int i=1; i <= NbSegments(); i++)
1681 //      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());
1682 //  }
1683 //#endif
1684
1685   }
1686   else {
1687     if(nbsol==2) {  //== Droites confondues a la tolerance pres 
1688       //--On traite ici le cas de segments resultats non neccess. bornes
1689       //-- 
1690       //--On prend la droite D1 comme reference ( pour le sens positif )
1691       //--
1692       Standard_Integer ResHasFirstPoint=0;    
1693       Standard_Integer ResHasLastPoint=0;
1694       Standard_Real ParamStart = 0.,ParamStart2,ParamEnd = 0.,ParamEnd2;
1695       Standard_Real Org2SurL1=ElCLib::Parameter(L1,L2.Location());
1696       //== 3 : L1 et L2 bornent
1697       //== 2 :       L2 borne
1698       //== 1 : L1 borne
1699       if(Domain1.HasFirstPoint()) ResHasFirstPoint=1;
1700       if(Domain1.HasLastPoint())   ResHasLastPoint=1;
1701       if(Opposite) {
1702         if(Domain2.HasLastPoint())     ResHasFirstPoint+=2;
1703         if(Domain2.HasFirstPoint())   ResHasLastPoint+=2;
1704       }
1705       else {
1706         if(Domain2.HasLastPoint())     ResHasLastPoint+=2;
1707         if(Domain2.HasFirstPoint())   ResHasFirstPoint+=2;
1708       }
1709       if(ResHasFirstPoint==0 && ResHasLastPoint==0) {
1710         //~~~~ Creation d un segment infini avec Opposite
1711         Append(IntRes2d_IntersectionSegment(Opposite));
1712       }
1713       else {  //-- On obtient au pire une demi-droite
1714         switch(ResHasFirstPoint) {
1715         case 1: 
1716           ParamStart=Domain1.FirstParameter(); 
1717           ParamStart2=(Opposite)? (Org2SurL1-ParamStart) 
1718                                  :(ParamStart-Org2SurL1); 
1719           break;
1720         case 2:
1721           if(Opposite) {
1722             ParamStart2=Domain2.LastParameter();
1723             ParamStart=Org2SurL1 - ParamStart2; 
1724           }
1725           else {
1726             ParamStart2=Domain2.FirstParameter();
1727             ParamStart=Org2SurL1 + ParamStart2;
1728           }
1729           break;
1730         case 3:
1731           if(Opposite) {
1732             ParamStart2=Domain2.LastParameter();
1733             ParamStart=Org2SurL1 - ParamStart2; 
1734             if(ParamStart < Domain1.FirstParameter()) {
1735               ParamStart=Domain1.FirstParameter();
1736               ParamStart2=Org2SurL1 -  ParamStart;
1737             }
1738           }
1739           else {
1740             ParamStart2=Domain2.FirstParameter();
1741             ParamStart=Org2SurL1 + ParamStart2;
1742             if(ParamStart < Domain1.FirstParameter()) {
1743               ParamStart=Domain1.FirstParameter();
1744               ParamStart2=ParamStart - Org2SurL1;
1745             }
1746           }
1747           break;
1748         default:  //~~~ Segment Infini a gauche
1749           break;
1750         }
1751         
1752         switch(ResHasLastPoint) {
1753         case 1: 
1754           ParamEnd=Domain1.LastParameter(); 
1755           ParamEnd2=(Opposite)? (Org2SurL1-ParamEnd) 
1756                                  :(ParamEnd-Org2SurL1); 
1757           break;
1758         case 2:
1759           if(Opposite) {
1760             ParamEnd2=Domain2.FirstParameter();
1761             ParamEnd=Org2SurL1 - ParamEnd2; 
1762           }
1763           else {
1764             ParamEnd2=Domain2.LastParameter();
1765             ParamEnd=Org2SurL1 + ParamEnd2;
1766           }
1767           break;
1768         case 3:
1769           if(Opposite) {
1770             ParamEnd2=Domain2.FirstParameter();
1771             ParamEnd=Org2SurL1 - ParamEnd2; 
1772             if(ParamEnd > Domain1.LastParameter()) {
1773               ParamEnd=Domain1.LastParameter();
1774               ParamEnd2=Org2SurL1 -  ParamEnd;
1775             }
1776           }
1777           else {
1778             ParamEnd2=Domain2.LastParameter();
1779             ParamEnd=Org2SurL1 + ParamEnd2;
1780             if(ParamEnd > Domain1.LastParameter()) {
1781               ParamEnd=Domain1.LastParameter();
1782               ParamEnd2=ParamEnd - Org2SurL1;
1783             }
1784           }
1785         default:  //~~~ Segment Infini a droite
1786           break;
1787         }
1788         
1789         IntRes2d_Transition Tinf,Tsup;
1790
1791         if(ResHasFirstPoint) {
1792           if(ResHasLastPoint) {
1793             //~~~ Creation de la borne superieure
1794             //~~~ L1 :     |------------->       ou          |-------------->
1795             //~~~ L2 : <------------|            ou  <----|
1796             if(ParamEnd >= (ParamStart-Tol)) { 
1797               //~~~ Creation d un segment
1798               IntRes2d_Position Pos1,Pos2;
1799               Pos1=FindPositionLL(ParamStart,Domain1);
1800               Pos2=FindPositionLL(ParamStart2,Domain2);
1801               Tinf.SetValue(Standard_True,Pos1,IntRes2d_Unknown,Opposite);
1802               Tsup.SetValue(Standard_True,Pos2,IntRes2d_Unknown,Opposite);
1803               IntRes2d_IntersectionPoint P1(ElCLib::Value(ParamStart,L1)
1804                                             ,ParamStart,ParamStart2
1805                                             ,Tinf,Tsup,Standard_False);
1806               if(ParamEnd > (ParamStart+Tol)) {
1807                 //~~~ Le segment est assez long
1808                 Pos1=FindPositionLL(ParamEnd,Domain1);
1809                 Pos2=FindPositionLL(ParamEnd2,Domain2);
1810                 Tinf.SetValue(Standard_True,Pos1,IntRes2d_Unknown,Opposite);
1811                 Tsup.SetValue(Standard_True,Pos2,IntRes2d_Unknown,Opposite);
1812
1813                 IntRes2d_IntersectionPoint P2(ElCLib::Value(ParamEnd,L1)
1814                                               ,ParamEnd,ParamEnd2
1815                                               ,Tinf,Tsup,Standard_False);
1816                 IntRes2d_IntersectionSegment Seg(P1,P2,Opposite,Standard_False);
1817                 Append(Seg);
1818               }
1819               else {   //~~~~ le segment est de longueur inferieure a Tol
1820                 Append(P1);
1821               }
1822             } //-- if( ParamEnd >= ...)
1823           }   //-- if(ResHasLastPoint)
1824           else { 
1825             //~~~ Creation de la demi droite   |----------->
1826             IntRes2d_Position Pos1=FindPositionLL(ParamStart,Domain1);
1827             IntRes2d_Position Pos2=FindPositionLL(ParamStart2,Domain2);
1828             Tinf.SetValue(Standard_True,Pos1,IntRes2d_Unknown,Opposite);
1829             Tsup.SetValue(Standard_True,Pos2,IntRes2d_Unknown,Opposite);
1830
1831             IntRes2d_IntersectionPoint P(ElCLib::Value(ParamStart,L1)
1832                                           ,ParamStart,ParamStart2
1833                                           ,Tinf,Tsup,Standard_False);
1834             IntRes2d_IntersectionSegment Seg(P,Standard_True,Opposite,Standard_False);
1835             Append(Seg);
1836           }
1837         }
1838         else {
1839           IntRes2d_Position Pos1=FindPositionLL(ParamEnd,Domain1);
1840           IntRes2d_Position Pos2=FindPositionLL(ParamEnd2,Domain2);
1841           Tinf.SetValue(Standard_True,Pos1,IntRes2d_Unknown,Opposite);
1842           Tsup.SetValue(Standard_True,Pos2,IntRes2d_Unknown,Opposite);
1843
1844           IntRes2d_IntersectionPoint P2(ElCLib::Value(ParamEnd,L1)
1845                                         ,ParamEnd,ParamEnd2
1846                                         ,Tinf,Tsup,Standard_False);
1847           IntRes2d_IntersectionSegment Seg(P2,Standard_False,Opposite,Standard_False);
1848           Append(Seg);
1849           //~~~ Creation de la demi droite   <-----------|
1850         }
1851       }
1852     }
1853   }
1854 }
1855
1856
1857 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1858 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1859 void IntCurve_IntConicConic::Perform(const gp_Lin2d& Line
1860                                      ,const IntRes2d_Domain& LIG_Domain
1861                                      ,const gp_Circ2d& Circle
1862                                      ,const IntRes2d_Domain& CIRC_Domain
1863                                      ,const Standard_Real TolConf,const Standard_Real Tol) {
1864
1865 //--  if(! CIRC_Domain.IsClosed()) {
1866 //--    throw Standard_ConstructionError("Domaine incorrect");
1867 //--  }
1868
1869   Standard_Boolean TheReversedParameters=ReversedParameters();
1870   this->ResetFields();
1871   this->SetReversedParameters(TheReversedParameters);
1872
1873   Standard_Integer nbsol=0;
1874   PeriodicInterval CInt1,CInt2;  
1875   
1876   LineCircleGeometricIntersection(Line,Circle,TolConf,Tol
1877                                   ,CInt1,CInt2
1878                                   ,nbsol);
1879
1880   done=Standard_True;
1881
1882   if(nbsol==0) { //-- Pas de solutions 
1883     return;
1884   }
1885   
1886 //  Modified by Sergey KHROMOV - Mon Dec 18 11:13:18 2000 Begin
1887   if (nbsol == 2 && CInt2.Bsup == CInt1.Binf + PIpPI) {
1888     Standard_Real FirstBound = CIRC_Domain.FirstParameter();
1889     Standard_Real LastBound = CIRC_Domain.LastParameter();
1890     Standard_Real FirstTol = CIRC_Domain.FirstTolerance();
1891     Standard_Real LastTol = CIRC_Domain.LastTolerance();
1892     if (CInt1.Binf == 0 && FirstBound - FirstTol > CInt1.Bsup) {
1893       nbsol = 1;
1894       CInt1.SetValues(CInt2.Binf, CInt2.Bsup);
1895     } else if (CInt2.Bsup == PIpPI && LastBound + LastTol < CInt2.Binf)
1896       nbsol = 1;
1897   }
1898 //  Modified by Sergey KHROMOV - Mon Dec 18 11:13:20 2000 End
1899
1900   PeriodicInterval CDomain(CIRC_Domain);
1901   Standard_Real deltat = CDomain.Bsup-CDomain.Binf;
1902   while(CDomain.Binf >= PIpPI) CDomain.Binf-=PIpPI;
1903   while(CDomain.Binf <  0.0)   CDomain.Binf+=PIpPI;
1904   CDomain.Bsup=CDomain.Binf+deltat;
1905
1906   //------------------------------------------------------------
1907   //-- Ajout : Jeudi 28 mars 96 
1908   //-- On agrandit artificiellement les domaines
1909   Standard_Real BinfModif = CDomain.Binf;
1910   Standard_Real BsupModif = CDomain.Bsup;
1911   BinfModif-=CIRC_Domain.FirstTolerance() / Circle.Radius();
1912   BsupModif+=CIRC_Domain.LastTolerance() / Circle.Radius();
1913   deltat = BsupModif-BinfModif;
1914   if(deltat<=PIpPI) { 
1915     CDomain.Binf = BinfModif;
1916     CDomain.Bsup = BsupModif;
1917   }
1918   else { 
1919     Standard_Real t=PIpPI-deltat;
1920     t*=0.5;
1921     CDomain.Binf = BinfModif+t;
1922     CDomain.Bsup = BsupModif-t; 
1923   }
1924   deltat = CDomain.Bsup-CDomain.Binf;
1925   while(CDomain.Binf >= PIpPI) CDomain.Binf-=PIpPI;
1926   while(CDomain.Binf <  0.0)   CDomain.Binf+=PIpPI;
1927   CDomain.Bsup=CDomain.Binf+deltat;
1928   //-- ------------------------------------------------------------
1929
1930   Interval LDomain(LIG_Domain);
1931   
1932   Standard_Integer NbSolTotal=0;
1933   
1934   PeriodicInterval SolutionCircle[4];
1935   Interval SolutionLine[4];
1936   
1937   //----------------------------------------------------------------------
1938   //----------- Traitement du premier intervalle Geometrique  CInt1   ----
1939   //----------------------------------------------------------------------
1940   //-- NbSolTotal est incremente a chaque Intervalle solution.
1941   //-- On stocke les intervalles dans les tableaux : SolutionCircle[4] 
1942   //--                                            et SolutionLine[4]
1943   //-- des Exemples faciles donnent 3 Intersections
1944   //-- des Problemes numeriques peuvent peut etre en donner 4 ??????
1945   //--
1946   PeriodicInterval CDomainAndRes=CDomain.FirstIntersection(CInt1);
1947   
1948   ProjectOnLAndIntersectWithLDomain(Circle,Line
1949                                     ,CDomainAndRes
1950                                     ,LDomain
1951                                     ,SolutionCircle
1952                                     ,SolutionLine
1953                                     ,NbSolTotal
1954                                     ,LIG_Domain
1955                                     ,CIRC_Domain);
1956   
1957   CDomainAndRes=CDomain.SecondIntersection(CInt1);
1958   
1959   ProjectOnLAndIntersectWithLDomain(Circle,Line
1960                                     ,CDomainAndRes
1961                                     ,LDomain
1962                                     ,SolutionCircle
1963                                     ,SolutionLine
1964                                     ,NbSolTotal
1965                                     ,LIG_Domain
1966                                     ,CIRC_Domain);
1967   
1968   //----------------------------------------------------------------------
1969   //----------- Traitement du second intervalle Geometrique   C1_Int2 ----
1970   //----------------------------------------------------------------------
1971   if(nbsol==2) {
1972     CDomainAndRes=CDomain.FirstIntersection(CInt2);
1973     
1974     ProjectOnLAndIntersectWithLDomain(Circle,Line
1975                                       ,CDomainAndRes
1976                                       ,LDomain
1977                                       ,SolutionCircle
1978                                       ,SolutionLine
1979                                       ,NbSolTotal
1980                                       ,LIG_Domain
1981                                       ,CIRC_Domain);
1982     
1983     //--------------------------------------------------------------------
1984     CDomainAndRes=CDomain.SecondIntersection(CInt2);
1985     
1986     
1987     ProjectOnLAndIntersectWithLDomain(Circle,Line
1988                                       ,CDomainAndRes
1989                                       ,LDomain
1990                                       ,SolutionCircle
1991                                       ,SolutionLine
1992                                       ,NbSolTotal
1993                                       ,LIG_Domain
1994                                       ,CIRC_Domain);
1995   }
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005   //----------------------------------------------------------------------
2006   //-- Calcul de toutes les transitions et Positions.
2007   //--
2008   //-- On determine si des intervalles sont reduit a des points 
2009   //--      ( Rayon * Intervalle.Length()    <    TolConf   )   ### Modif 19 Nov Tol-->TolConf
2010   //--
2011   Standard_Real R=Circle.Radius();
2012   Standard_Integer i ;
2013   Standard_Real MaxTol = TolConf;
2014   if(MaxTol<Tol) MaxTol = Tol;
2015   if(MaxTol<1.0e-10) MaxTol = 1.0e-10; 
2016
2017   for( i=0; i<NbSolTotal ; i++) { 
2018     if((R * SolutionCircle[i].Length())<MaxTol 
2019        && (SolutionLine[i].Length())<MaxTol) {
2020       
2021       Standard_Real t=(SolutionCircle[i].Binf+SolutionCircle[i].Bsup)*0.5;
2022       SolutionCircle[i].Binf=SolutionCircle[i].Bsup=t;
2023       
2024       t=(SolutionLine[i].Binf+SolutionLine[i].Bsup)*0.5;
2025       SolutionLine[i].Binf=SolutionLine[i].Bsup=t;
2026     }
2027   }
2028 #if 0 
2029   if(NbSolTotal == 2) { 
2030     if(SolutionLine[0].Binf==SolutionLine[0].BSup) { 
2031       if(SolutionLine[1].Binf==SolutionLine[1].BSup) {
2032         if(Abs(SolutionLine[0].Binf-SolutionLine[1].Binf)<TolConf) { 
2033           SolutionLine[0].Binf=0.5*(SolutionLine[0].BSup+SolutionLine[1].BSup);
2034           SolutionLine[0].BSup=SolutionLine[0].Binf;
2035           NbSolTotal = 1;
2036         }
2037       }
2038     }
2039   }
2040 #endif
2041   //----------------------------------------------------------------------
2042   //-- Traitement des intervalles (ou des points obtenus)
2043   //-- 
2044   if(NbSolTotal) { 
2045     gp_Ax22d CircleAxis=Circle.Axis();
2046     gp_Ax2d LineAxis=Line.Position();
2047     gp_Pnt2d P1a,P2a,P1b,P2b;
2048     gp_Vec2d Tan1,Tan2,Norm1;
2049     gp_Vec2d Norm2(0.0,0.0);
2050     IntRes2d_Transition T1a,T2a,T1b,T2b;
2051     IntRes2d_Position Pos1a,Pos1b,Pos2a,Pos2b;
2052     
2053     ElCLib::CircleD1(SolutionCircle[0].Binf,CircleAxis,R,P1a,Tan1);
2054     ElCLib::LineD1(SolutionLine[0].Binf,LineAxis,P2a,Tan2);
2055     
2056     Standard_Boolean Opposite=((Tan1.Dot(Tan2))<0.0)? Standard_True : Standard_False;
2057     
2058     
2059     for(i=0; i<NbSolTotal; i++ ) {
2060
2061
2062       //-- 7 aout 97 
2063       //-- On recentre Bin et Bsup de facon a avoir une portion commune avec CIRC_Domain
2064       Standard_Real p1=SolutionCircle[i].Binf;
2065       Standard_Real p2=SolutionCircle[i].Bsup;
2066       Standard_Real q1=CIRC_Domain.FirstParameter();
2067       Standard_Real q2=CIRC_Domain.LastParameter();
2068       //--          |------ CircDomain ------|   [-- Sol --]
2069       if(p1>q2) {       
2070         do { 
2071           p1-=PIpPI; 
2072           p2-=PIpPI;
2073         }
2074         while( (p1>q2) );
2075       }
2076       else if(p2<q1) { 
2077         do { 
2078           p1+=PIpPI; 
2079           p2+=PIpPI;
2080         }
2081         while( (p2<q1) );       
2082       }
2083       if(p1<q1 && p2>q1) { 
2084         p1=q1;
2085       }
2086       if(p1<q2 && p2>q2) { 
2087         p2=q2;
2088       }
2089       
2090 #if 0
2091       if(SolutionCircle[i].Binf!=p1 || SolutionCircle[i].Bsup!=p2) { 
2092         printf("\n IntCurve_IntConicConic_1.cxx : (%g , %g) --> (%g , %g)\n",
2093                SolutionCircle[i].Binf,SolutionCircle[i].Bsup,p1,p2); 
2094       } 
2095 #endif
2096       SolutionCircle[i].Binf=p1;
2097       SolutionCircle[i].Bsup=p2;
2098       
2099 //-- Fin 7 aout 97
2100
2101       
2102       Standard_Real Linf=(Opposite)? SolutionLine[i].Bsup : SolutionLine[i].Binf;
2103       Standard_Real Lsup=(Opposite)? SolutionLine[i].Binf : SolutionLine[i].Bsup;
2104       
2105       //---------------------------------------------------------------
2106       //-- Si les parametres sur le cercle sont en premier 
2107       //-- On doit retourner ces parametres dans l ordre croissant
2108       //---------------------------------------------------------------
2109       if(Linf > Lsup) {
2110         Standard_Real T=SolutionCircle[i].Binf;
2111         SolutionCircle[i].Binf=SolutionCircle[i].Bsup;
2112         SolutionCircle[i].Bsup=T;
2113         
2114         T=Linf; Linf=Lsup; Lsup=T;
2115       }
2116       
2117       
2118       ElCLib::CircleD2(SolutionCircle[i].Binf,CircleAxis,R,P1a,Tan1,Norm1); 
2119       ElCLib::LineD1(Linf,LineAxis,P2a,Tan2);
2120       
2121       IntImpParGen::DeterminePosition(Pos1a,CIRC_Domain,P1a,SolutionCircle[i].Binf);
2122       IntImpParGen::DeterminePosition(Pos2a,LIG_Domain,P2a,Linf); 
2123       Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
2124       Standard_Real Cinf;
2125       if(Pos1a==IntRes2d_End) {
2126         Cinf = CIRC_Domain.LastParameter();
2127         P1a  = CIRC_Domain.LastPoint();
2128         Linf = ElCLib::Parameter(Line,P1a);
2129         
2130         ElCLib::CircleD2(Cinf,CircleAxis,R,P1a,Tan1,Norm1); 
2131         ElCLib::LineD1(Linf,LineAxis,P2a,Tan2); 
2132         IntImpParGen::DeterminePosition(Pos1a,CIRC_Domain,P1a,Cinf);
2133         IntImpParGen::DeterminePosition(Pos2a,LIG_Domain,P2a,Linf); 
2134         Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
2135       }
2136       else if(Pos1a==IntRes2d_Head) { 
2137         Cinf = CIRC_Domain.FirstParameter();
2138         P1a  = CIRC_Domain.FirstPoint();
2139         Linf = ElCLib::Parameter(Line,P1a);
2140         
2141         ElCLib::CircleD2(Cinf,CircleAxis,R,P1a,Tan1,Norm1); 
2142         ElCLib::LineD1(Linf,LineAxis,P2a,Tan2); 
2143         IntImpParGen::DeterminePosition(Pos1a,CIRC_Domain,P1a,Cinf);
2144         IntImpParGen::DeterminePosition(Pos2a,LIG_Domain,P2a,Linf); 
2145         Determine_Transition_LC(Pos1a,Tan1,Norm1,T1a , Pos2a,Tan2,Norm2,T2a, Tol);
2146       }
2147       else { 
2148         Cinf=NormalizeOnCircleDomain(SolutionCircle[i].Binf,CIRC_Domain);
2149       }
2150
2151       IntRes2d_IntersectionPoint NewPoint1(P1a,Linf,Cinf,T2a,T1a,ReversedParameters());
2152       
2153       if((SolutionLine[i].Length()+SolutionCircle[i].Length()) >0.0) {
2154         
2155         ElCLib::CircleD2(SolutionCircle[i].Bsup,CircleAxis,R,P1b,Tan1,Norm1); 
2156         ElCLib::LineD1(Lsup,LineAxis,P2b,Tan2);
2157           
2158         IntImpParGen::DeterminePosition(Pos1b,CIRC_Domain,P1b,SolutionCircle[i].Bsup);
2159         IntImpParGen::DeterminePosition(Pos2b,LIG_Domain,P2b,Lsup);
2160         Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);
2161         Standard_Real Csup;
2162         if(Pos1b==IntRes2d_End) {
2163           Csup = CIRC_Domain.LastParameter();
2164           P1b  = CIRC_Domain.LastPoint();
2165           Lsup = ElCLib::Parameter(Line,P1b);
2166           ElCLib::CircleD2(Csup,CircleAxis,R,P1b,Tan1,Norm1); 
2167           ElCLib::LineD1(Lsup,LineAxis,P2b,Tan2);
2168           
2169           IntImpParGen::DeterminePosition(Pos1b,CIRC_Domain,P1b,Csup);
2170           IntImpParGen::DeterminePosition(Pos2b,LIG_Domain,P2b,Lsup);
2171           Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);      
2172         }
2173         else if(Pos1b==IntRes2d_Head) { 
2174           Csup = CIRC_Domain.FirstParameter();
2175           P1b  = CIRC_Domain.FirstPoint();
2176           Lsup = ElCLib::Parameter(Line,P1b);
2177           ElCLib::CircleD2(Csup,CircleAxis,R,P1b,Tan1,Norm1); 
2178           ElCLib::LineD1(Lsup,LineAxis,P2b,Tan2);
2179           
2180           IntImpParGen::DeterminePosition(Pos1b,CIRC_Domain,P1b,Csup);
2181           IntImpParGen::DeterminePosition(Pos2b,LIG_Domain,P2b,Lsup);
2182           Determine_Transition_LC(Pos1b,Tan1,Norm1,T1b , Pos2b,Tan2,Norm2,T2b, Tol);    
2183         }
2184         else { 
2185           Csup=NormalizeOnCircleDomain(SolutionCircle[i].Bsup,CIRC_Domain);
2186         }
2187
2188         IntRes2d_IntersectionPoint NewPoint2(P1b,Lsup,Csup,T2b,T1b,ReversedParameters());
2189         
2190         if(((Abs(Csup-Cinf)*R >  MaxTol) && (Abs(Lsup-Linf) > MaxTol))
2191            || (T1a.TransitionType() != T2a.TransitionType())) {  
2192           //-- Verifier egalement les transitions 
2193           
2194           IntRes2d_IntersectionSegment NewSeg(NewPoint1,NewPoint2
2195                                               ,Opposite,ReversedParameters());
2196           Append(NewSeg);
2197         }
2198         else { 
2199           if(Pos1a!=IntRes2d_Middle ||  Pos2a!=IntRes2d_Middle) { 
2200             Insert(NewPoint1);
2201           }
2202           if(Pos1b!=IntRes2d_Middle ||  Pos2b!=IntRes2d_Middle) { 
2203             Insert(NewPoint2);
2204           }
2205
2206         }
2207       }
2208       else {
2209         //--Standard_Real Cmid=NormalizeOnCircleDomain(0.5*(SolutionCircle[i].Bsup+SolutionCircle[i].Binf)
2210         //--                                       ,CIRC_Domain);        
2211         //--IntRes2d_IntersectionPoint NewPoint(P2a,0.5*(Linf+Lsup)
2212         //--                                ,Cmid
2213         //--                                ,T2a,T1a,ReversedParameters());
2214         Insert(NewPoint1);
2215       }
2216     }
2217   }
2218 }
2219
2220
2221
2222
2223 const IntRes2d_IntersectionPoint SegmentToPoint( const IntRes2d_IntersectionPoint& Pa
2224                                                 ,const IntRes2d_Transition& T1a
2225                                                 ,const IntRes2d_Transition& T2a
2226                                                 ,const IntRes2d_IntersectionPoint& Pb
2227                                                 ,const IntRes2d_Transition& T1b
2228                                                 ,const IntRes2d_Transition& T2b) {  
2229   
2230   if((T1b.PositionOnCurve() == IntRes2d_Middle) 
2231      && (T2b.PositionOnCurve() == IntRes2d_Middle)) { 
2232     return(Pa);
2233   }
2234   if((T1a.PositionOnCurve() == IntRes2d_Middle) 
2235      && (T2a.PositionOnCurve() == IntRes2d_Middle)) { 
2236     return(Pb);
2237   }
2238   
2239   IntRes2d_Transition t1 = T1a;
2240   IntRes2d_Transition t2 = T2a;
2241   Standard_Real u1 = Pa.ParamOnFirst();
2242   Standard_Real u2 = Pa.ParamOnSecond();
2243   
2244   
2245   if(t1.PositionOnCurve() == IntRes2d_Middle) { 
2246     t1.SetPosition(T1b.PositionOnCurve());
2247     u1 = Pb.ParamOnFirst();
2248   }
2249   if(t2.PositionOnCurve() == IntRes2d_Middle) {
2250     t2.SetPosition(T2b.PositionOnCurve());
2251     u2 = Pb.ParamOnSecond();
2252   } 
2253   return(IntRes2d_IntersectionPoint(Pa.Value(),u1,u2,t1,t2,Standard_False));
2254 }