0025819: Bad result of BOP cut on valid shapes
[occt.git] / src / IntPatch / IntPatch_ImpImpIntersection_4.gxx
1 // Created on: 1992-05-07
2 // Created by: Jacques GOUSSARD
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 #include <IntAna_ListOfCurve.hxx>
18 #include <IntAna_ListIteratorOfListOfCurve.hxx>
19 #include <IntPatch_WLine.hxx>
20
21 //
22 static 
23   Standard_Boolean ExploreCurve(const gp_Cylinder& aCy,
24                                 const gp_Cone& aCo,
25                                 IntAna_Curve& aC,
26                                 const Standard_Real aTol,
27                                 IntAna_ListOfCurve& aLC);
28 static
29   Standard_Boolean IsToReverse(const gp_Cylinder& Cy1,
30                                const gp_Cylinder& Cy2,
31                                const Standard_Real Tol);
32
33 // ------------------------------------------------------------------
34 // MinMax : Replaces  theParMIN = MIN(theParMIN, theParMAX),
35 //                    theParMAX = MAX(theParMIN, theParMAX).
36 // ------------------------------------------------------------------
37 static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
38 {
39   if(theParMIN > theParMAX)
40   {
41     const Standard_Real aux = theParMAX;
42     theParMAX = theParMIN;
43     theParMIN = aux;
44   }
45 }
46
47
48 //=======================================================================
49 //function : ProcessBounds
50 //purpose  : 
51 //=======================================================================
52 void ProcessBounds(const Handle(IntPatch_ALine)& alig,          //-- ligne courante
53                    const IntPatch_SequenceOfLine& slin,
54                    const IntSurf_Quadric& Quad1,
55                    const IntSurf_Quadric& Quad2,
56                    Standard_Boolean& procf,
57                    const gp_Pnt& ptf,                     //-- Debut Ligne Courante
58                    const Standard_Real first,             //-- Paramf
59                    Standard_Boolean& procl,
60                    const gp_Pnt& ptl,                     //-- Fin Ligne courante
61                    const Standard_Real last,              //-- Paraml
62                    Standard_Boolean& Multpoint,
63                    const Standard_Real Tol)
64 {  
65   Standard_Integer j,k;
66   Standard_Real U1,V1,U2,V2;
67   IntPatch_Point ptsol;
68   Standard_Real d;
69   
70   if (procf && procl) {
71     j = slin.Length() + 1;
72   }
73   else {
74     j = 1;
75   }
76
77
78   //-- On prend les lignes deja enregistrees
79
80   while (j <= slin.Length()) {  
81     if(slin.Value(j)->ArcType() == IntPatch_Analytic) { 
82       const Handle(IntPatch_ALine)& aligold = *((Handle(IntPatch_ALine)*)&slin.Value(j));
83       k = 1;
84
85       //-- On prend les vertex des lignes deja enregistrees
86
87       while (k <= aligold->NbVertex()) {
88         ptsol = aligold->Vertex(k);            
89         if (!procf) {
90           d=ptf.Distance(ptsol.Value());
91           if (d <= Tol) {
92             if (!ptsol.IsMultiple()) {
93               //-- le point ptsol (de aligold) est declare multiple sur aligold
94               Multpoint = Standard_True;
95               ptsol.SetMultiple(Standard_True);
96               aligold->Replace(k,ptsol);
97             }
98             ptsol.SetParameter(first);
99             alig->AddVertex(ptsol);
100             alig->SetFirstPoint(alig->NbVertex());
101             procf = Standard_True;
102
103             //-- On restore le point avec son parametre sur aligold
104             ptsol = aligold->Vertex(k); 
105                                         
106           }
107         }
108         if (!procl) {
109           if (ptl.Distance(ptsol.Value()) <= Tol) {
110             if (!ptsol.IsMultiple()) {
111               Multpoint = Standard_True;
112               ptsol.SetMultiple(Standard_True);
113               aligold->Replace(k,ptsol);
114             }
115             ptsol.SetParameter(last);
116             alig->AddVertex(ptsol);
117             alig->SetLastPoint(alig->NbVertex());
118             procl = Standard_True;
119
120             //-- On restore le point avec son parametre sur aligold
121             ptsol = aligold->Vertex(k); 
122              
123           }
124         }
125         if (procf && procl) {
126           k = aligold->NbVertex()+1;
127         }
128         else {
129           k = k+1;
130         }
131       }
132       if (procf && procl) {
133         j = slin.Length()+1;
134       }
135       else {
136         j = j+1;
137       }
138     }
139   }
140   if (!procf && !procl) {
141     Quad1.Parameters(ptf,U1,V1);
142     Quad2.Parameters(ptf,U2,V2);
143     ptsol.SetValue(ptf,Tol,Standard_False);
144     ptsol.SetParameters(U1,V1,U2,V2);
145     ptsol.SetParameter(first);
146     if (ptf.Distance(ptl) <= Tol) {
147       ptsol.SetMultiple(Standard_True); // a voir
148       Multpoint = Standard_True;        // a voir de meme
149       alig->AddVertex(ptsol);
150       alig->SetFirstPoint(alig->NbVertex());
151       
152       ptsol.SetParameter(last);
153       alig->AddVertex(ptsol);
154       alig->SetLastPoint(alig->NbVertex());
155     }
156     else { 
157       alig->AddVertex(ptsol);
158       alig->SetFirstPoint(alig->NbVertex());
159       Quad1.Parameters(ptl,U1,V1);
160       Quad2.Parameters(ptl,U2,V2);
161       ptsol.SetValue(ptl,Tol,Standard_False);
162       ptsol.SetParameters(U1,V1,U2,V2);
163       ptsol.SetParameter(last);
164       alig->AddVertex(ptsol);
165       alig->SetLastPoint(alig->NbVertex());
166     }
167   }
168   else if (!procf) {
169     Quad1.Parameters(ptf,U1,V1);
170     Quad2.Parameters(ptf,U2,V2);
171     ptsol.SetValue(ptf,Tol,Standard_False);
172     ptsol.SetParameters(U1,V1,U2,V2);
173     ptsol.SetParameter(first);
174     alig->AddVertex(ptsol);
175     alig->SetFirstPoint(alig->NbVertex());
176   }
177   else if (!procl) {
178     Quad1.Parameters(ptl,U1,V1);
179     Quad2.Parameters(ptl,U2,V2);
180     ptsol.SetValue(ptl,Tol,Standard_False);
181     ptsol.SetParameters(U1,V1,U2,V2);
182     ptsol.SetParameter(last);
183     alig->AddVertex(ptsol);
184     alig->SetLastPoint(alig->NbVertex());
185   }
186 }
187 //=======================================================================
188 //function : IntCyCy
189 //purpose  : 
190 //=======================================================================
191 Standard_Boolean IntCyCy(const IntSurf_Quadric& Quad1,
192                          const IntSurf_Quadric& Quad2,
193                          const Standard_Real Tol,
194                          Standard_Boolean& Empty,
195                          Standard_Boolean& Same,
196                          Standard_Boolean& Multpoint,
197                          IntPatch_SequenceOfLine& slin,
198                          IntPatch_SequenceOfPoint& spnt)
199
200 {
201   IntPatch_Point ptsol;
202
203   Standard_Integer i;
204
205   IntSurf_TypeTrans trans1,trans2;
206   IntAna_ResultType typint;
207
208   gp_Elips elipsol;
209   gp_Lin linsol;
210
211   gp_Cylinder Cy1(Quad1.Cylinder());
212   gp_Cylinder Cy2(Quad2.Cylinder());
213
214   IntAna_QuadQuadGeo inter(Cy1,Cy2,Tol);
215
216   if (!inter.IsDone())
217   {
218     return Standard_False;
219   }
220
221   typint = inter.TypeInter();
222   Standard_Integer NbSol = inter.NbSolutions();
223   Empty = Standard_False;
224   Same  = Standard_False;
225
226   switch (typint)
227   {
228   case IntAna_Empty:
229     {
230       Empty = Standard_True;
231     }
232     break;
233
234   case IntAna_Same:
235     {
236       Same  = Standard_True;
237     }
238     break;
239     
240   case IntAna_Point:
241     {
242       gp_Pnt psol(inter.Point(1));
243       Standard_Real U1,V1,U2,V2;
244       Quad1.Parameters(psol,U1,V1);
245       Quad2.Parameters(psol,U2,V2);
246       ptsol.SetValue(psol,Tol,Standard_True);
247       ptsol.SetParameters(U1,V1,U2,V2);
248       spnt.Append(ptsol);
249     }
250     break;
251
252   case IntAna_Line:
253     {
254       gp_Pnt ptref;
255       if (NbSol == 1)
256       { // Cylinders are tangent to each other by line
257         linsol = inter.Line(1);
258         ptref = linsol.Location();
259         gp_Dir crb1(gp_Vec(ptref,Cy1.Location()));
260         gp_Dir crb2(gp_Vec(ptref,Cy2.Location()));
261         gp_Vec norm1(Quad1.Normale(ptref));
262         gp_Vec norm2(Quad2.Normale(ptref));
263         IntSurf_Situation situcyl1;
264         IntSurf_Situation situcyl2;
265
266         if (crb1.Dot(crb2) < 0.)
267         { // centre de courbures "opposes"
268           if (norm1.Dot(crb1) > 0.)
269           {
270             situcyl2 = IntSurf_Inside;
271           }
272           else
273           {
274             situcyl2 = IntSurf_Outside;
275           }
276
277           if (norm2.Dot(crb2) > 0.)
278           {
279             situcyl1 = IntSurf_Inside;
280           }
281           else
282           {
283             situcyl1 = IntSurf_Outside;
284           }
285         }
286         else
287         {
288           if (Cy1.Radius() < Cy2.Radius())
289           {
290             if (norm1.Dot(crb1) > 0.)
291             {
292               situcyl2 = IntSurf_Inside;
293             }
294             else
295             {
296               situcyl2 = IntSurf_Outside;
297             }
298
299             if (norm2.Dot(crb2) > 0.)
300             {
301               situcyl1 = IntSurf_Outside;
302             }
303             else
304             {
305               situcyl1 = IntSurf_Inside;
306             }
307           }
308           else
309           {
310             if (norm1.Dot(crb1) > 0.)
311             {
312               situcyl2 = IntSurf_Outside;
313             }
314             else
315             {
316               situcyl2 = IntSurf_Inside;
317             }
318
319             if (norm2.Dot(crb2) > 0.)
320             {
321               situcyl1 = IntSurf_Inside;
322             }
323             else
324             {
325               situcyl1 = IntSurf_Outside;
326             }
327           }
328         }
329
330         Handle(IntPatch_GLine) glig =  new IntPatch_GLine(linsol, Standard_True, situcyl1, situcyl2);
331         slin.Append(glig);
332       }
333       else
334       {
335         for (i=1; i <= NbSol; i++)
336         {
337           linsol = inter.Line(i);
338           ptref = linsol.Location();
339           gp_Vec lsd = linsol.Direction();
340           Standard_Real qwe = lsd.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
341           if (qwe >0.00000001)
342           {
343             trans1 = IntSurf_Out;
344             trans2 = IntSurf_In;
345           }
346           else if (qwe <-0.00000001)
347           {
348             trans1 = IntSurf_In;
349             trans2 = IntSurf_Out;
350           }
351           else
352           {
353             trans1=trans2=IntSurf_Undecided;
354           }
355
356           Handle(IntPatch_GLine) glig = new IntPatch_GLine(linsol, Standard_False,trans1,trans2);
357           slin.Append(glig);
358         }
359       }
360     }
361     break;
362     
363   case IntAna_Ellipse:
364     {
365       gp_Vec Tgt;
366       gp_Pnt ptref;
367       IntPatch_Point pmult1, pmult2;
368       
369       elipsol = inter.Ellipse(1);
370       
371       gp_Pnt pttang1(ElCLib::Value(0.5*M_PI, elipsol));
372       gp_Pnt pttang2(ElCLib::Value(1.5*M_PI, elipsol));
373       
374       Multpoint = Standard_True;
375       pmult1.SetValue(pttang1,Tol,Standard_True);
376       pmult2.SetValue(pttang2,Tol,Standard_True);
377       pmult1.SetMultiple(Standard_True);
378       pmult2.SetMultiple(Standard_True);
379       
380       Standard_Real oU1,oV1,oU2,oV2;
381       Quad1.Parameters(pttang1,oU1,oV1); 
382       Quad2.Parameters(pttang1,oU2,oV2);
383       pmult1.SetParameters(oU1,oV1,oU2,oV2);
384
385       Quad1.Parameters(pttang2,oU1,oV1); 
386       Quad2.Parameters(pttang2,oU2,oV2);
387       pmult2.SetParameters(oU1,oV1,oU2,oV2);
388       
389       // on traite la premiere ellipse
390
391       //-- Calcul de la Transition de la ligne 
392       ElCLib::D1(0.,elipsol,ptref,Tgt);
393       Standard_Real qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
394       if (qwe>0.00000001)
395       {
396         trans1 = IntSurf_Out;
397         trans2 = IntSurf_In;
398       }
399       else if (qwe<-0.00000001)
400       {
401         trans1 = IntSurf_In;
402         trans2 = IntSurf_Out;
403       }
404       else
405       { 
406         trans1=trans2=IntSurf_Undecided; 
407       }
408
409       //-- Transition calculee au point 0 -> Trans2 , Trans1 
410       //-- car ici, on devarit calculer en PI
411       Handle(IntPatch_GLine) glig = new IntPatch_GLine(elipsol,Standard_False,trans2,trans1);
412       //
413       {
414         Standard_Real aU1, aV1, aU2, aV2;
415         IntPatch_Point aIP;
416         gp_Pnt aP (ElCLib::Value(0., elipsol));
417         //
418         aIP.SetValue(aP,Tol,Standard_False);
419         aIP.SetMultiple(Standard_False);
420         //
421         Quad1.Parameters(aP, aU1, aV1); 
422         Quad2.Parameters(aP, aU2, aV2);
423         aIP.SetParameters(aU1, aV1, aU2, aV2);
424         //
425         aIP.SetParameter(0.);
426         glig->AddVertex(aIP);
427         glig->SetFirstPoint(1);
428         //
429         aIP.SetParameter(2.*M_PI);
430         glig->AddVertex(aIP);
431         glig->SetLastPoint(2);
432       }
433       //
434       pmult1.SetParameter(0.5*M_PI);
435       glig->AddVertex(pmult1);
436       //
437       pmult2.SetParameter(1.5*M_PI);
438       glig->AddVertex(pmult2);
439      
440       //
441       slin.Append(glig);
442       
443       //-- Transitions calculee au point 0    OK
444       //
445       // on traite la deuxieme ellipse
446       elipsol = inter.Ellipse(2);
447
448       Standard_Real param1 = ElCLib::Parameter(elipsol,pttang1);
449       Standard_Real param2 = ElCLib::Parameter(elipsol,pttang2);
450       Standard_Real parampourtransition = 0.0;
451       if (param1 < param2)
452       {
453         pmult1.SetParameter(0.5*M_PI);
454         pmult2.SetParameter(1.5*M_PI);
455         parampourtransition = M_PI;
456       }
457       else {
458         pmult1.SetParameter(1.5*M_PI);
459         pmult2.SetParameter(0.5*M_PI);
460         parampourtransition = 0.0;
461       }
462       
463       //-- Calcul des transitions de ligne pour la premiere ligne 
464       ElCLib::D1(parampourtransition,elipsol,ptref,Tgt);      
465       qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
466       if(qwe> 0.00000001)
467       {
468         trans1 = IntSurf_Out;
469         trans2 = IntSurf_In;
470       }
471       else if(qwe< -0.00000001)
472       {
473         trans1 = IntSurf_In;
474         trans2 = IntSurf_Out;
475       }
476       else
477       { 
478         trans1=trans2=IntSurf_Undecided;
479       }
480
481       //-- La transition a ete calculee sur un point de cette ligne 
482       glig = new IntPatch_GLine(elipsol,Standard_False,trans1,trans2);
483       //
484       {
485         Standard_Real aU1, aV1, aU2, aV2;
486         IntPatch_Point aIP;
487         gp_Pnt aP (ElCLib::Value(0., elipsol));
488         //
489         aIP.SetValue(aP,Tol,Standard_False);
490         aIP.SetMultiple(Standard_False);
491         //
492         Quad1.Parameters(aP, aU1, aV1); 
493         Quad2.Parameters(aP, aU2, aV2);
494         aIP.SetParameters(aU1, aV1, aU2, aV2);
495         //
496         aIP.SetParameter(0.);
497         glig->AddVertex(aIP);
498         glig->SetFirstPoint(1);
499         //
500         aIP.SetParameter(2.*M_PI);
501         glig->AddVertex(aIP);
502         glig->SetLastPoint(2);
503       }
504       //
505       glig->AddVertex(pmult1);
506       glig->AddVertex(pmult2);
507       //
508       slin.Append(glig);
509     }
510     break;
511
512   case IntAna_NoGeometricSolution:
513     {
514       Standard_Boolean bReverse;
515       Standard_Real U1,V1,U2,V2;
516       gp_Pnt psol;
517       //
518       bReverse=IsToReverse(Cy1, Cy2, Tol);
519       if (bReverse)
520       {
521         Cy2=Quad1.Cylinder();
522         Cy1=Quad2.Cylinder();
523       }
524       //
525       IntAna_IntQuadQuad anaint(Cy1,Cy2,Tol);
526       if (!anaint.IsDone())
527       {
528         return Standard_False;
529       }
530       
531       if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0)
532       {
533         Empty = Standard_True;
534       }
535       else
536       {
537         NbSol = anaint.NbPnt();
538         for (i = 1; i <= NbSol; i++)
539         {
540           psol = anaint.Point(i);
541           Quad1.Parameters(psol,U1,V1);
542           Quad2.Parameters(psol,U2,V2);
543           ptsol.SetValue(psol,Tol,Standard_True);
544           ptsol.SetParameters(U1,V1,U2,V2);
545           spnt.Append(ptsol);
546         }
547
548         gp_Pnt ptvalid, ptf, ptl;
549         gp_Vec tgvalid;
550
551         Standard_Real first,last,para;
552         IntAna_Curve curvsol;
553         Standard_Boolean tgfound;
554         Standard_Integer kount;
555
556         NbSol = anaint.NbCurve();
557         for (i = 1; i <= NbSol; i++)
558         {
559           curvsol = anaint.Curve(i);
560           curvsol.Domain(first,last);
561           ptf = curvsol.Value(first);
562           ptl = curvsol.Value(last);
563
564           para = last;
565           kount = 1;
566           tgfound = Standard_False;
567
568           while (!tgfound)
569           {
570             para = (1.123*first + para)/2.123;
571             tgfound = curvsol.D1u(para,ptvalid,tgvalid);
572             if (!tgfound)
573             {
574               kount ++;
575               tgfound = kount > 5;
576             }
577           }
578
579           Handle(IntPatch_ALine) alig;
580           if (kount <= 5)
581           {
582             Standard_Real qwe = tgvalid.DotCross( Quad2.Normale(ptvalid),
583                                                   Quad1.Normale(ptvalid));
584             if(qwe>0.00000001)
585             { 
586               trans1 = IntSurf_Out;
587               trans2 = IntSurf_In;
588             }
589             else if(qwe<-0.00000001)
590             {
591               trans1 = IntSurf_In;
592               trans2 = IntSurf_Out;
593             }
594             else
595             { 
596               trans1=trans2=IntSurf_Undecided; 
597             }
598             alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
599           }
600           else
601           {
602             alig = new IntPatch_ALine(curvsol,Standard_False);
603             //-- cout << "Transition indeterminee" << endl;
604           }
605
606           Standard_Boolean TempFalse1 = Standard_False;
607           Standard_Boolean TempFalse2 = Standard_False;
608
609           ProcessBounds(alig,slin,Quad1,Quad2,TempFalse1,ptf,first,
610                         TempFalse2,ptl,last,Multpoint,Tol);
611           slin.Append(alig);
612         }
613       }
614     }
615     break;
616
617   default:
618     return Standard_False;
619   }
620
621   return Standard_True;
622 }
623
624 //=======================================================================
625 //function : ShortCosForm
626 //purpose  : Represents theCosFactor*cosA+theSinFactor*sinA as
627 //            theCoeff*cos(A-theAngle) if it is possibly (all angles are
628 //            in radians).
629 //=======================================================================
630 static void ShortCosForm( const Standard_Real theCosFactor,
631                           const Standard_Real theSinFactor,
632                           Standard_Real& theCoeff,
633                           Standard_Real& theAngle)
634 {
635   theCoeff = sqrt(theCosFactor*theCosFactor+theSinFactor*theSinFactor);
636   theAngle = 0.0;
637   if(IsEqual(theCoeff, 0.0))
638   {
639     theAngle = 0.0;
640     return;
641   }
642
643   theAngle = acos(Abs(theCosFactor/theCoeff));
644
645   if(theSinFactor > 0.0)
646   {
647     if(IsEqual(theCosFactor, 0.0))
648     {
649       theAngle = M_PI/2.0;
650     }
651     else if(theCosFactor < 0.0)
652     {
653       theAngle = M_PI-theAngle;
654     }
655   }
656   else if(IsEqual(theSinFactor, 0.0))
657   {
658     if(theCosFactor < 0.0)
659     {
660       theAngle = M_PI;
661     }
662   }
663   if(theSinFactor < 0.0)
664   {
665     if(theCosFactor > 0.0)
666     {
667       theAngle = 2.0*M_PI-theAngle;
668     }
669     else if(IsEqual(theCosFactor, 0.0))
670     {
671       theAngle = 3.0*M_PI/2.0;
672     }
673     else if(theCosFactor < 0.0)
674     {
675       theAngle = M_PI+theAngle;
676     }
677   }
678 }
679
680 enum SearchBoundType
681 {
682   SearchNONE = 0,
683   SearchV1 = 1,
684   SearchV2 = 2
685 };
686
687 //Stores equations coefficients
688 struct stCoeffsValue
689 {
690   stCoeffsValue(const gp_Cylinder&, const gp_Cylinder&);
691
692   gp_Vec mVecA1;
693   gp_Vec mVecA2;
694   gp_Vec mVecB1;
695   gp_Vec mVecB2;
696   gp_Vec mVecC1;
697   gp_Vec mVecC2;
698   gp_Vec mVecD;
699
700   Standard_Real mK21; //sinU2
701   Standard_Real mK11; //sinU1
702   Standard_Real mL21; //cosU2
703   Standard_Real mL11;  //cosU1
704   Standard_Real mM1;  //Free member
705
706   Standard_Real mK22; //sinU2
707   Standard_Real mK12; //sinU1
708   Standard_Real mL22; //cosU2
709   Standard_Real mL12; //cosU1
710   Standard_Real mM2; //Free member
711   
712   Standard_Real mK1;
713   Standard_Real mL1;
714   Standard_Real mK2;
715   Standard_Real mL2;
716
717   Standard_Real mFIV1;
718   Standard_Real mPSIV1;
719   Standard_Real mFIV2;
720   Standard_Real mPSIV2;
721
722   Standard_Real mB;
723   Standard_Real mC;
724   Standard_Real mFI1;
725   Standard_Real mFI2;
726 };
727
728 stCoeffsValue::stCoeffsValue( const gp_Cylinder& theCyl1,
729                               const gp_Cylinder& theCyl2)
730 {
731   const Standard_Real aNulValue = 0.01*Precision::PConfusion();
732
733   mVecA1 = -theCyl1.Radius()*theCyl1.XAxis().Direction();
734   mVecA2 = theCyl2.Radius()*theCyl2.XAxis().Direction();
735
736   mVecB1 = -theCyl1.Radius()*theCyl1.YAxis().Direction();
737   mVecB2 = theCyl2.Radius()*theCyl2.YAxis().Direction();
738
739   mVecC1 = theCyl1.Axis().Direction();
740   mVecC2 = -(theCyl2.Axis().Direction());
741
742   mVecD = theCyl2.Location().XYZ() - theCyl1.Location().XYZ();
743
744   enum CoupleOfEquation
745   {
746     COENONE = 0,
747     COE12 = 1,
748     COE23 = 2,
749     COE13 = 3
750   }aFoundCouple = COENONE;
751
752
753   Standard_Real aDetV1V2 = 0.0;
754   
755   const Standard_Real aDelta1 = mVecC1.X()*mVecC2.Y()-mVecC1.Y()*mVecC2.X(); //1-2
756   const Standard_Real aDelta2 = mVecC1.Y()*mVecC2.Z()-mVecC1.Z()*mVecC2.Y(); //2-3
757   const Standard_Real aDelta3 = mVecC1.X()*mVecC2.Z()-mVecC1.Z()*mVecC2.X(); //1-3
758   const Standard_Real anAbsD1 = Abs(aDelta1); //1-2
759   const Standard_Real anAbsD2 = Abs(aDelta2); //2-3
760   const Standard_Real anAbsD3 = Abs(aDelta3); //1-3
761
762   if(anAbsD1 >= anAbsD2)
763   {
764     if(anAbsD3 > anAbsD1)
765     {
766       aFoundCouple = COE13;
767       aDetV1V2 = aDelta3;
768     }
769     else
770     {
771       aFoundCouple = COE12;
772       aDetV1V2 = aDelta1;
773     }
774   }
775   else
776   {
777     if(anAbsD3 > anAbsD2)
778     {
779       aFoundCouple = COE13;
780       aDetV1V2 = aDelta3;
781     }
782     else
783     {
784       aFoundCouple = COE23;
785       aDetV1V2 = aDelta2;
786     }
787   }
788
789   if(Abs(aDetV1V2) < aNulValue)
790   {
791     Standard_Failure::Raise("Error. Exception in divide by zerro (IntCyCyTrim)!!!!");
792   }
793
794   switch(aFoundCouple)
795   {
796   case COE12:
797     break;
798   case COE23:
799     {
800       gp_Vec aVTemp = mVecA1;
801       mVecA1.SetX(aVTemp.Y());
802       mVecA1.SetY(aVTemp.Z());
803       mVecA1.SetZ(aVTemp.X());
804
805       aVTemp = mVecA2;
806       mVecA2.SetX(aVTemp.Y());
807       mVecA2.SetY(aVTemp.Z());
808       mVecA2.SetZ(aVTemp.X());
809
810       aVTemp = mVecB1;
811       mVecB1.SetX(aVTemp.Y());
812       mVecB1.SetY(aVTemp.Z());
813       mVecB1.SetZ(aVTemp.X());
814       
815       aVTemp = mVecB2;
816       mVecB2.SetX(aVTemp.Y());
817       mVecB2.SetY(aVTemp.Z());
818       mVecB2.SetZ(aVTemp.X());
819
820       aVTemp = mVecC1;
821       mVecC1.SetX(aVTemp.Y());
822       mVecC1.SetY(aVTemp.Z());
823       mVecC1.SetZ(aVTemp.X());
824
825       aVTemp = mVecC2;
826       mVecC2.SetX(aVTemp.Y());
827       mVecC2.SetY(aVTemp.Z());
828       mVecC2.SetZ(aVTemp.X());
829
830       aVTemp = mVecD;
831       mVecD.SetX(aVTemp.Y());
832       mVecD.SetY(aVTemp.Z());
833       mVecD.SetZ(aVTemp.X());
834
835       break;
836     }
837   case COE13:
838     {
839       gp_Vec aVTemp = mVecA1;
840       mVecA1.SetY(aVTemp.Z());
841       mVecA1.SetZ(aVTemp.Y());
842
843       aVTemp = mVecA2;
844       mVecA2.SetY(aVTemp.Z());
845       mVecA2.SetZ(aVTemp.Y());
846
847       aVTemp = mVecB1;
848       mVecB1.SetY(aVTemp.Z());
849       mVecB1.SetZ(aVTemp.Y());
850
851       aVTemp = mVecB2;
852       mVecB2.SetY(aVTemp.Z());
853       mVecB2.SetZ(aVTemp.Y());
854
855       aVTemp = mVecC1;
856       mVecC1.SetY(aVTemp.Z());
857       mVecC1.SetZ(aVTemp.Y());
858
859       aVTemp = mVecC2;
860       mVecC2.SetY(aVTemp.Z());
861       mVecC2.SetZ(aVTemp.Y());
862
863       aVTemp = mVecD;
864       mVecD.SetY(aVTemp.Z());
865       mVecD.SetZ(aVTemp.Y());
866
867       break;
868     }
869   default:
870     break;
871   }
872
873   //------- For V1 (begin)
874   //sinU2
875   mK21 = (mVecC2.Y()*mVecB2.X()-mVecC2.X()*mVecB2.Y())/aDetV1V2;
876   //sinU1
877   mK11 = (mVecC2.Y()*mVecB1.X()-mVecC2.X()*mVecB1.Y())/aDetV1V2;
878   //cosU2
879   mL21 = (mVecC2.Y()*mVecA2.X()-mVecC2.X()*mVecA2.Y())/aDetV1V2;
880   //cosU1
881   mL11 = (mVecC2.Y()*mVecA1.X()-mVecC2.X()*mVecA1.Y())/aDetV1V2;
882   //Free member
883   mM1 = (mVecC2.Y()*mVecD.X()-mVecC2.X()*mVecD.Y())/aDetV1V2;
884   //------- For V1 (end)
885
886   //------- For V2 (begin)
887   //sinU2
888   mK22 = (mVecC1.X()*mVecB2.Y()-mVecC1.Y()*mVecB2.X())/aDetV1V2;
889   //sinU1
890   mK12 = (mVecC1.X()*mVecB1.Y()-mVecC1.Y()*mVecB1.X())/aDetV1V2;
891   //cosU2
892   mL22 = (mVecC1.X()*mVecA2.Y()-mVecC1.Y()*mVecA2.X())/aDetV1V2;
893   //cosU1
894   mL12 = (mVecC1.X()*mVecA1.Y()-mVecC1.Y()*mVecA1.X())/aDetV1V2;
895   //Free member
896   mM2 = (mVecC1.X()*mVecD.Y()-mVecC1.Y()*mVecD.X())/aDetV1V2;
897   //------- For V1 (end)
898
899   ShortCosForm(mL11, mK11, mK1, mFIV1);
900   ShortCosForm(mL21, mK21, mL1, mPSIV1);
901   ShortCosForm(mL12, mK12, mK2, mFIV2);
902   ShortCosForm(mL22, mK22, mL2, mPSIV2);
903
904   const Standard_Real aA1=mVecC1.Z()*mK21+mVecC2.Z()*mK22-mVecB2.Z(), //sinU2
905                       aA2=mVecC1.Z()*mL21+mVecC2.Z()*mL22-mVecA2.Z(), //cosU2
906                       aB1=mVecB1.Z()-mVecC1.Z()*mK11-mVecC2.Z()*mK12, //sinU1
907                       aB2=mVecA1.Z()-mVecC1.Z()*mL11-mVecC2.Z()*mL12; //cosU1
908
909   mC =mVecD.Z() -mVecC1.Z()*mM1 -mVecC2.Z()*mM2;  //Free
910
911   Standard_Real aA = 0.0;
912
913   ShortCosForm(aB2,aB1,mB,mFI1);
914   ShortCosForm(aA2,aA1,aA,mFI2);
915
916   mB /= aA;
917   mC /= aA;
918 }
919
920 //=======================================================================
921 //function : SearchOnVBounds
922 //purpose  : 
923 //=======================================================================
924 static Standard_Boolean SearchOnVBounds(const SearchBoundType theSBType,
925                                         const stCoeffsValue& theCoeffs,
926                                         const Standard_Real theVzad,
927                                         const Standard_Real theInitU2,
928                                         const Standard_Real theInitMainVar,
929                                         Standard_Real& theMainVariableValue)
930 {
931   const Standard_Real aMaxError = 4.0*M_PI; // two periods
932   
933   theMainVariableValue = RealLast();
934   const Standard_Real aTol2 = Precision::PConfusion()*Precision::PConfusion();
935   Standard_Real aMainVarPrev = theInitMainVar, aU2Prev = theInitU2, anOtherVar = theVzad;
936   
937   Standard_Real anError = RealLast();
938   Standard_Integer aNbIter = 0;
939   do
940   {
941     if(++aNbIter > 1000)
942       return Standard_False;
943
944     gp_Vec aVecMainVar = theCoeffs.mVecA1 * sin(aMainVarPrev) - theCoeffs.mVecB1 * cos(aMainVarPrev);
945     gp_Vec aVecFreeMem =  (theCoeffs.mVecA2 * aU2Prev + theCoeffs.mVecB2) * sin(aU2Prev) -
946                           (theCoeffs.mVecB2 * aU2Prev - theCoeffs.mVecA2) * cos(aU2Prev) +
947                           (theCoeffs.mVecA1 * aMainVarPrev + theCoeffs.mVecB1) * sin(aMainVarPrev) -
948                           (theCoeffs.mVecB1 * aMainVarPrev - theCoeffs.mVecA1) * cos(aMainVarPrev) + theCoeffs.mVecD;
949
950     gp_Vec aVecVar1 = theCoeffs.mVecA2 * sin(aU2Prev) - theCoeffs.mVecB2 * cos(aU2Prev);
951     gp_Vec aVecVar2;
952
953     switch(theSBType)
954     {
955     case SearchV1:
956       aVecVar2 = theCoeffs.mVecC2;
957       aVecFreeMem -= theCoeffs.mVecC1 * theVzad;
958       break;
959
960     case SearchV2:
961       aVecVar2 = theCoeffs.mVecC1;
962       aVecFreeMem -= theCoeffs.mVecC2 * theVzad;
963       break;
964
965     default:
966       return Standard_False;
967     }
968
969     Standard_Real aDetMainSyst =  aVecMainVar.X()*(aVecVar1.Y()*aVecVar2.Z()-aVecVar1.Z()*aVecVar2.Y())-
970                                   aVecMainVar.Y()*(aVecVar1.X()*aVecVar2.Z()-aVecVar1.Z()*aVecVar2.X())+
971                                   aVecMainVar.Z()*(aVecVar1.X()*aVecVar2.Y()-aVecVar1.Y()*aVecVar2.X());
972
973     if(IsEqual(aDetMainSyst, 0.0))
974     {
975       return Standard_False;
976     }
977
978   
979     Standard_Real aDetMainVar = aVecFreeMem.X()*(aVecVar1.Y()*aVecVar2.Z()-aVecVar1.Z()*aVecVar2.Y())-
980                                 aVecFreeMem.Y()*(aVecVar1.X()*aVecVar2.Z()-aVecVar1.Z()*aVecVar2.X())+
981                                 aVecFreeMem.Z()*(aVecVar1.X()*aVecVar2.Y()-aVecVar1.Y()*aVecVar2.X());
982
983     Standard_Real aDetVar1    = aVecMainVar.X()*(aVecFreeMem.Y()*aVecVar2.Z()-aVecFreeMem.Z()*aVecVar2.Y())-
984                                 aVecMainVar.Y()*(aVecFreeMem.X()*aVecVar2.Z()-aVecFreeMem.Z()*aVecVar2.X())+
985                                 aVecMainVar.Z()*(aVecFreeMem.X()*aVecVar2.Y()-aVecFreeMem.Y()*aVecVar2.X());
986
987     Standard_Real aDetVar2    = aVecMainVar.X()*(aVecVar1.Y()*aVecFreeMem.Z()-aVecVar1.Z()*aVecFreeMem.Y())-
988                                 aVecMainVar.Y()*(aVecVar1.X()*aVecFreeMem.Z()-aVecVar1.Z()*aVecFreeMem.X())+
989                                 aVecMainVar.Z()*(aVecVar1.X()*aVecFreeMem.Y()-aVecVar1.Y()*aVecFreeMem.X());
990
991     Standard_Real aDelta = aDetMainVar/aDetMainSyst-aMainVarPrev;
992
993     if(Abs(aDelta) > aMaxError)
994       return Standard_False;
995
996     anError = aDelta*aDelta;
997     aMainVarPrev += aDelta;
998         
999     ///
1000     aDelta = aDetVar1/aDetMainSyst-aU2Prev;
1001
1002     if(Abs(aDelta) > aMaxError)
1003       return Standard_False;
1004
1005     anError += aDelta*aDelta;
1006     aU2Prev += aDelta;
1007
1008     ///
1009     aDelta = aDetVar2/aDetMainSyst-anOtherVar;
1010     anError += aDelta*aDelta;
1011     anOtherVar += aDelta;
1012   }
1013   while(anError > aTol2);
1014
1015   theMainVariableValue = aMainVarPrev;
1016
1017   return Standard_True;
1018 }
1019
1020 //=======================================================================
1021 //function : InscribePoint
1022 //purpose  : If theFlForce==TRUE theUGiven will be changed forcefully
1023 //            even if theUGiven is already inscibed in the boundary
1024 //            (if it is possible; i.e. if new theUGiven is inscribed
1025 //            in the boundary, too).
1026 //=======================================================================
1027 static Standard_Boolean InscribePoint(const Standard_Real theUfTarget,
1028                                       const Standard_Real theUlTarget,
1029                                       Standard_Real& theUGiven,
1030                                       const Standard_Real theTol2D,
1031                                       const Standard_Real thePeriod,
1032                                       const Standard_Boolean theFlForce)
1033 {
1034   if((theUfTarget - theUGiven <= theTol2D) &&
1035               (theUGiven - theUlTarget <= theTol2D))
1036   {//it has already inscribed
1037
1038     /*
1039              Utf    U      Utl
1040               +     *       +
1041     */
1042     
1043     if(theFlForce)
1044     {
1045       Standard_Real anUtemp = theUGiven + thePeriod;
1046       if((theUfTarget - anUtemp <= theTol2D) &&
1047                 (anUtemp - theUlTarget <= theTol2D))
1048       {
1049         theUGiven = anUtemp;
1050         return Standard_True;
1051       }
1052       
1053       anUtemp = theUGiven - thePeriod;
1054       if((theUfTarget - anUtemp <= theTol2D) &&
1055                 (anUtemp - theUlTarget <= theTol2D))
1056       {
1057         theUGiven = anUtemp;
1058       }
1059     }
1060
1061     return Standard_True;
1062   }
1063
1064   if(IsEqual(thePeriod, 0.0))
1065   {//it cannot be inscribed
1066     return Standard_False;
1067   }
1068
1069   Standard_Real aDU = theUGiven - theUfTarget;
1070
1071   if(aDU > 0.0)
1072     aDU = -thePeriod;
1073   else
1074     aDU = +thePeriod;
1075
1076   while(((theUGiven - theUfTarget)*aDU < 0.0) && !((theUfTarget - theUGiven <= theTol2D) && (theUGiven - theUlTarget <= theTol2D)))
1077   {
1078     theUGiven += aDU;
1079   }
1080   
1081   return ((theUfTarget - theUGiven <= theTol2D) && (theUGiven - theUlTarget <= theTol2D));
1082 }
1083
1084 //=======================================================================
1085 //function : InscribeInterval
1086 //purpose  : Adjusts theUfGiven and after that fits theUlGiven to result
1087 //=======================================================================
1088 static Standard_Boolean InscribeInterval(const Standard_Real theUfTarget,
1089                                       const Standard_Real theUlTarget,
1090                                       Standard_Real& theUfGiven,
1091                                       Standard_Real& theUlGiven,
1092                                       const Standard_Real theTol2D,
1093                                       const Standard_Real thePeriod)
1094 {
1095   Standard_Real anUpar = theUfGiven;
1096   const Standard_Real aDelta = theUlGiven - theUfGiven;
1097   if(InscribePoint(theUfTarget, theUlTarget, anUpar,
1098                         theTol2D, thePeriod, Standard_False))
1099   {
1100     theUfGiven = anUpar;
1101     theUlGiven = theUfGiven + aDelta;
1102   }
1103   else 
1104   {
1105     anUpar = theUlGiven;
1106     if(InscribePoint(theUfTarget, theUlTarget, anUpar,
1107                         theTol2D, thePeriod, Standard_False))
1108     {
1109       theUlGiven = anUpar;
1110       theUfGiven = theUlGiven - aDelta;
1111     }
1112     else
1113     {
1114       return Standard_False;
1115     }
1116   }
1117
1118   return Standard_True;
1119 }
1120
1121 //=======================================================================
1122 //function : InscribeAndSortArray
1123 //purpose  : Sort from Min to Max value
1124 //=======================================================================
1125 static void InscribeAndSortArray( Standard_Real theArr[],
1126                                   const Standard_Integer theNOfMembers,
1127                                   const Standard_Real theUf,
1128                                   const Standard_Real theUl,
1129                                   const Standard_Real theTol2D,
1130                                   const Standard_Real thePeriod)
1131 {
1132   for(Standard_Integer i = 0; i < theNOfMembers; i++)
1133   {
1134     if(Precision::IsInfinite(theArr[i]))
1135     {
1136       if(theArr[i] < 0.0)
1137         theArr[i] = -theArr[i];
1138
1139       continue;
1140     }
1141
1142     InscribePoint(theUf, theUl, theArr[i], theTol2D, thePeriod, Standard_False);
1143
1144     for(Standard_Integer j = i - 1; j >= 0; j--)
1145     {
1146
1147       if(theArr[j+1] < theArr[j])
1148       {
1149         Standard_Real anUtemp = theArr[j+1];
1150         theArr[j+1] = theArr[j];
1151         theArr[j] = anUtemp;
1152       }
1153     }
1154   }
1155 }
1156
1157
1158 //=======================================================================
1159 //function : AddPointIntoWL
1160 //purpose  : Surf1 is a surface, whose U-par is variable.
1161 //=======================================================================
1162 static Standard_Boolean AddPointIntoWL( const IntSurf_Quadric& theQuad1,
1163                                         const IntSurf_Quadric& theQuad2,
1164                                         const Standard_Boolean isTheReverse,
1165                                         const gp_Pnt2d& thePntOnSurf1,
1166                                         const gp_Pnt2d& thePntOnSurf2,
1167                                         const Standard_Real theUfSurf1,
1168                                         const Standard_Real theUlSurf1,
1169                                         const Standard_Real thePeriodOfSurf1,
1170                                         const Handle(IntSurf_LineOn2S)& theLine,
1171                                         const Standard_Real theTol3D,
1172                                         const Standard_Real theTol2D,
1173                                         const Standard_Boolean theFlForce)
1174 {
1175   gp_Pnt  aPt1(theQuad1.Value(thePntOnSurf1.X(), thePntOnSurf1.Y())),
1176           aPt2(theQuad2.Value(thePntOnSurf2.X(), thePntOnSurf2.Y()));
1177
1178   Standard_Real anUpar = thePntOnSurf1.X();
1179   if(!InscribePoint(theUfSurf1, theUlSurf1, anUpar, theTol2D,
1180                                     thePeriodOfSurf1, theFlForce))
1181     return Standard_False;
1182
1183   IntSurf_PntOn2S aPnt;
1184   
1185   if(isTheReverse)
1186   {
1187     aPnt.SetValue((aPt1.XYZ()+aPt2.XYZ())/2.0,
1188                         thePntOnSurf2.X(), thePntOnSurf2.Y(),
1189                         anUpar, thePntOnSurf1.Y());
1190   }
1191   else
1192   {
1193     aPnt.SetValue((aPt1.XYZ()+aPt2.XYZ())/2.0,
1194                         anUpar, thePntOnSurf1.Y(),
1195                         thePntOnSurf2.X(), thePntOnSurf2.Y());
1196   }
1197
1198   const Standard_Integer aNbPnts = theLine->NbPoints();
1199   if(aNbPnts > 0)
1200   {
1201     Standard_Real aUl = 0.0, aVl = 0.0;
1202     const IntSurf_PntOn2S aPlast = theLine->Value(aNbPnts);
1203     if(isTheReverse)
1204       aPlast.ParametersOnS2(aUl, aVl);
1205     else
1206       aPlast.ParametersOnS1(aUl, aVl);
1207
1208     if(anUpar <= aUl)
1209     {//Parameter value will be always increased.
1210       return Standard_False;
1211     }
1212
1213     //theTol2D is minimal step along parameter changed. 
1214     //Therefore, if we apply this minimal step two 
1215     //neighbour points will be always "same". Consequently,
1216     //we should reduce tolerance for IsSame checking.
1217     const Standard_Real aDTol = 1.0-Epsilon(1.0);
1218     if(aPnt.IsSame(aPlast, theTol3D*aDTol, theTol2D*aDTol))
1219     {
1220       theLine->RemovePoint(aNbPnts);
1221     }
1222   }
1223
1224   theLine->Add(aPnt);
1225   return Standard_True;
1226 }
1227
1228 //=======================================================================
1229 //function : AddBoundaryPoint
1230 //purpose  : 
1231 //=======================================================================
1232 static Standard_Boolean AddBoundaryPoint( const IntSurf_Quadric& theQuad1,
1233                                           const IntSurf_Quadric& theQuad2,
1234                                           const Handle(IntPatch_WLine)& theWL,
1235                                           const stCoeffsValue& theCoeffs,
1236                                           const Bnd_Box2d& theUVSurf1,
1237                                           const Bnd_Box2d& theUVSurf2,
1238                                           const Standard_Real theTol3D,
1239                                           const Standard_Real theTol2D,
1240                                           const Standard_Real thePeriod,
1241                                           const Standard_Real theNulValue,
1242                                           const Standard_Real theU1,
1243                                           const Standard_Real theU2,
1244                                           const Standard_Real theV1,
1245                                           const Standard_Real theV1Prev,
1246                                           const Standard_Real theV2,
1247                                           const Standard_Real theV2Prev,
1248                                           const Standard_Boolean isTheReverse,
1249                                           const Standard_Real theArccosFactor,
1250                                           const Standard_Boolean theFlForce,
1251                                           Standard_Boolean& isTheFound1,
1252                                           Standard_Boolean& isTheFound2)
1253 {
1254   Standard_Real aUSurf1f = 0.0, //const
1255                 aUSurf1l = 0.0,
1256                 aVSurf1f = 0.0,
1257                 aVSurf1l = 0.0;
1258   Standard_Real aUSurf2f = 0.0, //const
1259                 aUSurf2l = 0.0,
1260                 aVSurf2f = 0.0,
1261                 aVSurf2l = 0.0;
1262
1263   theUVSurf1.Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l);
1264   theUVSurf2.Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l);
1265
1266   SearchBoundType aTS1 = SearchNONE, aTS2 = SearchNONE;
1267   Standard_Real aV1zad = aVSurf1f, aV2zad = aVSurf2f;
1268
1269   Standard_Real anUpar1 = theU1, anUpar2 = theU1;
1270   Standard_Real aVf = theV1, aVl = theV1Prev;
1271   MinMax(aVf, aVl);
1272   if((aVf <= aVSurf1f) && (aVSurf1f <= aVl))
1273   {
1274     aTS1 = SearchV1;
1275     aV1zad = aVSurf1f;
1276     isTheFound1 = SearchOnVBounds(aTS1, theCoeffs, aVSurf1f, theU2, theU1, anUpar1);
1277   }
1278   else if((aVf <= aVSurf1l) && (aVSurf1l <= aVl))
1279   {
1280     aTS1 = SearchV1;
1281     aV1zad = aVSurf1l;
1282     isTheFound1 = SearchOnVBounds(aTS1, theCoeffs, aVSurf1l, theU2, theU1, anUpar1);
1283   }
1284
1285   aVf = theV2;
1286   aVl = theV2Prev;
1287   MinMax(aVf, aVl);
1288
1289   if((aVf <= aVSurf2f) && (aVSurf2f <= aVl))
1290   {
1291     aTS2 = SearchV2;
1292     aV2zad = aVSurf2f;
1293     isTheFound2 = SearchOnVBounds(aTS2, theCoeffs, aVSurf2f, theU2, theU1, anUpar2);
1294   }
1295   else if((aVf <= aVSurf2l) && (aVSurf2l <= aVl))
1296   {
1297     aTS2 = SearchV2;
1298     aV2zad = aVSurf2l;
1299     isTheFound2 = SearchOnVBounds(aTS2, theCoeffs, aVSurf2l, theU2, theU1, anUpar2);
1300   }
1301
1302   if(anUpar1 < anUpar2)
1303   {
1304     if(isTheFound1)
1305     {
1306       Standard_Real anArg = theCoeffs.mB * cos(anUpar1 - theCoeffs.mFI1) + theCoeffs.mC;
1307
1308       if(theNulValue > 1.0 - anArg)
1309         anArg = 1.0;
1310       if(anArg + 1.0 < theNulValue)
1311         anArg = -1.0;
1312
1313       Standard_Real aU2 = theCoeffs.mFI2 + theArccosFactor * acos(anArg);
1314       
1315       if(InscribePoint(aUSurf2f, aUSurf2l, aU2, theTol2D, thePeriod, Standard_False))
1316       {
1317         const Standard_Real aV1 = 
1318               (aTS1 == SearchV1) ? aV1zad : 
1319                                   theCoeffs.mK21 * sin(aU2) + theCoeffs.mK11 * sin(anUpar1) +
1320                                   theCoeffs.mL21 * cos(aU2) + theCoeffs.mL11 * cos(anUpar1) + theCoeffs.mM1;
1321         const Standard_Real aV2 = 
1322               (aTS1 == SearchV2) ? aV2zad : 
1323                                   theCoeffs.mK22 * sin(aU2) + theCoeffs.mK12 * sin(anUpar1) +
1324                                   theCoeffs.mL22 * cos(aU2) + theCoeffs.mL12 * cos(anUpar1) + theCoeffs.mM2;
1325
1326         AddPointIntoWL(theQuad1, theQuad2, isTheReverse,
1327                           gp_Pnt2d(anUpar1, aV1), gp_Pnt2d(aU2, aV2),
1328                           aUSurf1f, aUSurf1l, thePeriod,
1329                           theWL->Curve(), theTol3D, theTol2D, theFlForce);
1330       }
1331       else
1332       {
1333         isTheFound1 = Standard_False;
1334       }
1335     }
1336
1337     if(isTheFound2)
1338     {
1339       Standard_Real anArg = theCoeffs.mB * cos(anUpar2 - theCoeffs.mFI1) + theCoeffs.mC;
1340
1341       if(theNulValue > 1.0 - anArg)
1342         anArg = 1.0;
1343       if(anArg + 1.0 < theNulValue)
1344         anArg = -1.0;
1345
1346       Standard_Real aU2 = theCoeffs.mFI2 + theArccosFactor * acos(anArg);
1347       if(InscribePoint(aUSurf2f, aUSurf2l, aU2, theTol2D, thePeriod, Standard_False))
1348       {
1349         const Standard_Real aV1 = 
1350               (aTS2 == SearchV1) ? aV1zad : 
1351                                   theCoeffs.mK21 * sin(aU2) + theCoeffs.mK11 * sin(anUpar2) +
1352                                   theCoeffs.mL21 * cos(aU2) + theCoeffs.mL11 * cos(anUpar2) + theCoeffs.mM1;
1353         const Standard_Real aV2 = 
1354               (aTS2 == SearchV2) ? aV2zad : 
1355                                   theCoeffs.mK22 * sin(aU2) + theCoeffs.mK12 * sin(anUpar2) +
1356                                   theCoeffs.mL22 * cos(aU2) + theCoeffs.mL12 * cos(anUpar2) + theCoeffs.mM2;
1357
1358         AddPointIntoWL(theQuad1, theQuad2, isTheReverse,
1359                         gp_Pnt2d(anUpar2, aV1), gp_Pnt2d(aU2, aV2),
1360                         aUSurf1f, aUSurf1l, thePeriod,
1361                         theWL->Curve(),theTol3D, theTol2D, theFlForce);
1362       }
1363       else
1364       {
1365         isTheFound2 = Standard_False;
1366       }
1367     }
1368   }
1369   else
1370   {
1371     if(isTheFound2)
1372     {
1373       Standard_Real anArg = theCoeffs.mB * cos(anUpar2 - theCoeffs.mFI1) + theCoeffs.mC;
1374
1375       if(theNulValue > 1.0 - anArg)
1376         anArg = 1.0;
1377       if(anArg + 1.0 < theNulValue)
1378         anArg = -1.0;
1379
1380       Standard_Real aU2 = theCoeffs.mFI2 + theArccosFactor * acos(anArg);
1381       
1382       if(InscribePoint(aUSurf2f, aUSurf2l, aU2, theTol2D, thePeriod, Standard_False))
1383       {
1384         const Standard_Real aV1 = (aTS2 == SearchV1) ? aV1zad : 
1385                                   theCoeffs.mK21 * sin(aU2) + theCoeffs.mK11 * sin(anUpar2) +
1386                                   theCoeffs.mL21 * cos(aU2) + theCoeffs.mL11 * cos(anUpar2) + theCoeffs.mM1;
1387         const Standard_Real aV2 = (aTS2 == SearchV2) ? aV2zad : 
1388                                   theCoeffs.mK22 * sin(aU2) + theCoeffs.mK12 * sin(anUpar2) +
1389                                   theCoeffs.mL22 * cos(aU2) + theCoeffs.mL12 * cos(anUpar2) + theCoeffs.mM2;
1390
1391         AddPointIntoWL(theQuad1, theQuad2, isTheReverse, 
1392                         gp_Pnt2d(anUpar2, aV1), gp_Pnt2d(aU2, aV2),
1393                         aUSurf1f, aUSurf1l, thePeriod,
1394                         theWL->Curve(), theTol3D, theTol2D, theFlForce);
1395       }
1396       else
1397       {
1398         isTheFound2 = Standard_False;
1399       }
1400     }
1401
1402     if(isTheFound1)
1403     {
1404       Standard_Real anArg = theCoeffs.mB*cos(anUpar1-theCoeffs.mFI1)+theCoeffs.mC;
1405
1406       if(theNulValue > 1.0 - anArg)
1407         anArg = 1.0;
1408       if(anArg + 1.0 < theNulValue)
1409         anArg = -1.0;
1410
1411       Standard_Real aU2 = theCoeffs.mFI2+theArccosFactor*acos(anArg);
1412       if(InscribePoint(aUSurf2f, aUSurf2l, aU2, theTol2D, thePeriod, Standard_False))
1413       {
1414         const Standard_Real aV1 = (aTS1 == SearchV1) ? aV1zad :
1415                                   theCoeffs.mK21 * sin(aU2) + theCoeffs.mK11 * sin(anUpar1) +
1416                                   theCoeffs.mL21 * cos(aU2) + theCoeffs.mL11 * cos(anUpar1) + theCoeffs.mM1;
1417         const Standard_Real aV2 = (aTS1 == SearchV2) ? aV2zad : 
1418                                   theCoeffs.mK22 * sin(aU2) + theCoeffs.mK12 * sin(anUpar1) +
1419                                   theCoeffs.mL22 * cos(aU2) + theCoeffs.mL12 * cos(anUpar1) + theCoeffs.mM2;
1420
1421         AddPointIntoWL(theQuad1, theQuad2, isTheReverse,
1422                         gp_Pnt2d(anUpar1, aV1), gp_Pnt2d(aU2, aV2),
1423                         aUSurf1f, aUSurf1l, thePeriod,
1424                         theWL->Curve(), theTol3D, theTol2D, theFlForce);
1425       }
1426       else
1427       {
1428         isTheFound1 = Standard_False;
1429       }
1430     }
1431   }
1432
1433   return Standard_True;
1434 }
1435
1436 //=======================================================================
1437 //function : SeekAdditionalPoints
1438 //purpose  : 
1439 //=======================================================================
1440 static void SeekAdditionalPoints( const IntSurf_Quadric& theQuad1,
1441                                   const IntSurf_Quadric& theQuad2,
1442                                   const Handle(IntSurf_LineOn2S)& theLile,
1443                                   const stCoeffsValue& theCoeffs,
1444                                   const Standard_Integer theMinNbPoints,
1445                                   const Standard_Real theU2f,
1446                                   const Standard_Real theU2l,
1447                                   const Standard_Real theTol2D,
1448                                   const Standard_Real thePeriodOfSurf2,
1449                                   const Standard_Real theArccosFactor,
1450                                   const Standard_Boolean isTheReverse)
1451 {
1452   Standard_Integer aNbPoints = theLile->NbPoints();
1453   if(aNbPoints >= theMinNbPoints)
1454   {
1455     return;
1456   }
1457
1458   Standard_Real U1prec = 0.0, V1prec = 0.0, U2prec = 0.0, V2prec = 0.0;
1459
1460   Standard_Integer aNbPointsPrev = 0;
1461   while(aNbPoints < theMinNbPoints && (aNbPoints != aNbPointsPrev))
1462   {
1463     aNbPointsPrev = aNbPoints;
1464     for(Standard_Integer fp = 1, lp = 2; fp < aNbPoints; fp = lp + 1)
1465     {
1466       Standard_Real U1f = 0.0, V1f = 0.0; //first point in 1st suraface
1467       Standard_Real U1l = 0.0, V1l = 0.0; //last  point in 1st suraface
1468
1469       Standard_Real U2f = 0.0, V2f = 0.0; //first point in 2nd suraface
1470       Standard_Real U2l = 0.0, V2l = 0.0; //last  point in 2nd suraface
1471
1472       lp = fp+1;
1473       
1474       if(isTheReverse)
1475       {
1476         theLile->Value(fp).ParametersOnS2(U1f, V1f);
1477         theLile->Value(lp).ParametersOnS2(U1l, V1l);
1478
1479         theLile->Value(fp).ParametersOnS1(U2f, V2f);
1480         theLile->Value(lp).ParametersOnS1(U2l, V2l);
1481       }
1482       else
1483       {
1484         theLile->Value(fp).ParametersOnS1(U1f, V1f);
1485         theLile->Value(lp).ParametersOnS1(U1l, V1l);
1486
1487         theLile->Value(fp).ParametersOnS2(U2f, V2f);
1488         theLile->Value(lp).ParametersOnS2(U2l, V2l);
1489       }
1490
1491       if(Abs(U1l - U1f) <= theTol2D)
1492       {
1493         //Step is minimal. It is not necessary to divide it.
1494         continue;
1495       }
1496
1497       U1prec = 0.5*(U1f+U1l);
1498       
1499       Standard_Real anArg = theCoeffs.mB * cos(U1prec - theCoeffs.mFI1) + theCoeffs.mC;
1500       if(anArg > 1.0)
1501         anArg = 1.0;
1502       if(anArg < -1.0)
1503         anArg = -1.0;
1504
1505       U2prec = theCoeffs.mFI2 + theArccosFactor*acos(anArg);
1506       InscribePoint(theU2f, theU2l, U2prec, theTol2D, thePeriodOfSurf2, Standard_False);
1507
1508       gp_Pnt aP1, aP2;
1509
1510       V1prec = theCoeffs.mK21 * sin(U2prec) + 
1511                 theCoeffs.mK11 * sin(U1prec) + 
1512                 theCoeffs.mL21 * cos(U2prec) + 
1513                 theCoeffs.mL11 * cos(U1prec) + theCoeffs.mM1;
1514       V2prec = theCoeffs.mK22 * sin(U2prec) + 
1515                 theCoeffs.mK12 * sin(U1prec) + 
1516                 theCoeffs.mL22 * cos(U2prec) + 
1517                 theCoeffs.mL12 * cos(U1prec) + theCoeffs.mM2;
1518
1519       aP1 = theQuad1.Value(U1prec, V1prec);
1520       aP2 = theQuad2.Value(U2prec, V2prec);
1521
1522       gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
1523
1524 #ifdef OCCT_DEBUG
1525       //cout << "|P1Pi| = " << aP1.SquareDistance(aPInt) << "; |P2Pi| = " << aP2.SquareDistance(aPInt) << endl;
1526 #endif
1527
1528       IntSurf_PntOn2S anIP;
1529       if(isTheReverse)
1530       {
1531         anIP.SetValue(aPInt, U2prec, V2prec, U1prec, V1prec);
1532       }
1533       else
1534       {
1535         anIP.SetValue(aPInt, U1prec, V1prec, U2prec, V2prec);
1536       }
1537
1538       theLile->InsertBefore(lp, anIP);
1539
1540       aNbPoints = theLile->NbPoints();
1541       if(aNbPoints >= theMinNbPoints)
1542       {
1543         return;
1544       }
1545     }
1546   }
1547 }
1548
1549 //=======================================================================
1550 //function : CriticalPointsComputing
1551 //purpose  : 
1552 //=======================================================================
1553 static void CriticalPointsComputing(const stCoeffsValue& theCoeffs,
1554                                     const Standard_Real theUSurf1f,
1555                                     const Standard_Real theUSurf1l,
1556                                     const Standard_Real theUSurf2f,
1557                                     const Standard_Real theUSurf2l,
1558                                     const Standard_Real thePeriod,
1559                                     const Standard_Real theTol2D,
1560                                     const Standard_Integer theNbCritPointsMax,
1561                                     Standard_Real theU1crit[])
1562 {
1563   theU1crit[0] = 0.0;
1564   theU1crit[1] = thePeriod;
1565   theU1crit[2] = theUSurf1f;
1566   theU1crit[3] = theUSurf1l;
1567
1568   const Standard_Real aCOS = cos(theCoeffs.mFI2);
1569   const Standard_Real aBSB = Abs(theCoeffs.mB);
1570   if((theCoeffs.mC - aBSB <= aCOS) && (aCOS <= theCoeffs.mC + aBSB))
1571   {
1572     Standard_Real anArg = (aCOS - theCoeffs.mC) / theCoeffs.mB;
1573     if(anArg > 1.0)
1574       anArg = 1.0;
1575     if(anArg < -1.0)
1576       anArg = -1.0;
1577
1578     theU1crit[4] = -acos(anArg) + theCoeffs.mFI1;
1579     theU1crit[5] = acos(anArg) + theCoeffs.mFI1;
1580   }
1581
1582   Standard_Real aSf = cos(theUSurf2f - theCoeffs.mFI2);
1583   Standard_Real aSl = cos(theUSurf2l - theCoeffs.mFI2);
1584   MinMax(aSf, aSl);
1585
1586   theU1crit[6] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? -acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : -Precision::Infinite();
1587   theU1crit[7] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? -acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : Precision::Infinite();
1588   theU1crit[8] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?  acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : -Precision::Infinite();
1589   theU1crit[9] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?  acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : Precision::Infinite();
1590
1591   //preparative treatment of array
1592   InscribeAndSortArray(theU1crit, theNbCritPointsMax, 0.0, thePeriod, theTol2D, thePeriod);
1593   for(Standard_Integer i = 1; i < theNbCritPointsMax; i++)
1594   {
1595     Standard_Real &a = theU1crit[i],
1596                   &b = theU1crit[i-1];
1597     const Standard_Real aRemain = fmod(Abs(a - b), thePeriod); // >= 0, because Abs(a - b) >= 0
1598     if((Abs(a - b) < theTol2D) || (aRemain < theTol2D) || (Abs(aRemain - thePeriod) < theTol2D))
1599     {
1600       a = (a + b)/2.0;
1601       b = Precision::Infinite();
1602     }
1603   }
1604 }
1605
1606 //=======================================================================
1607 //function : IntCyCyTrim
1608 //purpose  : 
1609 //=======================================================================
1610 Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
1611                               const IntSurf_Quadric& theQuad2,
1612                               const Standard_Real theTol3D,
1613                               const Standard_Real theTol2D,
1614                               const Bnd_Box2d& theUVSurf1,
1615                               const Bnd_Box2d& theUVSurf2,
1616                               const Standard_Boolean isTheReverse,
1617                               Standard_Boolean& isTheEmpty,
1618                               IntPatch_SequenceOfLine& theSlin,
1619                               IntPatch_SequenceOfPoint& theSPnt)
1620 {
1621   Standard_Real aUSurf1f = 0.0, //const
1622                 aUSurf1l = 0.0,
1623                 aVSurf1f = 0.0,
1624                 aVSurf1l = 0.0;
1625   Standard_Real aUSurf2f = 0.0, //const
1626                 aUSurf2l = 0.0,
1627                 aVSurf2f = 0.0,
1628                 aVSurf2l = 0.0;
1629
1630   theUVSurf1.Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l);
1631   theUVSurf2.Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l);
1632
1633   const Standard_Real aNulValue = 0.01*Precision::PConfusion();
1634
1635   const gp_Cylinder&  aCyl1 = theQuad1.Cylinder(),
1636                       aCyl2 = theQuad2.Cylinder();
1637
1638   IntAna_QuadQuadGeo anInter(aCyl1,aCyl2,theTol3D);
1639
1640   if (!anInter.IsDone())
1641   {
1642     return Standard_False;
1643   }
1644
1645   IntAna_ResultType aTypInt = anInter.TypeInter();
1646
1647   if(aTypInt != IntAna_NoGeometricSolution)
1648   { //It is not necessary (because result is an analytic curve) or
1649     //it is impossible to make Walking-line.
1650
1651     return Standard_False;
1652   }
1653     
1654   theSlin.Clear();
1655   theSPnt.Clear();
1656   const Standard_Integer aNbMaxPoints = 2000;
1657   const Standard_Integer aNbMinPoints = 200;
1658   const Standard_Integer aNbPoints = Min(Max(aNbMinPoints, 
1659                       RealToInt(20.0*aCyl1.Radius())), aNbMaxPoints);
1660   const Standard_Real aPeriod = 2.0*M_PI;
1661   const Standard_Real aStepMin = theTol2D, 
1662                       aStepMax = (aUSurf1l-aUSurf1f)/IntToReal(aNbPoints);
1663   const Standard_Integer aNbWLines = 2;
1664
1665   const stCoeffsValue anEquationCoeffs(aCyl1, aCyl2);
1666
1667   //Boundaries
1668   const Standard_Integer aNbOfBoundaries = 2;
1669   Standard_Real aU1f[aNbOfBoundaries] = {-Precision::Infinite(), -Precision::Infinite()};
1670   Standard_Real aU1l[aNbOfBoundaries] = {Precision::Infinite(), Precision::Infinite()};
1671
1672   if(anEquationCoeffs.mB > 0.0)
1673   {
1674     if(anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) < -1.0)
1675     {//There is NOT intersection
1676       return Standard_True;
1677     }
1678     else if(anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) <= 1.0)
1679     {//U=[0;2*PI]+aFI1
1680       aU1f[0] = anEquationCoeffs.mFI1;
1681       aU1l[0] = aPeriod + anEquationCoeffs.mFI1;
1682     }
1683     else if((1 + anEquationCoeffs.mC <= anEquationCoeffs.mB) &&
1684             (anEquationCoeffs.mB <= 1 - anEquationCoeffs.mC))
1685     {
1686       Standard_Real anArg = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB;
1687       if(anArg > 1.0)
1688         anArg = 1.0;
1689       if(anArg < -1.0)
1690         anArg = -1.0;
1691
1692       const Standard_Real aDAngle = acos(anArg);
1693       //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1)
1694       aU1f[0] = anEquationCoeffs.mFI1;
1695       aU1l[0] = aDAngle + anEquationCoeffs.mFI1;
1696       aU1f[1] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
1697       aU1l[1] = aPeriod + anEquationCoeffs.mFI1;
1698     }
1699     else if((1 - anEquationCoeffs.mC <= anEquationCoeffs.mB) &&
1700             (anEquationCoeffs.mB <= 1 + anEquationCoeffs.mC))
1701     {
1702       Standard_Real anArg = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB;
1703       if(anArg > 1.0)
1704         anArg = 1.0;
1705       if(anArg < -1.0)
1706         anArg = -1.0;
1707
1708       const Standard_Real aDAngle = acos(anArg);
1709       //U=[aDAngle;2*PI-aDAngle]+aFI1
1710
1711       aU1f[0] = aDAngle + anEquationCoeffs.mFI1;
1712       aU1l[0] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
1713     }
1714     else if(anEquationCoeffs.mB - Abs(anEquationCoeffs.mC) >= 1.0)
1715     {
1716       Standard_Real anArg1 = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB,
1717                     anArg2 = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB;
1718       if(anArg1 > 1.0)
1719         anArg1 = 1.0;
1720       if(anArg1 < -1.0)
1721         anArg1 = -1.0;
1722
1723       if(anArg2 > 1.0)
1724         anArg2 = 1.0;
1725       if(anArg2 < -1.0)
1726         anArg2 = -1.0;
1727
1728       const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2);
1729       //(U=[aDAngle1;aDAngle2]+aFI1) ||
1730       //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
1731
1732       aU1f[0] = aDAngle1 + anEquationCoeffs.mFI1;
1733       aU1l[0] = aDAngle2 + anEquationCoeffs.mFI1;
1734       aU1f[1] = aPeriod - aDAngle2 + anEquationCoeffs.mFI1;
1735       aU1l[1] = aPeriod - aDAngle1 + anEquationCoeffs.mFI1;
1736     }
1737     else
1738     {
1739       Standard_Failure::Raise("Error. Exception. Unhandled case (Range computation)!");
1740     }
1741   }
1742   else if(anEquationCoeffs.mB < 0.0)
1743   {
1744     if(anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) > 1.0)
1745     {//There is NOT intersection
1746       return Standard_True;
1747     }
1748     else if(-anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) <= 1.0)
1749     {//U=[0;2*PI]+aFI1
1750       aU1f[0] = anEquationCoeffs.mFI1;
1751       aU1l[0] = aPeriod + anEquationCoeffs.mFI1;
1752     }
1753     else if((-anEquationCoeffs.mC - 1 <= anEquationCoeffs.mB) &&
1754             ( anEquationCoeffs.mB <= anEquationCoeffs.mC - 1))
1755     {
1756       Standard_Real anArg = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB;
1757       if(anArg > 1.0)
1758         anArg = 1.0;
1759       if(anArg < -1.0)
1760         anArg = -1.0;
1761
1762       const Standard_Real aDAngle = acos(anArg);
1763       //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1)
1764
1765       aU1f[0] = anEquationCoeffs.mFI1;
1766       aU1l[0] = aDAngle + anEquationCoeffs.mFI1;
1767       aU1f[1] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
1768       aU1l[1] = aPeriod + anEquationCoeffs.mFI1;
1769     }
1770     else if((anEquationCoeffs.mC - 1 <= anEquationCoeffs.mB) &&
1771             (anEquationCoeffs.mB <= -anEquationCoeffs.mB - 1))
1772     {
1773       Standard_Real anArg = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB;
1774       if(anArg > 1.0)
1775         anArg = 1.0;
1776       if(anArg < -1.0)
1777         anArg = -1.0;
1778
1779       const Standard_Real aDAngle = acos(anArg);
1780       //U=[aDAngle;2*PI-aDAngle]+aFI1
1781
1782       aU1f[0] = aDAngle + anEquationCoeffs.mFI1;
1783       aU1l[0] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
1784     }
1785     else if(-anEquationCoeffs.mB - Abs(anEquationCoeffs.mC) >= 1.0)
1786     {
1787       Standard_Real anArg1 = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB,
1788                     anArg2 = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB;
1789       if(anArg1 > 1.0)
1790         anArg1 = 1.0;
1791       if(anArg1 < -1.0)
1792         anArg1 = -1.0;
1793
1794       if(anArg2 > 1.0)
1795         anArg2 = 1.0;
1796       if(anArg2 < -1.0)
1797         anArg2 = -1.0;
1798
1799       const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2);
1800       //(U=[aDAngle1;aDAngle2]+aFI1) ||
1801       //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
1802
1803       aU1f[0] = aDAngle1 + anEquationCoeffs.mFI1;
1804       aU1l[0] = aDAngle2 + anEquationCoeffs.mFI1;
1805       aU1f[1] = aPeriod - aDAngle2 + anEquationCoeffs.mFI1;
1806       aU1l[1] = aPeriod - aDAngle1 + anEquationCoeffs.mFI1;
1807     }
1808     else
1809     {
1810       Standard_Failure::Raise("Error. Exception. Unhandled case (Range computation)!");
1811     }
1812   }
1813   else
1814   {
1815     Standard_Failure::Raise("Error. Exception. Unhandled case (B-parameter computation)!");
1816   }
1817
1818   for(Standard_Integer i = 0; i < aNbOfBoundaries; i++)
1819   {
1820     if(Precision::IsInfinite(aU1f[i]) && Precision::IsInfinite(aU1l[i]))
1821       continue;
1822
1823     InscribeInterval(aUSurf1f, aUSurf1l, aU1f[i], aU1l[i], theTol2D, aPeriod);
1824   }
1825
1826   if( !Precision::IsInfinite(aU1f[0]) && !Precision::IsInfinite(aU1f[1]) &&
1827       !Precision::IsInfinite(aU1l[0]) && !Precision::IsInfinite(aU1l[1]))
1828   {
1829     if( ((aU1f[1] <= aU1l[0]) || (aU1l[1] <= aU1l[0])) && 
1830         ((aU1f[0] <= aU1l[1]) || (aU1l[0] <= aU1l[1])))
1831     {//Join all intervals to one
1832       aU1f[0] = Min(aU1f[0], aU1f[1]);
1833       aU1l[0] = Max(aU1l[0], aU1l[1]);
1834
1835       aU1f[1] = -Precision::Infinite();
1836       aU1l[1] = Precision::Infinite();
1837     }
1838   }
1839
1840   //Critical points
1841   //[0...1] - in these points parameter U1 goes through
1842   //          the seam-edge of the first cylinder.
1843   //[2...3] - First and last U1 parameter.
1844   //[4...5] - in these points parameter U2 goes through
1845   //          the seam-edge of the second cylinder.
1846   //[6...9] - in these points an intersection line goes through
1847   //          U-boundaries of the second surface.
1848   const Standard_Integer aNbCritPointsMax = 10;
1849   Standard_Real anU1crit[aNbCritPointsMax] = {Precision::Infinite(),
1850                                               Precision::Infinite(),
1851                                               Precision::Infinite(),
1852                                               Precision::Infinite(),
1853                                               Precision::Infinite(),
1854                                               Precision::Infinite(),
1855                                               Precision::Infinite(),
1856                                               Precision::Infinite(),
1857                                               Precision::Infinite(),
1858                                               Precision::Infinite()};
1859
1860   CriticalPointsComputing(anEquationCoeffs, aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
1861                                       aPeriod, theTol2D, aNbCritPointsMax, anU1crit);
1862
1863
1864   //Getting Walking-line
1865
1866   enum WLFStatus
1867   {
1868     WLFStatus_Absent = 0,
1869     WLFStatus_Exist  = 1,
1870     WLFStatus_Broken = 2
1871   };
1872
1873   for(Standard_Integer aCurInterval = 0; aCurInterval < aNbOfBoundaries; aCurInterval++)
1874   {
1875     if(Precision::IsInfinite(aU1f[aCurInterval]) && Precision::IsInfinite(aU1l[aCurInterval]))
1876       continue;
1877
1878     Standard_Boolean isAddedIntoWL[aNbWLines];
1879     for(Standard_Integer i = 0; i < aNbWLines; i++)
1880       isAddedIntoWL[i] = Standard_False;
1881
1882     Standard_Real anUf = aU1f[aCurInterval], anUl = aU1l[aCurInterval];
1883     const Standard_Boolean isDeltaPeriod  = IsEqual(anUl-anUf, aPeriod);
1884
1885     //Inscribe and sort critical points
1886     InscribeAndSortArray(anU1crit, aNbCritPointsMax, anUf, anUl, theTol2D, aPeriod);
1887
1888     while(anUf < anUl)
1889     {
1890       Standard_Real aU2[aNbWLines], aV1[aNbWLines], aV2[aNbWLines];
1891       WLFStatus aWLFindStatus[aNbWLines];
1892       Standard_Real aV1Prev[aNbWLines], aV2Prev[aNbWLines];
1893       Standard_Real anArccosFactor[aNbWLines] = {1.0, -1.0};
1894       Standard_Boolean isAddingWLEnabled[aNbWLines];
1895
1896       Handle(IntSurf_LineOn2S) aL2S[aNbWLines];
1897       Handle(IntPatch_WLine) aWLine[aNbWLines];
1898       for(Standard_Integer i = 0; i < aNbWLines; i++)
1899       {
1900         aL2S[i] = new IntSurf_LineOn2S();
1901         aWLine[i] = new IntPatch_WLine(aL2S[i], Standard_False);
1902         aWLFindStatus[i] = WLFStatus_Absent;
1903         isAddingWLEnabled[i] = Standard_True;
1904         aU2[i] = aV1[i] = aV2[i] = 0.0;
1905         aV1Prev[i] = aV2Prev[i] = 0.0;
1906       }
1907       
1908       Standard_Real anU1 = anUf;
1909
1910       Standard_Real aCriticalDelta[aNbCritPointsMax];
1911       for(Standard_Integer i = 0; i < aNbCritPointsMax; i++)
1912         aCriticalDelta[i] = anU1 - anU1crit[i];
1913
1914       Standard_Boolean isFirst = Standard_True;
1915
1916       while(anU1 <= anUl)
1917       {
1918         if(isDeltaPeriod)
1919         {
1920           if(IsEqual(anU1, anUl))
1921           {
1922             //if isAddedIntoWL* == TRUE WLine contains only one point
1923             //(which was end point of previous WLine). If we will
1924             //add point found on the current step WLine will contain only
1925             //two points. At that both these points will be equal to the
1926             //points found earlier. Therefore, new WLine will repeat 
1927             //already existing WLine. Consequently, it is necessary 
1928             //to forbid building new line in this case.
1929
1930             for(Standard_Integer i = 0; i < aNbWLines; i++)
1931               isAddingWLEnabled[i] = !isAddedIntoWL[i];
1932           }
1933         }
1934
1935         for(Standard_Integer i = 0; i < aNbCritPointsMax; i++)
1936         {
1937           if((anU1 - anU1crit[i])*aCriticalDelta[i] < 0.0)
1938           {
1939             anU1 = anU1crit[i];
1940
1941             for(Standard_Integer i = 0; i < aNbWLines; i++)
1942               aWLFindStatus[i] = WLFStatus_Broken;
1943
1944             break;
1945           }
1946         }
1947
1948         Standard_Real anArg = anEquationCoeffs.mB * 
1949               cos(anU1 - anEquationCoeffs.mFI1) + anEquationCoeffs.mC;
1950         
1951         if(aNulValue > 1.0 - anArg)
1952           anArg = 1.0;
1953         if(anArg + 1.0 < aNulValue)
1954           anArg = -1.0;
1955
1956         for(Standard_Integer i = 0; i < aNbWLines; i++)
1957         {
1958           const Standard_Integer aNbPntsWL =  aWLine[i].IsNull() ? 0 :
1959                                               aWLine[i]->Curve()->NbPoints();
1960           aU2[i] = anEquationCoeffs.mFI2 + anArccosFactor[i]*acos(anArg);
1961
1962           InscribePoint(aUSurf2f, aUSurf2l, aU2[i], theTol2D, aPeriod, Standard_False);
1963
1964           if(aNbPntsWL == 0)
1965           {//the line has not contained any points yet
1966             if(((aUSurf2f + aPeriod - aUSurf2l) <= 2.0*theTol2D) && 
1967                 ((Abs(aU2[i] - aUSurf2f) < theTol2D) ||
1968                   (Abs(aU2[i]-aUSurf2l) < theTol2D)))
1969             {
1970               //In this case aU2[i] can have two values: current aU2[i] or
1971               //aU2[i] +/- aPeriod. It is necessary to choose correct value.
1972
1973               // U2(U1) = FI2 + anArccosFactor*acos(B*cos(U1 - FI1) + C);
1974               //Accordingly,
1975               //Func. U2(X1) = FI2 + X1;
1976               //Func. X1(X2) = anArccosFactor*X2;
1977               //Func. X2(X3) = acos(X3);
1978               //Func. X3(X4) = B*X4 + C;
1979               //Func. X4(U1) = cos(U1 - FI1).
1980               //
1981               //Consequently,
1982               //U2(X1) is always increasing.
1983               //X1(X2) is increasing if anArccosFactor > 0.0 and
1984               //is decreasing otherwise.
1985               //X2(X3) is always decreasing.
1986               //Therefore, U2(X3) is decreasing if anArccosFactor > 0.0 and
1987               //is increasing otherwise.
1988               //X3(X4) is increasing if B > 0 and is decreasing otherwise.
1989               //X4(U1) is increasing if U1 - FI1 in [PI, 2*PI) and
1990               //is decreasing U1 - FI1 in [0, PI) or if (U1 - FI1 == 2PI).
1991               //After that, we can predict behaviour of U2(U1) function:
1992               //if it is increasing or decreasing.
1993               Standard_Real aU1Temp = anU1 - anEquationCoeffs.mFI1;
1994               InscribePoint(0, aPeriod, aU1Temp, 0.0, aPeriod, Standard_False);
1995               
1996               Standard_Boolean isIncreasing = Standard_True;
1997
1998               if(((M_PI - aU1Temp) < RealSmall()) && (aU1Temp < aPeriod))
1999               {
2000                 isIncreasing = Standard_False;
2001               }
2002
2003               if(anEquationCoeffs.mB < 0.0)
2004               {
2005                 isIncreasing = !isIncreasing;
2006               }
2007
2008               if(anArccosFactor[i] < 0.0)
2009               {
2010                 isIncreasing = !isIncreasing;
2011               }
2012               
2013               //If U2(U1) is increasing and U2 is considered to be equal aUSurf2l
2014               //then after the next step (when U1 will be increased) U2 will be
2015               //increased too. And we will go out of surface boundary.
2016               //Therefore, If U2(U1) is increasing then U2 must be equal aUSurf2f.
2017               //Analogically, if U2(U1) is decreasing.
2018               if(isIncreasing)
2019               {
2020                 aU2[i] = aUSurf2f;
2021               }
2022               else
2023               {
2024                 aU2[i] = aUSurf2l;
2025               }
2026             }
2027           }
2028           else
2029           {//aNbPntsWL > 0
2030             if(((aUSurf2l - aUSurf2f) >= aPeriod) && 
2031                 ((Abs(aU2[i] - aUSurf2f) < theTol2D) ||
2032                   (Abs(aU2[i]-aUSurf2l) < theTol2D)))
2033             {//end of the line
2034               Standard_Real aU2prev = 0.0, aV2prev = 0.0;
2035               if(isTheReverse)
2036                 aWLine[i]->Curve()->Value(aNbPntsWL).ParametersOnS1(aU2prev, aV2prev);
2037               else
2038                 aWLine[i]->Curve()->Value(aNbPntsWL).ParametersOnS2(aU2prev, aV2prev);
2039
2040               if(2.0*Abs(aU2prev - aU2[i]) > aPeriod)
2041               {
2042                 if(aU2prev > aU2[i])
2043                   aU2[i] += aPeriod;
2044                 else
2045                   aU2[i] -= aPeriod;
2046               }
2047             }
2048           }
2049
2050           if( (aWLFindStatus[i] == WLFStatus_Broken) ||
2051               (aWLFindStatus[i] == WLFStatus_Absent))
2052           {//Begin and end of WLine must be on boundary point
2053            //or on seam-edge strictly (if it is possible).
2054             if(Abs(aU2[i]) <= theTol2D)
2055               aU2[i] = 0.0;
2056             else if(Abs(aU2[i] - aPeriod) <= theTol2D)
2057               aU2[i] = aPeriod;
2058             else if(Abs(aU2[i] - aUSurf2f) <= theTol2D)
2059               aU2[i] = aUSurf2f;
2060             else if(Abs(aU2[i] - aUSurf2l) <= theTol2D)
2061               aU2[i] = aUSurf2l;
2062           }
2063
2064           aV1[i] =  anEquationCoeffs.mK21 * sin(aU2[i]) + 
2065                     anEquationCoeffs.mK11 * sin(anU1) +
2066                     anEquationCoeffs.mL21 * cos(aU2[i]) +
2067                     anEquationCoeffs.mL11 * cos(anU1) + anEquationCoeffs.mM1;
2068
2069           aV2[i] =  anEquationCoeffs.mK22 * sin(aU2[i]) +
2070                     anEquationCoeffs.mK12 * sin(anU1) +
2071                     anEquationCoeffs.mL22 * cos(aU2[i]) +
2072                     anEquationCoeffs.mL12 * cos(anU1) + anEquationCoeffs.mM2;
2073
2074           if(isFirst)
2075           {
2076             aV1Prev[i] = aV1[i];
2077             aV2Prev[i] = aV2[i];
2078           }
2079         }//for(Standard_Integer i = 0; i < aNbWLines; i++)
2080
2081         isFirst = Standard_False;
2082
2083         //Looking for points into WLine
2084         Standard_Boolean isBroken = Standard_False;
2085         for(Standard_Integer i = 0; i < aNbWLines; i++)
2086         {
2087           if(!isAddingWLEnabled[i])
2088           {
2089             aV1Prev[i] = aV1[i];
2090             aV2Prev[i] = aV2[i];
2091
2092             if(aWLFindStatus[i] == WLFStatus_Broken)
2093               isBroken = Standard_True;
2094
2095             continue;
2096           }
2097
2098           if( ((aUSurf2f-aU2[i]) <= theTol2D) && ((aU2[i]-aUSurf2l) <= theTol2D) &&
2099               ((aVSurf1f - aV1[i]) <= theTol2D) && ((aV1[i] - aVSurf1l) <= theTol2D) &&
2100               ((aVSurf2f - aV2[i]) <= theTol2D) && ((aV2[i] - aVSurf2l) <= theTol2D))
2101           {
2102             Standard_Boolean isForce = Standard_False;
2103             if(aWLFindStatus[i] == WLFStatus_Absent)
2104             {
2105               Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
2106
2107               if(((aUSurf2l - aUSurf2f) >= aPeriod) && (Abs(anU1-aUSurf1l) < theTol2D))
2108               {
2109                 isForce = Standard_True;
2110               }
2111
2112               AddBoundaryPoint( theQuad1, theQuad2, aWLine[i], anEquationCoeffs,
2113                                 theUVSurf1, theUVSurf2, theTol3D, theTol2D, aPeriod,
2114                                 aNulValue, anU1, aU2[i], aV1[i], aV1Prev[i],
2115                                 aV2[i], aV2Prev[i], isTheReverse,
2116                                 anArccosFactor[i], isForce, isFound1, isFound2);
2117               
2118               if(isFound1 || isFound2)
2119               {
2120                 aWLFindStatus[i] = WLFStatus_Exist;
2121               }
2122             }
2123
2124             if(( aWLFindStatus[i] != WLFStatus_Broken) || (aWLine[i]->NbPnts() >= 1))
2125             {
2126               if(AddPointIntoWL(theQuad1, theQuad2, isTheReverse, 
2127                                 gp_Pnt2d(anU1, aV1[i]), gp_Pnt2d(aU2[i], aV2[i]),
2128                                 aUSurf1f, aUSurf1l, aPeriod,
2129                                 aWLine[i]->Curve(), theTol3D, theTol2D, isForce))
2130               {
2131                 if(aWLFindStatus[i] == WLFStatus_Absent)
2132                 {
2133                   aWLFindStatus[i] = WLFStatus_Exist;
2134                 }
2135               }
2136             }
2137           }
2138           else
2139           {
2140             if(aWLFindStatus[i] == WLFStatus_Exist)
2141             {
2142               Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
2143
2144               AddBoundaryPoint( theQuad1, theQuad2, aWLine[i], anEquationCoeffs,
2145                                 theUVSurf1, theUVSurf2, theTol3D, theTol2D, aPeriod,
2146                                 aNulValue, anU1, aU2[i], aV1[i], aV1Prev[i],
2147                                 aV2[i], aV2Prev[i], isTheReverse,
2148                                 anArccosFactor[i], Standard_False, isFound1, isFound2);
2149
2150               if(isFound1 || isFound2)
2151                 aWLFindStatus[i] = WLFStatus_Broken; //start a new line
2152             }
2153           }
2154
2155           aV1Prev[i] = aV1[i];
2156           aV2Prev[i] = aV2[i];
2157
2158           if(aWLFindStatus[i] == WLFStatus_Broken)
2159             isBroken = Standard_True;
2160         }//for(Standard_Integer i = 0; i < aNbWLines; i++)
2161
2162         if(isBroken)
2163         {//current lines are filled. Go to the next lines
2164           anUf = anU1;
2165           break;
2166         }
2167
2168         //Step computing
2169
2170         Standard_Real aStepU1 = aStepMax;
2171
2172         for(Standard_Integer i = 0; i < aNbWLines; i++)
2173         {
2174           Standard_Real aDeltaU1V1 = aStepU1, aDeltaU1V2 = aStepU1;
2175
2176           Standard_Real aFact1 = !IsEqual(sin(aU2[i] - anEquationCoeffs.mFI2), 0.0) ? 
2177                                   anEquationCoeffs.mK1 * sin(anU1 - anEquationCoeffs.mFIV1) +
2178                                   anEquationCoeffs.mL1 * anEquationCoeffs.mB * sin(aU2[i] - anEquationCoeffs.mPSIV1) *
2179                                   sin(anU1 - anEquationCoeffs.mFI1)/sin(aU2[i]-anEquationCoeffs.mFI2) : 0.0,
2180                         aFact2 = !IsEqual(sin(aU2[i]-anEquationCoeffs.mFI2), 0.0) ? 
2181                                   anEquationCoeffs.mK2 * sin(anU1 - anEquationCoeffs.mFIV2) + 
2182                                   anEquationCoeffs.mL2 * anEquationCoeffs.mB * sin(aU2[i] - anEquationCoeffs.mPSIV2) *
2183                                   sin(anU1 - anEquationCoeffs.mFI1)/sin(aU2[i] - anEquationCoeffs.mFI2) : 0.0;
2184
2185           Standard_Real aDeltaV1 = (aVSurf1l - aVSurf1f)/IntToReal(aNbPoints),
2186                         aDeltaV2 = (aVSurf2l - aVSurf2f)/IntToReal(aNbPoints);
2187
2188           if((aV1[i] < aVSurf1f) && (aFact1 < 0.0))
2189           {//Make close to aVSurf1f by increasing anU1
2190             aDeltaV1 = Min(aDeltaV1, Abs(aV1[i]-aVSurf1f));
2191           }
2192
2193           if((aV1[i] > aVSurf1l) && (aFact1 > 0.0))
2194           {//Make close to aVSurf1l by increasing anU1
2195             aDeltaV1 = Min(aDeltaV1, Abs(aV1[i]-aVSurf1l));
2196           }
2197
2198           if((aV2[i] < aVSurf2f) && (aFact2 < 0.0))
2199           {//Make close to aVSurf2f by increasing anU1
2200             aDeltaV2 = Min(aDeltaV2, Abs(aV2[i]-aVSurf2f));
2201           }
2202
2203           if((aV2[i] > aVSurf2l) && (aFact2 > 0.0))
2204           {//Make close to aVSurf2l by increasing anU1
2205             aDeltaV2 = Min(aDeltaV2, Abs(aV2[i]-aVSurf1l));
2206           }
2207
2208           aDeltaU1V1 = !IsEqual(aFact1,0.0)? Abs(aDeltaV1/aFact1) : aStepMax;
2209           aDeltaU1V2 = !IsEqual(aFact2,0.0)? Abs(aDeltaV2/aFact2) : aStepMax;
2210
2211           if(aDeltaU1V1 < aStepU1)
2212             aStepU1 = aDeltaU1V1;
2213
2214           if(aDeltaU1V2 < aStepU1)
2215             aStepU1 = aDeltaU1V2;
2216         }
2217
2218         if(aStepU1 < aStepMin)
2219           aStepU1 = aStepMin;
2220       
2221         if(aStepU1 > aStepMax)
2222           aStepU1 = aStepMax;
2223
2224         anU1 += aStepU1;
2225
2226         const Standard_Real aDiff = anU1 - anUl;
2227         if((0.0 < aDiff) && (aDiff < aStepU1-Precision::PConfusion()))
2228           anU1 = anUl;
2229
2230         anUf = anU1;
2231
2232         for(Standard_Integer i = 0; i < aNbWLines; i++)
2233         {
2234           if(aWLine[i]->NbPnts() != 1)
2235             isAddedIntoWL[i] = Standard_False;
2236         }
2237       }
2238
2239       for(Standard_Integer i = 0; i < aNbWLines; i++)
2240       {
2241         if((aWLine[i]->NbPnts() == 1) && (!isAddedIntoWL[i]))
2242         {
2243           isTheEmpty = Standard_False;
2244           Standard_Real u1, v1, u2, v2;
2245           aWLine[i]->Point(1).Parameters(u1, v1, u2, v2);
2246           IntPatch_Point aP;
2247           aP.SetParameter(u1);
2248           aP.SetParameters(u1, v1, u2, v2);
2249           aP.SetTolerance(theTol3D);
2250           aP.SetValue(aWLine[i]->Point(1).Value());
2251
2252           theSPnt.Append(aP);
2253         }
2254         else if(aWLine[i]->NbPnts() > 1)
2255         {
2256           Standard_Boolean isGood = Standard_True;
2257
2258           if(aWLine[i]->NbPnts() == 2)
2259           {
2260             const IntSurf_PntOn2S& aPf = aWLine[i]->Point(1);
2261             const IntSurf_PntOn2S& aPl = aWLine[i]->Point(2);
2262             
2263             if(aPf.IsSame(aPl, Precision::Confusion()))
2264               isGood = Standard_False;
2265           }
2266
2267           if(isGood)
2268           {
2269             isTheEmpty = Standard_False;
2270             isAddedIntoWL[i] = Standard_True;
2271             SeekAdditionalPoints( theQuad1, theQuad2, aWLine[i]->Curve(), 
2272                                   anEquationCoeffs, aNbPoints, aUSurf2f, aUSurf2l,
2273                                   theTol2D, aPeriod, anArccosFactor[i], isTheReverse);
2274
2275             aWLine[i]->ComputeVertexParameters(theTol3D);
2276             theSlin.Append(aWLine[i]);
2277           }
2278         }
2279         else
2280         {
2281           isAddedIntoWL[i] = Standard_False;
2282         }
2283       }
2284     }
2285   }
2286
2287   return Standard_True;
2288 }
2289
2290 //=======================================================================
2291 //function : IntCySp
2292 //purpose  : 
2293 //=======================================================================
2294 Standard_Boolean IntCySp(const IntSurf_Quadric& Quad1,
2295                          const IntSurf_Quadric& Quad2,
2296                          const Standard_Real Tol,
2297                          const Standard_Boolean Reversed,
2298                          Standard_Boolean& Empty,
2299                          Standard_Boolean& Multpoint,
2300                          IntPatch_SequenceOfLine& slin,
2301                          IntPatch_SequenceOfPoint& spnt)
2302
2303 {
2304   Standard_Integer i;
2305
2306   IntSurf_TypeTrans trans1,trans2;
2307   IntAna_ResultType typint;
2308   IntPatch_Point ptsol;
2309   gp_Circ cirsol;
2310
2311   gp_Cylinder Cy;
2312   gp_Sphere Sp;
2313
2314   if (!Reversed) {
2315     Cy = Quad1.Cylinder();
2316     Sp = Quad2.Sphere();
2317   }
2318   else {
2319     Cy = Quad2.Cylinder();
2320     Sp = Quad1.Sphere();
2321   }
2322   IntAna_QuadQuadGeo inter(Cy,Sp,Tol);
2323
2324   if (!inter.IsDone()) {return Standard_False;}
2325
2326   typint = inter.TypeInter();
2327   Standard_Integer NbSol = inter.NbSolutions();
2328   Empty = Standard_False;
2329
2330   switch (typint) {
2331
2332   case IntAna_Empty :
2333     {
2334       Empty = Standard_True;
2335     }
2336     break;
2337
2338   case IntAna_Point :
2339     {
2340       gp_Pnt psol(inter.Point(1));
2341       Standard_Real U1,V1,U2,V2;
2342       Quad1.Parameters(psol,U1,V1);
2343       Quad2.Parameters(psol,U2,V2);
2344       ptsol.SetValue(psol,Tol,Standard_True);
2345       ptsol.SetParameters(U1,V1,U2,V2);
2346       spnt.Append(ptsol);
2347     }
2348     break;
2349
2350   case IntAna_Circle:
2351     {
2352       cirsol = inter.Circle(1);
2353       gp_Vec Tgt;
2354       gp_Pnt ptref;
2355       ElCLib::D1(0.,cirsol,ptref,Tgt);
2356
2357       if (NbSol == 1) {
2358         gp_Vec TestCurvature(ptref,Sp.Location());
2359         gp_Vec Normsp,Normcyl;
2360         if (!Reversed) {
2361           Normcyl = Quad1.Normale(ptref);
2362           Normsp  = Quad2.Normale(ptref);
2363         }
2364         else {
2365           Normcyl = Quad2.Normale(ptref);
2366           Normsp  = Quad1.Normale(ptref);
2367         }
2368         
2369         IntSurf_Situation situcyl;
2370         IntSurf_Situation situsp;
2371         
2372         if (Normcyl.Dot(TestCurvature) > 0.) {
2373           situsp = IntSurf_Outside;
2374           if (Normsp.Dot(Normcyl) > 0.) {
2375             situcyl = IntSurf_Inside;
2376           }
2377           else {
2378             situcyl = IntSurf_Outside;
2379           }
2380         }
2381         else {
2382           situsp = IntSurf_Inside;
2383           if (Normsp.Dot(Normcyl) > 0.) {
2384             situcyl = IntSurf_Outside;
2385           }
2386           else {
2387             situcyl = IntSurf_Inside;
2388           }
2389         }
2390         Handle(IntPatch_GLine) glig;
2391         if (!Reversed) {
2392           glig = new IntPatch_GLine(cirsol, Standard_True, situcyl, situsp);
2393         }
2394         else {
2395           glig = new IntPatch_GLine(cirsol, Standard_True, situsp, situcyl);
2396         }
2397         slin.Append(glig);
2398       }
2399       else {
2400         if (Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref)) > 0.0) {
2401           trans1 = IntSurf_Out;
2402           trans2 = IntSurf_In;
2403         }
2404         else {
2405           trans1 = IntSurf_In;
2406           trans2 = IntSurf_Out;
2407         }
2408         Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
2409         slin.Append(glig);
2410
2411         cirsol = inter.Circle(2);
2412         ElCLib::D1(0.,cirsol,ptref,Tgt);
2413         Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
2414         if(qwe> 0.0000001) {
2415           trans1 = IntSurf_Out;
2416           trans2 = IntSurf_In;
2417         }
2418         else if(qwe<-0.0000001) {
2419           trans1 = IntSurf_In;
2420           trans2 = IntSurf_Out;
2421         }
2422         else { 
2423           trans1=trans2=IntSurf_Undecided; 
2424         }
2425         glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
2426         slin.Append(glig);
2427       }
2428     }
2429     break;
2430     
2431   case IntAna_NoGeometricSolution:
2432     {
2433       gp_Pnt psol;
2434       Standard_Real U1,V1,U2,V2;
2435       IntAna_IntQuadQuad anaint(Cy,Sp,Tol);
2436       if (!anaint.IsDone()) {
2437         return Standard_False;
2438       }
2439
2440       if (anaint.NbPnt()==0 && anaint.NbCurve()==0) {
2441         Empty = Standard_True;
2442       }
2443       else {
2444
2445         NbSol = anaint.NbPnt();
2446         for (i = 1; i <= NbSol; i++) {
2447           psol = anaint.Point(i);
2448           Quad1.Parameters(psol,U1,V1);
2449           Quad2.Parameters(psol,U2,V2);
2450           ptsol.SetValue(psol,Tol,Standard_True);
2451           ptsol.SetParameters(U1,V1,U2,V2);
2452           spnt.Append(ptsol);
2453         }
2454         
2455         gp_Pnt ptvalid,ptf,ptl;
2456         gp_Vec tgvalid;
2457         Standard_Real first,last,para;
2458         IntAna_Curve curvsol;
2459         Standard_Boolean tgfound;
2460         Standard_Integer kount;
2461         
2462         NbSol = anaint.NbCurve();
2463         for (i = 1; i <= NbSol; i++) {
2464           curvsol = anaint.Curve(i);
2465           curvsol.Domain(first,last);
2466           ptf = curvsol.Value(first);
2467           ptl = curvsol.Value(last);
2468
2469           para = last;
2470           kount = 1;
2471           tgfound = Standard_False;
2472           
2473           while (!tgfound) {
2474             para = (1.123*first + para)/2.123;
2475             tgfound = curvsol.D1u(para,ptvalid,tgvalid);
2476             if (!tgfound) {
2477               kount ++;
2478               tgfound = kount > 5;
2479             }
2480           }
2481           Handle(IntPatch_ALine) alig;
2482           if (kount <= 5) {
2483             Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid),
2484                                                  Quad1.Normale(ptvalid));
2485             if(qwe> 0.00000001) {
2486               trans1 = IntSurf_Out;
2487               trans2 = IntSurf_In;
2488             }
2489             else if(qwe<-0.00000001) {
2490               trans1 = IntSurf_In;
2491               trans2 = IntSurf_Out;
2492             }
2493             else { 
2494               trans1=trans2=IntSurf_Undecided; 
2495             }
2496             alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
2497           }
2498           else {
2499             alig = new IntPatch_ALine(curvsol,Standard_False);
2500           }
2501           Standard_Boolean TempFalse1a = Standard_False;
2502           Standard_Boolean TempFalse2a = Standard_False;
2503
2504           //-- ptf et ptl : points debut et fin de alig 
2505           
2506           ProcessBounds(alig,slin,Quad1,Quad2,TempFalse1a,ptf,first,
2507                         TempFalse2a,ptl,last,Multpoint,Tol);
2508           slin.Append(alig);
2509         } //-- boucle sur les lignes 
2510       } //-- solution avec au moins une lihne 
2511     }
2512     break;
2513
2514   default:
2515     {
2516       return Standard_False;
2517     }
2518   }
2519   return Standard_True;
2520 }
2521 //=======================================================================
2522 //function : IntCyCo
2523 //purpose  : 
2524 //=======================================================================
2525 Standard_Boolean IntCyCo(const IntSurf_Quadric& Quad1,
2526                          const IntSurf_Quadric& Quad2,
2527                          const Standard_Real Tol,
2528                          const Standard_Boolean Reversed,
2529                          Standard_Boolean& Empty,
2530                          Standard_Boolean& Multpoint,
2531                          IntPatch_SequenceOfLine& slin,
2532                          IntPatch_SequenceOfPoint& spnt)
2533
2534 {
2535   IntPatch_Point ptsol;
2536
2537   Standard_Integer i;
2538
2539   IntSurf_TypeTrans trans1,trans2;
2540   IntAna_ResultType typint;
2541   gp_Circ cirsol;
2542
2543   gp_Cylinder Cy;
2544   gp_Cone     Co;
2545
2546   if (!Reversed) {
2547     Cy = Quad1.Cylinder();
2548     Co = Quad2.Cone();
2549   }
2550   else {
2551     Cy = Quad2.Cylinder();
2552     Co = Quad1.Cone();
2553   }
2554   IntAna_QuadQuadGeo inter(Cy,Co,Tol);
2555
2556   if (!inter.IsDone()) {return Standard_False;}
2557
2558   typint = inter.TypeInter();
2559   Standard_Integer NbSol = inter.NbSolutions();
2560   Empty = Standard_False;
2561
2562   switch (typint) {
2563
2564   case IntAna_Empty : {
2565     Empty = Standard_True;
2566   }
2567     break;
2568
2569   case IntAna_Point :{
2570     gp_Pnt psol(inter.Point(1));
2571     Standard_Real U1,V1,U2,V2;
2572     Quad1.Parameters(psol,U1,V1);
2573     Quad1.Parameters(psol,U2,V2);
2574     ptsol.SetValue(psol,Tol,Standard_True);
2575     ptsol.SetParameters(U1,V1,U2,V2);
2576     spnt.Append(ptsol);
2577   }
2578     break;
2579     
2580   case IntAna_Circle:  {
2581     gp_Vec Tgt;
2582     gp_Pnt ptref;
2583     Standard_Integer j;
2584     Standard_Real qwe;
2585     //
2586     for(j=1; j<=2; ++j) { 
2587       cirsol = inter.Circle(j);
2588       ElCLib::D1(0.,cirsol,ptref,Tgt);
2589       qwe = Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
2590       if(qwe> 0.00000001) {
2591         trans1 = IntSurf_Out;
2592         trans2 = IntSurf_In;
2593       }
2594       else if(qwe<-0.00000001) {
2595         trans1 = IntSurf_In;
2596         trans2 = IntSurf_Out;
2597       }
2598       else { 
2599         trans1=trans2=IntSurf_Undecided; 
2600       }
2601       Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
2602       slin.Append(glig);
2603     }
2604   }
2605     break;
2606     
2607   case IntAna_NoGeometricSolution:    {
2608     gp_Pnt psol;
2609     Standard_Real U1,V1,U2,V2;
2610     IntAna_IntQuadQuad anaint(Cy,Co,Tol);
2611     if (!anaint.IsDone()) {
2612       return Standard_False;
2613     }
2614     
2615     if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0) {
2616       Empty = Standard_True;
2617     }
2618     else {
2619       NbSol = anaint.NbPnt();
2620       for (i = 1; i <= NbSol; i++) {
2621         psol = anaint.Point(i);
2622         Quad1.Parameters(psol,U1,V1);
2623         Quad2.Parameters(psol,U2,V2);
2624         ptsol.SetValue(psol,Tol,Standard_True);
2625         ptsol.SetParameters(U1,V1,U2,V2);
2626         spnt.Append(ptsol);
2627       }
2628       
2629       gp_Pnt ptvalid, ptf, ptl;
2630       gp_Vec tgvalid;
2631       //
2632       Standard_Real first,last,para;
2633       Standard_Boolean tgfound,firstp,lastp,kept;
2634       Standard_Integer kount;
2635       //
2636       //
2637       //IntAna_Curve curvsol;
2638       IntAna_Curve aC;
2639       IntAna_ListOfCurve aLC;
2640       IntAna_ListIteratorOfListOfCurve aIt;
2641       
2642       //
2643       NbSol = anaint.NbCurve();
2644       for (i = 1; i <= NbSol; ++i) {
2645         kept = Standard_False;
2646         //curvsol = anaint.Curve(i);
2647         aC=anaint.Curve(i);
2648         aLC.Clear();
2649         ExploreCurve(Cy, Co, aC, 10.*Tol, aLC);
2650         //
2651         aIt.Initialize(aLC);
2652         for (; aIt.More(); aIt.Next()) {
2653           IntAna_Curve& curvsol=aIt.Value();
2654           //
2655           curvsol.Domain(first, last);
2656           firstp = !curvsol.IsFirstOpen();
2657           lastp  = !curvsol.IsLastOpen();
2658           if (firstp) {
2659             ptf = curvsol.Value(first);
2660           }
2661           if (lastp) {
2662             ptl = curvsol.Value(last);
2663           }
2664           para = last;
2665           kount = 1;
2666           tgfound = Standard_False;
2667           
2668           while (!tgfound) {
2669             para = (1.123*first + para)/2.123;
2670             tgfound = curvsol.D1u(para,ptvalid,tgvalid);
2671             if (!tgfound) {
2672               kount ++;
2673               tgfound = kount > 5;
2674             }
2675           }
2676           Handle(IntPatch_ALine) alig;
2677           if (kount <= 5) {
2678             Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid),
2679                                                  Quad1.Normale(ptvalid));
2680             if(qwe> 0.00000001) {
2681               trans1 = IntSurf_Out;
2682               trans2 = IntSurf_In;
2683             }
2684             else if(qwe<-0.00000001) {
2685               trans1 = IntSurf_In;
2686               trans2 = IntSurf_Out;
2687             }
2688             else { 
2689               trans1=trans2=IntSurf_Undecided; 
2690             }
2691             alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
2692             kept = Standard_True;
2693           }
2694           else {
2695             ptvalid = curvsol.Value(para);
2696             alig = new IntPatch_ALine(curvsol,Standard_False);
2697             kept = Standard_True;
2698             //-- cout << "Transition indeterminee" << endl;
2699           }
2700           if (kept) {
2701             Standard_Boolean Nfirstp = !firstp;
2702             Standard_Boolean Nlastp  = !lastp;
2703             ProcessBounds(alig,slin,Quad1,Quad2,Nfirstp,ptf,first,
2704                           Nlastp,ptl,last,Multpoint,Tol);
2705             slin.Append(alig);
2706           }
2707         } // for (; aIt.More(); aIt.Next())
2708       } // for (i = 1; i <= NbSol; ++i) 
2709     }
2710   }
2711     break;
2712     
2713   default:
2714     return Standard_False;
2715     
2716   } // switch (typint)
2717   
2718   return Standard_True;
2719 }
2720 //=======================================================================
2721 //function : ExploreCurve
2722 //purpose  : 
2723 //=======================================================================
2724 Standard_Boolean ExploreCurve(const gp_Cylinder& ,//aCy,
2725                               const gp_Cone& aCo,
2726                               IntAna_Curve& aC,
2727                               const Standard_Real aTol,
2728                               IntAna_ListOfCurve& aLC)
2729                               
2730 {
2731   Standard_Boolean bFind=Standard_False;
2732   Standard_Real aTheta, aT1, aT2, aDst;
2733   gp_Pnt aPapx, aPx;
2734   //
2735   //aC.Dump();
2736   //
2737   aLC.Clear();
2738   aLC.Append(aC);
2739   //
2740   aPapx=aCo.Apex();
2741   //
2742   aC.Domain(aT1, aT2);
2743   //
2744   aPx=aC.Value(aT1);
2745   aDst=aPx.Distance(aPapx);
2746   if (aDst<aTol) {
2747     return bFind;
2748   }
2749   aPx=aC.Value(aT2);
2750   aDst=aPx.Distance(aPapx);
2751   if (aDst<aTol) {
2752     return bFind;
2753   }
2754   //
2755   bFind=aC.FindParameter(aPapx, aTheta);
2756   if (!bFind){
2757     return bFind;
2758   }
2759   //
2760   aPx=aC.Value(aTheta);
2761   aDst=aPx.Distance(aPapx);
2762   if (aDst>aTol) {
2763     return !bFind;
2764   }
2765   //
2766   // need to be splitted at aTheta
2767   IntAna_Curve aC1, aC2;
2768   //
2769   aC1=aC;
2770   aC1.SetDomain(aT1, aTheta);
2771   aC2=aC;
2772   aC2.SetDomain(aTheta, aT2);
2773   //
2774   aLC.Clear();
2775   aLC.Append(aC1);
2776   aLC.Append(aC2);
2777   //
2778   return bFind;
2779 }
2780 //=======================================================================
2781 //function : IsToReverse
2782 //purpose  : 
2783 //=======================================================================
2784 Standard_Boolean IsToReverse(const gp_Cylinder& Cy1,
2785                              const gp_Cylinder& Cy2,
2786                              const Standard_Real Tol)
2787 {
2788   Standard_Boolean bRet;
2789   Standard_Real aR1,aR2, dR, aSc1, aSc2;
2790   //
2791   bRet=Standard_False;
2792   //
2793   aR1=Cy1.Radius();
2794   aR2=Cy2.Radius();
2795   dR=aR1-aR2;
2796   if (dR<0.) {
2797     dR=-dR;
2798   }
2799   if (dR>Tol) {
2800     bRet=aR1>aR2;
2801   }
2802   else {
2803     gp_Dir aDZ(0.,0.,1.);
2804     //
2805     const gp_Dir& aDir1=Cy1.Axis().Direction();
2806     aSc1=aDir1*aDZ;
2807     if (aSc1<0.) {
2808       aSc1=-aSc1;
2809     }
2810     //
2811     const gp_Dir& aDir2=Cy2.Axis().Direction();
2812     aSc2=aDir2*aDZ;
2813     if (aSc2<0.) {
2814       aSc2=-aSc2;
2815     }
2816     //
2817     if (aSc2<aSc1) {
2818       bRet=!bRet;
2819     }
2820   }//if (dR<Tol) {
2821   return bRet;
2822 }