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