0025531: Difference in intersection result on Windows and Linux platform is very...
[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 adjasted forceful.
1023 //=======================================================================
1024 static Standard_Boolean InscribePoint(const Standard_Real theUfTarget,
1025                                       const Standard_Real theUlTarget,
1026                                       Standard_Real& theUGiven,
1027                                       const Standard_Real theTol2D,
1028                                       const Standard_Real thePeriod,
1029                                       const Standard_Boolean theFlForce)
1030 {
1031   if((theUfTarget - theUGiven <= theTol2D) &&
1032               (theUGiven - theUlTarget <= theTol2D))
1033   {//it has already inscribed
1034
1035     /*
1036              Utf    U      Utl
1037               +     *       +
1038     */
1039     
1040     if(theFlForce)
1041     {
1042       Standard_Real anUtemp = theUGiven + thePeriod;
1043       if((theUfTarget - anUtemp <= theTol2D) &&
1044                 (anUtemp - theUlTarget <= theTol2D))
1045       {
1046         theUGiven = anUtemp;
1047         return Standard_True;
1048       }
1049       
1050       anUtemp = theUGiven - thePeriod;
1051       if((theUfTarget - anUtemp <= theTol2D) &&
1052                 (anUtemp - theUlTarget <= theTol2D))
1053       {
1054         theUGiven = anUtemp;
1055       }
1056     }
1057
1058     return Standard_True;
1059   }
1060
1061   if(IsEqual(thePeriod, 0.0))
1062   {//it cannot be inscribed
1063     return Standard_False;
1064   }
1065
1066   Standard_Real aDU = theUGiven - theUfTarget;
1067
1068   if(aDU > 0.0)
1069     aDU = -thePeriod;
1070   else
1071     aDU = +thePeriod;
1072
1073   while(((theUGiven - theUfTarget)*aDU < 0.0) && !((theUfTarget - theUGiven <= theTol2D) && (theUGiven - theUlTarget <= theTol2D)))
1074   {
1075     theUGiven += aDU;
1076   }
1077   
1078   return ((theUfTarget - theUGiven <= theTol2D) && (theUGiven - theUlTarget <= theTol2D));
1079 }
1080
1081 //=======================================================================
1082 //function : InscribeInterval
1083 //purpose  : Adjusts theUfGiven and after that fits theUlGiven to result
1084 //=======================================================================
1085 static Standard_Boolean InscribeInterval(const Standard_Real theUfTarget,
1086                                       const Standard_Real theUlTarget,
1087                                       Standard_Real& theUfGiven,
1088                                       Standard_Real& theUlGiven,
1089                                       const Standard_Real theTol2D,
1090                                       const Standard_Real thePeriod)
1091 {
1092   Standard_Real anUpar = theUfGiven;
1093   const Standard_Real aDelta = theUlGiven - theUfGiven;
1094   if(InscribePoint(theUfTarget, theUlTarget, anUpar,
1095                         theTol2D, thePeriod, Standard_False))
1096   {
1097     theUfGiven = anUpar;
1098     theUlGiven = theUfGiven + aDelta;
1099   }
1100   else 
1101   {
1102     anUpar = theUlGiven;
1103     if(InscribePoint(theUfTarget, theUlTarget, anUpar,
1104                         theTol2D, thePeriod, Standard_False))
1105     {
1106       theUlGiven = anUpar;
1107       theUfGiven = theUlGiven - aDelta;
1108     }
1109     else
1110     {
1111       return Standard_False;
1112     }
1113   }
1114
1115   return Standard_True;
1116 }
1117
1118 //=======================================================================
1119 //function : InscribeAndSortArray
1120 //purpose  : Sort from Min to Max value
1121 //=======================================================================
1122 static void InscribeAndSortArray( Standard_Real theArr[],
1123                                   const Standard_Integer theNOfMembers,
1124                                   const Standard_Real theUf,
1125                                   const Standard_Real theUl,
1126                                   const Standard_Real theTol2D,
1127                                   const Standard_Real thePeriod)
1128 {
1129   for(Standard_Integer i = 0; i < theNOfMembers; i++)
1130   {
1131     if(Precision::IsInfinite(theArr[i]))
1132     {
1133       if(theArr[i] < 0.0)
1134         theArr[i] = -theArr[i];
1135
1136       continue;
1137     }
1138
1139     InscribePoint(theUf, theUl, theArr[i], theTol2D, thePeriod, Standard_False);
1140
1141     for(Standard_Integer j = i - 1; j >= 0; j--)
1142     {
1143
1144       if(theArr[j+1] < theArr[j])
1145       {
1146         Standard_Real anUtemp = theArr[j+1];
1147         theArr[j+1] = theArr[j];
1148         theArr[j] = anUtemp;
1149       }
1150     }
1151   }
1152 }
1153
1154
1155 //=======================================================================
1156 //function : AddPointIntoWL
1157 //purpose  : Surf1 is a surface, whose U-par is variable.
1158 //=======================================================================
1159 static Standard_Boolean AddPointIntoWL( const IntSurf_Quadric& theQuad1,
1160                                         const IntSurf_Quadric& theQuad2,
1161                                         const Standard_Boolean isTheReverse,
1162                                         const gp_Pnt2d& thePntOnSurf1,
1163                                         const gp_Pnt2d& thePntOnSurf2,
1164                                         const Standard_Real theUfSurf1,
1165                                         const Standard_Real theUlSurf1,
1166                                         const Standard_Real thePeriodOfSurf1,
1167                                         const Handle(IntSurf_LineOn2S)& theLine,
1168                                         const Standard_Real theTol3D,
1169                                         const Standard_Real theTol2D,
1170                                         const Standard_Boolean theFlForce)
1171 {
1172   gp_Pnt  aPt1(theQuad1.Value(thePntOnSurf1.X(), thePntOnSurf1.Y())),
1173           aPt2(theQuad2.Value(thePntOnSurf2.X(), thePntOnSurf2.Y()));
1174
1175   Standard_Real anUpar = thePntOnSurf1.X();
1176   if(!InscribePoint(theUfSurf1, theUlSurf1, anUpar, theTol2D,
1177                                     thePeriodOfSurf1, theFlForce))
1178     return Standard_False;
1179
1180   IntSurf_PntOn2S aPnt;
1181   
1182   if(isTheReverse)
1183   {
1184     aPnt.SetValue((aPt1.XYZ()+aPt2.XYZ())/2.0,
1185                         thePntOnSurf2.X(), thePntOnSurf2.Y(),
1186                         anUpar, thePntOnSurf1.Y());
1187   }
1188   else
1189   {
1190     aPnt.SetValue((aPt1.XYZ()+aPt2.XYZ())/2.0,
1191                         anUpar, thePntOnSurf1.Y(),
1192                         thePntOnSurf2.X(), thePntOnSurf2.Y());
1193   }
1194
1195   const Standard_Integer aNbPnts = theLine->NbPoints();
1196   if(aNbPnts > 0)
1197   {
1198     Standard_Real aUl = 0.0, aVl = 0.0;
1199     const IntSurf_PntOn2S aPlast = theLine->Value(aNbPnts);
1200     if(isTheReverse)
1201       aPlast.ParametersOnS2(aUl, aVl);
1202     else
1203       aPlast.ParametersOnS1(aUl, aVl);
1204
1205     if(anUpar <= aUl)
1206     {//Parameter value will be always increased.
1207       return Standard_False;
1208     }
1209
1210     //theTol2D is minimal step along parameter changed. 
1211     //Therefore, if we apply this minimal step two 
1212     //neighbour points will be always "same". Consequently,
1213     //we should reduce tolerance for IsSame checking.
1214     const Standard_Real aDTol = 1.0-Epsilon(1.0);
1215     if(aPnt.IsSame(aPlast, theTol3D*aDTol, theTol2D*aDTol))
1216     {
1217       theLine->RemovePoint(aNbPnts);
1218     }
1219   }
1220
1221   theLine->Add(aPnt);
1222   return Standard_True;
1223 }
1224
1225 //=======================================================================
1226 //function : AddBoundaryPoint
1227 //purpose  : 
1228 //=======================================================================
1229 static Standard_Boolean AddBoundaryPoint( const IntSurf_Quadric& theQuad1,
1230                                           const IntSurf_Quadric& theQuad2,
1231                                           const Handle(IntPatch_WLine)& theWL,
1232                                           const stCoeffsValue& theCoeffs,
1233                                           const Bnd_Box2d& theUVSurf1,
1234                                           const Bnd_Box2d& theUVSurf2,
1235                                           const Standard_Real theTol3D,
1236                                           const Standard_Real theTol2D,
1237                                           const Standard_Real thePeriod,
1238                                           const Standard_Real theNulValue,
1239                                           const Standard_Real theU1,
1240                                           const Standard_Real theU2,
1241                                           const Standard_Real theV1,
1242                                           const Standard_Real theV1Prev,
1243                                           const Standard_Real theV2,
1244                                           const Standard_Real theV2Prev,
1245                                           const Standard_Boolean isTheReverse,
1246                                           const Standard_Real theArccosFactor,
1247                                           const Standard_Boolean theFlForce,
1248                                           Standard_Boolean& isTheFound1,
1249                                           Standard_Boolean& isTheFound2)
1250 {
1251   Standard_Real aUSurf1f = 0.0, //const
1252                 aUSurf1l = 0.0,
1253                 aVSurf1f = 0.0,
1254                 aVSurf1l = 0.0;
1255   Standard_Real aUSurf2f = 0.0, //const
1256                 aUSurf2l = 0.0,
1257                 aVSurf2f = 0.0,
1258                 aVSurf2l = 0.0;
1259
1260   theUVSurf1.Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l);
1261   theUVSurf2.Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l);
1262
1263   SearchBoundType aTS1 = SearchNONE, aTS2 = SearchNONE;
1264   Standard_Real aV1zad = aVSurf1f, aV2zad = aVSurf2f;
1265
1266   Standard_Real anUpar1 = theU1, anUpar2 = theU1;
1267   Standard_Real aVf = theV1, aVl = theV1Prev;
1268   MinMax(aVf, aVl);
1269   if((aVf <= aVSurf1f) && (aVSurf1f <= aVl))
1270   {
1271     aTS1 = SearchV1;
1272     aV1zad = aVSurf1f;
1273     isTheFound1 = SearchOnVBounds(aTS1, theCoeffs, aVSurf1f, theU2, theU1, anUpar1);
1274   }
1275   else if((aVf <= aVSurf1l) && (aVSurf1l <= aVl))
1276   {
1277     aTS1 = SearchV1;
1278     aV1zad = aVSurf1l;
1279     isTheFound1 = SearchOnVBounds(aTS1, theCoeffs, aVSurf1l, theU2, theU1, anUpar1);
1280   }
1281
1282   aVf = theV2;
1283   aVl = theV2Prev;
1284   MinMax(aVf, aVl);
1285
1286   if((aVf <= aVSurf2f) && (aVSurf2f <= aVl))
1287   {
1288     aTS2 = SearchV2;
1289     aV2zad = aVSurf2f;
1290     isTheFound2 = SearchOnVBounds(aTS2, theCoeffs, aVSurf2f, theU2, theU1, anUpar2);
1291   }
1292   else if((aVf <= aVSurf2l) && (aVSurf2l <= aVl))
1293   {
1294     aTS2 = SearchV2;
1295     aV2zad = aVSurf2l;
1296     isTheFound2 = SearchOnVBounds(aTS2, theCoeffs, aVSurf2l, theU2, theU1, anUpar2);
1297   }
1298
1299   if(anUpar1 < anUpar2)
1300   {
1301     if(isTheFound1)
1302     {
1303       Standard_Real anArg = theCoeffs.mB * cos(anUpar1 - theCoeffs.mFI1) + theCoeffs.mC;
1304
1305       if(theNulValue > 1.0 - anArg)
1306         anArg = 1.0;
1307       if(anArg + 1.0 < theNulValue)
1308         anArg = -1.0;
1309
1310       Standard_Real aU2 = theCoeffs.mFI2 + theArccosFactor * acos(anArg);
1311       
1312       if(InscribePoint(aUSurf2f, aUSurf2l, aU2, theTol2D, thePeriod, Standard_False))
1313       {
1314         const Standard_Real aV1 = 
1315               (aTS1 == SearchV1) ? aV1zad : 
1316                                   theCoeffs.mK21 * sin(aU2) + theCoeffs.mK11 * sin(anUpar1) +
1317                                   theCoeffs.mL21 * cos(aU2) + theCoeffs.mL11 * cos(anUpar1) + theCoeffs.mM1;
1318         const Standard_Real aV2 = 
1319               (aTS1 == SearchV2) ? aV2zad : 
1320                                   theCoeffs.mK22 * sin(aU2) + theCoeffs.mK12 * sin(anUpar1) +
1321                                   theCoeffs.mL22 * cos(aU2) + theCoeffs.mL12 * cos(anUpar1) + theCoeffs.mM2;
1322
1323         AddPointIntoWL(theQuad1, theQuad2, isTheReverse,
1324                           gp_Pnt2d(anUpar1, aV1), gp_Pnt2d(aU2, aV2),
1325                           aUSurf1f, aUSurf1l, thePeriod,
1326                           theWL->Curve(), theTol3D, theTol2D, theFlForce);
1327       }
1328       else
1329       {
1330         isTheFound1 = Standard_False;
1331       }
1332     }
1333
1334     if(isTheFound2)
1335     {
1336       Standard_Real anArg = theCoeffs.mB * cos(anUpar2 - theCoeffs.mFI1) + theCoeffs.mC;
1337
1338       if(theNulValue > 1.0 - anArg)
1339         anArg = 1.0;
1340       if(anArg + 1.0 < theNulValue)
1341         anArg = -1.0;
1342
1343       Standard_Real aU2 = theCoeffs.mFI2 + theArccosFactor * acos(anArg);
1344       if(InscribePoint(aUSurf2f, aUSurf2l, aU2, theTol2D, thePeriod, Standard_False))
1345       {
1346         const Standard_Real aV1 = 
1347               (aTS2 == SearchV1) ? aV1zad : 
1348                                   theCoeffs.mK21 * sin(aU2) + theCoeffs.mK11 * sin(anUpar2) +
1349                                   theCoeffs.mL21 * cos(aU2) + theCoeffs.mL11 * cos(anUpar2) + theCoeffs.mM1;
1350         const Standard_Real aV2 = 
1351               (aTS2 == SearchV2) ? aV2zad : 
1352                                   theCoeffs.mK22 * sin(aU2) + theCoeffs.mK12 * sin(anUpar2) +
1353                                   theCoeffs.mL22 * cos(aU2) + theCoeffs.mL12 * cos(anUpar2) + theCoeffs.mM2;
1354
1355         AddPointIntoWL(theQuad1, theQuad2, isTheReverse,
1356                         gp_Pnt2d(anUpar2, aV1), gp_Pnt2d(aU2, aV2),
1357                         aUSurf1f, aUSurf1l, thePeriod,
1358                         theWL->Curve(),theTol3D, theTol2D, theFlForce);
1359       }
1360       else
1361       {
1362         isTheFound2 = Standard_False;
1363       }
1364     }
1365   }
1366   else
1367   {
1368     if(isTheFound2)
1369     {
1370       Standard_Real anArg = theCoeffs.mB * cos(anUpar2 - theCoeffs.mFI1) + theCoeffs.mC;
1371
1372       if(theNulValue > 1.0 - anArg)
1373         anArg = 1.0;
1374       if(anArg + 1.0 < theNulValue)
1375         anArg = -1.0;
1376
1377       Standard_Real aU2 = theCoeffs.mFI2 + theArccosFactor * acos(anArg);
1378       
1379       if(InscribePoint(aUSurf2f, aUSurf2l, aU2, theTol2D, thePeriod, Standard_False))
1380       {
1381         const Standard_Real aV1 = (aTS2 == SearchV1) ? aV1zad : 
1382                                   theCoeffs.mK21 * sin(aU2) + theCoeffs.mK11 * sin(anUpar2) +
1383                                   theCoeffs.mL21 * cos(aU2) + theCoeffs.mL11 * cos(anUpar2) + theCoeffs.mM1;
1384         const Standard_Real aV2 = (aTS2 == SearchV2) ? aV2zad : 
1385                                   theCoeffs.mK22 * sin(aU2) + theCoeffs.mK12 * sin(anUpar2) +
1386                                   theCoeffs.mL22 * cos(aU2) + theCoeffs.mL12 * cos(anUpar2) + theCoeffs.mM2;
1387
1388         AddPointIntoWL(theQuad1, theQuad2, isTheReverse, 
1389                         gp_Pnt2d(anUpar2, aV1), gp_Pnt2d(aU2, aV2),
1390                         aUSurf1f, aUSurf1l, thePeriod,
1391                         theWL->Curve(), theTol3D, theTol2D, theFlForce);
1392       }
1393       else
1394       {
1395         isTheFound2 = Standard_False;
1396       }
1397     }
1398
1399     if(isTheFound1)
1400     {
1401       Standard_Real anArg = theCoeffs.mB*cos(anUpar1-theCoeffs.mFI1)+theCoeffs.mC;
1402
1403       if(theNulValue > 1.0 - anArg)
1404         anArg = 1.0;
1405       if(anArg + 1.0 < theNulValue)
1406         anArg = -1.0;
1407
1408       Standard_Real aU2 = theCoeffs.mFI2+theArccosFactor*acos(anArg);
1409       if(InscribePoint(aUSurf2f, aUSurf2l, aU2, theTol2D, thePeriod, Standard_False))
1410       {
1411         const Standard_Real aV1 = (aTS1 == SearchV1) ? aV1zad :
1412                                   theCoeffs.mK21 * sin(aU2) + theCoeffs.mK11 * sin(anUpar1) +
1413                                   theCoeffs.mL21 * cos(aU2) + theCoeffs.mL11 * cos(anUpar1) + theCoeffs.mM1;
1414         const Standard_Real aV2 = (aTS1 == SearchV2) ? aV2zad : 
1415                                   theCoeffs.mK22 * sin(aU2) + theCoeffs.mK12 * sin(anUpar1) +
1416                                   theCoeffs.mL22 * cos(aU2) + theCoeffs.mL12 * cos(anUpar1) + theCoeffs.mM2;
1417
1418         AddPointIntoWL(theQuad1, theQuad2, isTheReverse,
1419                         gp_Pnt2d(anUpar1, aV1), gp_Pnt2d(aU2, aV2),
1420                         aUSurf1f, aUSurf1l, thePeriod,
1421                         theWL->Curve(), theTol3D, theTol2D, theFlForce);
1422       }
1423       else
1424       {
1425         isTheFound1 = Standard_False;
1426       }
1427     }
1428   }
1429
1430   return Standard_True;
1431 }
1432
1433 //=======================================================================
1434 //function : SeekAdditionalPoints
1435 //purpose  : 
1436 //=======================================================================
1437 static void SeekAdditionalPoints( const IntSurf_Quadric& theQuad1,
1438                                   const IntSurf_Quadric& theQuad2,
1439                                   const Handle(IntSurf_LineOn2S)& theLile,
1440                                   const stCoeffsValue& theCoeffs,
1441                                   const Standard_Integer theMinNbPoints,
1442                                   const Standard_Real theU2f,
1443                                   const Standard_Real theU2l,
1444                                   const Standard_Real theTol2D,
1445                                   const Standard_Real thePeriodOfSurf2,
1446                                   const Standard_Real theArccosFactor,
1447                                   const Standard_Boolean isTheReverse)
1448 {
1449   Standard_Integer aNbPoints = theLile->NbPoints();
1450   if(aNbPoints >= theMinNbPoints)
1451   {
1452     return;
1453   }
1454
1455   Standard_Real U1prec = 0.0, V1prec = 0.0, U2prec = 0.0, V2prec = 0.0;
1456
1457   Standard_Integer aNbPointsPrev = 0;
1458   while(aNbPoints < theMinNbPoints && (aNbPoints != aNbPointsPrev))
1459   {
1460     aNbPointsPrev = aNbPoints;
1461     for(Standard_Integer fp = 1, lp = 2; fp < aNbPoints; fp = lp + 1)
1462     {
1463       Standard_Real U1f = 0.0, V1f = 0.0; //first point in 1st suraface
1464       Standard_Real U1l = 0.0, V1l = 0.0; //last  point in 1st suraface
1465
1466       Standard_Real U2f = 0.0, V2f = 0.0; //first point in 2nd suraface
1467       Standard_Real U2l = 0.0, V2l = 0.0; //last  point in 2nd suraface
1468
1469       lp = fp+1;
1470       
1471       if(isTheReverse)
1472       {
1473         theLile->Value(fp).ParametersOnS2(U1f, V1f);
1474         theLile->Value(lp).ParametersOnS2(U1l, V1l);
1475
1476         theLile->Value(fp).ParametersOnS1(U2f, V2f);
1477         theLile->Value(lp).ParametersOnS1(U2l, V2l);
1478       }
1479       else
1480       {
1481         theLile->Value(fp).ParametersOnS1(U1f, V1f);
1482         theLile->Value(lp).ParametersOnS1(U1l, V1l);
1483
1484         theLile->Value(fp).ParametersOnS2(U2f, V2f);
1485         theLile->Value(lp).ParametersOnS2(U2l, V2l);
1486       }
1487
1488       if(Abs(U1l - U1f) <= theTol2D)
1489       {
1490         //Step is minimal. It is not necessary to divide it.
1491         continue;
1492       }
1493
1494       U1prec = 0.5*(U1f+U1l);
1495       
1496       Standard_Real anArg = theCoeffs.mB * cos(U1prec - theCoeffs.mFI1) + theCoeffs.mC;
1497       if(anArg > 1.0)
1498         anArg = 1.0;
1499       if(anArg < -1.0)
1500         anArg = -1.0;
1501
1502       U2prec = theCoeffs.mFI2 + theArccosFactor*acos(anArg);
1503       InscribePoint(theU2f, theU2l, U2prec, theTol2D, thePeriodOfSurf2, Standard_False);
1504
1505       gp_Pnt aP1, aP2;
1506
1507       V1prec = theCoeffs.mK21 * sin(U2prec) + 
1508                 theCoeffs.mK11 * sin(U1prec) + 
1509                 theCoeffs.mL21 * cos(U2prec) + 
1510                 theCoeffs.mL11 * cos(U1prec) + theCoeffs.mM1;
1511       V2prec = theCoeffs.mK22 * sin(U2prec) + 
1512                 theCoeffs.mK12 * sin(U1prec) + 
1513                 theCoeffs.mL22 * cos(U2prec) + 
1514                 theCoeffs.mL12 * cos(U1prec) + theCoeffs.mM2;
1515
1516       aP1 = theQuad1.Value(U1prec, V1prec);
1517       aP2 = theQuad2.Value(U2prec, V2prec);
1518
1519       gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
1520
1521 #ifdef OCCT_DEBUG
1522       //cout << "|P1Pi| = " << aP1.SquareDistance(aPInt) << "; |P2Pi| = " << aP2.SquareDistance(aPInt) << endl;
1523 #endif
1524
1525       IntSurf_PntOn2S anIP;
1526       if(isTheReverse)
1527       {
1528         anIP.SetValue(aPInt, U2prec, V2prec, U1prec, V1prec);
1529       }
1530       else
1531       {
1532         anIP.SetValue(aPInt, U1prec, V1prec, U2prec, V2prec);
1533       }
1534
1535       theLile->InsertBefore(lp, anIP);
1536
1537       aNbPoints = theLile->NbPoints();
1538       if(aNbPoints >= theMinNbPoints)
1539       {
1540         return;
1541       }
1542     }
1543   }
1544 }
1545
1546 //=======================================================================
1547 //function : CriticalPointsComputing
1548 //purpose  : 
1549 //=======================================================================
1550 static void CriticalPointsComputing(const stCoeffsValue& theCoeffs,
1551                                     const Standard_Real theUSurf1f,
1552                                     const Standard_Real theUSurf1l,
1553                                     const Standard_Real theUSurf2f,
1554                                     const Standard_Real theUSurf2l,
1555                                     const Standard_Real thePeriod,
1556                                     const Standard_Real theTol2D,
1557                                     const Standard_Integer theNbCritPointsMax,
1558                                     Standard_Real theU1crit[])
1559 {
1560   theU1crit[0] = 0.0;
1561   theU1crit[1] = thePeriod;
1562   theU1crit[2] = theUSurf1f;
1563   theU1crit[3] = theUSurf1l;
1564
1565   const Standard_Real aCOS = cos(theCoeffs.mFI2);
1566   const Standard_Real aBSB = Abs(theCoeffs.mB);
1567   if((theCoeffs.mC - aBSB <= aCOS) && (aCOS <= theCoeffs.mC + aBSB))
1568   {
1569     Standard_Real anArg = (aCOS - theCoeffs.mC) / theCoeffs.mB;
1570     if(anArg > 1.0)
1571       anArg = 1.0;
1572     if(anArg < -1.0)
1573       anArg = -1.0;
1574
1575     theU1crit[4] = -acos(anArg) + theCoeffs.mFI1;
1576     theU1crit[5] = acos(anArg) + theCoeffs.mFI1;
1577   }
1578
1579   Standard_Real aSf = cos(theUSurf2f - theCoeffs.mFI2);
1580   Standard_Real aSl = cos(theUSurf2l - theCoeffs.mFI2);
1581   MinMax(aSf, aSl);
1582
1583   theU1crit[6] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? -acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : -Precision::Infinite();
1584   theU1crit[7] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? -acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : Precision::Infinite();
1585   theU1crit[8] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?  acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : -Precision::Infinite();
1586   theU1crit[9] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?  acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : Precision::Infinite();
1587
1588   //preparative treatment of array
1589   InscribeAndSortArray(theU1crit, theNbCritPointsMax, 0.0, thePeriod, theTol2D, thePeriod);
1590   for(Standard_Integer i = 1; i < theNbCritPointsMax; i++)
1591   {
1592     Standard_Real &a = theU1crit[i],
1593                   &b = theU1crit[i-1];
1594     const Standard_Real aRemain = fmod(Abs(a - b), thePeriod); // >= 0, because Abs(a - b) >= 0
1595     if((Abs(a - b) < theTol2D) || (aRemain < theTol2D) || (Abs(aRemain - thePeriod) < theTol2D))
1596     {
1597       a = (a + b)/2.0;
1598       b = Precision::Infinite();
1599     }
1600   }
1601 }
1602
1603 //=======================================================================
1604 //function : IntCyCyTrim
1605 //purpose  : 
1606 //=======================================================================
1607 Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
1608                               const IntSurf_Quadric& theQuad2,
1609                               const Standard_Real theTol3D,
1610                               const Standard_Real theTol2D,
1611                               const Bnd_Box2d& theUVSurf1,
1612                               const Bnd_Box2d& theUVSurf2,
1613                               const Standard_Boolean isTheReverse,
1614                               Standard_Boolean& isTheEmpty,
1615                               IntPatch_SequenceOfLine& theSlin,
1616                               IntPatch_SequenceOfPoint& theSPnt)
1617 {
1618   Standard_Real aUSurf1f = 0.0, //const
1619                 aUSurf1l = 0.0,
1620                 aVSurf1f = 0.0,
1621                 aVSurf1l = 0.0;
1622   Standard_Real aUSurf2f = 0.0, //const
1623                 aUSurf2l = 0.0,
1624                 aVSurf2f = 0.0,
1625                 aVSurf2l = 0.0;
1626
1627   theUVSurf1.Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l);
1628   theUVSurf2.Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l);
1629
1630   const Standard_Real aNulValue = 0.01*Precision::PConfusion();
1631
1632   const gp_Cylinder&  aCyl1 = theQuad1.Cylinder(),
1633                       aCyl2 = theQuad2.Cylinder();
1634
1635   IntAna_QuadQuadGeo anInter(aCyl1,aCyl2,theTol3D);
1636
1637   if (!anInter.IsDone())
1638   {
1639     return Standard_False;
1640   }
1641
1642   IntAna_ResultType aTypInt = anInter.TypeInter();
1643
1644   if(aTypInt != IntAna_NoGeometricSolution)
1645   { //It is not necessary (because result is an analytic curve) or
1646     //it is impossible to make Walking-line.
1647
1648     return Standard_False;
1649   }
1650     
1651   theSlin.Clear();
1652   theSPnt.Clear();
1653   const Standard_Integer aNbMaxPoints = 2000;
1654   const Standard_Integer aNbMinPoints = 200;
1655   const Standard_Integer aNbPoints = Min(Max(aNbMinPoints, 
1656                       RealToInt(20.0*aCyl1.Radius())), aNbMaxPoints);
1657   const Standard_Real aPeriod = 2.0*M_PI;
1658   const Standard_Real aStepMin = theTol2D, 
1659                       aStepMax = (aUSurf1l-aUSurf1f)/IntToReal(aNbPoints);
1660   const Standard_Integer aNbWLines = 2;
1661
1662   const stCoeffsValue anEquationCoeffs(aCyl1, aCyl2);
1663
1664   //Boundaries
1665   const Standard_Integer aNbOfBoundaries = 2;
1666   Standard_Real aU1f[aNbOfBoundaries] = {-Precision::Infinite(), -Precision::Infinite()};
1667   Standard_Real aU1l[aNbOfBoundaries] = {Precision::Infinite(), Precision::Infinite()};
1668
1669   if(anEquationCoeffs.mB > 0.0)
1670   {
1671     if(anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) < -1.0)
1672     {//There is NOT intersection
1673       return Standard_True;
1674     }
1675     else if(anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) <= 1.0)
1676     {//U=[0;2*PI]+aFI1
1677       aU1f[0] = anEquationCoeffs.mFI1;
1678       aU1l[0] = aPeriod + anEquationCoeffs.mFI1;
1679     }
1680     else if((1 + anEquationCoeffs.mC <= anEquationCoeffs.mB) &&
1681             (anEquationCoeffs.mB <= 1 - anEquationCoeffs.mC))
1682     {
1683       Standard_Real anArg = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB;
1684       if(anArg > 1.0)
1685         anArg = 1.0;
1686       if(anArg < -1.0)
1687         anArg = -1.0;
1688
1689       const Standard_Real aDAngle = acos(anArg);
1690       //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1)
1691       aU1f[0] = anEquationCoeffs.mFI1;
1692       aU1l[0] = aDAngle + anEquationCoeffs.mFI1;
1693       aU1f[1] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
1694       aU1l[1] = aPeriod + anEquationCoeffs.mFI1;
1695     }
1696     else if((1 - anEquationCoeffs.mC <= anEquationCoeffs.mB) &&
1697             (anEquationCoeffs.mB <= 1 + anEquationCoeffs.mC))
1698     {
1699       Standard_Real anArg = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB;
1700       if(anArg > 1.0)
1701         anArg = 1.0;
1702       if(anArg < -1.0)
1703         anArg = -1.0;
1704
1705       const Standard_Real aDAngle = acos(anArg);
1706       //U=[aDAngle;2*PI-aDAngle]+aFI1
1707
1708       aU1f[0] = aDAngle + anEquationCoeffs.mFI1;
1709       aU1l[0] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
1710     }
1711     else if(anEquationCoeffs.mB - Abs(anEquationCoeffs.mC) >= 1.0)
1712     {
1713       Standard_Real anArg1 = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB,
1714                     anArg2 = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB;
1715       if(anArg1 > 1.0)
1716         anArg1 = 1.0;
1717       if(anArg1 < -1.0)
1718         anArg1 = -1.0;
1719
1720       if(anArg2 > 1.0)
1721         anArg2 = 1.0;
1722       if(anArg2 < -1.0)
1723         anArg2 = -1.0;
1724
1725       const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2);
1726       //(U=[aDAngle1;aDAngle2]+aFI1) ||
1727       //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
1728
1729       aU1f[0] = aDAngle1 + anEquationCoeffs.mFI1;
1730       aU1l[0] = aDAngle2 + anEquationCoeffs.mFI1;
1731       aU1f[1] = aPeriod - aDAngle2 + anEquationCoeffs.mFI1;
1732       aU1l[1] = aPeriod - aDAngle1 + anEquationCoeffs.mFI1;
1733     }
1734     else
1735     {
1736       Standard_Failure::Raise("Error. Exception. Unhandled case (Range computation)!");
1737     }
1738   }
1739   else if(anEquationCoeffs.mB < 0.0)
1740   {
1741     if(anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) > 1.0)
1742     {//There is NOT intersection
1743       return Standard_True;
1744     }
1745     else if(-anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) <= 1.0)
1746     {//U=[0;2*PI]+aFI1
1747       aU1f[0] = anEquationCoeffs.mFI1;
1748       aU1l[0] = aPeriod + anEquationCoeffs.mFI1;
1749     }
1750     else if((-anEquationCoeffs.mC - 1 <= anEquationCoeffs.mB) &&
1751             ( anEquationCoeffs.mB <= anEquationCoeffs.mC - 1))
1752     {
1753       Standard_Real anArg = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB;
1754       if(anArg > 1.0)
1755         anArg = 1.0;
1756       if(anArg < -1.0)
1757         anArg = -1.0;
1758
1759       const Standard_Real aDAngle = acos(anArg);
1760       //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1)
1761
1762       aU1f[0] = anEquationCoeffs.mFI1;
1763       aU1l[0] = aDAngle + anEquationCoeffs.mFI1;
1764       aU1f[1] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
1765       aU1l[1] = aPeriod + anEquationCoeffs.mFI1;
1766     }
1767     else if((anEquationCoeffs.mC - 1 <= anEquationCoeffs.mB) &&
1768             (anEquationCoeffs.mB <= -anEquationCoeffs.mB - 1))
1769     {
1770       Standard_Real anArg = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB;
1771       if(anArg > 1.0)
1772         anArg = 1.0;
1773       if(anArg < -1.0)
1774         anArg = -1.0;
1775
1776       const Standard_Real aDAngle = acos(anArg);
1777       //U=[aDAngle;2*PI-aDAngle]+aFI1
1778
1779       aU1f[0] = aDAngle + anEquationCoeffs.mFI1;
1780       aU1l[0] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
1781     }
1782     else if(-anEquationCoeffs.mB - Abs(anEquationCoeffs.mC) >= 1.0)
1783     {
1784       Standard_Real anArg1 = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB,
1785                     anArg2 = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB;
1786       if(anArg1 > 1.0)
1787         anArg1 = 1.0;
1788       if(anArg1 < -1.0)
1789         anArg1 = -1.0;
1790
1791       if(anArg2 > 1.0)
1792         anArg2 = 1.0;
1793       if(anArg2 < -1.0)
1794         anArg2 = -1.0;
1795
1796       const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2);
1797       //(U=[aDAngle1;aDAngle2]+aFI1) ||
1798       //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
1799
1800       aU1f[0] = aDAngle1 + anEquationCoeffs.mFI1;
1801       aU1l[0] = aDAngle2 + anEquationCoeffs.mFI1;
1802       aU1f[1] = aPeriod - aDAngle2 + anEquationCoeffs.mFI1;
1803       aU1l[1] = aPeriod - aDAngle1 + anEquationCoeffs.mFI1;
1804     }
1805     else
1806     {
1807       Standard_Failure::Raise("Error. Exception. Unhandled case (Range computation)!");
1808     }
1809   }
1810   else
1811   {
1812     Standard_Failure::Raise("Error. Exception. Unhandled case (B-parameter computation)!");
1813   }
1814
1815   for(Standard_Integer i = 0; i < aNbOfBoundaries; i++)
1816   {
1817     if(Precision::IsInfinite(aU1f[i]) && Precision::IsInfinite(aU1l[i]))
1818       continue;
1819
1820     InscribeInterval(aUSurf1f, aUSurf1l, aU1f[i], aU1l[i], theTol2D, aPeriod);
1821   }
1822
1823   if( !Precision::IsInfinite(aU1f[0]) && !Precision::IsInfinite(aU1f[1]) &&
1824       !Precision::IsInfinite(aU1l[0]) && !Precision::IsInfinite(aU1l[1]))
1825   {
1826     if( ((aU1f[1] <= aU1l[0]) || (aU1l[1] <= aU1l[0])) && 
1827         ((aU1f[0] <= aU1l[1]) || (aU1l[0] <= aU1l[1])))
1828     {//Join all intervals to one
1829       aU1f[0] = Min(aU1f[0], aU1f[1]);
1830       aU1l[0] = Max(aU1l[0], aU1l[1]);
1831
1832       aU1f[1] = -Precision::Infinite();
1833       aU1l[1] = Precision::Infinite();
1834     }
1835   }
1836
1837   //Critical points
1838   //[0...1] - in these points parameter U1 goes through
1839   //          the seam-edge of the first cylinder.
1840   //[2...3] - First and last U1 parameter.
1841   //[4...5] - in these points parameter U2 goes through
1842   //          the seam-edge of the second cylinder.
1843   //[6...9] - in these points an intersection line goes through
1844   //          U-boundaries of the second surface.
1845   const Standard_Integer aNbCritPointsMax = 10;
1846   Standard_Real anU1crit[aNbCritPointsMax] = {Precision::Infinite(),
1847                                               Precision::Infinite(),
1848                                               Precision::Infinite(),
1849                                               Precision::Infinite(),
1850                                               Precision::Infinite(),
1851                                               Precision::Infinite(),
1852                                               Precision::Infinite(),
1853                                               Precision::Infinite(),
1854                                               Precision::Infinite(),
1855                                               Precision::Infinite()};
1856
1857   CriticalPointsComputing(anEquationCoeffs, aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
1858                                       aPeriod, theTol2D, aNbCritPointsMax, anU1crit);
1859
1860
1861   //Getting Walking-line
1862
1863   for(Standard_Integer aCurInterval = 0; aCurInterval < aNbOfBoundaries; aCurInterval++)
1864   {
1865     if(Precision::IsInfinite(aU1f[aCurInterval]) && Precision::IsInfinite(aU1l[aCurInterval]))
1866       continue;
1867
1868     Standard_Boolean isAddedIntoWL[aNbWLines];
1869     for(Standard_Integer i = 0; i < aNbWLines; i++)
1870       isAddedIntoWL[i] = Standard_False;
1871
1872     Standard_Real anUf = aU1f[aCurInterval], anUl = aU1l[aCurInterval];
1873     const Standard_Boolean isDeltaPeriod  = IsEqual(anUl-anUf, aPeriod);
1874
1875     //Inscribe and sort critical points
1876     InscribeAndSortArray(anU1crit, aNbCritPointsMax, anUf, anUl, theTol2D, aPeriod);
1877
1878     while(anUf < anUl)
1879     {
1880       Standard_Real aU2[aNbWLines], aV1[aNbWLines], aV2[aNbWLines];
1881       Standard_Integer aWLFindStatus[aNbWLines];
1882       Standard_Real aV1Prev[aNbWLines], aV2Prev[aNbWLines];
1883       Standard_Real anArccosFactor[aNbWLines] = {1.0, -1.0};
1884       Standard_Boolean isAddingWLEnabled[aNbWLines];
1885
1886       Handle(IntSurf_LineOn2S) aL2S[aNbWLines];
1887       Handle(IntPatch_WLine) aWLine[aNbWLines];
1888       for(Standard_Integer i = 0; i < aNbWLines; i++)
1889       {
1890         aL2S[i] = new IntSurf_LineOn2S();
1891         aWLine[i] = new IntPatch_WLine(aL2S[i], Standard_False);
1892         aWLFindStatus[i] = 0;
1893         isAddingWLEnabled[i] = Standard_True;
1894         aU2[i] = aV1[i] = aV2[i] = 0.0;
1895         aV1Prev[i] = aV2Prev[i] = 0.0;
1896       }
1897       
1898       Standard_Real anU1 = anUf;
1899
1900       Standard_Real aCriticalDelta[aNbCritPointsMax];
1901       for(Standard_Integer i = 0; i < aNbCritPointsMax; i++)
1902         aCriticalDelta[i] = anU1 - anU1crit[i];
1903
1904       Standard_Boolean isFirst = Standard_True;
1905
1906       while(anU1 <= anUl)
1907       {
1908         if(isDeltaPeriod)
1909         {
1910           if(IsEqual(anU1, anUl))
1911           {
1912             //if isAddedIntoWL* == TRUE WLine contains only one point
1913             //(which was end point of previous WLine). If we will
1914             //add point found on the current step WLine will contain only
1915             //two points. At that both these points will be equal to the
1916             //points found earlier. Therefore, new WLine will repeat 
1917             //already existing WLine. Consequently, it is necessary 
1918             //to forbid building new line in this case.
1919
1920             for(Standard_Integer i = 0; i < aNbWLines; i++)
1921               isAddingWLEnabled[i] = !isAddedIntoWL[i];
1922           }
1923         }
1924
1925         for(Standard_Integer i = 0; i < aNbCritPointsMax; i++)
1926         {
1927           if((anU1 - anU1crit[i])*aCriticalDelta[i] < 0.0)
1928           {
1929             anU1 = anU1crit[i];
1930
1931             for(Standard_Integer i = 0; i < aNbWLines; i++)
1932               aWLFindStatus[i] = 2;
1933
1934             break;
1935           }
1936         }
1937
1938         Standard_Real anArg = anEquationCoeffs.mB * 
1939               cos(anU1 - anEquationCoeffs.mFI1) + anEquationCoeffs.mC;
1940         
1941         if(aNulValue > 1.0 - anArg)
1942           anArg = 1.0;
1943         if(anArg + 1.0 < aNulValue)
1944           anArg = -1.0;
1945
1946         for(Standard_Integer i = 0; i < aNbWLines; i++)
1947         {
1948           const Standard_Integer aNbPntsWL =  aWLine[i].IsNull() ? 0 :
1949                                               aWLine[i]->Curve()->NbPoints();
1950           aU2[i] = anEquationCoeffs.mFI2 + anArccosFactor[i]*acos(anArg);
1951
1952           InscribePoint(aUSurf2f, aUSurf2l, aU2[i], theTol2D, aPeriod, Standard_False);
1953
1954           if(aNbPntsWL == 0)
1955           {//the line has not contained any points yet
1956             if(((aUSurf2l - aUSurf2f) >= aPeriod) && 
1957                 ((Abs(aU2[i] - aUSurf2f) < theTol2D) ||
1958                   (Abs(aU2[i]-aUSurf2l) < theTol2D)))
1959             {
1960               const Standard_Real anU1Temp = anU1 + aStepMin;
1961               Standard_Real anArgTemp = anEquationCoeffs.mB * 
1962                                         cos(anU1Temp - anEquationCoeffs.mFI1) +
1963                                         anEquationCoeffs.mC;
1964
1965               if(aNulValue > 1.0 - anArgTemp)
1966                 anArgTemp = 1.0;
1967
1968               if(anArgTemp + 1.0 < aNulValue)
1969                 anArgTemp = -1.0;
1970
1971               Standard_Real aU2Temp = anEquationCoeffs.mFI2 +
1972                                       anArccosFactor[i]*acos(anArgTemp);
1973
1974               InscribePoint(aUSurf2f, aUSurf2l, aU2Temp, theTol2D, aPeriod, Standard_False);
1975
1976               if(2.0*Abs(aU2Temp - aU2[i]) > aPeriod)
1977               {
1978                 if(aU2Temp > aU2[i])
1979                   aU2[i] += aPeriod;
1980                 else
1981                   aU2[i] -= aPeriod;
1982               }
1983             }
1984           }
1985
1986           if(aNbPntsWL > 0)
1987           {
1988             if(((aUSurf2l - aUSurf2f) >= aPeriod) && 
1989                 ((Abs(aU2[i] - aUSurf2f) < theTol2D) ||
1990                   (Abs(aU2[i]-aUSurf2l) < theTol2D)))
1991             {//end of the line
1992               Standard_Real aU2prev = 0.0, aV2prev = 0.0;
1993               if(isTheReverse)
1994                 aWLine[i]->Curve()->Value(aNbPntsWL).ParametersOnS1(aU2prev, aV2prev);
1995               else
1996                 aWLine[i]->Curve()->Value(aNbPntsWL).ParametersOnS2(aU2prev, aV2prev);
1997
1998               if(2.0*Abs(aU2prev - aU2[i]) > aPeriod)
1999               {
2000                 if(aU2prev > aU2[i])
2001                   aU2[i] += aPeriod;
2002                 else
2003                   aU2[i] -= aPeriod;
2004               }
2005             }
2006           }
2007
2008           aV1[i] =  anEquationCoeffs.mK21 * sin(aU2[i]) + 
2009                     anEquationCoeffs.mK11 * sin(anU1) +
2010                     anEquationCoeffs.mL21 * cos(aU2[i]) +
2011                     anEquationCoeffs.mL11 * cos(anU1) + anEquationCoeffs.mM1;
2012
2013           aV2[i] =  anEquationCoeffs.mK22 * sin(aU2[i]) +
2014                     anEquationCoeffs.mK12 * sin(anU1) +
2015                     anEquationCoeffs.mL22 * cos(aU2[i]) +
2016                     anEquationCoeffs.mL12 * cos(anU1) + anEquationCoeffs.mM2;
2017
2018           if(isFirst)
2019           {
2020             aV1Prev[i] = aV1[i];
2021             aV2Prev[i] = aV2[i];
2022           }
2023         }//for(Standard_Integer i = 0; i < aNbWLines; i++)
2024
2025         isFirst = Standard_False;
2026
2027         //Looking for points into WLine
2028         Standard_Boolean isBroken = Standard_False;
2029         for(Standard_Integer i = 0; i < aNbWLines; i++)
2030         {
2031           if(!isAddingWLEnabled[i])
2032           {
2033             aV1Prev[i] = aV1[i];
2034             aV2Prev[i] = aV2[i];
2035
2036             if(aWLFindStatus[i] == 2)
2037               isBroken = Standard_True;
2038
2039             continue;
2040           }
2041
2042           if( ((aUSurf2f-aU2[i]) <= theTol2D) && ((aU2[i]-aUSurf2l) <= theTol2D) &&
2043               ((aVSurf1f - aV1[i]) <= theTol2D) && ((aV1[i] - aVSurf1l) <= theTol2D) &&
2044               ((aVSurf2f - aV2[i]) <= theTol2D) && ((aV2[i] - aVSurf2l) <= theTol2D))
2045           {
2046             Standard_Boolean isForce = Standard_False;
2047             if(!aWLFindStatus[i])
2048             {
2049               Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
2050
2051               if(((aUSurf2l - aUSurf2f) >= aPeriod) && (Abs(anU1-aUSurf1l) < theTol2D))
2052               {
2053                 isForce = Standard_True;
2054               }
2055
2056               AddBoundaryPoint( theQuad1, theQuad2, aWLine[i], anEquationCoeffs,
2057                                 theUVSurf1, theUVSurf2, theTol3D, theTol2D, aPeriod,
2058                                 aNulValue, anU1, aU2[i], aV1[i], aV1Prev[i],
2059                                 aV2[i], aV2Prev[i], isTheReverse,
2060                                 anArccosFactor[i], isForce, isFound1, isFound2);
2061               
2062               if(isFound1 || isFound2)
2063               {
2064                 aWLFindStatus[i] = 1;
2065               }
2066             }
2067
2068             if(( aWLFindStatus[i] != 2) || (aWLine[i]->NbPnts() >= 1))
2069             {
2070               if(AddPointIntoWL(theQuad1, theQuad2, isTheReverse, 
2071                                 gp_Pnt2d(anU1, aV1[i]), gp_Pnt2d(aU2[i], aV2[i]),
2072                                 aUSurf1f, aUSurf1l, aPeriod,
2073                                 aWLine[i]->Curve(), theTol3D, theTol2D, isForce))
2074               {
2075                 if(!aWLFindStatus[i])
2076                 {
2077                   aWLFindStatus[i] = 1;
2078                 }
2079               }
2080             }
2081           }
2082           else
2083           {
2084             if(aWLFindStatus[i] == 1)
2085             {
2086               Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
2087
2088               AddBoundaryPoint( theQuad1, theQuad2, aWLine[i], anEquationCoeffs,
2089                                 theUVSurf1, theUVSurf2, theTol3D, theTol2D, aPeriod,
2090                                 aNulValue, anU1, aU2[i], aV1[i], aV1Prev[i],
2091                                 aV2[i], aV2Prev[i], isTheReverse,
2092                                 anArccosFactor[i], Standard_False, isFound1, isFound2);
2093
2094               if(isFound1 || isFound2)
2095                 aWLFindStatus[i] = 2; //start a new line
2096             }
2097           }
2098
2099           aV1Prev[i] = aV1[i];
2100           aV2Prev[i] = aV2[i];
2101
2102           if(aWLFindStatus[i] == 2)
2103             isBroken = Standard_True;
2104         }//for(Standard_Integer i = 0; i < aNbWLines; i++)
2105
2106         if(isBroken)
2107         {//current lines are filled. Go to the next lines
2108           anUf = anU1;
2109           break;
2110         }
2111
2112         //Step computing
2113
2114         Standard_Real aStepU1 = aStepMax;
2115
2116         for(Standard_Integer i = 0; i < aNbWLines; i++)
2117         {
2118           Standard_Real aDeltaU1V1 = aStepU1, aDeltaU1V2 = aStepU1;
2119
2120           Standard_Real aFact1 = !IsEqual(sin(aU2[i] - anEquationCoeffs.mFI2), 0.0) ? 
2121                                   anEquationCoeffs.mK1 * sin(anU1 - anEquationCoeffs.mFIV1) +
2122                                   anEquationCoeffs.mL1 * anEquationCoeffs.mB * sin(aU2[i] - anEquationCoeffs.mPSIV1) *
2123                                   sin(anU1 - anEquationCoeffs.mFI1)/sin(aU2[i]-anEquationCoeffs.mFI2) : 0.0,
2124                         aFact2 = !IsEqual(sin(aU2[i]-anEquationCoeffs.mFI2), 0.0) ? 
2125                                   anEquationCoeffs.mK2 * sin(anU1 - anEquationCoeffs.mFIV2) + 
2126                                   anEquationCoeffs.mL2 * anEquationCoeffs.mB * sin(aU2[i] - anEquationCoeffs.mPSIV2) *
2127                                   sin(anU1 - anEquationCoeffs.mFI1)/sin(aU2[i] - anEquationCoeffs.mFI2) : 0.0;
2128
2129           Standard_Real aDeltaV1 = (aVSurf1l - aVSurf1f)/IntToReal(aNbPoints),
2130                         aDeltaV2 = (aVSurf2l - aVSurf2f)/IntToReal(aNbPoints);
2131
2132           if((aV1[i] < aVSurf1f) && (aFact1 < 0.0))
2133           {//Make close to aVSurf1f by increasing anU1
2134             aDeltaV1 = Min(aDeltaV1, Abs(aV1[i]-aVSurf1f));
2135           }
2136
2137           if((aV1[i] > aVSurf1l) && (aFact1 > 0.0))
2138           {//Make close to aVSurf1l by increasing anU1
2139             aDeltaV1 = Min(aDeltaV1, Abs(aV1[i]-aVSurf1l));
2140           }
2141
2142           if((aV2[i] < aVSurf2f) && (aFact2 < 0.0))
2143           {//Make close to aVSurf2f by increasing anU1
2144             aDeltaV2 = Min(aDeltaV2, Abs(aV2[i]-aVSurf2f));
2145           }
2146
2147           if((aV2[i] > aVSurf2l) && (aFact2 > 0.0))
2148           {//Make close to aVSurf2l by increasing anU1
2149             aDeltaV2 = Min(aDeltaV2, Abs(aV2[i]-aVSurf1l));
2150           }
2151
2152           aDeltaU1V1 = !IsEqual(aFact1,0.0)? Abs(aDeltaV1/aFact1) : aStepMax;
2153           aDeltaU1V2 = !IsEqual(aFact2,0.0)? Abs(aDeltaV2/aFact2) : aStepMax;
2154
2155           if(aDeltaU1V1 < aStepU1)
2156             aStepU1 = aDeltaU1V1;
2157
2158           if(aDeltaU1V2 < aStepU1)
2159             aStepU1 = aDeltaU1V2;
2160         }
2161
2162         if(aStepU1 < aStepMin)
2163           aStepU1 = aStepMin;
2164       
2165         if(aStepU1 > aStepMax)
2166           aStepU1 = aStepMax;
2167
2168         anU1 += aStepU1;
2169
2170         const Standard_Real aDiff = anU1 - anUl;
2171         if((0.0 < aDiff) && (aDiff < aStepU1-Precision::PConfusion()))
2172           anU1 = anUl;
2173
2174         anUf = anU1;
2175
2176         for(Standard_Integer i = 0; i < aNbWLines; i++)
2177         {
2178           if(aWLine[i]->NbPnts() != 1)
2179             isAddedIntoWL[i] = Standard_False;
2180         }
2181       }
2182
2183       for(Standard_Integer i = 0; i < aNbWLines; i++)
2184       {
2185         if((aWLine[i]->NbPnts() == 1) && (!isAddedIntoWL[i]))
2186         {
2187           isTheEmpty = Standard_False;
2188           Standard_Real u1, v1, u2, v2;
2189           aWLine[i]->Point(1).Parameters(u1, v1, u2, v2);
2190           IntPatch_Point aP;
2191           aP.SetParameter(u1);
2192           aP.SetParameters(u1, v1, u2, v2);
2193           aP.SetTolerance(theTol3D);
2194           aP.SetValue(aWLine[i]->Point(1).Value());
2195
2196           theSPnt.Append(aP);
2197         }
2198         else if(aWLine[i]->NbPnts() > 1)
2199         {
2200           Standard_Boolean isGood = Standard_True;
2201
2202           if(aWLine[i]->NbPnts() == 2)
2203           {
2204             const IntSurf_PntOn2S& aPf = aWLine[i]->Point(1);
2205             const IntSurf_PntOn2S& aPl = aWLine[i]->Point(2);
2206             
2207             if(aPf.IsSame(aPl, Precision::Confusion()))
2208               isGood = Standard_False;
2209           }
2210
2211           if(isGood)
2212           {
2213             isTheEmpty = Standard_False;
2214             isAddedIntoWL[i] = Standard_True;
2215             SeekAdditionalPoints( theQuad1, theQuad2, aWLine[i]->Curve(), 
2216                                   anEquationCoeffs, aNbPoints, aUSurf2f, aUSurf2l,
2217                                   theTol2D, aPeriod, anArccosFactor[i], isTheReverse);
2218
2219             aWLine[i]->ComputeVertexParameters(theTol3D);
2220             theSlin.Append(aWLine[i]);
2221           }
2222         }
2223         else
2224         {
2225           isAddedIntoWL[i] = Standard_False;
2226         }
2227       }
2228     }
2229   }
2230
2231   if(theSlin.Length() > 0)
2232   {
2233     for(Standard_Integer aNumOfLine = 2; aNumOfLine <= theSlin.Length(); aNumOfLine++)
2234     {
2235       const Handle(IntPatch_WLine)& aWLine = Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine));
2236
2237       const IntSurf_PntOn2S& aPntFWL = aWLine->Point(1);
2238
2239       Standard_Real aU1 = 0.0, aU2 = 0.0, aV1 = 0.0, aV2 = 0.0;
2240       aPntFWL.Parameters(aU1, aV1, aU2, aV2);
2241
2242       if( IsEqual(aU1, 0.0) || IsEqual(aU1, aPeriod))
2243       {
2244         theSlin.Exchange(1, aNumOfLine);
2245         break;
2246       }
2247     }
2248
2249     for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
2250     {
2251       const Handle(IntPatch_WLine)& aWLine1 = Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine1));
2252
2253       const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
2254       const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
2255       const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
2256
2257       for(Standard_Integer aNPt = 1; aNPt <= theSPnt.Length(); aNPt++)
2258       {
2259         const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNPt).PntOn2S();
2260
2261         if( aPntCur.IsSame(aPntFWL1, Precision::Confusion()) ||
2262             aPntCur.IsSame(aPntLWL1, Precision::Confusion()))
2263         {
2264           theSPnt.Remove(aNPt);
2265           aNPt--;
2266         }
2267       }
2268
2269       Standard_Boolean hasBeenRemoved = Standard_False;
2270       for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1; aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
2271       {
2272         const Handle(IntPatch_WLine)& aWLine2 = Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine2));
2273
2274         const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
2275         const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
2276
2277         const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
2278         const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
2279
2280         const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
2281         const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
2282
2283         if(aPntFWL1.IsSame(aPntFWL2, Precision::Confusion()))
2284         {
2285           Standard_Real aU11 = 0.0, aU12 = 0.0, aV11 = 0.0, aV12 = 0.0;
2286           Standard_Real aU21 = 0.0, aU22 = 0.0, aV21 = 0.0, aV22 = 0.0;
2287
2288           aPntFWL1.Parameters(aU11, aV11, aU12, aV12);
2289           aPntFWL2.Parameters(aU21, aV21, aU22, aV22);
2290
2291           if( !(IsEqual(fmod(aU11, aPeriod), 0.0) ||
2292                 IsEqual(fmod(aU12, aPeriod), 0.0) ||
2293                 IsEqual(fmod(aU21, aPeriod), 0.0) ||
2294                 IsEqual(fmod(aU22, aPeriod), 0.0) ||
2295                 IsEqual(aU11, aUSurf1f) || IsEqual(aU11, aUSurf1l) ||
2296                 IsEqual(aU21, aUSurf1f) || IsEqual(aU21, aUSurf1l) ||
2297                 IsEqual(aU12, aUSurf2f) || IsEqual(aU12, aUSurf2l) ||
2298                 IsEqual(aU22, aUSurf2f) || IsEqual(aU22, aUSurf2l)))
2299           {
2300             aWLine1->ClearVertexes();
2301             for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
2302             {
2303               const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
2304               aWLine1->Curve()->InsertBefore(1, aPt);
2305             }
2306
2307             aWLine1->ComputeVertexParameters(theTol3D);
2308
2309             theSlin.Remove(aNumOfLine2);
2310             aNumOfLine2--;
2311             hasBeenRemoved = Standard_True;
2312
2313             continue;
2314           }
2315         }
2316
2317         if(aPntFWL1.IsSame(aPntLWL2, Precision::Confusion()))
2318         {
2319           Standard_Real aU11 = 0.0, aU12 = 0.0, aV11 = 0.0, aV12 = 0.0;
2320           Standard_Real aU21 = 0.0, aU22 = 0.0, aV21 = 0.0, aV22 = 0.0;
2321
2322           aPntFWL1.Parameters(aU11, aV11, aU12, aV12);
2323           aPntLWL2.Parameters(aU21, aV21, aU22, aV22);
2324
2325           if( !(IsEqual(fmod(aU11, aPeriod), 0.0) ||
2326                 IsEqual(fmod(aU12, aPeriod), 0.0) ||
2327                 IsEqual(fmod(aU21, aPeriod), 0.0) ||
2328                 IsEqual(fmod(aU22, aPeriod), 0.0) ||
2329                 IsEqual(aU11, aUSurf1f) || IsEqual(aU11, aUSurf1l) ||
2330                 IsEqual(aU21, aUSurf1f) || IsEqual(aU21, aUSurf1l) ||
2331                 IsEqual(aU12, aUSurf2f) || IsEqual(aU12, aUSurf2l) ||
2332                 IsEqual(aU22, aUSurf2f) || IsEqual(aU22, aUSurf2l)))
2333           {
2334             aWLine1->ClearVertexes();
2335             for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
2336             {
2337               const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
2338               aWLine1->Curve()->InsertBefore(1, aPt);
2339             }
2340
2341             aWLine1->ComputeVertexParameters(theTol3D);
2342
2343             theSlin.Remove(aNumOfLine2);
2344             aNumOfLine2--;
2345             hasBeenRemoved = Standard_True;
2346
2347             continue;
2348           }
2349         }
2350
2351         if(aPntLWL1.IsSame(aPntFWL2, Precision::Confusion()))
2352         {
2353           Standard_Real aU11 = 0.0, aU12 = 0.0, aV11 = 0.0, aV12 = 0.0;
2354           Standard_Real aU21 = 0.0, aU22 = 0.0, aV21 = 0.0, aV22 = 0.0;
2355
2356           aPntLWL1.Parameters(aU11, aV11, aU12, aV12);
2357           aPntFWL2.Parameters(aU21, aV21, aU22, aV22);
2358
2359           if( !(IsEqual(fmod(aU11, aPeriod), 0.0) ||
2360                 IsEqual(fmod(aU12, aPeriod), 0.0) ||
2361                 IsEqual(fmod(aU21, aPeriod), 0.0) ||
2362                 IsEqual(fmod(aU22, aPeriod), 0.0) ||
2363                 IsEqual(aU11, aUSurf1f) || IsEqual(aU11, aUSurf1l) ||
2364                 IsEqual(aU21, aUSurf1f) || IsEqual(aU21, aUSurf1l) ||
2365                 IsEqual(aU12, aUSurf2f) || IsEqual(aU12, aUSurf2l) ||
2366                 IsEqual(aU22, aUSurf2f) || IsEqual(aU22, aUSurf2l)))
2367           {
2368             aWLine1->ClearVertexes();
2369             for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
2370             {
2371               const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
2372               aWLine1->Curve()->Add(aPt);
2373             }
2374
2375             aWLine1->ComputeVertexParameters(theTol3D);
2376
2377             theSlin.Remove(aNumOfLine2);
2378             aNumOfLine2--;
2379             hasBeenRemoved = Standard_True;
2380
2381             continue;
2382           }
2383         }
2384
2385         if(aPntLWL1.IsSame(aPntLWL2, Precision::Confusion()))
2386         {
2387           Standard_Real aU11 = 0.0, aU12 = 0.0, aV11 = 0.0, aV12 = 0.0;
2388           Standard_Real aU21 = 0.0, aU22 = 0.0, aV21 = 0.0, aV22 = 0.0;
2389
2390           aPntLWL1.Parameters(aU11, aV11, aU12, aV12);
2391           aPntLWL2.Parameters(aU21, aV21, aU22, aV22);
2392
2393           if( !(IsEqual(fmod(aU11, aPeriod), 0.0) ||
2394                 IsEqual(fmod(aU12, aPeriod), 0.0) ||
2395                 IsEqual(fmod(aU21, aPeriod), 0.0) ||
2396                 IsEqual(fmod(aU22, aPeriod), 0.0) ||
2397                 IsEqual(aU11, aUSurf1f) || IsEqual(aU11, aUSurf1l) ||
2398                 IsEqual(aU21, aUSurf1f) || IsEqual(aU21, aUSurf1l) ||
2399                 IsEqual(aU12, aUSurf2f) || IsEqual(aU12, aUSurf2l) ||
2400                 IsEqual(aU22, aUSurf2f) || IsEqual(aU22, aUSurf2l)))
2401           {
2402             aWLine1->ClearVertexes();
2403             for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
2404             {
2405               const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
2406               aWLine1->Curve()->Add(aPt);
2407             }
2408
2409             aWLine1->ComputeVertexParameters(theTol3D);
2410
2411             theSlin.Remove(aNumOfLine2);
2412             aNumOfLine2--;
2413             hasBeenRemoved = Standard_True;
2414
2415             continue;
2416           }
2417         }
2418       }
2419
2420       if(hasBeenRemoved)
2421         aNumOfLine1--;
2422     }
2423   }//if(theSlin.Length() > 0)
2424
2425
2426   return Standard_True;
2427 }
2428
2429 //=======================================================================
2430 //function : IntCySp
2431 //purpose  : 
2432 //=======================================================================
2433 Standard_Boolean IntCySp(const IntSurf_Quadric& Quad1,
2434                          const IntSurf_Quadric& Quad2,
2435                          const Standard_Real Tol,
2436                          const Standard_Boolean Reversed,
2437                          Standard_Boolean& Empty,
2438                          Standard_Boolean& Multpoint,
2439                          IntPatch_SequenceOfLine& slin,
2440                          IntPatch_SequenceOfPoint& spnt)
2441
2442 {
2443   Standard_Integer i;
2444
2445   IntSurf_TypeTrans trans1,trans2;
2446   IntAna_ResultType typint;
2447   IntPatch_Point ptsol;
2448   gp_Circ cirsol;
2449
2450   gp_Cylinder Cy;
2451   gp_Sphere Sp;
2452
2453   if (!Reversed) {
2454     Cy = Quad1.Cylinder();
2455     Sp = Quad2.Sphere();
2456   }
2457   else {
2458     Cy = Quad2.Cylinder();
2459     Sp = Quad1.Sphere();
2460   }
2461   IntAna_QuadQuadGeo inter(Cy,Sp,Tol);
2462
2463   if (!inter.IsDone()) {return Standard_False;}
2464
2465   typint = inter.TypeInter();
2466   Standard_Integer NbSol = inter.NbSolutions();
2467   Empty = Standard_False;
2468
2469   switch (typint) {
2470
2471   case IntAna_Empty :
2472     {
2473       Empty = Standard_True;
2474     }
2475     break;
2476
2477   case IntAna_Point :
2478     {
2479       gp_Pnt psol(inter.Point(1));
2480       Standard_Real U1,V1,U2,V2;
2481       Quad1.Parameters(psol,U1,V1);
2482       Quad2.Parameters(psol,U2,V2);
2483       ptsol.SetValue(psol,Tol,Standard_True);
2484       ptsol.SetParameters(U1,V1,U2,V2);
2485       spnt.Append(ptsol);
2486     }
2487     break;
2488
2489   case IntAna_Circle:
2490     {
2491       cirsol = inter.Circle(1);
2492       gp_Vec Tgt;
2493       gp_Pnt ptref;
2494       ElCLib::D1(0.,cirsol,ptref,Tgt);
2495
2496       if (NbSol == 1) {
2497         gp_Vec TestCurvature(ptref,Sp.Location());
2498         gp_Vec Normsp,Normcyl;
2499         if (!Reversed) {
2500           Normcyl = Quad1.Normale(ptref);
2501           Normsp  = Quad2.Normale(ptref);
2502         }
2503         else {
2504           Normcyl = Quad2.Normale(ptref);
2505           Normsp  = Quad1.Normale(ptref);
2506         }
2507         
2508         IntSurf_Situation situcyl;
2509         IntSurf_Situation situsp;
2510         
2511         if (Normcyl.Dot(TestCurvature) > 0.) {
2512           situsp = IntSurf_Outside;
2513           if (Normsp.Dot(Normcyl) > 0.) {
2514             situcyl = IntSurf_Inside;
2515           }
2516           else {
2517             situcyl = IntSurf_Outside;
2518           }
2519         }
2520         else {
2521           situsp = IntSurf_Inside;
2522           if (Normsp.Dot(Normcyl) > 0.) {
2523             situcyl = IntSurf_Outside;
2524           }
2525           else {
2526             situcyl = IntSurf_Inside;
2527           }
2528         }
2529         Handle(IntPatch_GLine) glig;
2530         if (!Reversed) {
2531           glig = new IntPatch_GLine(cirsol, Standard_True, situcyl, situsp);
2532         }
2533         else {
2534           glig = new IntPatch_GLine(cirsol, Standard_True, situsp, situcyl);
2535         }
2536         slin.Append(glig);
2537       }
2538       else {
2539         if (Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref)) > 0.0) {
2540           trans1 = IntSurf_Out;
2541           trans2 = IntSurf_In;
2542         }
2543         else {
2544           trans1 = IntSurf_In;
2545           trans2 = IntSurf_Out;
2546         }
2547         Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
2548         slin.Append(glig);
2549
2550         cirsol = inter.Circle(2);
2551         ElCLib::D1(0.,cirsol,ptref,Tgt);
2552         Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
2553         if(qwe> 0.0000001) {
2554           trans1 = IntSurf_Out;
2555           trans2 = IntSurf_In;
2556         }
2557         else if(qwe<-0.0000001) {
2558           trans1 = IntSurf_In;
2559           trans2 = IntSurf_Out;
2560         }
2561         else { 
2562           trans1=trans2=IntSurf_Undecided; 
2563         }
2564         glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
2565         slin.Append(glig);
2566       }
2567     }
2568     break;
2569     
2570   case IntAna_NoGeometricSolution:
2571     {
2572       gp_Pnt psol;
2573       Standard_Real U1,V1,U2,V2;
2574       IntAna_IntQuadQuad anaint(Cy,Sp,Tol);
2575       if (!anaint.IsDone()) {
2576         return Standard_False;
2577       }
2578
2579       if (anaint.NbPnt()==0 && anaint.NbCurve()==0) {
2580         Empty = Standard_True;
2581       }
2582       else {
2583
2584         NbSol = anaint.NbPnt();
2585         for (i = 1; i <= NbSol; i++) {
2586           psol = anaint.Point(i);
2587           Quad1.Parameters(psol,U1,V1);
2588           Quad2.Parameters(psol,U2,V2);
2589           ptsol.SetValue(psol,Tol,Standard_True);
2590           ptsol.SetParameters(U1,V1,U2,V2);
2591           spnt.Append(ptsol);
2592         }
2593         
2594         gp_Pnt ptvalid,ptf,ptl;
2595         gp_Vec tgvalid;
2596         Standard_Real first,last,para;
2597         IntAna_Curve curvsol;
2598         Standard_Boolean tgfound;
2599         Standard_Integer kount;
2600         
2601         NbSol = anaint.NbCurve();
2602         for (i = 1; i <= NbSol; i++) {
2603           curvsol = anaint.Curve(i);
2604           curvsol.Domain(first,last);
2605           ptf = curvsol.Value(first);
2606           ptl = curvsol.Value(last);
2607
2608           para = last;
2609           kount = 1;
2610           tgfound = Standard_False;
2611           
2612           while (!tgfound) {
2613             para = (1.123*first + para)/2.123;
2614             tgfound = curvsol.D1u(para,ptvalid,tgvalid);
2615             if (!tgfound) {
2616               kount ++;
2617               tgfound = kount > 5;
2618             }
2619           }
2620           Handle(IntPatch_ALine) alig;
2621           if (kount <= 5) {
2622             Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid),
2623                                                  Quad1.Normale(ptvalid));
2624             if(qwe> 0.00000001) {
2625               trans1 = IntSurf_Out;
2626               trans2 = IntSurf_In;
2627             }
2628             else if(qwe<-0.00000001) {
2629               trans1 = IntSurf_In;
2630               trans2 = IntSurf_Out;
2631             }
2632             else { 
2633               trans1=trans2=IntSurf_Undecided; 
2634             }
2635             alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
2636           }
2637           else {
2638             alig = new IntPatch_ALine(curvsol,Standard_False);
2639           }
2640           Standard_Boolean TempFalse1a = Standard_False;
2641           Standard_Boolean TempFalse2a = Standard_False;
2642
2643           //-- ptf et ptl : points debut et fin de alig 
2644           
2645           ProcessBounds(alig,slin,Quad1,Quad2,TempFalse1a,ptf,first,
2646                         TempFalse2a,ptl,last,Multpoint,Tol);
2647           slin.Append(alig);
2648         } //-- boucle sur les lignes 
2649       } //-- solution avec au moins une lihne 
2650     }
2651     break;
2652
2653   default:
2654     {
2655       return Standard_False;
2656     }
2657   }
2658   return Standard_True;
2659 }
2660 //=======================================================================
2661 //function : IntCyCo
2662 //purpose  : 
2663 //=======================================================================
2664 Standard_Boolean IntCyCo(const IntSurf_Quadric& Quad1,
2665                          const IntSurf_Quadric& Quad2,
2666                          const Standard_Real Tol,
2667                          const Standard_Boolean Reversed,
2668                          Standard_Boolean& Empty,
2669                          Standard_Boolean& Multpoint,
2670                          IntPatch_SequenceOfLine& slin,
2671                          IntPatch_SequenceOfPoint& spnt)
2672
2673 {
2674   IntPatch_Point ptsol;
2675
2676   Standard_Integer i;
2677
2678   IntSurf_TypeTrans trans1,trans2;
2679   IntAna_ResultType typint;
2680   gp_Circ cirsol;
2681
2682   gp_Cylinder Cy;
2683   gp_Cone     Co;
2684
2685   if (!Reversed) {
2686     Cy = Quad1.Cylinder();
2687     Co = Quad2.Cone();
2688   }
2689   else {
2690     Cy = Quad2.Cylinder();
2691     Co = Quad1.Cone();
2692   }
2693   IntAna_QuadQuadGeo inter(Cy,Co,Tol);
2694
2695   if (!inter.IsDone()) {return Standard_False;}
2696
2697   typint = inter.TypeInter();
2698   Standard_Integer NbSol = inter.NbSolutions();
2699   Empty = Standard_False;
2700
2701   switch (typint) {
2702
2703   case IntAna_Empty : {
2704     Empty = Standard_True;
2705   }
2706     break;
2707
2708   case IntAna_Point :{
2709     gp_Pnt psol(inter.Point(1));
2710     Standard_Real U1,V1,U2,V2;
2711     Quad1.Parameters(psol,U1,V1);
2712     Quad1.Parameters(psol,U2,V2);
2713     ptsol.SetValue(psol,Tol,Standard_True);
2714     ptsol.SetParameters(U1,V1,U2,V2);
2715     spnt.Append(ptsol);
2716   }
2717     break;
2718     
2719   case IntAna_Circle:  {
2720     gp_Vec Tgt;
2721     gp_Pnt ptref;
2722     Standard_Integer j;
2723     Standard_Real qwe;
2724     //
2725     for(j=1; j<=2; ++j) { 
2726       cirsol = inter.Circle(j);
2727       ElCLib::D1(0.,cirsol,ptref,Tgt);
2728       qwe = Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
2729       if(qwe> 0.00000001) {
2730         trans1 = IntSurf_Out;
2731         trans2 = IntSurf_In;
2732       }
2733       else if(qwe<-0.00000001) {
2734         trans1 = IntSurf_In;
2735         trans2 = IntSurf_Out;
2736       }
2737       else { 
2738         trans1=trans2=IntSurf_Undecided; 
2739       }
2740       Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
2741       slin.Append(glig);
2742     }
2743   }
2744     break;
2745     
2746   case IntAna_NoGeometricSolution:    {
2747     gp_Pnt psol;
2748     Standard_Real U1,V1,U2,V2;
2749     IntAna_IntQuadQuad anaint(Cy,Co,Tol);
2750     if (!anaint.IsDone()) {
2751       return Standard_False;
2752     }
2753     
2754     if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0) {
2755       Empty = Standard_True;
2756     }
2757     else {
2758       NbSol = anaint.NbPnt();
2759       for (i = 1; i <= NbSol; i++) {
2760         psol = anaint.Point(i);
2761         Quad1.Parameters(psol,U1,V1);
2762         Quad2.Parameters(psol,U2,V2);
2763         ptsol.SetValue(psol,Tol,Standard_True);
2764         ptsol.SetParameters(U1,V1,U2,V2);
2765         spnt.Append(ptsol);
2766       }
2767       
2768       gp_Pnt ptvalid, ptf, ptl;
2769       gp_Vec tgvalid;
2770       //
2771       Standard_Real first,last,para;
2772       Standard_Boolean tgfound,firstp,lastp,kept;
2773       Standard_Integer kount;
2774       //
2775       //
2776       //IntAna_Curve curvsol;
2777       IntAna_Curve aC;
2778       IntAna_ListOfCurve aLC;
2779       IntAna_ListIteratorOfListOfCurve aIt;
2780       
2781       //
2782       NbSol = anaint.NbCurve();
2783       for (i = 1; i <= NbSol; ++i) {
2784         kept = Standard_False;
2785         //curvsol = anaint.Curve(i);
2786         aC=anaint.Curve(i);
2787         aLC.Clear();
2788         ExploreCurve(Cy, Co, aC, 10.*Tol, aLC);
2789         //
2790         aIt.Initialize(aLC);
2791         for (; aIt.More(); aIt.Next()) {
2792           IntAna_Curve& curvsol=aIt.Value();
2793           //
2794           curvsol.Domain(first, last);
2795           firstp = !curvsol.IsFirstOpen();
2796           lastp  = !curvsol.IsLastOpen();
2797           if (firstp) {
2798             ptf = curvsol.Value(first);
2799           }
2800           if (lastp) {
2801             ptl = curvsol.Value(last);
2802           }
2803           para = last;
2804           kount = 1;
2805           tgfound = Standard_False;
2806           
2807           while (!tgfound) {
2808             para = (1.123*first + para)/2.123;
2809             tgfound = curvsol.D1u(para,ptvalid,tgvalid);
2810             if (!tgfound) {
2811               kount ++;
2812               tgfound = kount > 5;
2813             }
2814           }
2815           Handle(IntPatch_ALine) alig;
2816           if (kount <= 5) {
2817             Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid),
2818                                                  Quad1.Normale(ptvalid));
2819             if(qwe> 0.00000001) {
2820               trans1 = IntSurf_Out;
2821               trans2 = IntSurf_In;
2822             }
2823             else if(qwe<-0.00000001) {
2824               trans1 = IntSurf_In;
2825               trans2 = IntSurf_Out;
2826             }
2827             else { 
2828               trans1=trans2=IntSurf_Undecided; 
2829             }
2830             alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
2831             kept = Standard_True;
2832           }
2833           else {
2834             ptvalid = curvsol.Value(para);
2835             alig = new IntPatch_ALine(curvsol,Standard_False);
2836             kept = Standard_True;
2837             //-- cout << "Transition indeterminee" << endl;
2838           }
2839           if (kept) {
2840             Standard_Boolean Nfirstp = !firstp;
2841             Standard_Boolean Nlastp  = !lastp;
2842             ProcessBounds(alig,slin,Quad1,Quad2,Nfirstp,ptf,first,
2843                           Nlastp,ptl,last,Multpoint,Tol);
2844             slin.Append(alig);
2845           }
2846         } // for (; aIt.More(); aIt.Next())
2847       } // for (i = 1; i <= NbSol; ++i) 
2848     }
2849   }
2850     break;
2851     
2852   default:
2853     return Standard_False;
2854     
2855   } // switch (typint)
2856   
2857   return Standard_True;
2858 }
2859 //=======================================================================
2860 //function : ExploreCurve
2861 //purpose  : 
2862 //=======================================================================
2863 Standard_Boolean ExploreCurve(const gp_Cylinder& ,//aCy,
2864                               const gp_Cone& aCo,
2865                               IntAna_Curve& aC,
2866                               const Standard_Real aTol,
2867                               IntAna_ListOfCurve& aLC)
2868                               
2869 {
2870   Standard_Boolean bFind=Standard_False;
2871   Standard_Real aTheta, aT1, aT2, aDst;
2872   gp_Pnt aPapx, aPx;
2873   //
2874   //aC.Dump();
2875   //
2876   aLC.Clear();
2877   aLC.Append(aC);
2878   //
2879   aPapx=aCo.Apex();
2880   //
2881   aC.Domain(aT1, aT2);
2882   //
2883   aPx=aC.Value(aT1);
2884   aDst=aPx.Distance(aPapx);
2885   if (aDst<aTol) {
2886     return bFind;
2887   }
2888   aPx=aC.Value(aT2);
2889   aDst=aPx.Distance(aPapx);
2890   if (aDst<aTol) {
2891     return bFind;
2892   }
2893   //
2894   bFind=aC.FindParameter(aPapx, aTheta);
2895   if (!bFind){
2896     return bFind;
2897   }
2898   //
2899   aPx=aC.Value(aTheta);
2900   aDst=aPx.Distance(aPapx);
2901   if (aDst>aTol) {
2902     return !bFind;
2903   }
2904   //
2905   // need to be splitted at aTheta
2906   IntAna_Curve aC1, aC2;
2907   //
2908   aC1=aC;
2909   aC1.SetDomain(aT1, aTheta);
2910   aC2=aC;
2911   aC2.SetDomain(aTheta, aT2);
2912   //
2913   aLC.Clear();
2914   aLC.Append(aC1);
2915   aLC.Append(aC2);
2916   //
2917   return bFind;
2918 }
2919 //=======================================================================
2920 //function : IsToReverse
2921 //purpose  : 
2922 //=======================================================================
2923 Standard_Boolean IsToReverse(const gp_Cylinder& Cy1,
2924                              const gp_Cylinder& Cy2,
2925                              const Standard_Real Tol)
2926 {
2927   Standard_Boolean bRet;
2928   Standard_Real aR1,aR2, dR, aSc1, aSc2;
2929   //
2930   bRet=Standard_False;
2931   //
2932   aR1=Cy1.Radius();
2933   aR2=Cy2.Radius();
2934   dR=aR1-aR2;
2935   if (dR<0.) {
2936     dR=-dR;
2937   }
2938   if (dR>Tol) {
2939     bRet=aR1>aR2;
2940   }
2941   else {
2942     gp_Dir aDZ(0.,0.,1.);
2943     //
2944     const gp_Dir& aDir1=Cy1.Axis().Direction();
2945     aSc1=aDir1*aDZ;
2946     if (aSc1<0.) {
2947       aSc1=-aSc1;
2948     }
2949     //
2950     const gp_Dir& aDir2=Cy2.Axis().Direction();
2951     aSc2=aDir2*aDZ;
2952     if (aSc2<0.) {
2953       aSc2=-aSc2;
2954     }
2955     //
2956     if (aSc2<aSc1) {
2957       bRet=!bRet;
2958     }
2959   }//if (dR<Tol) {
2960   return bRet;
2961 }