6b05437b7a14b1befbae146772779aee791c5e29
[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 <algorithm>
18 #include <Standard_DivideByZero.hxx>
19 #include <IntAna_ListOfCurve.hxx>
20 #include <IntAna_ListIteratorOfListOfCurve.hxx>
21 #include <IntPatch_WLine.hxx>
22
23 #include <math_Matrix.hxx>
24
25 //If Abs(a) <= aNulValue then it is considered that a = 0.
26 static const Standard_Real aNulValue = 1.0e-11;
27
28 struct stCoeffsValue;
29 //
30 static 
31   Standard_Boolean ExploreCurve(const gp_Cylinder& aCy,
32                                 const gp_Cone& aCo,
33                                 IntAna_Curve& aC,
34                                 const Standard_Real aTol,
35                                 IntAna_ListOfCurve& aLC);
36 static
37   Standard_Boolean IsToReverse(const gp_Cylinder& Cy1,
38                                const gp_Cylinder& Cy2,
39                                const Standard_Real Tol);
40
41 static Standard_Boolean InscribePoint(const Standard_Real theUfTarget,
42                                       const Standard_Real theUlTarget,
43                                       Standard_Real& theUGiven,
44                                       const Standard_Real theTol2D,
45                                       const Standard_Real thePeriod,
46                                       const Standard_Boolean theFlForce);
47
48 static void SeekAdditionalPoints( const IntSurf_Quadric& theQuad1,
49                                   const IntSurf_Quadric& theQuad2,
50                                   const Handle(IntSurf_LineOn2S)& theLine,
51                                   const stCoeffsValue& theCoeffs,
52                                   const Standard_Integer theWLIndex,
53                                   const Standard_Integer theMinNbPoints,
54                                   const Standard_Integer theStartPointOnLine,
55                                   const Standard_Integer theEndPointOnLine,
56                                   const Standard_Real theU2f,
57                                   const Standard_Real theU2l,
58                                   const Standard_Real theTol2D,
59                                   const Standard_Real thePeriodOfSurf2,
60                                   const Standard_Boolean isTheReverse);
61
62 //=======================================================================
63 //function : MinMax
64 //purpose  : Replaces theParMIN = MIN(theParMIN, theParMAX),
65 //                    theParMAX = MAX(theParMIN, theParMAX).
66 //=======================================================================
67 static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
68 {
69   if(theParMIN > theParMAX)
70   {
71     const Standard_Real aux = theParMAX;
72     theParMAX = theParMIN;
73     theParMIN = aux;
74   }
75 }
76
77 //=======================================================================
78 //function : VBoundaryPrecise
79 //purpose  : By default, we shall consider, that V1 and V2 will increase
80 //            if U1 increases. But if it is not, new V1set and/or V2set
81 //            must be computed as [V1current - DeltaV1] (analogically
82 //            for V2). This function processes this case.
83 //=======================================================================
84 static void VBoundaryPrecise( const math_Matrix& theMatr,
85                               const Standard_Real theV1AfterDecrByDelta,
86                               const Standard_Real theV2AfterDecrByDelta,
87                               Standard_Real& theV1Set,
88                               Standard_Real& theV2Set)
89 {
90   //Now we are going to define if V1 (and V2) increases
91   //(or decreases) when U1 will increase.
92   const Standard_Integer aNbDim = 3;
93   math_Matrix aSyst(1, aNbDim, 1, aNbDim);
94
95   aSyst.SetCol(1, theMatr.Col(1));
96   aSyst.SetCol(2, theMatr.Col(2));
97   aSyst.SetCol(3, theMatr.Col(4));
98
99   const Standard_Real aDet = aSyst.Determinant();
100
101   aSyst.SetCol(1, theMatr.Col(3));
102   const Standard_Real aDet1 = aSyst.Determinant();
103
104   aSyst.SetCol(1, theMatr.Col(1));
105   aSyst.SetCol(2, theMatr.Col(3));
106
107   const Standard_Real aDet2 = aSyst.Determinant();
108
109   if(aDet*aDet1 > 0.0)
110   {
111     theV1Set = theV1AfterDecrByDelta;
112   }
113
114   if(aDet*aDet2 > 0.0)
115   {
116     theV2Set = theV2AfterDecrByDelta;
117   }
118 }
119
120 //=======================================================================
121 //function : DeltaU1Computing
122 //purpose  : Computes new step for U1 parameter.
123 //=======================================================================
124 static inline 
125         Standard_Boolean DeltaU1Computing(const math_Matrix& theSyst,
126                                           const math_Vector& theFree,
127                                           Standard_Real& theDeltaU1Found)
128 {
129   Standard_Real aDet = theSyst.Determinant();
130
131   if(Abs(aDet) > aNulValue)
132   {
133     math_Matrix aSyst1(theSyst);
134     aSyst1.SetCol(2, theFree);
135
136     theDeltaU1Found = Abs(aSyst1.Determinant()/aDet);
137     return Standard_True;
138   }
139
140   return Standard_False;
141 }
142
143 //=======================================================================
144 //function : StepComputing
145 //purpose  : 
146 //
147 //Attention!!!:
148 //            theMatr must have 3*5-dimension strictly.
149 //            For system
150 //                {a11*V1+a12*V2+a13*dU1+a14*dU2=b1; 
151 //                {a21*V1+a22*V2+a23*dU1+a24*dU2=b2; 
152 //                {a31*V1+a32*V2+a33*dU1+a34*dU2=b3; 
153 //            theMatr must be following:
154 //                (a11 a12 a13 a14 b1) 
155 //                (a21 a22 a23 a24 b2) 
156 //                (a31 a32 a33 a34 b3) 
157 //=======================================================================
158 static Standard_Boolean StepComputing(const math_Matrix& theMatr,
159                                       const Standard_Real theV1Cur,
160                                       const Standard_Real theV2Cur,
161                                       const Standard_Real theDeltaV1,
162                                       const Standard_Real theDeltaV2,
163                                       Standard_Real& theDeltaU1Found/*,
164                                       Standard_Real& theDeltaU2Found,
165                                       Standard_Real& theV1Found,
166                                       Standard_Real& theV2Found*/)
167 {
168 #ifdef OCCT_DEBUG
169   bool flShow = false;
170
171   if(flShow)
172   {
173     printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
174               theMatr(1,1), theMatr(1,2), theMatr(1,3), theMatr(1,4), theMatr(1,5));
175     printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
176               theMatr(2,1), theMatr(2,2), theMatr(2,3), theMatr(2,4), theMatr(2,5));
177     printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
178               theMatr(3,1), theMatr(3,2), theMatr(3,3), theMatr(3,4), theMatr(3,5));
179   }
180 #endif
181
182   Standard_Boolean isSuccess = Standard_False;
183   theDeltaU1Found/* = theDeltaU2Found*/ = RealLast();
184   //theV1Found = theV1set;
185   //theV2Found = theV2Set;
186   const Standard_Integer aNbDim = 3;
187
188   math_Matrix aSyst(1, aNbDim, 1, aNbDim);
189   math_Vector aFree(1, aNbDim);
190
191   //By default, increasing V1(U1) and V2(U1) functions is
192   //considered
193   Standard_Real aV1Set = theV1Cur + theDeltaV1,
194                 aV2Set = theV2Cur + theDeltaV2;
195
196   //However, what is indeed?
197   VBoundaryPrecise( theMatr, theV1Cur - theDeltaV1,
198                     theV2Cur - theDeltaV2, aV1Set, aV2Set);
199
200   aSyst.SetCol(2, theMatr.Col(3));
201   aSyst.SetCol(3, theMatr.Col(4));
202
203   for(Standard_Integer i = 0; i < 2; i++)
204   {
205     if(i == 0)
206     {//V1 is known
207       aSyst.SetCol(1, theMatr.Col(2));
208       aFree.Set(1, aNbDim, theMatr.Col(5)-aV1Set*theMatr.Col(1));
209     }
210     else
211     {//i==1 => V2 is known
212       aSyst.SetCol(1, theMatr.Col(1));
213       aFree.Set(1, aNbDim, theMatr.Col(5)-aV2Set*theMatr.Col(2));
214     }
215
216     Standard_Real aNewDU = theDeltaU1Found;
217     if(DeltaU1Computing(aSyst, aFree, aNewDU))
218     {
219       isSuccess = Standard_True;
220       if(aNewDU < theDeltaU1Found)
221       {
222         theDeltaU1Found = aNewDU;
223       }
224     }
225   }
226
227   if(!isSuccess)
228   {
229     aFree = theMatr.Col(5) - aV1Set*theMatr.Col(1) - aV2Set*theMatr.Col(2);
230     math_Matrix aSyst1(1, aNbDim, 1, 2);
231     aSyst1.SetCol(1, aSyst.Col(2));
232     aSyst1.SetCol(2, aSyst.Col(3));
233
234     //Now we have overdetermined system.
235
236     const Standard_Real aDet1 = theMatr(1,3)*theMatr(2,4) - theMatr(2,3)*theMatr(1,4);
237     const Standard_Real aDet2 = theMatr(1,3)*theMatr(3,4) - theMatr(3,3)*theMatr(1,4);
238     const Standard_Real aDet3 = theMatr(2,3)*theMatr(3,4) - theMatr(3,3)*theMatr(2,4);
239     const Standard_Real anAbsD1 = Abs(aDet1);
240     const Standard_Real anAbsD2 = Abs(aDet2);
241     const Standard_Real anAbsD3 = Abs(aDet3);
242
243     if(anAbsD1 >= anAbsD2)
244     {
245       if(anAbsD1 >= anAbsD3)
246       {
247         //Det1
248         if(anAbsD1 <= aNulValue)
249           return isSuccess;
250
251         theDeltaU1Found = Abs(aFree(1)*theMatr(2,4) - aFree(2)*theMatr(1,4))/anAbsD1;
252         isSuccess = Standard_True;
253       }
254       else
255       {
256         //Det3
257         if(anAbsD3 <= aNulValue)
258           return isSuccess;
259
260         theDeltaU1Found = Abs(aFree(2)*theMatr(3,4) - aFree(3)*theMatr(2,4))/anAbsD3;
261         isSuccess = Standard_True;
262       }
263     }
264     else
265     {
266       if(anAbsD2 >= anAbsD3)
267       {
268         //Det2
269         if(anAbsD2 <= aNulValue)
270           return isSuccess;
271
272         theDeltaU1Found = Abs(aFree(1)*theMatr(3,4) - aFree(3)*theMatr(1,4))/anAbsD2;
273         isSuccess = Standard_True;
274       }
275       else
276       {
277         //Det3
278         if(anAbsD3 <= aNulValue)
279           return isSuccess;
280
281         theDeltaU1Found = Abs(aFree(2)*theMatr(3,4) - aFree(3)*theMatr(2,4))/anAbsD3;
282         isSuccess = Standard_True;
283       }
284     }
285   }
286
287   return isSuccess;
288 }
289
290 //=======================================================================
291 //function : ProcessBounds
292 //purpose  : 
293 //=======================================================================
294 void ProcessBounds(const Handle(IntPatch_ALine)& alig,          //-- ligne courante
295                    const IntPatch_SequenceOfLine& slin,
296                    const IntSurf_Quadric& Quad1,
297                    const IntSurf_Quadric& Quad2,
298                    Standard_Boolean& procf,
299                    const gp_Pnt& ptf,                     //-- Debut Ligne Courante
300                    const Standard_Real first,             //-- Paramf
301                    Standard_Boolean& procl,
302                    const gp_Pnt& ptl,                     //-- Fin Ligne courante
303                    const Standard_Real last,              //-- Paraml
304                    Standard_Boolean& Multpoint,
305                    const Standard_Real Tol)
306 {  
307   Standard_Integer j,k;
308   Standard_Real U1,V1,U2,V2;
309   IntPatch_Point ptsol;
310   Standard_Real d;
311   
312   if (procf && procl) {
313     j = slin.Length() + 1;
314   }
315   else {
316     j = 1;
317   }
318
319
320   //-- On prend les lignes deja enregistrees
321
322   while (j <= slin.Length()) {  
323     if(slin.Value(j)->ArcType() == IntPatch_Analytic) { 
324       const Handle(IntPatch_ALine)& aligold = *((Handle(IntPatch_ALine)*)&slin.Value(j));
325       k = 1;
326
327       //-- On prend les vertex des lignes deja enregistrees
328
329       while (k <= aligold->NbVertex()) {
330         ptsol = aligold->Vertex(k);            
331         if (!procf) {
332           d=ptf.Distance(ptsol.Value());
333           if (d <= Tol) {
334             if (!ptsol.IsMultiple()) {
335               //-- le point ptsol (de aligold) est declare multiple sur aligold
336               Multpoint = Standard_True;
337               ptsol.SetMultiple(Standard_True);
338               aligold->Replace(k,ptsol);
339             }
340             ptsol.SetParameter(first);
341             alig->AddVertex(ptsol);
342             alig->SetFirstPoint(alig->NbVertex());
343             procf = Standard_True;
344
345             //-- On restore le point avec son parametre sur aligold
346             ptsol = aligold->Vertex(k); 
347                                         
348           }
349         }
350         if (!procl) {
351           if (ptl.Distance(ptsol.Value()) <= Tol) {
352             if (!ptsol.IsMultiple()) {
353               Multpoint = Standard_True;
354               ptsol.SetMultiple(Standard_True);
355               aligold->Replace(k,ptsol);
356             }
357             ptsol.SetParameter(last);
358             alig->AddVertex(ptsol);
359             alig->SetLastPoint(alig->NbVertex());
360             procl = Standard_True;
361
362             //-- On restore le point avec son parametre sur aligold
363             ptsol = aligold->Vertex(k); 
364              
365           }
366         }
367         if (procf && procl) {
368           k = aligold->NbVertex()+1;
369         }
370         else {
371           k = k+1;
372         }
373       }
374       if (procf && procl) {
375         j = slin.Length()+1;
376       }
377       else {
378         j = j+1;
379       }
380     }
381   }
382   if (!procf && !procl) {
383     Quad1.Parameters(ptf,U1,V1);
384     Quad2.Parameters(ptf,U2,V2);
385     ptsol.SetValue(ptf,Tol,Standard_False);
386     ptsol.SetParameters(U1,V1,U2,V2);
387     ptsol.SetParameter(first);
388     if (ptf.Distance(ptl) <= Tol) {
389       ptsol.SetMultiple(Standard_True); // a voir
390       Multpoint = Standard_True;        // a voir de meme
391       alig->AddVertex(ptsol);
392       alig->SetFirstPoint(alig->NbVertex());
393       
394       ptsol.SetParameter(last);
395       alig->AddVertex(ptsol);
396       alig->SetLastPoint(alig->NbVertex());
397     }
398     else { 
399       alig->AddVertex(ptsol);
400       alig->SetFirstPoint(alig->NbVertex());
401       Quad1.Parameters(ptl,U1,V1);
402       Quad2.Parameters(ptl,U2,V2);
403       ptsol.SetValue(ptl,Tol,Standard_False);
404       ptsol.SetParameters(U1,V1,U2,V2);
405       ptsol.SetParameter(last);
406       alig->AddVertex(ptsol);
407       alig->SetLastPoint(alig->NbVertex());
408     }
409   }
410   else if (!procf) {
411     Quad1.Parameters(ptf,U1,V1);
412     Quad2.Parameters(ptf,U2,V2);
413     ptsol.SetValue(ptf,Tol,Standard_False);
414     ptsol.SetParameters(U1,V1,U2,V2);
415     ptsol.SetParameter(first);
416     alig->AddVertex(ptsol);
417     alig->SetFirstPoint(alig->NbVertex());
418   }
419   else if (!procl) {
420     Quad1.Parameters(ptl,U1,V1);
421     Quad2.Parameters(ptl,U2,V2);
422     ptsol.SetValue(ptl,Tol,Standard_False);
423     ptsol.SetParameters(U1,V1,U2,V2);
424     ptsol.SetParameter(last);
425     alig->AddVertex(ptsol);
426     alig->SetLastPoint(alig->NbVertex());
427   }
428 }
429 //=======================================================================
430 //function : IntCyCy
431 //purpose  : 
432 //=======================================================================
433 Standard_Boolean IntCyCy(const IntSurf_Quadric& Quad1,
434                          const IntSurf_Quadric& Quad2,
435                          const Standard_Real Tol,
436                          Standard_Boolean& Empty,
437                          Standard_Boolean& Same,
438                          Standard_Boolean& Multpoint,
439                          IntPatch_SequenceOfLine& slin,
440                          IntPatch_SequenceOfPoint& spnt)
441
442 {
443   IntPatch_Point ptsol;
444
445   Standard_Integer i;
446
447   IntSurf_TypeTrans trans1,trans2;
448   IntAna_ResultType typint;
449
450   gp_Elips elipsol;
451   gp_Lin linsol;
452
453   gp_Cylinder Cy1(Quad1.Cylinder());
454   gp_Cylinder Cy2(Quad2.Cylinder());
455
456   IntAna_QuadQuadGeo inter(Cy1,Cy2,Tol);
457
458   if (!inter.IsDone())
459   {
460     return Standard_False;
461   }
462
463   typint = inter.TypeInter();
464   Standard_Integer NbSol = inter.NbSolutions();
465   Empty = Standard_False;
466   Same  = Standard_False;
467
468   switch (typint)
469   {
470   case IntAna_Empty:
471     {
472       Empty = Standard_True;
473     }
474     break;
475
476   case IntAna_Same:
477     {
478       Same  = Standard_True;
479     }
480     break;
481     
482   case IntAna_Point:
483     {
484       gp_Pnt psol(inter.Point(1));
485       Standard_Real U1,V1,U2,V2;
486       Quad1.Parameters(psol,U1,V1);
487       Quad2.Parameters(psol,U2,V2);
488       ptsol.SetValue(psol,Tol,Standard_True);
489       ptsol.SetParameters(U1,V1,U2,V2);
490       spnt.Append(ptsol);
491     }
492     break;
493
494   case IntAna_Line:
495     {
496       gp_Pnt ptref;
497       if (NbSol == 1)
498       { // Cylinders are tangent to each other by line
499         linsol = inter.Line(1);
500         ptref = linsol.Location();
501         gp_Dir crb1(gp_Vec(ptref,Cy1.Location()));
502         gp_Dir crb2(gp_Vec(ptref,Cy2.Location()));
503         gp_Vec norm1(Quad1.Normale(ptref));
504         gp_Vec norm2(Quad2.Normale(ptref));
505         IntSurf_Situation situcyl1;
506         IntSurf_Situation situcyl2;
507
508         if (crb1.Dot(crb2) < 0.)
509         { // centre de courbures "opposes"
510           if (norm1.Dot(crb1) > 0.)
511           {
512             situcyl2 = IntSurf_Inside;
513           }
514           else
515           {
516             situcyl2 = IntSurf_Outside;
517           }
518
519           if (norm2.Dot(crb2) > 0.)
520           {
521             situcyl1 = IntSurf_Inside;
522           }
523           else
524           {
525             situcyl1 = IntSurf_Outside;
526           }
527         }
528         else
529         {
530           if (Cy1.Radius() < Cy2.Radius())
531           {
532             if (norm1.Dot(crb1) > 0.)
533             {
534               situcyl2 = IntSurf_Inside;
535             }
536             else
537             {
538               situcyl2 = IntSurf_Outside;
539             }
540
541             if (norm2.Dot(crb2) > 0.)
542             {
543               situcyl1 = IntSurf_Outside;
544             }
545             else
546             {
547               situcyl1 = IntSurf_Inside;
548             }
549           }
550           else
551           {
552             if (norm1.Dot(crb1) > 0.)
553             {
554               situcyl2 = IntSurf_Outside;
555             }
556             else
557             {
558               situcyl2 = IntSurf_Inside;
559             }
560
561             if (norm2.Dot(crb2) > 0.)
562             {
563               situcyl1 = IntSurf_Inside;
564             }
565             else
566             {
567               situcyl1 = IntSurf_Outside;
568             }
569           }
570         }
571
572         Handle(IntPatch_GLine) glig =  new IntPatch_GLine(linsol, Standard_True, situcyl1, situcyl2);
573         slin.Append(glig);
574       }
575       else
576       {
577         for (i=1; i <= NbSol; i++)
578         {
579           linsol = inter.Line(i);
580           ptref = linsol.Location();
581           gp_Vec lsd = linsol.Direction();
582           Standard_Real qwe = lsd.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
583           if (qwe >0.00000001)
584           {
585             trans1 = IntSurf_Out;
586             trans2 = IntSurf_In;
587           }
588           else if (qwe <-0.00000001)
589           {
590             trans1 = IntSurf_In;
591             trans2 = IntSurf_Out;
592           }
593           else
594           {
595             trans1=trans2=IntSurf_Undecided;
596           }
597
598           Handle(IntPatch_GLine) glig = new IntPatch_GLine(linsol, Standard_False,trans1,trans2);
599           slin.Append(glig);
600         }
601       }
602     }
603     break;
604     
605   case IntAna_Ellipse:
606     {
607       gp_Vec Tgt;
608       gp_Pnt ptref;
609       IntPatch_Point pmult1, pmult2;
610       
611       elipsol = inter.Ellipse(1);
612       
613       gp_Pnt pttang1(ElCLib::Value(0.5*M_PI, elipsol));
614       gp_Pnt pttang2(ElCLib::Value(1.5*M_PI, elipsol));
615       
616       Multpoint = Standard_True;
617       pmult1.SetValue(pttang1,Tol,Standard_True);
618       pmult2.SetValue(pttang2,Tol,Standard_True);
619       pmult1.SetMultiple(Standard_True);
620       pmult2.SetMultiple(Standard_True);
621       
622       Standard_Real oU1,oV1,oU2,oV2;
623       Quad1.Parameters(pttang1,oU1,oV1); 
624       Quad2.Parameters(pttang1,oU2,oV2);
625       pmult1.SetParameters(oU1,oV1,oU2,oV2);
626
627       Quad1.Parameters(pttang2,oU1,oV1); 
628       Quad2.Parameters(pttang2,oU2,oV2);
629       pmult2.SetParameters(oU1,oV1,oU2,oV2);
630       
631       // on traite la premiere ellipse
632
633       //-- Calcul de la Transition de la ligne 
634       ElCLib::D1(0.,elipsol,ptref,Tgt);
635       Standard_Real qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
636       if (qwe>0.00000001)
637       {
638         trans1 = IntSurf_Out;
639         trans2 = IntSurf_In;
640       }
641       else if (qwe<-0.00000001)
642       {
643         trans1 = IntSurf_In;
644         trans2 = IntSurf_Out;
645       }
646       else
647       { 
648         trans1=trans2=IntSurf_Undecided; 
649       }
650
651       //-- Transition calculee au point 0 -> Trans2 , Trans1 
652       //-- car ici, on devarit calculer en PI
653       Handle(IntPatch_GLine) glig = new IntPatch_GLine(elipsol,Standard_False,trans2,trans1);
654       //
655       {
656         Standard_Real aU1, aV1, aU2, aV2;
657         IntPatch_Point aIP;
658         gp_Pnt aP (ElCLib::Value(0., elipsol));
659         //
660         aIP.SetValue(aP,Tol,Standard_False);
661         aIP.SetMultiple(Standard_False);
662         //
663         Quad1.Parameters(aP, aU1, aV1); 
664         Quad2.Parameters(aP, aU2, aV2);
665         aIP.SetParameters(aU1, aV1, aU2, aV2);
666         //
667         aIP.SetParameter(0.);
668         glig->AddVertex(aIP);
669         glig->SetFirstPoint(1);
670         //
671         aIP.SetParameter(2.*M_PI);
672         glig->AddVertex(aIP);
673         glig->SetLastPoint(2);
674       }
675       //
676       pmult1.SetParameter(0.5*M_PI);
677       glig->AddVertex(pmult1);
678       //
679       pmult2.SetParameter(1.5*M_PI);
680       glig->AddVertex(pmult2);
681      
682       //
683       slin.Append(glig);
684       
685       //-- Transitions calculee au point 0    OK
686       //
687       // on traite la deuxieme ellipse
688       elipsol = inter.Ellipse(2);
689
690       Standard_Real param1 = ElCLib::Parameter(elipsol,pttang1);
691       Standard_Real param2 = ElCLib::Parameter(elipsol,pttang2);
692       Standard_Real parampourtransition = 0.0;
693       if (param1 < param2)
694       {
695         pmult1.SetParameter(0.5*M_PI);
696         pmult2.SetParameter(1.5*M_PI);
697         parampourtransition = M_PI;
698       }
699       else {
700         pmult1.SetParameter(1.5*M_PI);
701         pmult2.SetParameter(0.5*M_PI);
702         parampourtransition = 0.0;
703       }
704       
705       //-- Calcul des transitions de ligne pour la premiere ligne 
706       ElCLib::D1(parampourtransition,elipsol,ptref,Tgt);      
707       qwe=Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
708       if(qwe> 0.00000001)
709       {
710         trans1 = IntSurf_Out;
711         trans2 = IntSurf_In;
712       }
713       else if(qwe< -0.00000001)
714       {
715         trans1 = IntSurf_In;
716         trans2 = IntSurf_Out;
717       }
718       else
719       { 
720         trans1=trans2=IntSurf_Undecided;
721       }
722
723       //-- La transition a ete calculee sur un point de cette ligne 
724       glig = new IntPatch_GLine(elipsol,Standard_False,trans1,trans2);
725       //
726       {
727         Standard_Real aU1, aV1, aU2, aV2;
728         IntPatch_Point aIP;
729         gp_Pnt aP (ElCLib::Value(0., elipsol));
730         //
731         aIP.SetValue(aP,Tol,Standard_False);
732         aIP.SetMultiple(Standard_False);
733         //
734         Quad1.Parameters(aP, aU1, aV1); 
735         Quad2.Parameters(aP, aU2, aV2);
736         aIP.SetParameters(aU1, aV1, aU2, aV2);
737         //
738         aIP.SetParameter(0.);
739         glig->AddVertex(aIP);
740         glig->SetFirstPoint(1);
741         //
742         aIP.SetParameter(2.*M_PI);
743         glig->AddVertex(aIP);
744         glig->SetLastPoint(2);
745       }
746       //
747       glig->AddVertex(pmult1);
748       glig->AddVertex(pmult2);
749       //
750       slin.Append(glig);
751     }
752     break;
753
754   case IntAna_NoGeometricSolution:
755     {
756       Standard_Boolean bReverse;
757       Standard_Real U1,V1,U2,V2;
758       gp_Pnt psol;
759       //
760       bReverse=IsToReverse(Cy1, Cy2, Tol);
761       if (bReverse)
762       {
763         Cy2=Quad1.Cylinder();
764         Cy1=Quad2.Cylinder();
765       }
766       //
767       IntAna_IntQuadQuad anaint(Cy1,Cy2,Tol);
768       if (!anaint.IsDone())
769       {
770         return Standard_False;
771       }
772       
773       if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0)
774       {
775         Empty = Standard_True;
776       }
777       else
778       {
779         NbSol = anaint.NbPnt();
780         for (i = 1; i <= NbSol; i++)
781         {
782           psol = anaint.Point(i);
783           Quad1.Parameters(psol,U1,V1);
784           Quad2.Parameters(psol,U2,V2);
785           ptsol.SetValue(psol,Tol,Standard_True);
786           ptsol.SetParameters(U1,V1,U2,V2);
787           spnt.Append(ptsol);
788         }
789
790         gp_Pnt ptvalid, ptf, ptl;
791         gp_Vec tgvalid;
792
793         Standard_Real first,last,para;
794         IntAna_Curve curvsol;
795         Standard_Boolean tgfound;
796         Standard_Integer kount;
797
798         NbSol = anaint.NbCurve();
799         for (i = 1; i <= NbSol; i++)
800         {
801           curvsol = anaint.Curve(i);
802           curvsol.Domain(first,last);
803           ptf = curvsol.Value(first);
804           ptl = curvsol.Value(last);
805
806           para = last;
807           kount = 1;
808           tgfound = Standard_False;
809
810           while (!tgfound)
811           {
812             para = (1.123*first + para)/2.123;
813             tgfound = curvsol.D1u(para,ptvalid,tgvalid);
814             if (!tgfound)
815             {
816               kount ++;
817               tgfound = kount > 5;
818             }
819           }
820
821           Handle(IntPatch_ALine) alig;
822           if (kount <= 5)
823           {
824             Standard_Real qwe = tgvalid.DotCross( Quad2.Normale(ptvalid),
825                                                   Quad1.Normale(ptvalid));
826             if(qwe>0.00000001)
827             { 
828               trans1 = IntSurf_Out;
829               trans2 = IntSurf_In;
830             }
831             else if(qwe<-0.00000001)
832             {
833               trans1 = IntSurf_In;
834               trans2 = IntSurf_Out;
835             }
836             else
837             { 
838               trans1=trans2=IntSurf_Undecided; 
839             }
840             alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
841           }
842           else
843           {
844             alig = new IntPatch_ALine(curvsol,Standard_False);
845             //-- cout << "Transition indeterminee" << endl;
846           }
847
848           Standard_Boolean TempFalse1 = Standard_False;
849           Standard_Boolean TempFalse2 = Standard_False;
850
851           ProcessBounds(alig,slin,Quad1,Quad2,TempFalse1,ptf,first,
852                         TempFalse2,ptl,last,Multpoint,Tol);
853           slin.Append(alig);
854         }
855       }
856     }
857     break;
858
859   default:
860     return Standard_False;
861   }
862
863   return Standard_True;
864 }
865
866 //=======================================================================
867 //function : ShortCosForm
868 //purpose  : Represents theCosFactor*cosA+theSinFactor*sinA as
869 //            theCoeff*cos(A-theAngle) if it is possibly (all angles are
870 //            in radians).
871 //=======================================================================
872 static void ShortCosForm( const Standard_Real theCosFactor,
873                           const Standard_Real theSinFactor,
874                           Standard_Real& theCoeff,
875                           Standard_Real& theAngle)
876 {
877   theCoeff = sqrt(theCosFactor*theCosFactor+theSinFactor*theSinFactor);
878   theAngle = 0.0;
879   if(IsEqual(theCoeff, 0.0))
880   {
881     theAngle = 0.0;
882     return;
883   }
884
885   theAngle = acos(Abs(theCosFactor/theCoeff));
886
887   if(theSinFactor > 0.0)
888   {
889     if(IsEqual(theCosFactor, 0.0))
890     {
891       theAngle = M_PI/2.0;
892     }
893     else if(theCosFactor < 0.0)
894     {
895       theAngle = M_PI-theAngle;
896     }
897   }
898   else if(IsEqual(theSinFactor, 0.0))
899   {
900     if(theCosFactor < 0.0)
901     {
902       theAngle = M_PI;
903     }
904   }
905   if(theSinFactor < 0.0)
906   {
907     if(theCosFactor > 0.0)
908     {
909       theAngle = 2.0*M_PI-theAngle;
910     }
911     else if(IsEqual(theCosFactor, 0.0))
912     {
913       theAngle = 3.0*M_PI/2.0;
914     }
915     else if(theCosFactor < 0.0)
916     {
917       theAngle = M_PI+theAngle;
918     }
919   }
920 }
921
922 enum SearchBoundType
923 {
924   SearchNONE = 0,
925   SearchV1 = 1,
926   SearchV2 = 2
927 };
928
929 //Stores equations coefficients
930 struct stCoeffsValue
931 {
932   stCoeffsValue(const gp_Cylinder&, const gp_Cylinder&);
933
934   math_Vector mVecA1;
935   math_Vector mVecA2;
936   math_Vector mVecB1;
937   math_Vector mVecB2;
938   math_Vector mVecC1;
939   math_Vector mVecC2;
940   math_Vector mVecD;
941
942   Standard_Real mK21; //sinU2
943   Standard_Real mK11; //sinU1
944   Standard_Real mL21; //cosU2
945   Standard_Real mL11;  //cosU1
946   Standard_Real mM1;  //Free member
947
948   Standard_Real mK22; //sinU2
949   Standard_Real mK12; //sinU1
950   Standard_Real mL22; //cosU2
951   Standard_Real mL12; //cosU1
952   Standard_Real mM2; //Free member
953   
954   Standard_Real mK1;
955   Standard_Real mL1;
956   Standard_Real mK2;
957   Standard_Real mL2;
958
959   Standard_Real mFIV1;
960   Standard_Real mPSIV1;
961   Standard_Real mFIV2;
962   Standard_Real mPSIV2;
963
964   Standard_Real mB;
965   Standard_Real mC;
966   Standard_Real mFI1;
967   Standard_Real mFI2;
968 };
969
970 stCoeffsValue::stCoeffsValue( const gp_Cylinder& theCyl1,
971                               const gp_Cylinder& theCyl2):
972   mVecA1(-theCyl1.Radius()*theCyl1.XAxis().Direction().XYZ()),
973   mVecA2(theCyl2.Radius()*theCyl2.XAxis().Direction().XYZ()),
974   mVecB1(-theCyl1.Radius()*theCyl1.YAxis().Direction().XYZ()),
975   mVecB2(theCyl2.Radius()*theCyl2.YAxis().Direction().XYZ()),
976   mVecC1(theCyl1.Axis().Direction().XYZ()),
977   mVecC2(theCyl2.Axis().Direction().XYZ().Reversed()),
978   mVecD(theCyl2.Location().XYZ() - theCyl1.Location().XYZ())
979 {
980   enum CoupleOfEquation
981   {
982     COENONE = 0,
983     COE12 = 1,
984     COE23 = 2,
985     COE13 = 3
986   }aFoundCouple = COENONE;
987
988
989   Standard_Real aDetV1V2 = 0.0;
990   
991   const Standard_Real aDelta1 = mVecC1(1)*mVecC2(2)-mVecC1(2)*mVecC2(1); //1-2
992   const Standard_Real aDelta2 = mVecC1(2)*mVecC2(3)-mVecC1(3)*mVecC2(2); //2-3
993   const Standard_Real aDelta3 = mVecC1(1)*mVecC2(3)-mVecC1(3)*mVecC2(1); //1-3
994   const Standard_Real anAbsD1 = Abs(aDelta1); //1-2
995   const Standard_Real anAbsD2 = Abs(aDelta2); //2-3
996   const Standard_Real anAbsD3 = Abs(aDelta3); //1-3
997
998   if(anAbsD1 >= anAbsD2)
999   {
1000     if(anAbsD3 > anAbsD1)
1001     {
1002       aFoundCouple = COE13;
1003       aDetV1V2 = aDelta3;
1004     }
1005     else
1006     {
1007       aFoundCouple = COE12;
1008       aDetV1V2 = aDelta1;
1009     }
1010   }
1011   else
1012   {
1013     if(anAbsD3 > anAbsD2)
1014     {
1015       aFoundCouple = COE13;
1016       aDetV1V2 = aDelta3;
1017     }
1018     else
1019     {
1020       aFoundCouple = COE23;
1021       aDetV1V2 = aDelta2;
1022     }
1023   }
1024
1025   if(Abs(aDetV1V2) < aNulValue)
1026   {
1027     Standard_Failure::Raise("Error. Exception in divide by zerro (IntCyCyTrim)!!!!");
1028   }
1029
1030   switch(aFoundCouple)
1031   {
1032   case COE12:
1033     break;
1034   case COE23:
1035     {
1036       math_Vector aVTemp(mVecA1);
1037       mVecA1(1) = aVTemp(2);
1038       mVecA1(2) = aVTemp(3);
1039       mVecA1(3) = aVTemp(1);
1040
1041       aVTemp = mVecA2;
1042       mVecA2(1) = aVTemp(2);
1043       mVecA2(2) = aVTemp(3);
1044       mVecA2(3) = aVTemp(1);
1045
1046       aVTemp = mVecB1;
1047       mVecB1(1) = aVTemp(2);
1048       mVecB1(2) = aVTemp(3);
1049       mVecB1(3) = aVTemp(1);
1050       
1051       aVTemp = mVecB2;
1052       mVecB2(1) = aVTemp(2);
1053       mVecB2(2) = aVTemp(3);
1054       mVecB2(3) = aVTemp(1);
1055
1056       aVTemp = mVecC1;
1057       mVecC1(1) = aVTemp(2);
1058       mVecC1(2) = aVTemp(3);
1059       mVecC1(3) = aVTemp(1);
1060
1061       aVTemp = mVecC2;
1062       mVecC2(1) = aVTemp(2);
1063       mVecC2(2) = aVTemp(3);
1064       mVecC2(3) = aVTemp(1);
1065
1066       aVTemp = mVecD;
1067       mVecD(1) = aVTemp(2);
1068       mVecD(2) = aVTemp(3);
1069       mVecD(3) = aVTemp(1);
1070
1071       break;
1072     }
1073   case COE13:
1074     {
1075       math_Vector aVTemp = mVecA1;
1076       mVecA1(2) = aVTemp(3);
1077       mVecA1(3) = aVTemp(2);
1078
1079       aVTemp = mVecA2;
1080       mVecA2(2) = aVTemp(3);
1081       mVecA2(3) = aVTemp(2);
1082
1083       aVTemp = mVecB1;
1084       mVecB1(2) = aVTemp(3);
1085       mVecB1(3) = aVTemp(2);
1086
1087       aVTemp = mVecB2;
1088       mVecB2(2) = aVTemp(3);
1089       mVecB2(3) = aVTemp(2);
1090
1091       aVTemp = mVecC1;
1092       mVecC1(2) = aVTemp(3);
1093       mVecC1(3) = aVTemp(2);
1094
1095       aVTemp = mVecC2;
1096       mVecC2(2) = aVTemp(3);
1097       mVecC2(3) = aVTemp(2);
1098
1099       aVTemp = mVecD;
1100       mVecD(2) = aVTemp(3);
1101       mVecD(3) = aVTemp(2);
1102
1103       break;
1104     }
1105   default:
1106     break;
1107   }
1108
1109   //------- For V1 (begin)
1110   //sinU2
1111   mK21 = (mVecC2(2)*mVecB2(1)-mVecC2(1)*mVecB2(2))/aDetV1V2;
1112   //sinU1
1113   mK11 = (mVecC2(2)*mVecB1(1)-mVecC2(1)*mVecB1(2))/aDetV1V2;
1114   //cosU2
1115   mL21 = (mVecC2(2)*mVecA2(1)-mVecC2(1)*mVecA2(2))/aDetV1V2;
1116   //cosU1
1117   mL11 = (mVecC2(2)*mVecA1(1)-mVecC2(1)*mVecA1(2))/aDetV1V2;
1118   //Free member
1119   mM1 =  (mVecC2(2)*mVecD(1)-mVecC2(1)*mVecD(2))/aDetV1V2;
1120   //------- For V1 (end)
1121
1122   //------- For V2 (begin)
1123   //sinU2
1124   mK22 = (mVecC1(1)*mVecB2(2)-mVecC1(2)*mVecB2(1))/aDetV1V2;
1125   //sinU1
1126   mK12 = (mVecC1(1)*mVecB1(2)-mVecC1(2)*mVecB1(1))/aDetV1V2;
1127   //cosU2
1128   mL22 = (mVecC1(1)*mVecA2(2)-mVecC1(2)*mVecA2(1))/aDetV1V2;
1129   //cosU1
1130   mL12 = (mVecC1(1)*mVecA1(2)-mVecC1(2)*mVecA1(1))/aDetV1V2;
1131   //Free member
1132   mM2 = (mVecC1(1)*mVecD(2)-mVecC1(2)*mVecD(1))/aDetV1V2;
1133   //------- For V1 (end)
1134
1135   ShortCosForm(mL11, mK11, mK1, mFIV1);
1136   ShortCosForm(mL21, mK21, mL1, mPSIV1);
1137   ShortCosForm(mL12, mK12, mK2, mFIV2);
1138   ShortCosForm(mL22, mK22, mL2, mPSIV2);
1139
1140   const Standard_Real aA1=mVecC1(3)*mK21+mVecC2(3)*mK22-mVecB2(3), //sinU2
1141                       aA2=mVecC1(3)*mL21+mVecC2(3)*mL22-mVecA2(3), //cosU2
1142                       aB1=mVecB1(3)-mVecC1(3)*mK11-mVecC2(3)*mK12, //sinU1
1143                       aB2=mVecA1(3)-mVecC1(3)*mL11-mVecC2(3)*mL12; //cosU1
1144
1145   mC =mVecD(3) - mVecC1(3)*mM1 -mVecC2(3)*mM2;  //Free
1146
1147   Standard_Real aA = 0.0;
1148
1149   ShortCosForm(aB2,aB1,mB,mFI1);
1150   ShortCosForm(aA2,aA1,aA,mFI2);
1151
1152   mB /= aA;
1153   mC /= aA;
1154 }
1155
1156 //=======================================================================
1157 //function : CylCylMonotonicity
1158 //purpose  : Determines, if U2(U1) function is increasing.
1159 //=======================================================================
1160 static Standard_Boolean CylCylMonotonicity( const Standard_Real theU1par,
1161                                             const Standard_Integer theWLIndex,
1162                                             const stCoeffsValue& theCoeffs,
1163                                             const Standard_Real thePeriod,
1164                                             Standard_Boolean& theIsIncreasing)
1165 {
1166   // U2(U1) = FI2 + (+/-)acos(B*cos(U1 - FI1) + C);
1167   //Accordingly,
1168   //Func. U2(X1) = FI2 + X1;
1169   //Func. X1(X2) = anArccosFactor*X2;
1170   //Func. X2(X3) = acos(X3);
1171   //Func. X3(X4) = B*X4 + C;
1172   //Func. X4(U1) = cos(U1 - FI1).
1173   //
1174   //Consequently,
1175   //U2(X1) is always increasing.
1176   //X1(X2) is increasing if anArccosFactor > 0.0 and
1177   //is decreasing otherwise.
1178   //X2(X3) is always decreasing.
1179   //Therefore, U2(X3) is decreasing if anArccosFactor > 0.0 and
1180   //is increasing otherwise.
1181   //X3(X4) is increasing if B > 0 and is decreasing otherwise.
1182   //X4(U1) is increasing if U1 - FI1 in [PI, 2*PI) and
1183   //is decreasing U1 - FI1 in [0, PI) or if (U1 - FI1 == 2PI).
1184   //After that, we can predict behaviour of U2(U1) function:
1185   //if it is increasing or decreasing.
1186
1187   //For "+/-" sign. If isPlus == TRUE, "+" is chosen, otherwise, we choose "-".
1188   Standard_Boolean isPlus = Standard_False;
1189
1190   switch(theWLIndex)
1191   {
1192   case 0: 
1193     isPlus = Standard_True;
1194     break;
1195   case 1:
1196     isPlus = Standard_False;
1197     break;
1198   default:
1199     //Standard_Failure::Raise("Error. Range Error!!!!");
1200     return Standard_False;
1201   }
1202
1203   Standard_Real aU1Temp = theU1par - theCoeffs.mFI1;
1204   InscribePoint(0, thePeriod, aU1Temp, 0.0, thePeriod, Standard_False);
1205
1206   theIsIncreasing = Standard_True;
1207
1208   if(((M_PI - aU1Temp) < RealSmall()) && (aU1Temp < thePeriod))
1209   {
1210     theIsIncreasing = Standard_False;
1211   }
1212
1213   if(theCoeffs.mB < 0.0)
1214   {
1215     theIsIncreasing = !theIsIncreasing;
1216   }
1217
1218   if(!isPlus)
1219   {
1220     theIsIncreasing = !theIsIncreasing;
1221   }  
1222
1223   return Standard_True;
1224 }
1225
1226 //=======================================================================
1227 //function : CylCylComputeParameters
1228 //purpose  : Computes U2 (U-parameter of the 2nd cylinder) and, if theDelta != 0,
1229 //            esimates the tolerance of U2-computing (estimation result is
1230 //            assigned to *theDelta value).
1231 //=======================================================================
1232 static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1par,
1233                                                 const Standard_Integer theWLIndex,
1234                                                 const stCoeffsValue& theCoeffs,
1235                                                 Standard_Real& theU2,
1236                                                 Standard_Real* const theDelta = 0)
1237 {
1238   //This formula is got from some experience and can be changed.
1239   const Standard_Real aTol0 = Min(10.0*Epsilon(1.0)*theCoeffs.mB, aNulValue);
1240   const Standard_Real aTol = 1.0 - aTol0;
1241
1242   if(theWLIndex < 0 || theWLIndex > 1)
1243     return Standard_False;
1244
1245   const Standard_Real aSign = theWLIndex ? -1.0 : 1.0;
1246
1247   Standard_Real anArg = cos(theU1par - theCoeffs.mFI1);
1248   anArg = theCoeffs.mB*anArg + theCoeffs.mC;
1249
1250   if(anArg > aTol)
1251   {
1252     if(theDelta)
1253       *theDelta = 0.0;
1254
1255     anArg = 1.0;
1256   }
1257   else if(anArg < -aTol)
1258   {
1259     if(theDelta)
1260       *theDelta = 0.0;
1261
1262     anArg = -1.0;
1263   }
1264   else if(theDelta)
1265   {
1266     //There is a case, when
1267     //  const double aPar = 0.99999999999721167;
1268     //  const double aFI2 = 2.3593296083566181e-006;
1269
1270     //Then
1271     //  aPar - cos(aFI2) == -5.10703e-015 ==> cos(aFI2) == aPar. 
1272     //Theoreticaly, in this case 
1273     //  aFI2 == +/- acos(aPar).
1274     //However,
1275     //  acos(aPar) - aFI2 == 2.16362e-009.
1276     //Error is quite big.
1277
1278     //This error should be estimated. Let use following way, which is based
1279     //on expanding to Taylor series.
1280
1281     //  acos(p)-acos(p+x) = x/sqrt(1-p*p).
1282
1283     //If p == (1-d) (when p > 0) or p == (-1+d) (when p < 0) then
1284     //  acos(p)-acos(p+x) = x/sqrt(d*(2-d)).
1285
1286     //Here always aTol0 <= d <= 1. Max(x) is considered (!) to be equal to aTol0.
1287     //In this case
1288     //  8*aTol0 <= acos(p)-acos(p+x) <= sqrt(2/(2-aTol0)-1),
1289     //                                              because 0 < aTol0 < 1.
1290     //E.g. when aTol0 = 1.0e-11,
1291     //   8.0e-11 <= acos(p)-acos(p+x) < 2.24e-6.
1292
1293     const Standard_Real aDelta = Min(1.0-anArg, 1.0+anArg);
1294     Standard_DivideByZero_Raise_if((aDelta*aDelta < RealSmall()) || (aDelta >= 2.0), 
1295           "IntPatch_ImpImpIntersection_4.gxx, CylCylComputeParameters()");
1296     *theDelta = aTol0/sqrt(aDelta*(2.0-aDelta));
1297   }
1298
1299   theU2 = acos(anArg);
1300   theU2 = theCoeffs.mFI2 + aSign*theU2;
1301
1302   return Standard_True;
1303 }
1304
1305 static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1,
1306                                                 const Standard_Real theU2,
1307                                                 const stCoeffsValue& theCoeffs,
1308                                                 Standard_Real& theV1,
1309                                                 Standard_Real& theV2)
1310 {
1311   theV1 = theCoeffs.mK21 * sin(theU2) + 
1312           theCoeffs.mK11 * sin(theU1) +
1313           theCoeffs.mL21 * cos(theU2) +
1314           theCoeffs.mL11 * cos(theU1) + theCoeffs.mM1;
1315
1316   theV2 = theCoeffs.mK22 * sin(theU2) +
1317           theCoeffs.mK12 * sin(theU1) +
1318           theCoeffs.mL22 * cos(theU2) +
1319           theCoeffs.mL12 * cos(theU1) + theCoeffs.mM2;
1320
1321   return Standard_True;
1322 }
1323
1324
1325 static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1par,
1326                                                 const Standard_Integer theWLIndex,
1327                                                 const stCoeffsValue& theCoeffs,
1328                                                 Standard_Real& theU2,
1329                                                 Standard_Real& theV1,
1330                                                 Standard_Real& theV2)
1331 {
1332   if(!CylCylComputeParameters(theU1par, theWLIndex, theCoeffs, theU2))
1333     return Standard_False;
1334
1335   if(!CylCylComputeParameters(theU1par, theU2, theCoeffs, theV1, theV2))
1336     return Standard_False;
1337
1338   return Standard_True;
1339 }
1340
1341 //=======================================================================
1342 //function : SearchOnVBounds
1343 //purpose  : 
1344 //=======================================================================
1345 static Standard_Boolean SearchOnVBounds(const SearchBoundType theSBType,
1346                                         const stCoeffsValue& theCoeffs,
1347                                         const Standard_Real theVzad,
1348                                         const Standard_Real theVInit,
1349                                         const Standard_Real theInitU2,
1350                                         const Standard_Real theInitMainVar,
1351                                         Standard_Real& theMainVariableValue)
1352 {
1353   const Standard_Integer aNbDim = 3;
1354   const Standard_Real aMaxError = 4.0*M_PI; // two periods
1355   
1356   theMainVariableValue = theInitMainVar;
1357   const Standard_Real aTol2 = 1.0e-18;
1358   Standard_Real aMainVarPrev = theInitMainVar, aU2Prev = theInitU2, anOtherVar = theVInit;
1359   
1360   //Structure of aMatr:
1361   //  C_{1}*U_{1} & C_{2}*U_{2} & C_{3}*V_{*},
1362   //where C_{1}, C_{2} and C_{3} are math_Vector.
1363   math_Matrix aMatr(1, aNbDim, 1, aNbDim);
1364
1365   Standard_Real anError = RealLast();
1366   Standard_Real anErrorPrev = anError;
1367   Standard_Integer aNbIter = 0;
1368   do
1369   {
1370     if(++aNbIter > 1000)
1371       return Standard_False;
1372
1373     const Standard_Real aSinU1 = sin(aMainVarPrev),
1374                         aCosU1 = cos(aMainVarPrev),
1375                         aSinU2 = sin(aU2Prev),
1376                         aCosU2 = cos(aU2Prev);
1377
1378     math_Vector aVecFreeMem = (theCoeffs.mVecA2 * aU2Prev +
1379                                               theCoeffs.mVecB2) * aSinU2 -
1380                               (theCoeffs.mVecB2 * aU2Prev -
1381                                               theCoeffs.mVecA2) * aCosU2 +
1382                               (theCoeffs.mVecA1 * aMainVarPrev +
1383                                               theCoeffs.mVecB1) * aSinU1 -
1384                               (theCoeffs.mVecB1 * aMainVarPrev -
1385                                               theCoeffs.mVecA1) * aCosU1 +
1386                                                             theCoeffs.mVecD;
1387
1388     math_Vector aMSum(1, 3);
1389
1390     switch(theSBType)
1391     {
1392     case SearchV1:
1393       aMatr.SetCol(3, theCoeffs.mVecC2);
1394       aMSum = theCoeffs.mVecC1 * theVzad;
1395       aVecFreeMem -= aMSum;
1396       aMSum += theCoeffs.mVecC2*anOtherVar;
1397       break;
1398
1399     case SearchV2:
1400       aMatr.SetCol(3, theCoeffs.mVecC1);
1401       aMSum = theCoeffs.mVecC2 * theVzad;
1402       aVecFreeMem -= aMSum;
1403       aMSum += theCoeffs.mVecC1*anOtherVar;
1404       break;
1405
1406     default:
1407       return Standard_False;
1408     }
1409
1410     aMatr.SetCol(1, theCoeffs.mVecA1 * aSinU1 - theCoeffs.mVecB1 * aCosU1);
1411     aMatr.SetCol(2, theCoeffs.mVecA2 * aSinU2 - theCoeffs.mVecB2 * aCosU2);
1412
1413     Standard_Real aDetMainSyst = aMatr.Determinant();
1414
1415     if(Abs(aDetMainSyst) < aNulValue)
1416     {
1417       return Standard_False;
1418     }
1419
1420     math_Matrix aM1(aMatr), aM2(aMatr), aM3(aMatr);
1421     aM1.SetCol(1, aVecFreeMem);
1422     aM2.SetCol(2, aVecFreeMem);
1423     aM3.SetCol(3, aVecFreeMem);
1424
1425     const Standard_Real aDetMainVar = aM1.Determinant();
1426     const Standard_Real aDetVar1    = aM2.Determinant();
1427     const Standard_Real aDetVar2    = aM3.Determinant();
1428
1429     Standard_Real aDelta = aDetMainVar/aDetMainSyst-aMainVarPrev;
1430
1431     if(Abs(aDelta) > aMaxError)
1432       return Standard_False;
1433
1434     anError = aDelta*aDelta;
1435     aMainVarPrev += aDelta;
1436         
1437     ///
1438     aDelta = aDetVar1/aDetMainSyst-aU2Prev;
1439
1440     if(Abs(aDelta) > aMaxError)
1441       return Standard_False;
1442
1443     anError += aDelta*aDelta;
1444     aU2Prev += aDelta;
1445
1446     ///
1447     aDelta = aDetVar2/aDetMainSyst-anOtherVar;
1448     anError += aDelta*aDelta;
1449     anOtherVar += aDelta;
1450
1451     if(anError > anErrorPrev)
1452     {//Method diverges. Keep the best result
1453       const Standard_Real aSinU1Last = sin(aMainVarPrev),
1454                           aCosU1Last = cos(aMainVarPrev),
1455                           aSinU2Last = sin(aU2Prev),
1456                           aCosU2Last = cos(aU2Prev);
1457       aMSum -= (theCoeffs.mVecA1*aCosU1Last + 
1458                 theCoeffs.mVecB1*aSinU1Last +
1459                 theCoeffs.mVecA2*aCosU2Last +
1460                 theCoeffs.mVecB2*aSinU2Last +
1461                 theCoeffs.mVecD);
1462       const Standard_Real aSQNorm = aMSum.Norm2();
1463       return (aSQNorm < aTol2);
1464     }
1465     else
1466     {
1467       theMainVariableValue = aMainVarPrev;
1468     }
1469
1470     anErrorPrev = anError;
1471   }
1472   while(anError > aTol2);
1473
1474   theMainVariableValue = aMainVarPrev;
1475
1476   return Standard_True;
1477 }
1478
1479 //=======================================================================
1480 //function : InscribePoint
1481 //purpose  : If theFlForce==TRUE theUGiven will be changed forcefully
1482 //            even if theUGiven is already inscibed in the boundary
1483 //            (if it is possible; i.e. if new theUGiven is inscribed
1484 //            in the boundary, too).
1485 //=======================================================================
1486 Standard_Boolean InscribePoint( const Standard_Real theUfTarget,
1487                                 const Standard_Real theUlTarget,
1488                                 Standard_Real& theUGiven,
1489                                 const Standard_Real theTol2D,
1490                                 const Standard_Real thePeriod,
1491                                 const Standard_Boolean theFlForce)
1492 {
1493   if(Precision::IsInfinite(theUGiven))
1494   {
1495     return Standard_False;
1496   }
1497
1498   if((theUfTarget - theUGiven <= theTol2D) &&
1499               (theUGiven - theUlTarget <= theTol2D))
1500   {//it has already inscribed
1501
1502     /*
1503              Utf    U      Utl
1504               +     *       +
1505     */
1506     
1507     if(theFlForce)
1508     {
1509       Standard_Real anUtemp = theUGiven + thePeriod;
1510       if((theUfTarget - anUtemp <= theTol2D) &&
1511                 (anUtemp - theUlTarget <= theTol2D))
1512       {
1513         theUGiven = anUtemp;
1514         return Standard_True;
1515       }
1516       
1517       anUtemp = theUGiven - thePeriod;
1518       if((theUfTarget - anUtemp <= theTol2D) &&
1519                 (anUtemp - theUlTarget <= theTol2D))
1520       {
1521         theUGiven = anUtemp;
1522       }
1523     }
1524
1525     return Standard_True;
1526   }
1527
1528   if(IsEqual(thePeriod, 0.0))
1529   {//it cannot be inscribed
1530     return Standard_False;
1531   }
1532
1533   //Make theUGiven nearer to theUfTarget (in order to avoid
1534   //excess iterations)
1535   theUGiven += thePeriod*Floor((theUfTarget-theUGiven)/thePeriod);
1536   Standard_Real aDU = theUGiven - theUfTarget;
1537
1538   if(aDU > 0.0)
1539     aDU = -thePeriod;
1540   else
1541     aDU = +thePeriod;
1542
1543   while(((theUGiven - theUfTarget)*aDU < 0.0) && 
1544         !((theUfTarget - theUGiven <= theTol2D) &&
1545         (theUGiven - theUlTarget <= theTol2D)))
1546   {
1547     theUGiven += aDU;
1548   }
1549   
1550   return ((theUfTarget - theUGiven <= theTol2D) &&
1551           (theUGiven - theUlTarget <= theTol2D));
1552 }
1553
1554 //=======================================================================
1555 //function : InscribeInterval
1556 //purpose  : Adjusts theUfGiven and after that fits theUlGiven to result
1557 //=======================================================================
1558 static Standard_Boolean InscribeInterval(const Standard_Real theUfTarget,
1559                                       const Standard_Real theUlTarget,
1560                                       Standard_Real& theUfGiven,
1561                                       Standard_Real& theUlGiven,
1562                                       const Standard_Real theTol2D,
1563                                       const Standard_Real thePeriod)
1564 {
1565   Standard_Real anUpar = theUfGiven;
1566   const Standard_Real aDelta = theUlGiven - theUfGiven;
1567   if(InscribePoint(theUfTarget, theUlTarget, anUpar,
1568                         theTol2D, thePeriod, Standard_False))
1569   {
1570     theUfGiven = anUpar;
1571     theUlGiven = theUfGiven + aDelta;
1572   }
1573   else 
1574   {
1575     anUpar = theUlGiven;
1576     if(InscribePoint(theUfTarget, theUlTarget, anUpar,
1577                         theTol2D, thePeriod, Standard_False))
1578     {
1579       theUlGiven = anUpar;
1580       theUfGiven = theUlGiven - aDelta;
1581     }
1582     else
1583     {
1584       return Standard_False;
1585     }
1586   }
1587
1588   return Standard_True;
1589 }
1590
1591 //=======================================================================
1592 //function : ExcludeNearElements
1593 //purpose  : Checks if theArr contains two almost equal elements.
1594 //            If it is true then one of equal elements will be excluded
1595 //            (made infinite).
1596 //           Returns TRUE if at least one element of theArr has been changed.
1597 //ATTENTION!!!
1598 //           1. Every not infinite element of theArr is considered to be 
1599 //            in [0, T] interval (where T is the period);
1600 //           2. theArr must be sorted in ascending order.
1601 //=======================================================================
1602 static Standard_Boolean ExcludeNearElements(Standard_Real theArr[],
1603                                             const Standard_Integer theNOfMembers,
1604                                             const Standard_Real theTol)
1605 {
1606   Standard_Boolean aRetVal = Standard_False;
1607   for(Standard_Integer i = 1; i < theNOfMembers; i++)
1608   {
1609     Standard_Real &anA = theArr[i],
1610                   &anB = theArr[i-1];
1611
1612     //Here, anA >= anB
1613
1614     if(Precision::IsInfinite(anA))
1615       break;
1616
1617     if((anA-anB) < theTol)
1618     {
1619       anA = (anA + anB)/2.0;
1620
1621       //Make this element infinite an forget it
1622       //(we will not use it in next iterations).
1623       anB = Precision::Infinite();
1624       aRetVal = Standard_True;
1625     }
1626   }
1627
1628   return aRetVal;
1629 }
1630
1631 //=======================================================================
1632 //function : AddPointIntoWL
1633 //purpose  : Surf1 is a surface, whose U-par is variable.
1634 //=======================================================================
1635 static Standard_Boolean AddPointIntoWL( const IntSurf_Quadric& theQuad1,
1636                                         const IntSurf_Quadric& theQuad2,
1637                                         const stCoeffsValue& theCoeffs,
1638                                         const Standard_Boolean isTheReverse,
1639                                         const Standard_Boolean isThePrecise,
1640                                         const gp_Pnt2d& thePntOnSurf1,
1641                                         const gp_Pnt2d& thePntOnSurf2,
1642                                         const Standard_Real theUfSurf1,
1643                                         const Standard_Real theUlSurf1,
1644                                         const Standard_Real theUfSurf2,
1645                                         const Standard_Real theUlSurf2,
1646                                         const Standard_Real theVfSurf1,
1647                                         const Standard_Real theVlSurf1,
1648                                         const Standard_Real theVfSurf2,
1649                                         const Standard_Real theVlSurf2,
1650                                         const Standard_Real thePeriodOfSurf1,
1651                                         const Handle(IntSurf_LineOn2S)& theLine,
1652                                         const Standard_Integer theWLIndex,
1653                                         const Standard_Real theTol3D,
1654                                         const Standard_Real theTol2D,
1655                                         const Standard_Boolean theFlForce,
1656                                         const Standard_Boolean theFlBefore = Standard_False)
1657 {
1658   gp_Pnt  aPt1(theQuad1.Value(thePntOnSurf1.X(), thePntOnSurf1.Y())),
1659           aPt2(theQuad2.Value(thePntOnSurf2.X(), thePntOnSurf2.Y()));
1660
1661   Standard_Real aU1par = thePntOnSurf1.X();
1662   if(!InscribePoint(theUfSurf1, theUlSurf1, aU1par, theTol2D,
1663                                     thePeriodOfSurf1, theFlForce))
1664     return Standard_False;
1665
1666   Standard_Real aU2par = thePntOnSurf2.X();
1667   if(!InscribePoint(theUfSurf2, theUlSurf2, aU2par, theTol2D,
1668                                     thePeriodOfSurf1, Standard_False))
1669     return Standard_False;
1670
1671   Standard_Real aV1par = thePntOnSurf1.Y();
1672   if((aV1par - theVlSurf1 > theTol2D) || (theVfSurf1 - aV1par > theTol2D))
1673     return Standard_False;
1674
1675   Standard_Real aV2par = thePntOnSurf2.Y();
1676   if((aV2par -  theVlSurf2 > theTol2D) || (theVfSurf2 - aV2par > theTol2D))
1677     return Standard_False;
1678   
1679   IntSurf_PntOn2S aPnt;
1680   
1681   if(isTheReverse)
1682   {
1683     aPnt.SetValue((aPt1.XYZ()+aPt2.XYZ())/2.0,
1684                         aU2par, aV2par,
1685                         aU1par, aV1par);
1686   }
1687   else
1688   {
1689     aPnt.SetValue((aPt1.XYZ()+aPt2.XYZ())/2.0,
1690                         aU1par, aV1par,
1691                         aU2par, aV2par);
1692   }
1693
1694   Standard_Integer aNbPnts = theLine->NbPoints();
1695   if(aNbPnts > 0)
1696   {
1697     Standard_Real aUl = 0.0, aVl = 0.0;
1698     const IntSurf_PntOn2S aPlast = theLine->Value(aNbPnts);
1699     if(isTheReverse)
1700       aPlast.ParametersOnS2(aUl, aVl);
1701     else
1702       aPlast.ParametersOnS1(aUl, aVl);
1703
1704     if(!theFlBefore && (aU1par <= aUl))
1705     {//Parameter value must be increased if theFlBefore == FALSE.
1706       return Standard_False;
1707     }
1708
1709     //theTol2D is minimal step along parameter changed. 
1710     //Therefore, if we apply this minimal step two 
1711     //neighbour points will be always "same". Consequently,
1712     //we should reduce tolerance for IsSame checking.
1713     const Standard_Real aDTol = 1.0-Epsilon(1.0);
1714     if(aPnt.IsSame(aPlast, theTol3D*aDTol, theTol2D*aDTol))
1715     {
1716       theLine->RemovePoint(aNbPnts);
1717     }
1718   }
1719
1720   theLine->Add(aPnt);
1721
1722   if(!isThePrecise)
1723     return Standard_True;
1724
1725   //Try to precise existing WLine
1726   aNbPnts = theLine->NbPoints();
1727   if(aNbPnts >= 3)
1728   {
1729     Standard_Real aU1 = 0.0, aU2 = 0.0, aU3 = 0.0, aV = 0.0;
1730     if(isTheReverse)
1731     {
1732       theLine->Value(aNbPnts).ParametersOnS2(aU3, aV);
1733       theLine->Value(aNbPnts-1).ParametersOnS2(aU2, aV);
1734       theLine->Value(aNbPnts-2).ParametersOnS2(aU1, aV);
1735     }
1736     else
1737     {
1738       theLine->Value(aNbPnts).ParametersOnS1(aU3, aV);
1739       theLine->Value(aNbPnts-1).ParametersOnS1(aU2, aV);
1740       theLine->Value(aNbPnts-2).ParametersOnS1(aU1, aV);
1741     }
1742
1743     const Standard_Real aStepPrev = aU2-aU1;
1744     const Standard_Real aStep = aU3-aU2;
1745
1746     const Standard_Integer aDeltaStep = RealToInt(aStepPrev/aStep);
1747
1748     if((1 < aDeltaStep) && (aDeltaStep < 2000))
1749     {
1750       SeekAdditionalPoints( theQuad1, theQuad2, theLine, 
1751                             theCoeffs, theWLIndex, aDeltaStep, aNbPnts-2,
1752                             aNbPnts-1, theUfSurf2, theUlSurf2,
1753                             theTol2D, thePeriodOfSurf1, isTheReverse);
1754     }
1755   }
1756
1757   return Standard_True;
1758 }
1759
1760 //=======================================================================
1761 //function : AddBoundaryPoint
1762 //purpose  : 
1763 //=======================================================================
1764 static Standard_Boolean AddBoundaryPoint( const IntSurf_Quadric& theQuad1,
1765                                           const IntSurf_Quadric& theQuad2,
1766                                           const Handle(IntPatch_WLine)& theWL,
1767                                           const stCoeffsValue& theCoeffs,
1768                                           const Bnd_Box2d& theUVSurf1,
1769                                           const Bnd_Box2d& theUVSurf2,
1770                                           const Standard_Real theTol3D,
1771                                           const Standard_Real theTol2D,
1772                                           const Standard_Real thePeriod,
1773                                           const Standard_Real theU1,
1774                                           const Standard_Real theU2,
1775                                           const Standard_Real theV1,
1776                                           const Standard_Real theV1Prev,
1777                                           const Standard_Real theV2,
1778                                           const Standard_Real theV2Prev,
1779                                           const Standard_Integer theWLIndex,
1780                                           const Standard_Boolean isTheReverse,
1781                                           const Standard_Boolean theFlForce,
1782                                           Standard_Boolean& isTheFound1,
1783                                           Standard_Boolean& isTheFound2)
1784 {
1785   Standard_Real aUSurf1f = 0.0, //const
1786                 aUSurf1l = 0.0,
1787                 aVSurf1f = 0.0,
1788                 aVSurf1l = 0.0;
1789   Standard_Real aUSurf2f = 0.0, //const
1790                 aUSurf2l = 0.0,
1791                 aVSurf2f = 0.0,
1792                 aVSurf2l = 0.0;
1793
1794   theUVSurf1.Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l);
1795   theUVSurf2.Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l);
1796
1797   SearchBoundType aTS1 = SearchNONE, aTS2 = SearchNONE;
1798   Standard_Real aV1zad = aVSurf1f, aV2zad = aVSurf2f;
1799
1800   Standard_Real anUpar1 = theU1, anUpar2 = theU1;
1801   Standard_Real aVf = theV1, aVl = theV1Prev;
1802
1803   if( (Abs(aVf-aVSurf1f) <= theTol2D) ||
1804       ((aVf-aVSurf1f)*(aVl-aVSurf1f) <= 0.0))
1805   {
1806     aTS1 = SearchV1;
1807     aV1zad = aVSurf1f;
1808     isTheFound1 = SearchOnVBounds(aTS1, theCoeffs, aVSurf1f, theV2, theU2, theU1, anUpar1);
1809   }
1810   else if((Abs(aVf-aVSurf1l) <= theTol2D) ||
1811           ((aVf-aVSurf1l)*(aVl-aVSurf1l) <= 0.0))
1812   {
1813     aTS1 = SearchV1;
1814     aV1zad = aVSurf1l;
1815     isTheFound1 = SearchOnVBounds(aTS1, theCoeffs, aVSurf1l, theV2, theU2, theU1, anUpar1);
1816   }
1817
1818   aVf = theV2;
1819   aVl = theV2Prev;
1820
1821   if((Abs(aVf-aVSurf2f) <= theTol2D) || 
1822       ((aVf-aVSurf2f)*(aVl-aVSurf2f) <= 0.0))
1823   {
1824     aTS2 = SearchV2;
1825     aV2zad = aVSurf2f;
1826     isTheFound2 = SearchOnVBounds(aTS2, theCoeffs, aVSurf2f, theV1, theU2, theU1, anUpar2);
1827   }
1828   else if((Abs(aVf-aVSurf2l) <= theTol2D) ||
1829           ((aVf-aVSurf2l)*(aVl-aVSurf2l) <= 0.0))
1830   {
1831     aTS2 = SearchV2;
1832     aV2zad = aVSurf2l;
1833     isTheFound2 = SearchOnVBounds(aTS2, theCoeffs, aVSurf2l, theV1, theU2, theU1, anUpar2);
1834   }
1835
1836   if(!isTheFound1 && !isTheFound2)
1837     return Standard_True;
1838
1839   //We increase U1 parameter. Therefore, added point must have U1 parameter less than
1840   //or equal to current (conditions "(anUpar1 < theU1)" and "(anUpar2 < theU1)").
1841
1842   if(anUpar1 < anUpar2)
1843   {
1844     if(isTheFound1 && (anUpar1 < theU1))
1845     {
1846       Standard_Real aU2 = theU2, aV1 = theV1, aV2 = theV2;
1847       if(!CylCylComputeParameters(anUpar1, theWLIndex, theCoeffs, aU2, aV1, aV2))
1848       {
1849         isTheFound1 = Standard_False;
1850       }
1851       
1852       if(aTS1 == SearchV1)
1853         aV1 = aV1zad;
1854
1855       if(aTS1 == SearchV2)
1856         aV2 = aV2zad;
1857
1858       if(isTheFound1 && !AddPointIntoWL(theQuad1, theQuad2, theCoeffs, isTheReverse, Standard_False,
1859                                         gp_Pnt2d(anUpar1, aV1), gp_Pnt2d(aU2, aV2),
1860                                         aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
1861                                         aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, thePeriod,
1862                                         theWL->Curve(), theWLIndex, theTol3D,
1863                                         theTol2D, theFlForce))
1864       {
1865         isTheFound1 = Standard_False;
1866       }
1867     }
1868     else
1869     {
1870       isTheFound1 = Standard_False;
1871     }
1872
1873     if(isTheFound2 && (anUpar2 < theU1))
1874     {
1875       Standard_Real aU2 = theU2, aV1 = theV1, aV2 = theV2;
1876       if(!CylCylComputeParameters(anUpar2, theWLIndex, theCoeffs, aU2, aV1, aV2))
1877       {
1878         isTheFound2 = Standard_False;
1879       }
1880
1881       if(aTS2 == SearchV1)
1882         aV1 = aV1zad;
1883
1884       if(aTS2 == SearchV2)
1885         aV2 = aV2zad;
1886
1887       if(isTheFound2 && !AddPointIntoWL(theQuad1, theQuad2, theCoeffs, isTheReverse, Standard_False,
1888                                         gp_Pnt2d(anUpar2, aV1), gp_Pnt2d(aU2, aV2),
1889                                         aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
1890                                         aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, thePeriod,
1891                                         theWL->Curve(), theWLIndex, theTol3D,
1892                                         theTol2D, theFlForce))
1893       {
1894         isTheFound2 = Standard_False;
1895       }
1896     }
1897     else
1898     {
1899       isTheFound2 = Standard_False;
1900     }
1901   }
1902   else
1903   {
1904     if(isTheFound2 && (anUpar2 < theU1))
1905     {
1906       Standard_Real aU2 = theU2, aV1 = theV1, aV2 = theV2;
1907       if(!CylCylComputeParameters(anUpar2, theWLIndex, theCoeffs, aU2, aV1, aV2))
1908       {
1909         isTheFound2 = Standard_False;
1910       }
1911
1912       if(aTS2 == SearchV1)
1913         aV1 = aV1zad;
1914
1915       if(aTS2 == SearchV2)
1916         aV2 = aV2zad;
1917
1918       if(isTheFound2 && !AddPointIntoWL(theQuad1, theQuad2, theCoeffs, isTheReverse, Standard_False,
1919                                         gp_Pnt2d(anUpar2, aV1), gp_Pnt2d(aU2, aV2),
1920                                         aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
1921                                         aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, thePeriod,
1922                                         theWL->Curve(), theWLIndex, theTol3D,
1923                                         theTol2D, theFlForce))
1924       {
1925         isTheFound2 = Standard_False;
1926       }
1927     }
1928     else
1929     {
1930       isTheFound2 = Standard_False;
1931     }
1932
1933     if(isTheFound1 && (anUpar1 < theU1))
1934     {
1935       Standard_Real aU2 = theU2, aV1 = theV1, aV2 = theV2;
1936       if(!CylCylComputeParameters(anUpar1, theWLIndex, theCoeffs, aU2, aV1, aV2))
1937       {
1938         isTheFound1 = Standard_False;
1939       }
1940
1941       if(aTS1 == SearchV1)
1942         aV1 = aV1zad;
1943
1944       if(aTS1 == SearchV2)
1945         aV2 = aV2zad;
1946
1947       if(isTheFound1 && !AddPointIntoWL(theQuad1, theQuad2, theCoeffs, isTheReverse, Standard_False,
1948                                         gp_Pnt2d(anUpar1, aV1), gp_Pnt2d(aU2, aV2),
1949                                         aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
1950                                         aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, thePeriod,
1951                                         theWL->Curve(), theWLIndex, theTol3D,
1952                                         theTol2D, theFlForce))
1953       {
1954         isTheFound1 = Standard_False;
1955       }
1956     }
1957     else
1958     {
1959       isTheFound1 = Standard_False;
1960     }
1961   }
1962
1963   return Standard_True;
1964 }
1965
1966 //=======================================================================
1967 //function : SeekAdditionalPoints
1968 //purpose  : 
1969 //=======================================================================
1970 static void SeekAdditionalPoints( const IntSurf_Quadric& theQuad1,
1971                                   const IntSurf_Quadric& theQuad2,
1972                                   const Handle(IntSurf_LineOn2S)& theLine,
1973                                   const stCoeffsValue& theCoeffs,
1974                                   const Standard_Integer theWLIndex,
1975                                   const Standard_Integer theMinNbPoints,
1976                                   const Standard_Integer theStartPointOnLine,
1977                                   const Standard_Integer theEndPointOnLine,
1978                                   const Standard_Real theU2f,
1979                                   const Standard_Real theU2l,
1980                                   const Standard_Real theTol2D,
1981                                   const Standard_Real thePeriodOfSurf2,
1982                                   const Standard_Boolean isTheReverse)
1983 {
1984   if(theLine.IsNull())
1985     return;
1986   
1987   Standard_Integer aNbPoints = theEndPointOnLine - theStartPointOnLine + 1;
1988   if(aNbPoints >= theMinNbPoints)
1989   {
1990     return;
1991   }
1992
1993   Standard_Real aMinDeltaParam = theTol2D;
1994
1995   {
1996     Standard_Real u1 = 0.0, v1 = 0.0, u2 = 0.0, v2 = 0.0;
1997
1998     if(isTheReverse)
1999     {
2000       theLine->Value(theStartPointOnLine).ParametersOnS2(u1, v1);
2001       theLine->Value(theEndPointOnLine).ParametersOnS2(u2, v2);
2002     }
2003     else
2004     {
2005       theLine->Value(theStartPointOnLine).ParametersOnS1(u1, v1);
2006       theLine->Value(theEndPointOnLine).ParametersOnS1(u2, v2);
2007     }
2008     
2009     aMinDeltaParam = Max(Abs(u2 - u1)/IntToReal(theMinNbPoints), aMinDeltaParam);
2010   }
2011
2012   Standard_Integer aLastPointIndex = theEndPointOnLine;
2013   Standard_Real U1prec = 0.0, V1prec = 0.0, U2prec = 0.0, V2prec = 0.0;
2014
2015   Standard_Integer aNbPointsPrev = 0;
2016   while(aNbPoints < theMinNbPoints && (aNbPoints != aNbPointsPrev))
2017   {
2018     aNbPointsPrev = aNbPoints;
2019     for(Standard_Integer fp = theStartPointOnLine, lp = 0; fp < aLastPointIndex; fp = lp + 1)
2020     {
2021       Standard_Real U1f = 0.0, V1f = 0.0; //first point in 1st suraface
2022       Standard_Real U1l = 0.0, V1l = 0.0; //last  point in 1st suraface
2023
2024       Standard_Real U2f = 0.0, V2f = 0.0; //first point in 2nd suraface
2025       Standard_Real U2l = 0.0, V2l = 0.0; //last  point in 2nd suraface
2026
2027       lp = fp+1;
2028       
2029       if(isTheReverse)
2030       {
2031         theLine->Value(fp).ParametersOnS2(U1f, V1f);
2032         theLine->Value(lp).ParametersOnS2(U1l, V1l);
2033
2034         theLine->Value(fp).ParametersOnS1(U2f, V2f);
2035         theLine->Value(lp).ParametersOnS1(U2l, V2l);
2036       }
2037       else
2038       {
2039         theLine->Value(fp).ParametersOnS1(U1f, V1f);
2040         theLine->Value(lp).ParametersOnS1(U1l, V1l);
2041
2042         theLine->Value(fp).ParametersOnS2(U2f, V2f);
2043         theLine->Value(lp).ParametersOnS2(U2l, V2l);
2044       }
2045
2046       if(Abs(U1l - U1f) <= aMinDeltaParam)
2047       {
2048         //Step is minimal. It is not necessary to divide it.
2049         continue;
2050       }
2051
2052       U1prec = 0.5*(U1f+U1l);
2053       
2054       if(!CylCylComputeParameters(U1prec, theWLIndex, theCoeffs, U2prec, V1prec, V2prec))
2055         continue;
2056
2057       InscribePoint(theU2f, theU2l, U2prec, theTol2D, thePeriodOfSurf2, Standard_False);
2058
2059       const gp_Pnt aP1(theQuad1.Value(U1prec, V1prec)), aP2(theQuad2.Value(U2prec, V2prec));
2060       const gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
2061
2062 #ifdef OCCT_DEBUG
2063       //cout << "|P1Pi| = " << aP1.SquareDistance(aPInt) << "; |P2Pi| = " << aP2.SquareDistance(aPInt) << endl;
2064 #endif
2065
2066       IntSurf_PntOn2S anIP;
2067       if(isTheReverse)
2068       {
2069         anIP.SetValue(aPInt, U2prec, V2prec, U1prec, V1prec);
2070       }
2071       else
2072       {
2073         anIP.SetValue(aPInt, U1prec, V1prec, U2prec, V2prec);
2074       }
2075
2076       theLine->InsertBefore(lp, anIP);
2077
2078       aNbPoints++;
2079       aLastPointIndex++;
2080     }
2081
2082     if(aNbPoints >= theMinNbPoints)
2083     {
2084       return;
2085     }
2086   }
2087 }
2088
2089 //=======================================================================
2090 //function : CriticalPointsComputing
2091 //purpose  : theNbCritPointsMax contains true number of critical points
2092 //=======================================================================
2093 static void CriticalPointsComputing(const stCoeffsValue& theCoeffs,
2094                                     const Standard_Real theUSurf1f,
2095                                     const Standard_Real theUSurf1l,
2096                                     const Standard_Real theUSurf2f,
2097                                     const Standard_Real theUSurf2l,
2098                                     const Standard_Real thePeriod,
2099                                     const Standard_Real theTol2D,
2100                                     Standard_Integer& theNbCritPointsMax,
2101                                     Standard_Real theU1crit[])
2102 {
2103   //[0...1] - in these points parameter U1 goes through
2104   //          the seam-edge of the first cylinder.
2105   //[2...3] - First and last U1 parameter.
2106   //[4...5] - in these points parameter U2 goes through
2107   //          the seam-edge of the second cylinder.
2108   //[6...9] - in these points an intersection line goes through
2109   //          U-boundaries of the second surface.
2110
2111   theNbCritPointsMax = 10;
2112
2113   theU1crit[0] = 0.0;
2114   theU1crit[1] = thePeriod;
2115   theU1crit[2] = theUSurf1f;
2116   theU1crit[3] = theUSurf1l;
2117
2118   const Standard_Real aCOS = cos(theCoeffs.mFI2);
2119   const Standard_Real aBSB = Abs(theCoeffs.mB);
2120   if((theCoeffs.mC - aBSB <= aCOS) && (aCOS <= theCoeffs.mC + aBSB))
2121   {
2122     Standard_Real anArg = (aCOS - theCoeffs.mC) / theCoeffs.mB;
2123     if(anArg > 1.0)
2124       anArg = 1.0;
2125     if(anArg < -1.0)
2126       anArg = -1.0;
2127
2128     theU1crit[4] = -acos(anArg) + theCoeffs.mFI1;
2129     theU1crit[5] =  acos(anArg) + theCoeffs.mFI1;
2130   }
2131
2132   Standard_Real aSf = cos(theUSurf2f - theCoeffs.mFI2);
2133   Standard_Real aSl = cos(theUSurf2l - theCoeffs.mFI2);
2134   MinMax(aSf, aSl);
2135
2136   //In accorance with pure mathematic, theU1crit[6] and [8]
2137   //must be -Precision::Infinite() instead of used +Precision::Infinite()
2138   theU1crit[6] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
2139                   -acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
2140                   Precision::Infinite();
2141   theU1crit[7] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
2142                   -acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
2143                   Precision::Infinite();
2144   theU1crit[8] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
2145                   acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
2146                   Precision::Infinite();
2147   theU1crit[9] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
2148                   acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
2149                   Precision::Infinite();
2150
2151   //preparative treatment of array. This array must have faled to contain negative
2152   //infinity number
2153
2154   for(Standard_Integer i = 0; i < theNbCritPointsMax; i++)
2155   {
2156     if(Precision::IsInfinite(theU1crit[i]))
2157     {
2158       continue;
2159     }
2160
2161     theU1crit[i] = fmod(theU1crit[i], thePeriod);
2162     if(theU1crit[i] < 0.0)
2163       theU1crit[i] += thePeriod;
2164   }
2165
2166   //Here all not infinite elements of theU1crit are in [0, thePeriod) range
2167
2168   do
2169   {
2170     std::sort(theU1crit, theU1crit + theNbCritPointsMax);
2171   }
2172   while(ExcludeNearElements(theU1crit, theNbCritPointsMax, theTol2D));
2173
2174   //Here all not infinite elements in theU1crit are different and sorted.
2175
2176   while(theNbCritPointsMax > 0)
2177   {
2178     Standard_Real &anB = theU1crit[theNbCritPointsMax-1];
2179     if(Precision::IsInfinite(anB))
2180     {
2181       theNbCritPointsMax--;
2182       continue;
2183     }
2184
2185     //1st not infinte element is found
2186
2187     if(theNbCritPointsMax == 1)
2188       break;
2189
2190     //Here theNbCritPointsMax > 1
2191
2192     Standard_Real &anA = theU1crit[0];
2193
2194     //Compare 1st and last significant elements of theU1crit
2195     //They may still differs by period.
2196
2197     if (Abs(anB - anA - thePeriod) < theTol2D)
2198     {//E.g. anA == 2.0e-17, anB == (thePeriod-1.0e-18)
2199       anA = (anA + anB - thePeriod)/2.0;
2200       anB = Precision::Infinite();
2201       theNbCritPointsMax--;
2202     }
2203
2204     //Out of "while(theNbCritPointsMax > 0)" cycle.
2205     break;
2206   }
2207
2208   //Attention! Here theU1crit may be unsorted.
2209 }
2210
2211 //=======================================================================
2212 //function : IntCyCyTrim
2213 //purpose  : 
2214 //=======================================================================
2215 Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
2216                               const IntSurf_Quadric& theQuad2,
2217                               const Standard_Real theTol3D,
2218                               const Standard_Real theTol2D,
2219                               const Bnd_Box2d& theUVSurf1,
2220                               const Bnd_Box2d& theUVSurf2,
2221                               const Standard_Boolean isTheReverse,
2222                               Standard_Boolean& isTheEmpty,
2223                               IntPatch_SequenceOfLine& theSlin,
2224                               IntPatch_SequenceOfPoint& theSPnt)
2225 {
2226   Standard_Real aUSurf1f = 0.0, //const
2227                 aUSurf1l = 0.0,
2228                 aVSurf1f = 0.0,
2229                 aVSurf1l = 0.0;
2230   Standard_Real aUSurf2f = 0.0, //const
2231                 aUSurf2l = 0.0,
2232                 aVSurf2f = 0.0,
2233                 aVSurf2l = 0.0;
2234
2235   theUVSurf1.Get(aUSurf1f, aVSurf1f, aUSurf1l, aVSurf1l);
2236   theUVSurf2.Get(aUSurf2f, aVSurf2f, aUSurf2l, aVSurf2l);
2237
2238   const gp_Cylinder&  aCyl1 = theQuad1.Cylinder(),
2239                       aCyl2 = theQuad2.Cylinder();
2240
2241   IntAna_QuadQuadGeo anInter(aCyl1,aCyl2,theTol3D);
2242
2243   if (!anInter.IsDone())
2244   {
2245     return Standard_False;
2246   }
2247
2248   IntAna_ResultType aTypInt = anInter.TypeInter();
2249
2250   if(aTypInt != IntAna_NoGeometricSolution)
2251   { //It is not necessary (because result is an analytic curve) or
2252     //it is impossible to make Walking-line.
2253
2254     return Standard_False;
2255   }
2256     
2257   theSlin.Clear();
2258   theSPnt.Clear();
2259   const Standard_Integer aNbMaxPoints = 2000;
2260   const Standard_Integer aNbMinPoints = 200;
2261   const Standard_Integer aNbPoints = Min(Max(aNbMinPoints, 
2262                       RealToInt(20.0*aCyl1.Radius())), aNbMaxPoints);
2263   const Standard_Real aPeriod = 2.0*M_PI;
2264   const Standard_Real aStepMin = theTol2D, 
2265                       aStepMax =  (aUSurf1l-aUSurf1f > M_PI/100.0) ?
2266                                   (aUSurf1l-aUSurf1f)/IntToReal(aNbPoints) :
2267                                   aUSurf1l-aUSurf1f;
2268
2269   const Standard_Integer aNbWLines = 2;
2270
2271   const stCoeffsValue anEquationCoeffs(aCyl1, aCyl2);
2272
2273   //Boundaries
2274   const Standard_Integer aNbOfBoundaries = 2;
2275   Standard_Real aU1f[aNbOfBoundaries] = {-Precision::Infinite(), -Precision::Infinite()};
2276   Standard_Real aU1l[aNbOfBoundaries] = {Precision::Infinite(), Precision::Infinite()};
2277
2278   if(anEquationCoeffs.mB > 0.0)
2279   {
2280     if(anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) < -1.0)
2281     {//There is NOT intersection
2282       return Standard_True;
2283     }
2284     else if(anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) <= 1.0)
2285     {//U=[0;2*PI]+aFI1
2286       aU1f[0] = anEquationCoeffs.mFI1;
2287       aU1l[0] = aPeriod + anEquationCoeffs.mFI1;
2288     }
2289     else if((1 + anEquationCoeffs.mC <= anEquationCoeffs.mB) &&
2290             (anEquationCoeffs.mB <= 1 - anEquationCoeffs.mC))
2291     {
2292       Standard_Real anArg = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB;
2293       if(anArg > 1.0)
2294         anArg = 1.0;
2295       if(anArg < -1.0)
2296         anArg = -1.0;
2297
2298       const Standard_Real aDAngle = acos(anArg);
2299       //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1)
2300       aU1f[0] = anEquationCoeffs.mFI1;
2301       aU1l[0] = aDAngle + anEquationCoeffs.mFI1;
2302       aU1f[1] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
2303       aU1l[1] = aPeriod + anEquationCoeffs.mFI1;
2304     }
2305     else if((1 - anEquationCoeffs.mC <= anEquationCoeffs.mB) &&
2306             (anEquationCoeffs.mB <= 1 + anEquationCoeffs.mC))
2307     {
2308       Standard_Real anArg = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB;
2309       if(anArg > 1.0)
2310         anArg = 1.0;
2311       if(anArg < -1.0)
2312         anArg = -1.0;
2313
2314       const Standard_Real aDAngle = acos(anArg);
2315       //U=[aDAngle;2*PI-aDAngle]+aFI1
2316
2317       aU1f[0] = aDAngle + anEquationCoeffs.mFI1;
2318       aU1l[0] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
2319     }
2320     else if(anEquationCoeffs.mB - Abs(anEquationCoeffs.mC) >= 1.0)
2321     {
2322       Standard_Real anArg1 = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB,
2323                     anArg2 = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB;
2324       if(anArg1 > 1.0)
2325         anArg1 = 1.0;
2326       if(anArg1 < -1.0)
2327         anArg1 = -1.0;
2328
2329       if(anArg2 > 1.0)
2330         anArg2 = 1.0;
2331       if(anArg2 < -1.0)
2332         anArg2 = -1.0;
2333
2334       const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2);
2335       //(U=[aDAngle1;aDAngle2]+aFI1) ||
2336       //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
2337
2338       aU1f[0] = aDAngle1 + anEquationCoeffs.mFI1;
2339       aU1l[0] = aDAngle2 + anEquationCoeffs.mFI1;
2340       aU1f[1] = aPeriod - aDAngle2 + anEquationCoeffs.mFI1;
2341       aU1l[1] = aPeriod - aDAngle1 + anEquationCoeffs.mFI1;
2342     }
2343     else
2344     {
2345       Standard_Failure::Raise("Error. Exception. Unhandled case (Range computation)!");
2346     }
2347   }
2348   else if(anEquationCoeffs.mB < 0.0)
2349   {
2350     if(anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) > 1.0)
2351     {//There is NOT intersection
2352       return Standard_True;
2353     }
2354     else if(-anEquationCoeffs.mB + Abs(anEquationCoeffs.mC) <= 1.0)
2355     {//U=[0;2*PI]+aFI1
2356       aU1f[0] = anEquationCoeffs.mFI1;
2357       aU1l[0] = aPeriod + anEquationCoeffs.mFI1;
2358     }
2359     else if((-anEquationCoeffs.mC - 1 <= anEquationCoeffs.mB) &&
2360             ( anEquationCoeffs.mB <= anEquationCoeffs.mC - 1))
2361     {
2362       Standard_Real anArg = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB;
2363       if(anArg > 1.0)
2364         anArg = 1.0;
2365       if(anArg < -1.0)
2366         anArg = -1.0;
2367
2368       const Standard_Real aDAngle = acos(anArg);
2369       //(U=[0;aDAngle]+aFI1) || (U=[2*PI-aDAngle;2*PI]+aFI1)
2370
2371       aU1f[0] = anEquationCoeffs.mFI1;
2372       aU1l[0] = aDAngle + anEquationCoeffs.mFI1;
2373       aU1f[1] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
2374       aU1l[1] = aPeriod + anEquationCoeffs.mFI1;
2375     }
2376     else if((anEquationCoeffs.mC - 1 <= anEquationCoeffs.mB) &&
2377             (anEquationCoeffs.mB <= -anEquationCoeffs.mB - 1))
2378     {
2379       Standard_Real anArg = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB;
2380       if(anArg > 1.0)
2381         anArg = 1.0;
2382       if(anArg < -1.0)
2383         anArg = -1.0;
2384
2385       const Standard_Real aDAngle = acos(anArg);
2386       //U=[aDAngle;2*PI-aDAngle]+aFI1
2387
2388       aU1f[0] = aDAngle + anEquationCoeffs.mFI1;
2389       aU1l[0] = aPeriod - aDAngle + anEquationCoeffs.mFI1;
2390     }
2391     else if(-anEquationCoeffs.mB - Abs(anEquationCoeffs.mC) >= 1.0)
2392     {
2393       Standard_Real anArg1 = -(anEquationCoeffs.mC + 1) / anEquationCoeffs.mB,
2394                     anArg2 = (1 - anEquationCoeffs.mC) / anEquationCoeffs.mB;
2395       if(anArg1 > 1.0)
2396         anArg1 = 1.0;
2397       if(anArg1 < -1.0)
2398         anArg1 = -1.0;
2399
2400       if(anArg2 > 1.0)
2401         anArg2 = 1.0;
2402       if(anArg2 < -1.0)
2403         anArg2 = -1.0;
2404
2405       const Standard_Real aDAngle1 = acos(anArg1), aDAngle2 = acos(anArg2);
2406       //(U=[aDAngle1;aDAngle2]+aFI1) ||
2407       //(U=[2*PI-aDAngle2;2*PI-aDAngle1]+aFI1)
2408
2409       aU1f[0] = aDAngle1 + anEquationCoeffs.mFI1;
2410       aU1l[0] = aDAngle2 + anEquationCoeffs.mFI1;
2411       aU1f[1] = aPeriod - aDAngle2 + anEquationCoeffs.mFI1;
2412       aU1l[1] = aPeriod - aDAngle1 + anEquationCoeffs.mFI1;
2413     }
2414     else
2415     {
2416       Standard_Failure::Raise("Error. Exception. Unhandled case (Range computation)!");
2417     }
2418   }
2419   else
2420   {
2421     Standard_Failure::Raise("Error. Exception. Unhandled case (B-parameter computation)!");
2422   }
2423
2424   for(Standard_Integer i = 0; i < aNbOfBoundaries; i++)
2425   {
2426     if(Precision::IsInfinite(aU1f[i]) && Precision::IsInfinite(aU1l[i]))
2427       continue;
2428
2429     InscribeInterval(aUSurf1f, aUSurf1l, aU1f[i], aU1l[i], theTol2D, aPeriod);
2430   }
2431
2432   if( !Precision::IsInfinite(aU1f[0]) && !Precision::IsInfinite(aU1f[1]) &&
2433       !Precision::IsInfinite(aU1l[0]) && !Precision::IsInfinite(aU1l[1]))
2434   {
2435     if( ((aU1f[1] <= aU1l[0]) || (aU1l[1] <= aU1l[0])) && 
2436         ((aU1f[0] <= aU1l[1]) || (aU1l[0] <= aU1l[1])))
2437     {//Join all intervals to one
2438       aU1f[0] = Min(aU1f[0], aU1f[1]);
2439       aU1l[0] = Max(aU1l[0], aU1l[1]);
2440
2441       aU1f[1] = -Precision::Infinite();
2442       aU1l[1] = Precision::Infinite();
2443     }
2444   }
2445
2446   //Critical points
2447   const Standard_Integer aNbCritPointsMax = 10;
2448   Standard_Real anU1crit[aNbCritPointsMax] = {Precision::Infinite(),
2449                                               Precision::Infinite(),
2450                                               Precision::Infinite(),
2451                                               Precision::Infinite(),
2452                                               Precision::Infinite(),
2453                                               Precision::Infinite(),
2454                                               Precision::Infinite(),
2455                                               Precision::Infinite(),
2456                                               Precision::Infinite(),
2457                                               Precision::Infinite()};
2458
2459   Standard_Integer aNbCritPoints = aNbCritPointsMax;
2460   CriticalPointsComputing(anEquationCoeffs, aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
2461                                       aPeriod, theTol2D, aNbCritPoints, anU1crit);
2462
2463   //Getting Walking-line
2464
2465   enum WLFStatus
2466   {
2467     WLFStatus_Absent = 0,
2468     WLFStatus_Exist  = 1,
2469     WLFStatus_Broken = 2
2470   };
2471
2472   for(Standard_Integer aCurInterval = 0; aCurInterval < aNbOfBoundaries; aCurInterval++)
2473   {
2474     if(Precision::IsInfinite(aU1f[aCurInterval]) && Precision::IsInfinite(aU1l[aCurInterval]))
2475       continue;
2476
2477     Standard_Boolean isAddedIntoWL[aNbWLines];
2478     for(Standard_Integer i = 0; i < aNbWLines; i++)
2479       isAddedIntoWL[i] = Standard_False;
2480
2481     Standard_Real anUf = aU1f[aCurInterval], anUl = aU1l[aCurInterval];
2482     const Standard_Boolean isDeltaPeriod  = IsEqual(anUl-anUf, aPeriod);
2483
2484     //Inscribe and sort critical points
2485     for(Standard_Integer i = 0; i < aNbCritPoints; i++)
2486     {
2487       InscribePoint(anUf, anUl, anU1crit[i], theTol2D, aPeriod, Standard_False);
2488     }
2489
2490     std::sort(anU1crit, anU1crit + aNbCritPoints);
2491
2492     while(anUf < anUl)
2493     {
2494       Standard_Real aU2[aNbWLines], aV1[aNbWLines], aV2[aNbWLines];
2495       WLFStatus aWLFindStatus[aNbWLines];
2496       Standard_Real aV1Prev[aNbWLines], aV2Prev[aNbWLines];
2497       Standard_Real anUexpect[aNbWLines];
2498       Standard_Boolean isAddingWLEnabled[aNbWLines];
2499
2500       Handle(IntSurf_LineOn2S) aL2S[aNbWLines];
2501       Handle(IntPatch_WLine) aWLine[aNbWLines];
2502       for(Standard_Integer i = 0; i < aNbWLines; i++)
2503       {
2504         aL2S[i] = new IntSurf_LineOn2S();
2505         aWLine[i] = new IntPatch_WLine(aL2S[i], Standard_False);
2506         aWLFindStatus[i] = WLFStatus_Absent;
2507         isAddingWLEnabled[i] = Standard_True;
2508         aU2[i] = aV1[i] = aV2[i] = 0.0;
2509         aV1Prev[i] = aV2Prev[i] = 0.0;
2510         anUexpect[i] = anUf;
2511       }
2512       
2513       Standard_Real aCriticalDelta[aNbCritPointsMax] = {0};
2514       for(Standard_Integer aCritPID = 0; aCritPID < aNbCritPoints; aCritPID++)
2515       { //We are not intersted in elements of aCriticalDelta array
2516         //if their index is greater than or equal to aNbCritPoints
2517
2518         aCriticalDelta[aCritPID] = anUf - anU1crit[aCritPID];
2519       }
2520
2521       Standard_Real anU1 = anUf;
2522       Standard_Boolean isFirst = Standard_True;
2523
2524       while(anU1 <= anUl)
2525       {
2526         for(Standard_Integer i = 0; i < aNbCritPoints; i++)
2527         {
2528           if((anU1 - anU1crit[i])*aCriticalDelta[i] < 0.0)
2529           {
2530             anU1 = anU1crit[i];
2531
2532             for(Standard_Integer j = 0; j < aNbWLines; j++)
2533             {
2534               aWLFindStatus[j] = WLFStatus_Broken;
2535               anUexpect[j] = anU1;
2536             }
2537
2538             break;
2539           }
2540         }
2541
2542         if(IsEqual(anU1, anUl))
2543         {
2544           for(Standard_Integer i = 0; i < aNbWLines; i++)
2545           {
2546             aWLFindStatus[i] = WLFStatus_Broken;
2547             anUexpect[i] = anU1;
2548
2549             if(isDeltaPeriod)
2550             {
2551               //if isAddedIntoWL[i] == TRUE WLine contains only one point
2552               //(which was end point of previous WLine). If we will
2553               //add point found on the current step WLine will contain only
2554               //two points. At that both these points will be equal to the
2555               //points found earlier. Therefore, new WLine will repeat 
2556               //already existing WLine. Consequently, it is necessary 
2557               //to forbid building new line in this case.
2558
2559               isAddingWLEnabled[i] = (!isAddedIntoWL[i]);
2560             }
2561             else
2562             {
2563               isAddingWLEnabled[i] = ((theTol2D >= (anUexpect[i] - anU1)) ||
2564                                       (aWLFindStatus[i] == WLFStatus_Absent));
2565             }
2566           }//for(Standard_Integer i = 0; i < aNbWLines; i++)
2567         }
2568         else
2569         {
2570           for(Standard_Integer i = 0; i < aNbWLines; i++)
2571           {
2572             isAddingWLEnabled[i] = ((theTol2D >= (anUexpect[i] - anU1)) ||
2573                                     (aWLFindStatus[i] == WLFStatus_Absent));
2574           }//for(Standard_Integer i = 0; i < aNbWLines; i++)
2575         }
2576
2577         for(Standard_Integer i = 0; i < aNbWLines; i++)
2578         {
2579           const Standard_Integer aNbPntsWL =  aWLine[i].IsNull() ? 0 :
2580                                               aWLine[i]->Curve()->NbPoints();
2581           
2582           if( (aWLFindStatus[i] == WLFStatus_Broken) ||
2583               (aWLFindStatus[i] == WLFStatus_Absent))
2584           {//Begin and end of WLine must be on boundary point
2585            //or on seam-edge strictly (if it is possible).
2586
2587             Standard_Real aTol = theTol2D;
2588             CylCylComputeParameters(anU1, i, anEquationCoeffs, aU2[i], &aTol);
2589             InscribePoint(aUSurf2f, aUSurf2l, aU2[i], theTol2D, aPeriod, Standard_False);
2590
2591             aTol = Max(aTol, theTol2D);
2592
2593             if(Abs(aU2[i]) <= aTol)
2594               aU2[i] = 0.0;
2595             else if(Abs(aU2[i] - aPeriod) <= aTol)
2596               aU2[i] = aPeriod;
2597             else if(Abs(aU2[i] - aUSurf2f) <= aTol)
2598               aU2[i] = aUSurf2f;
2599             else if(Abs(aU2[i] - aUSurf2l) <= aTol)
2600               aU2[i] = aUSurf2l;
2601           }
2602           else
2603           {
2604             CylCylComputeParameters(anU1, i, anEquationCoeffs, aU2[i]);
2605             InscribePoint(aUSurf2f, aUSurf2l, aU2[i], theTol2D, aPeriod, Standard_False);
2606           }
2607           
2608           if(aNbPntsWL == 0)
2609           {//the line has not contained any points yet
2610             if(((aUSurf2f + aPeriod - aUSurf2l) <= 2.0*theTol2D) && 
2611                 ((Abs(aU2[i] - aUSurf2f) < theTol2D) ||
2612                   (Abs(aU2[i]-aUSurf2l) < theTol2D)))
2613             {
2614               //In this case aU2[i] can have two values: current aU2[i] or
2615               //aU2[i]+aPeriod (aU2[i]-aPeriod). It is necessary to choose
2616               //correct value.
2617
2618               Standard_Boolean isIncreasing = Standard_True;
2619               CylCylMonotonicity(anU1, i, anEquationCoeffs, aPeriod, isIncreasing);
2620
2621               //If U2(U1) is increasing and U2 is considered to be equal aUSurf2l
2622               //then after the next step (when U1 will be increased) U2 will be
2623               //increased too. And we will go out of surface boundary.
2624               //Therefore, If U2(U1) is increasing then U2 must be equal aUSurf2f.
2625               //Analogically, if U2(U1) is decreasing.
2626               if(isIncreasing)
2627               {
2628                 aU2[i] = aUSurf2f;
2629               }
2630               else
2631               {
2632                 aU2[i] = aUSurf2l;
2633               }
2634             }
2635           }
2636           else
2637           {//aNbPntsWL > 0
2638             if(((aUSurf2l - aUSurf2f) >= aPeriod) && 
2639                 ((Abs(aU2[i] - aUSurf2f) < theTol2D) ||
2640                   (Abs(aU2[i]-aUSurf2l) < theTol2D)))
2641             {//end of the line
2642               Standard_Real aU2prev = 0.0, aV2prev = 0.0;
2643               if(isTheReverse)
2644                 aWLine[i]->Curve()->Value(aNbPntsWL).ParametersOnS1(aU2prev, aV2prev);
2645               else
2646                 aWLine[i]->Curve()->Value(aNbPntsWL).ParametersOnS2(aU2prev, aV2prev);
2647
2648               if(2.0*Abs(aU2prev - aU2[i]) > aPeriod)
2649               {
2650                 if(aU2prev > aU2[i])
2651                   aU2[i] += aPeriod;
2652                 else
2653                   aU2[i] -= aPeriod;
2654               }
2655             }
2656           }
2657
2658           CylCylComputeParameters(anU1, aU2[i], anEquationCoeffs, aV1[i], aV2[i]);
2659
2660           if(isFirst)
2661           {
2662             aV1Prev[i] = aV1[i];
2663             aV2Prev[i] = aV2[i];
2664           }
2665         }//for(Standard_Integer i = 0; i < aNbWLines; i++)
2666
2667         isFirst = Standard_False;
2668
2669         //Looking for points into WLine
2670         Standard_Boolean isBroken = Standard_False;
2671         for(Standard_Integer i = 0; i < aNbWLines; i++)
2672         {
2673           if(!isAddingWLEnabled[i])
2674           {
2675             Standard_Boolean isBoundIntersect = Standard_False;
2676             if( (Abs(aV1[i] - aVSurf1f) <= theTol2D) ||
2677                 ((aV1[i]-aVSurf1f)*(aV1Prev[i]-aVSurf1f) < 0.0))
2678             {
2679               isBoundIntersect = Standard_True;
2680             }
2681             else if(  (Abs(aV1[i] - aVSurf1l) <= theTol2D) ||
2682                     ( (aV1[i]-aVSurf1l)*(aV1Prev[i]-aVSurf1l) < 0.0))
2683             {
2684               isBoundIntersect = Standard_True;
2685             }
2686             else if(  (Abs(aV2[i] - aVSurf2f) <= theTol2D) ||
2687                     ( (aV2[i]-aVSurf2f)*(aV2Prev[i]-aVSurf2f) < 0.0))
2688             {
2689               isBoundIntersect = Standard_True;
2690             }
2691             else if(  (Abs(aV2[i] - aVSurf2l) <= theTol2D) ||
2692                     ( (aV2[i]-aVSurf2l)*(aV2Prev[i]-aVSurf2l) < 0.0))
2693             {
2694               isBoundIntersect = Standard_True;
2695             }
2696
2697             if(aWLFindStatus[i] == WLFStatus_Broken)
2698               isBroken = Standard_True;
2699
2700             if(!isBoundIntersect)
2701             {
2702               continue;
2703             }
2704             else
2705             {
2706               anUexpect[i] = anU1;
2707             }
2708           }
2709
2710           const Standard_Boolean isInscribe = 
2711               ((aUSurf2f-aU2[i]) <= theTol2D) && ((aU2[i]-aUSurf2l) <= theTol2D) &&
2712               ((aVSurf1f - aV1[i]) <= theTol2D) && ((aV1[i] - aVSurf1l) <= theTol2D) &&
2713               ((aVSurf2f - aV2[i]) <= theTol2D) && ((aV2[i] - aVSurf2l) <= theTol2D);
2714
2715           //isVIntersect == TRUE if intersection line intersects two (!)
2716           //V-bounds of cylinder (1st or 2nd - no matter)
2717           const Standard_Boolean isVIntersect =
2718               ( ((aVSurf1f-aV1[i])*(aVSurf1f-aV1Prev[i]) < RealSmall()) &&
2719                 ((aVSurf1l-aV1[i])*(aVSurf1l-aV1Prev[i]) < RealSmall())) ||
2720               ( ((aVSurf2f-aV2[i])*(aVSurf2f-aV2Prev[i]) < RealSmall()) &&
2721                 ((aVSurf2l-aV2[i])*(aVSurf2l-aV2Prev[i]) < RealSmall()));
2722
2723
2724           //isFound1 == TRUE if intersection line intersects V-bounds
2725           //  (First or Last - no matter) of the 1st cylynder
2726           //isFound2 == TRUE if intersection line intersects V-bounds
2727           //  (First or Last - no matter) of the 2nd cylynder
2728           Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
2729           Standard_Boolean isForce = Standard_False;
2730
2731           if (aWLFindStatus[i] == WLFStatus_Absent)
2732           {
2733             if(((aUSurf2l - aUSurf2f) >= aPeriod) && (Abs(anU1-aUSurf1l) < theTol2D))
2734             {
2735               isForce = Standard_True;
2736             }
2737           }
2738
2739           AddBoundaryPoint( theQuad1, theQuad2, aWLine[i], anEquationCoeffs,
2740                             theUVSurf1, theUVSurf2, theTol3D, theTol2D, aPeriod,
2741                             anU1, aU2[i], aV1[i], aV1Prev[i],
2742                             aV2[i], aV2Prev[i], i, isTheReverse,
2743                             isForce, isFound1, isFound2);
2744
2745           const Standard_Boolean isPrevVBound = !isVIntersect &&
2746                                                 ((Abs(aV1Prev[i] - aVSurf1f) <= theTol2D) ||
2747                                                  (Abs(aV1Prev[i] - aVSurf1l) <= theTol2D) ||
2748                                                  (Abs(aV2Prev[i] - aVSurf2f) <= theTol2D) ||
2749                                                  (Abs(aV2Prev[i] - aVSurf2l) <= theTol2D));
2750
2751
2752           aV1Prev[i] = aV1[i];
2753           aV2Prev[i] = aV2[i];
2754
2755           if((aWLFindStatus[i] == WLFStatus_Exist) && (isFound1 || isFound2) && !isPrevVBound)
2756           {
2757             aWLFindStatus[i] = WLFStatus_Broken; //start a new line
2758           }
2759           else if(isInscribe)
2760           {
2761             if((aWLFindStatus[i] == WLFStatus_Absent) && (isFound1 || isFound2))
2762             {
2763               aWLFindStatus[i] = WLFStatus_Exist;
2764             }
2765
2766             if(( aWLFindStatus[i] != WLFStatus_Broken) || (aWLine[i]->NbPnts() >= 1) || IsEqual(anU1, anUl))
2767             {
2768               if(aWLine[i]->NbPnts() > 0)
2769               {
2770                 Standard_Real aU2p = 0.0, aV2p = 0.0;
2771                 if(isTheReverse)
2772                   aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS1(aU2p, aV2p);
2773                 else
2774                   aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS2(aU2p, aV2p);
2775
2776                 const Standard_Real aDelta = aU2[i] - aU2p;
2777
2778                 if(2*Abs(aDelta) > aPeriod)
2779                 {
2780                   if(aDelta > 0.0)
2781                   {
2782                     aU2[i] -= aPeriod;
2783                   }
2784                   else
2785                   {
2786                     aU2[i] += aPeriod;
2787                   }
2788                 }
2789               }
2790
2791               if(AddPointIntoWL(theQuad1, theQuad2, anEquationCoeffs, isTheReverse, Standard_True,
2792                                 gp_Pnt2d(anU1, aV1[i]), gp_Pnt2d(aU2[i], aV2[i]),
2793                                 aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
2794                                 aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, aPeriod,
2795                                 aWLine[i]->Curve(), i, theTol3D, theTol2D, isForce))
2796               {
2797                 if(aWLFindStatus[i] == WLFStatus_Absent)
2798                 {
2799                   aWLFindStatus[i] = WLFStatus_Exist;
2800                 }
2801               }
2802               else if(!isFound1 && !isFound2)
2803               {//We do not add any point while doing this iteration
2804                 if(aWLFindStatus[i] == WLFStatus_Exist)
2805                 {
2806                   aWLFindStatus[i] = WLFStatus_Broken;
2807                 } 
2808               }
2809             }
2810           }
2811           else
2812           {//We do not add any point while doing this iteration
2813             if(aWLFindStatus[i] == WLFStatus_Exist)
2814             {
2815               aWLFindStatus[i] = WLFStatus_Broken;
2816             }
2817           }
2818           
2819           if(aWLFindStatus[i] == WLFStatus_Broken)
2820             isBroken = Standard_True;
2821         }//for(Standard_Integer i = 0; i < aNbWLines; i++)
2822
2823         if(isBroken)
2824         {//current lines are filled. Go to the next lines
2825           anUf = anU1;
2826
2827           Standard_Boolean isAdded = Standard_True;
2828
2829           for(Standard_Integer i = 0; i < aNbWLines; i++)
2830           {
2831             if(isAddingWLEnabled[i])
2832             {
2833               continue;
2834             }
2835
2836             isAdded = Standard_False;
2837
2838             Standard_Boolean isFound1 = Standard_False, isFound2 = Standard_False;
2839
2840             AddBoundaryPoint( theQuad1, theQuad2, aWLine[i], anEquationCoeffs,
2841                               theUVSurf1, theUVSurf2, theTol3D, theTol2D, aPeriod,
2842                               anU1, aU2[i], aV1[i], aV1Prev[i],
2843                               aV2[i], aV2Prev[i], i, isTheReverse,
2844                               Standard_False, isFound1, isFound2);
2845
2846             if(isFound1 || isFound2)
2847             {
2848               isAdded = Standard_True;
2849             }
2850
2851             if(aWLine[i]->NbPnts() > 0)
2852             {
2853               Standard_Real aU2p = 0.0, aV2p = 0.0;
2854               if(isTheReverse)
2855                 aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS1(aU2p, aV2p);
2856               else
2857                 aWLine[i]->Point(aWLine[i]->NbPnts()).ParametersOnS2(aU2p, aV2p);
2858
2859               const Standard_Real aDelta = aU2[i] - aU2p;
2860
2861               if(2*Abs(aDelta) > aPeriod)
2862               {
2863                 if(aDelta > 0.0)
2864                 {
2865                   aU2[i] -= aPeriod;
2866                 }
2867                 else
2868                 {
2869                   aU2[i] += aPeriod;
2870                 }
2871               }
2872             }
2873
2874             if(AddPointIntoWL(theQuad1, theQuad2, anEquationCoeffs, isTheReverse,
2875                               Standard_True, gp_Pnt2d(anU1, aV1[i]),
2876                               gp_Pnt2d(aU2[i], aV2[i]), aUSurf1f, aUSurf1l,
2877                               aUSurf2f, aUSurf2l, aVSurf1f, aVSurf1l,
2878                               aVSurf2f, aVSurf2l, aPeriod, aWLine[i]->Curve(),
2879                               i, theTol3D, theTol2D, Standard_False))
2880             {
2881               isAdded = Standard_True;
2882             }
2883           }
2884
2885           if(!isAdded)
2886           {
2887             Standard_Real anUmaxAdded = RealFirst();
2888             
2889             {
2890               Standard_Boolean isChanged = Standard_False;
2891               for(Standard_Integer i = 0; i < aNbWLines; i++)
2892               {
2893                 if(aWLFindStatus[i] == WLFStatus_Absent)
2894                   continue;
2895
2896                 Standard_Real aU1c = 0.0, aV1c = 0.0;
2897                 if(isTheReverse)
2898                   aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS2(aU1c, aV1c);
2899                 else
2900                   aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS1(aU1c, aV1c);
2901
2902                 anUmaxAdded = Max(anUmaxAdded, aU1c);
2903                 isChanged = Standard_True;
2904               }
2905
2906               if(!isChanged)
2907               { //If anUmaxAdded were not changed in previous cycle then
2908                 //we would break existing WLines.
2909                 break;
2910               }
2911             }
2912
2913             for(Standard_Integer i = 0; i < aNbWLines; i++)
2914             {
2915               if(isAddingWLEnabled[i])
2916               {
2917                 continue;
2918               }
2919
2920               CylCylComputeParameters(anUmaxAdded, i, anEquationCoeffs, aU2[i], aV1[i], aV2[i]);
2921
2922               AddPointIntoWL( theQuad1, theQuad2, anEquationCoeffs, isTheReverse,
2923                               Standard_True, gp_Pnt2d(anUmaxAdded, aV1[i]),
2924                               gp_Pnt2d(aU2[i], aV2[i]), aUSurf1f, aUSurf1l,
2925                               aUSurf2f, aUSurf2l, aVSurf1f, aVSurf1l,
2926                               aVSurf2f, aVSurf2l, aPeriod, aWLine[i]->Curve(),
2927                               i, theTol3D, theTol2D, Standard_False);
2928             }
2929           }
2930
2931           break;
2932         }
2933
2934         //Step computing
2935
2936         {
2937           const Standard_Real aDeltaV1 = (aVSurf1l - aVSurf1f)/IntToReal(aNbPoints),
2938                               aDeltaV2 = (aVSurf2l - aVSurf2f)/IntToReal(aNbPoints);
2939         
2940           math_Matrix aMatr(1, 3, 1, 5);
2941
2942           Standard_Real aMinUexp = RealLast();
2943         
2944           for(Standard_Integer i = 0; i < aNbWLines; i++)
2945           {
2946             if(theTol2D < (anUexpect[i] - anU1))
2947             {
2948               continue;
2949             }
2950
2951             if(aWLFindStatus[i] == WLFStatus_Absent)
2952             {
2953               anUexpect[i] += aStepMax;
2954               aMinUexp = Min(aMinUexp, anUexpect[i]);
2955               continue;
2956             }
2957
2958             Standard_Real aStepTmp = aStepMax;
2959
2960             const Standard_Real aSinU1 = sin(anU1),
2961                                 aCosU1 = cos(anU1),
2962                                 aSinU2 = sin(aU2[i]),
2963                                 aCosU2 = cos(aU2[i]);
2964
2965             aMatr.SetCol(1, anEquationCoeffs.mVecC1);
2966             aMatr.SetCol(2, anEquationCoeffs.mVecC2);
2967             aMatr.SetCol(3, anEquationCoeffs.mVecA1*aSinU1 - anEquationCoeffs.mVecB1*aCosU1);
2968             aMatr.SetCol(4, anEquationCoeffs.mVecA2*aSinU2 - anEquationCoeffs.mVecB2*aCosU2);
2969             aMatr.SetCol(5, anEquationCoeffs.mVecA1*aCosU1 + anEquationCoeffs.mVecB1*aSinU1 +
2970                             anEquationCoeffs.mVecA2*aCosU2 + anEquationCoeffs.mVecB2*aSinU2 +
2971                             anEquationCoeffs.mVecD);
2972
2973             if(!StepComputing(aMatr, aV1[i], aV2[i], aDeltaV1, aDeltaV2, aStepTmp))
2974             {
2975               //To avoid cycling-up
2976               anUexpect[i] += aStepMax;
2977               aMinUexp = Min(aMinUexp, anUexpect[i]);
2978
2979               continue;
2980             }
2981
2982             if(aStepTmp < aStepMin)
2983               aStepTmp = aStepMin;
2984       
2985             if(aStepTmp > aStepMax)
2986               aStepTmp = aStepMax;
2987
2988             anUexpect[i] = anU1 + aStepTmp;
2989             aMinUexp = Min(aMinUexp, anUexpect[i]);
2990           }
2991
2992           anU1 = aMinUexp;
2993         }
2994
2995         if(Precision::PConfusion() >= (anUl - anU1))
2996           anU1 = anUl;
2997
2998         anUf = anU1;
2999
3000         for(Standard_Integer i = 0; i < aNbWLines; i++)
3001         {
3002           if(aWLine[i]->NbPnts() != 1)
3003             isAddedIntoWL[i] = Standard_False;
3004
3005           if(anU1 == anUl)
3006           {//strictly equal. Tolerance is considered above.
3007             anUexpect[i] = anUl;
3008           }
3009         }
3010       }
3011
3012       for(Standard_Integer i = 0; i < aNbWLines; i++)
3013       {
3014         if((aWLine[i]->NbPnts() == 1) && (!isAddedIntoWL[i]))
3015         {
3016           isTheEmpty = Standard_False;
3017           Standard_Real u1, v1, u2, v2;
3018           aWLine[i]->Point(1).Parameters(u1, v1, u2, v2);
3019           IntPatch_Point aP;
3020           aP.SetParameter(u1);
3021           aP.SetParameters(u1, v1, u2, v2);
3022           aP.SetTolerance(theTol3D);
3023           aP.SetValue(aWLine[i]->Point(1).Value());
3024
3025           theSPnt.Append(aP);
3026         }
3027         else if(aWLine[i]->NbPnts() > 1)
3028         {
3029           Standard_Boolean isGood = Standard_True;
3030
3031           if(aWLine[i]->NbPnts() == 2)
3032           {
3033             const IntSurf_PntOn2S& aPf = aWLine[i]->Point(1);
3034             const IntSurf_PntOn2S& aPl = aWLine[i]->Point(2);
3035             
3036             if(aPf.IsSame(aPl, Precision::Confusion()))
3037               isGood = Standard_False;
3038           }
3039
3040           if(isGood)
3041           {
3042             isTheEmpty = Standard_False;
3043             isAddedIntoWL[i] = Standard_True;
3044             SeekAdditionalPoints( theQuad1, theQuad2, aWLine[i]->Curve(), 
3045                                   anEquationCoeffs, i, aNbPoints, 1,
3046                                   aWLine[i]->NbPnts(), aUSurf2f, aUSurf2l,
3047                                   theTol2D, aPeriod, isTheReverse);
3048
3049             aWLine[i]->ComputeVertexParameters(theTol3D);
3050             theSlin.Append(aWLine[i]);
3051           }
3052         }
3053         else
3054         {
3055           isAddedIntoWL[i] = Standard_False;
3056         }
3057
3058 #ifdef OCCT_DEBUG
3059         //aWLine[i]->Dump();
3060 #endif
3061       }
3062     }
3063   }
3064
3065
3066   //Delete the points in theSPnt, which
3067   //lie at least in one of the line in theSlin.
3068   for(Standard_Integer aNbPnt = 1; aNbPnt <= theSPnt.Length(); aNbPnt++)
3069   {
3070     for(Standard_Integer aNbLin = 1; aNbLin <= theSlin.Length(); aNbLin++)
3071     {
3072       Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNbLin)));
3073
3074       const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
3075       const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aWLine1->NbPnts());
3076
3077       const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNbPnt).PntOn2S();
3078       if( aPntCur.IsSame(aPntFWL1, Precision::Confusion()) ||
3079           aPntCur.IsSame(aPntLWL1, Precision::Confusion()))
3080       {
3081         theSPnt.Remove(aNbPnt);
3082         aNbPnt--;
3083         break;
3084       }
3085     }
3086   }
3087
3088   const Standard_Real aDU = aStepMin + Epsilon(aStepMin);
3089   //Try to add new points in the neighbourhood of existing point
3090   for(Standard_Integer aNbPnt = 1; aNbPnt <= theSPnt.Length(); aNbPnt++)
3091   {
3092     const IntPatch_Point& aPnt2S = theSPnt.Value(aNbPnt);
3093
3094     Standard_Real u1, v1, u2, v2;
3095     aPnt2S.Parameters(u1, v1, u2, v2);
3096
3097     Handle(IntSurf_LineOn2S) aL2S = new IntSurf_LineOn2S();
3098     Handle(IntPatch_WLine) aWLine = new IntPatch_WLine(aL2S, Standard_False);
3099     aWLine->Curve()->Add(aPnt2S.PntOn2S());
3100
3101     //Define the index of WLine, which lies the point aPnt2S in.
3102     Standard_Real anUf = 0.0, anUl = 0.0, aCurU2 = 0.0;
3103     Standard_Integer anIndex = 0;
3104     if(isTheReverse)
3105     {
3106       anUf = Max(u2 - aStepMax, aUSurf1f);
3107       anUl = u2;
3108       aCurU2 = u1;
3109     }
3110     else
3111     {
3112       anUf = Max(u1 - aStepMax, aUSurf1f);
3113       anUl = u1;
3114       aCurU2 = u2;
3115     }
3116     Standard_Real aDelta = RealLast();
3117     for (Standard_Integer i = 0; i < aNbWLines; i++)
3118     {
3119       Standard_Real anU2t = 0.0;
3120       if(!CylCylComputeParameters(anUl, i, anEquationCoeffs, anU2t))
3121         continue;
3122
3123       const Standard_Real aDU2 = Abs(anU2t - aCurU2);
3124       if(aDU2 < aDelta)
3125       {
3126         aDelta = aDU2; 
3127         anIndex = i;
3128       }
3129     }
3130
3131     //Try to fill aWLine by additional points
3132     while(anUl - anUf > RealSmall())
3133     {
3134       Standard_Real anU2 = 0.0, anV1 = 0.0, anV2 = 0.0;
3135       Standard_Boolean isDone = 
3136             CylCylComputeParameters(anUf, anIndex, anEquationCoeffs,
3137                                     anU2, anV1, anV2);
3138       anUf += aDU;
3139
3140       if(!isDone)
3141       {
3142         continue;
3143       }
3144
3145       if(AddPointIntoWL(theQuad1, theQuad2, anEquationCoeffs, isTheReverse, Standard_True,
3146                         gp_Pnt2d(anUf, anV1), gp_Pnt2d(anU2, anV2),
3147                         aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
3148                         aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l,
3149                         aPeriod, aWLine->Curve(), anIndex, theTol3D,
3150                         theTol2D, Standard_False, Standard_True))
3151       {
3152         break;
3153       }
3154     }
3155
3156     if(aWLine->NbPnts() > 1)
3157     {
3158       SeekAdditionalPoints( theQuad1, theQuad2, aWLine->Curve(), 
3159                             anEquationCoeffs, anIndex, aNbMinPoints,
3160                             1, aWLine->NbPnts(), aUSurf2f, aUSurf2l,
3161                             theTol2D, aPeriod, isTheReverse);
3162
3163       aWLine->ComputeVertexParameters(theTol3D);
3164       theSlin.Append(aWLine);
3165   
3166       theSPnt.Remove(aNbPnt);
3167       aNbPnt--;
3168     }
3169   }
3170   
3171   return Standard_True;
3172 }
3173
3174 //=======================================================================
3175 //function : IntCySp
3176 //purpose  : 
3177 //=======================================================================
3178 Standard_Boolean IntCySp(const IntSurf_Quadric& Quad1,
3179                          const IntSurf_Quadric& Quad2,
3180                          const Standard_Real Tol,
3181                          const Standard_Boolean Reversed,
3182                          Standard_Boolean& Empty,
3183                          Standard_Boolean& Multpoint,
3184                          IntPatch_SequenceOfLine& slin,
3185                          IntPatch_SequenceOfPoint& spnt)
3186
3187 {
3188   Standard_Integer i;
3189
3190   IntSurf_TypeTrans trans1,trans2;
3191   IntAna_ResultType typint;
3192   IntPatch_Point ptsol;
3193   gp_Circ cirsol;
3194
3195   gp_Cylinder Cy;
3196   gp_Sphere Sp;
3197
3198   if (!Reversed) {
3199     Cy = Quad1.Cylinder();
3200     Sp = Quad2.Sphere();
3201   }
3202   else {
3203     Cy = Quad2.Cylinder();
3204     Sp = Quad1.Sphere();
3205   }
3206   IntAna_QuadQuadGeo inter(Cy,Sp,Tol);
3207
3208   if (!inter.IsDone()) {return Standard_False;}
3209
3210   typint = inter.TypeInter();
3211   Standard_Integer NbSol = inter.NbSolutions();
3212   Empty = Standard_False;
3213
3214   switch (typint) {
3215
3216   case IntAna_Empty :
3217     {
3218       Empty = Standard_True;
3219     }
3220     break;
3221
3222   case IntAna_Point :
3223     {
3224       gp_Pnt psol(inter.Point(1));
3225       Standard_Real U1,V1,U2,V2;
3226       Quad1.Parameters(psol,U1,V1);
3227       Quad2.Parameters(psol,U2,V2);
3228       ptsol.SetValue(psol,Tol,Standard_True);
3229       ptsol.SetParameters(U1,V1,U2,V2);
3230       spnt.Append(ptsol);
3231     }
3232     break;
3233
3234   case IntAna_Circle:
3235     {
3236       cirsol = inter.Circle(1);
3237       gp_Vec Tgt;
3238       gp_Pnt ptref;
3239       ElCLib::D1(0.,cirsol,ptref,Tgt);
3240
3241       if (NbSol == 1) {
3242         gp_Vec TestCurvature(ptref,Sp.Location());
3243         gp_Vec Normsp,Normcyl;
3244         if (!Reversed) {
3245           Normcyl = Quad1.Normale(ptref);
3246           Normsp  = Quad2.Normale(ptref);
3247         }
3248         else {
3249           Normcyl = Quad2.Normale(ptref);
3250           Normsp  = Quad1.Normale(ptref);
3251         }
3252         
3253         IntSurf_Situation situcyl;
3254         IntSurf_Situation situsp;
3255         
3256         if (Normcyl.Dot(TestCurvature) > 0.) {
3257           situsp = IntSurf_Outside;
3258           if (Normsp.Dot(Normcyl) > 0.) {
3259             situcyl = IntSurf_Inside;
3260           }
3261           else {
3262             situcyl = IntSurf_Outside;
3263           }
3264         }
3265         else {
3266           situsp = IntSurf_Inside;
3267           if (Normsp.Dot(Normcyl) > 0.) {
3268             situcyl = IntSurf_Outside;
3269           }
3270           else {
3271             situcyl = IntSurf_Inside;
3272           }
3273         }
3274         Handle(IntPatch_GLine) glig;
3275         if (!Reversed) {
3276           glig = new IntPatch_GLine(cirsol, Standard_True, situcyl, situsp);
3277         }
3278         else {
3279           glig = new IntPatch_GLine(cirsol, Standard_True, situsp, situcyl);
3280         }
3281         slin.Append(glig);
3282       }
3283       else {
3284         if (Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref)) > 0.0) {
3285           trans1 = IntSurf_Out;
3286           trans2 = IntSurf_In;
3287         }
3288         else {
3289           trans1 = IntSurf_In;
3290           trans2 = IntSurf_Out;
3291         }
3292         Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
3293         slin.Append(glig);
3294
3295         cirsol = inter.Circle(2);
3296         ElCLib::D1(0.,cirsol,ptref,Tgt);
3297         Standard_Real qwe = Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
3298         if(qwe> 0.0000001) {
3299           trans1 = IntSurf_Out;
3300           trans2 = IntSurf_In;
3301         }
3302         else if(qwe<-0.0000001) {
3303           trans1 = IntSurf_In;
3304           trans2 = IntSurf_Out;
3305         }
3306         else { 
3307           trans1=trans2=IntSurf_Undecided; 
3308         }
3309         glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
3310         slin.Append(glig);
3311       }
3312     }
3313     break;
3314     
3315   case IntAna_NoGeometricSolution:
3316     {
3317       gp_Pnt psol;
3318       Standard_Real U1,V1,U2,V2;
3319       IntAna_IntQuadQuad anaint(Cy,Sp,Tol);
3320       if (!anaint.IsDone()) {
3321         return Standard_False;
3322       }
3323
3324       if (anaint.NbPnt()==0 && anaint.NbCurve()==0) {
3325         Empty = Standard_True;
3326       }
3327       else {
3328
3329         NbSol = anaint.NbPnt();
3330         for (i = 1; i <= NbSol; i++) {
3331           psol = anaint.Point(i);
3332           Quad1.Parameters(psol,U1,V1);
3333           Quad2.Parameters(psol,U2,V2);
3334           ptsol.SetValue(psol,Tol,Standard_True);
3335           ptsol.SetParameters(U1,V1,U2,V2);
3336           spnt.Append(ptsol);
3337         }
3338         
3339         gp_Pnt ptvalid,ptf,ptl;
3340         gp_Vec tgvalid;
3341         Standard_Real first,last,para;
3342         IntAna_Curve curvsol;
3343         Standard_Boolean tgfound;
3344         Standard_Integer kount;
3345         
3346         NbSol = anaint.NbCurve();
3347         for (i = 1; i <= NbSol; i++) {
3348           curvsol = anaint.Curve(i);
3349           curvsol.Domain(first,last);
3350           ptf = curvsol.Value(first);
3351           ptl = curvsol.Value(last);
3352
3353           para = last;
3354           kount = 1;
3355           tgfound = Standard_False;
3356           
3357           while (!tgfound) {
3358             para = (1.123*first + para)/2.123;
3359             tgfound = curvsol.D1u(para,ptvalid,tgvalid);
3360             if (!tgfound) {
3361               kount ++;
3362               tgfound = kount > 5;
3363             }
3364           }
3365           Handle(IntPatch_ALine) alig;
3366           if (kount <= 5) {
3367             Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid),
3368                                                  Quad1.Normale(ptvalid));
3369             if(qwe> 0.00000001) {
3370               trans1 = IntSurf_Out;
3371               trans2 = IntSurf_In;
3372             }
3373             else if(qwe<-0.00000001) {
3374               trans1 = IntSurf_In;
3375               trans2 = IntSurf_Out;
3376             }
3377             else { 
3378               trans1=trans2=IntSurf_Undecided; 
3379             }
3380             alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
3381           }
3382           else {
3383             alig = new IntPatch_ALine(curvsol,Standard_False);
3384           }
3385           Standard_Boolean TempFalse1a = Standard_False;
3386           Standard_Boolean TempFalse2a = Standard_False;
3387
3388           //-- ptf et ptl : points debut et fin de alig 
3389           
3390           ProcessBounds(alig,slin,Quad1,Quad2,TempFalse1a,ptf,first,
3391                         TempFalse2a,ptl,last,Multpoint,Tol);
3392           slin.Append(alig);
3393         } //-- boucle sur les lignes 
3394       } //-- solution avec au moins une lihne 
3395     }
3396     break;
3397
3398   default:
3399     {
3400       return Standard_False;
3401     }
3402   }
3403   return Standard_True;
3404 }
3405 //=======================================================================
3406 //function : IntCyCo
3407 //purpose  : 
3408 //=======================================================================
3409 Standard_Boolean IntCyCo(const IntSurf_Quadric& Quad1,
3410                          const IntSurf_Quadric& Quad2,
3411                          const Standard_Real Tol,
3412                          const Standard_Boolean Reversed,
3413                          Standard_Boolean& Empty,
3414                          Standard_Boolean& Multpoint,
3415                          IntPatch_SequenceOfLine& slin,
3416                          IntPatch_SequenceOfPoint& spnt)
3417
3418 {
3419   IntPatch_Point ptsol;
3420
3421   Standard_Integer i;
3422
3423   IntSurf_TypeTrans trans1,trans2;
3424   IntAna_ResultType typint;
3425   gp_Circ cirsol;
3426
3427   gp_Cylinder Cy;
3428   gp_Cone     Co;
3429
3430   if (!Reversed) {
3431     Cy = Quad1.Cylinder();
3432     Co = Quad2.Cone();
3433   }
3434   else {
3435     Cy = Quad2.Cylinder();
3436     Co = Quad1.Cone();
3437   }
3438   IntAna_QuadQuadGeo inter(Cy,Co,Tol);
3439
3440   if (!inter.IsDone()) {return Standard_False;}
3441
3442   typint = inter.TypeInter();
3443   Standard_Integer NbSol = inter.NbSolutions();
3444   Empty = Standard_False;
3445
3446   switch (typint) {
3447
3448   case IntAna_Empty : {
3449     Empty = Standard_True;
3450   }
3451     break;
3452
3453   case IntAna_Point :{
3454     gp_Pnt psol(inter.Point(1));
3455     Standard_Real U1,V1,U2,V2;
3456     Quad1.Parameters(psol,U1,V1);
3457     Quad1.Parameters(psol,U2,V2);
3458     ptsol.SetValue(psol,Tol,Standard_True);
3459     ptsol.SetParameters(U1,V1,U2,V2);
3460     spnt.Append(ptsol);
3461   }
3462     break;
3463     
3464   case IntAna_Circle:  {
3465     gp_Vec Tgt;
3466     gp_Pnt ptref;
3467     Standard_Integer j;
3468     Standard_Real qwe;
3469     //
3470     for(j=1; j<=2; ++j) { 
3471       cirsol = inter.Circle(j);
3472       ElCLib::D1(0.,cirsol,ptref,Tgt);
3473       qwe = Tgt.DotCross(Quad2.Normale(ptref),Quad1.Normale(ptref));
3474       if(qwe> 0.00000001) {
3475         trans1 = IntSurf_Out;
3476         trans2 = IntSurf_In;
3477       }
3478       else if(qwe<-0.00000001) {
3479         trans1 = IntSurf_In;
3480         trans2 = IntSurf_Out;
3481       }
3482       else { 
3483         trans1=trans2=IntSurf_Undecided; 
3484       }
3485       Handle(IntPatch_GLine) glig = new IntPatch_GLine(cirsol,Standard_False,trans1,trans2);
3486       slin.Append(glig);
3487     }
3488   }
3489     break;
3490     
3491   case IntAna_NoGeometricSolution:    {
3492     gp_Pnt psol;
3493     Standard_Real U1,V1,U2,V2;
3494     IntAna_IntQuadQuad anaint(Cy,Co,Tol);
3495     if (!anaint.IsDone()) {
3496       return Standard_False;
3497     }
3498     
3499     if (anaint.NbPnt() == 0 && anaint.NbCurve() == 0) {
3500       Empty = Standard_True;
3501     }
3502     else {
3503       NbSol = anaint.NbPnt();
3504       for (i = 1; i <= NbSol; i++) {
3505         psol = anaint.Point(i);
3506         Quad1.Parameters(psol,U1,V1);
3507         Quad2.Parameters(psol,U2,V2);
3508         ptsol.SetValue(psol,Tol,Standard_True);
3509         ptsol.SetParameters(U1,V1,U2,V2);
3510         spnt.Append(ptsol);
3511       }
3512       
3513       gp_Pnt ptvalid, ptf, ptl;
3514       gp_Vec tgvalid;
3515       //
3516       Standard_Real first,last,para;
3517       Standard_Boolean tgfound,firstp,lastp,kept;
3518       Standard_Integer kount;
3519       //
3520       //
3521       //IntAna_Curve curvsol;
3522       IntAna_Curve aC;
3523       IntAna_ListOfCurve aLC;
3524       IntAna_ListIteratorOfListOfCurve aIt;
3525       
3526       //
3527       NbSol = anaint.NbCurve();
3528       for (i = 1; i <= NbSol; ++i) {
3529         kept = Standard_False;
3530         //curvsol = anaint.Curve(i);
3531         aC=anaint.Curve(i);
3532         aLC.Clear();
3533         ExploreCurve(Cy, Co, aC, 10.*Tol, aLC);
3534         //
3535         aIt.Initialize(aLC);
3536         for (; aIt.More(); aIt.Next()) {
3537           IntAna_Curve& curvsol=aIt.Value();
3538           //
3539           curvsol.Domain(first, last);
3540           firstp = !curvsol.IsFirstOpen();
3541           lastp  = !curvsol.IsLastOpen();
3542           if (firstp) {
3543             ptf = curvsol.Value(first);
3544           }
3545           if (lastp) {
3546             ptl = curvsol.Value(last);
3547           }
3548           para = last;
3549           kount = 1;
3550           tgfound = Standard_False;
3551           
3552           while (!tgfound) {
3553             para = (1.123*first + para)/2.123;
3554             tgfound = curvsol.D1u(para,ptvalid,tgvalid);
3555             if (!tgfound) {
3556               kount ++;
3557               tgfound = kount > 5;
3558             }
3559           }
3560           Handle(IntPatch_ALine) alig;
3561           if (kount <= 5) {
3562             Standard_Real qwe = tgvalid.DotCross(Quad2.Normale(ptvalid),
3563                                                  Quad1.Normale(ptvalid));
3564             if(qwe> 0.00000001) {
3565               trans1 = IntSurf_Out;
3566               trans2 = IntSurf_In;
3567             }
3568             else if(qwe<-0.00000001) {
3569               trans1 = IntSurf_In;
3570               trans2 = IntSurf_Out;
3571             }
3572             else { 
3573               trans1=trans2=IntSurf_Undecided; 
3574             }
3575             alig = new IntPatch_ALine(curvsol,Standard_False,trans1,trans2);
3576             kept = Standard_True;
3577           }
3578           else {
3579             ptvalid = curvsol.Value(para);
3580             alig = new IntPatch_ALine(curvsol,Standard_False);
3581             kept = Standard_True;
3582             //-- cout << "Transition indeterminee" << endl;
3583           }
3584           if (kept) {
3585             Standard_Boolean Nfirstp = !firstp;
3586             Standard_Boolean Nlastp  = !lastp;
3587             ProcessBounds(alig,slin,Quad1,Quad2,Nfirstp,ptf,first,
3588                           Nlastp,ptl,last,Multpoint,Tol);
3589             slin.Append(alig);
3590           }
3591         } // for (; aIt.More(); aIt.Next())
3592       } // for (i = 1; i <= NbSol; ++i) 
3593     }
3594   }
3595     break;
3596     
3597   default:
3598     return Standard_False;
3599     
3600   } // switch (typint)
3601   
3602   return Standard_True;
3603 }
3604 //=======================================================================
3605 //function : ExploreCurve
3606 //purpose  : 
3607 //=======================================================================
3608 Standard_Boolean ExploreCurve(const gp_Cylinder& ,//aCy,
3609                               const gp_Cone& aCo,
3610                               IntAna_Curve& aC,
3611                               const Standard_Real aTol,
3612                               IntAna_ListOfCurve& aLC)
3613                               
3614 {
3615   Standard_Boolean bFind=Standard_False;
3616   Standard_Real aTheta, aT1, aT2, aDst;
3617   gp_Pnt aPapx, aPx;
3618   //
3619   //aC.Dump();
3620   //
3621   aLC.Clear();
3622   aLC.Append(aC);
3623   //
3624   aPapx=aCo.Apex();
3625   //
3626   aC.Domain(aT1, aT2);
3627   //
3628   aPx=aC.Value(aT1);
3629   aDst=aPx.Distance(aPapx);
3630   if (aDst<aTol) {
3631     return bFind;
3632   }
3633   aPx=aC.Value(aT2);
3634   aDst=aPx.Distance(aPapx);
3635   if (aDst<aTol) {
3636     return bFind;
3637   }
3638   //
3639   bFind=aC.FindParameter(aPapx, aTheta);
3640   if (!bFind){
3641     return bFind;
3642   }
3643   //
3644   aPx=aC.Value(aTheta);
3645   aDst=aPx.Distance(aPapx);
3646   if (aDst>aTol) {
3647     return !bFind;
3648   }
3649   //
3650   // need to be splitted at aTheta
3651   IntAna_Curve aC1, aC2;
3652   //
3653   aC1=aC;
3654   aC1.SetDomain(aT1, aTheta);
3655   aC2=aC;
3656   aC2.SetDomain(aTheta, aT2);
3657   //
3658   aLC.Clear();
3659   aLC.Append(aC1);
3660   aLC.Append(aC2);
3661   //
3662   return bFind;
3663 }
3664 //=======================================================================
3665 //function : IsToReverse
3666 //purpose  : 
3667 //=======================================================================
3668 Standard_Boolean IsToReverse(const gp_Cylinder& Cy1,
3669                              const gp_Cylinder& Cy2,
3670                              const Standard_Real Tol)
3671 {
3672   Standard_Boolean bRet;
3673   Standard_Real aR1,aR2, dR, aSc1, aSc2;
3674   //
3675   bRet=Standard_False;
3676   //
3677   aR1=Cy1.Radius();
3678   aR2=Cy2.Radius();
3679   dR=aR1-aR2;
3680   if (dR<0.) {
3681     dR=-dR;
3682   }
3683   if (dR>Tol) {
3684     bRet=aR1>aR2;
3685   }
3686   else {
3687     gp_Dir aDZ(0.,0.,1.);
3688     //
3689     const gp_Dir& aDir1=Cy1.Axis().Direction();
3690     aSc1=aDir1*aDZ;
3691     if (aSc1<0.) {
3692       aSc1=-aSc1;
3693     }
3694     //
3695     const gp_Dir& aDir2=Cy2.Axis().Direction();
3696     aSc2=aDir2*aDZ;
3697     if (aSc2<0.) {
3698       aSc2=-aSc2;
3699     }
3700     //
3701     if (aSc2<aSc1) {
3702       bRet=!bRet;
3703     }
3704   }//if (dR<Tol) {
3705   return bRet;
3706 }